Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit 1b456c1

Browse files
committed
Update from parent 'origin/master' (no conflict)
Commit: 046c22c Parent branch: origin/master Forked at: 2afecf8
2 parents 924ca71 + 046c22c commit 1b456c1

File tree

2 files changed

+95
-16
lines changed

2 files changed

+95
-16
lines changed

client/peerset/src/lib.rs

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use std::{collections::{HashSet, HashMap}, collections::VecDeque};
2323
use futures::{prelude::*, channel::mpsc};
2424
use log::{debug, error, trace};
2525
use serde_json::json;
26-
use std::{pin::Pin, task::Context, task::Poll};
26+
use std::{pin::Pin, task::{Context, Poll}, time::Duration};
2727
use wasm_timer::Instant;
2828

2929
pub use libp2p::PeerId;
@@ -34,6 +34,9 @@ const BANNED_THRESHOLD: i32 = 82 * (i32::min_value() / 100);
3434
const DISCONNECT_REPUTATION_CHANGE: i32 = -256;
3535
/// Reserved peers group ID
3636
const RESERVED_NODES: &'static str = "reserved";
37+
/// Amount of time between the moment we disconnect from a node and the moment we remove it from
38+
/// the list.
39+
const FORGET_AFTER: Duration = Duration::from_secs(3600);
3740

3841
#[derive(Debug)]
3942
enum Action {
@@ -310,10 +313,11 @@ impl Peerset {
310313
/// Updates the value of `self.latest_time_update` and performs all the updates that happen
311314
/// over time, such as reputation increases for staying connected.
312315
fn update_time(&mut self) {
316+
let now = Instant::now();
317+
313318
// We basically do `(now - self.latest_update).as_secs()`, except that by the way we do it
314319
// we know that we're not going to miss seconds because of rounding to integers.
315320
let secs_diff = {
316-
let now = Instant::now();
317321
let elapsed_latest = self.latest_time_update - self.created;
318322
let elapsed_now = now - self.created;
319323
self.latest_time_update = now;
@@ -345,10 +349,16 @@ impl Peerset {
345349
peer.set_reputation(after)
346350
}
347351
peersstate::Peer::NotConnected(mut peer) => {
348-
let before = peer.reputation();
349-
let after = reput_tick(before);
350-
trace!(target: "peerset", "Fleeting {}: {} -> {}", peer_id, before, after);
351-
peer.set_reputation(after)
352+
if peer.reputation() == 0 &&
353+
peer.last_connected_or_discovered() + FORGET_AFTER < now
354+
{
355+
peer.forget_peer();
356+
} else {
357+
let before = peer.reputation();
358+
let after = reput_tick(before);
359+
trace!(target: "peerset", "Fleeting {}: {} -> {}", peer_id, before, after);
360+
peer.set_reputation(after)
361+
}
352362
}
353363
peersstate::Peer::Unknown(_) => unreachable!("We iterate over known peers; qed")
354364
};
@@ -414,7 +424,10 @@ impl Peerset {
414424
let not_connected = match self.data.peer(&peer_id) {
415425
// If we're already connected, don't answer, as the docs mention.
416426
peersstate::Peer::Connected(_) => return,
417-
peersstate::Peer::NotConnected(entry) => entry,
427+
peersstate::Peer::NotConnected(mut entry) => {
428+
entry.bump_last_connected_or_discovered();
429+
entry
430+
},
418431
peersstate::Peer::Unknown(entry) => entry.discover(),
419432
};
420433

client/peerset/src/peersstate.rs

Lines changed: 75 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,9 @@
1717
//! Contains the state storage behind the peerset.
1818
1919
use libp2p::PeerId;
20+
use log::{error, warn};
2021
use std::{borrow::Cow, collections::{HashSet, HashMap}};
21-
use log::warn;
22+
use wasm_timer::Instant;
2223

2324
/// State storage behind the peerset.
2425
///
@@ -69,7 +70,9 @@ struct Node {
6970
impl Default for Node {
7071
fn default() -> Node {
7172
Node {
72-
connection_state: ConnectionState::NotConnected,
73+
connection_state: ConnectionState::NotConnected {
74+
last_connected: Instant::now(),
75+
},
7376
reputation: 0,
7477
}
7578
}
@@ -83,7 +86,11 @@ enum ConnectionState {
8386
/// We are connected through an outgoing connection.
8487
Out,
8588
/// We are not connected to this node.
86-
NotConnected,
89+
NotConnected {
90+
/// When we were last connected to the node, or if we were never connected when we
91+
/// discovered it.
92+
last_connected: Instant,
93+
},
8794
}
8895

8996
impl ConnectionState {
@@ -92,7 +99,7 @@ impl ConnectionState {
9299
match self {
93100
ConnectionState::In => true,
94101
ConnectionState::Out => true,
95-
ConnectionState::NotConnected => false,
102+
ConnectionState::NotConnected { .. } => false,
96103
}
97104
}
98105
}
@@ -212,11 +219,13 @@ impl PeersState {
212219
match node.connection_state {
213220
ConnectionState::In => self.num_in -= 1,
214221
ConnectionState::Out => self.num_out -= 1,
215-
ConnectionState::NotConnected =>
222+
ConnectionState::NotConnected { .. } =>
216223
debug_assert!(false, "State inconsistency: disconnecting a disconnected node")
217224
}
218225
}
219-
node.connection_state = ConnectionState::NotConnected;
226+
node.connection_state = ConnectionState::NotConnected {
227+
last_connected: Instant::now(),
228+
};
220229
} else {
221230
warn!(target: "peerset", "Attempting to disconnect unknown peer {}", peer_id);
222231
}
@@ -292,7 +301,7 @@ impl PeersState {
292301
match peer.connection_state {
293302
ConnectionState::In => self.num_in += 1,
294303
ConnectionState::Out => self.num_out += 1,
295-
ConnectionState::NotConnected => {},
304+
ConnectionState::NotConnected { .. } => {},
296305
}
297306
}
298307
}
@@ -305,7 +314,7 @@ impl PeersState {
305314
match peer.connection_state {
306315
ConnectionState::In => self.num_in -= 1,
307316
ConnectionState::Out => self.num_out -= 1,
308-
ConnectionState::NotConnected => {},
317+
ConnectionState::NotConnected { .. } => {},
309318
}
310319
}
311320
}
@@ -467,6 +476,45 @@ impl<'a> NotConnectedPeer<'a> {
467476
self.peer_id.into_owned()
468477
}
469478

479+
/// Bumps the value that `last_connected_or_discovered` would return to now, even if we
480+
/// didn't connect or disconnect.
481+
pub fn bump_last_connected_or_discovered(&mut self) {
482+
let state = match self.state.nodes.get_mut(&*self.peer_id) {
483+
Some(s) => s,
484+
None => return,
485+
};
486+
487+
if let ConnectionState::NotConnected { last_connected } = &mut state.connection_state {
488+
*last_connected = Instant::now();
489+
}
490+
}
491+
492+
/// Returns when we were last connected to this peer, or when we discovered it if we were
493+
/// never connected.
494+
///
495+
/// Guaranteed to be earlier than calling `Instant::now()` after the function returns.
496+
pub fn last_connected_or_discovered(&self) -> Instant {
497+
let state = match self.state.nodes.get(&*self.peer_id) {
498+
Some(s) => s,
499+
None => {
500+
error!(
501+
target: "peerset",
502+
"State inconsistency with {}; not connected after borrow",
503+
self.peer_id
504+
);
505+
return Instant::now();
506+
}
507+
};
508+
509+
match state.connection_state {
510+
ConnectionState::NotConnected { last_connected } => last_connected,
511+
_ => {
512+
error!(target: "peerset", "State inconsistency with {}", self.peer_id);
513+
Instant::now()
514+
}
515+
}
516+
}
517+
470518
/// Tries to set the peer as connected as an outgoing connection.
471519
///
472520
/// If there are enough slots available, switches the node to "connected" and returns `Ok`. If
@@ -518,6 +566,22 @@ impl<'a> NotConnectedPeer<'a> {
518566
pub fn add_reputation(&mut self, modifier: i32) {
519567
self.state.add_reputation(&self.peer_id, modifier)
520568
}
569+
570+
/// Un-discovers the peer. Removes it from the list.
571+
pub fn forget_peer(self) -> UnknownPeer<'a> {
572+
if self.state.nodes.remove(&*self.peer_id).is_none() {
573+
error!(
574+
target: "peerset",
575+
"State inconsistency with {} when forgetting peer",
576+
self.peer_id
577+
);
578+
}
579+
580+
UnknownPeer {
581+
parent: self.state,
582+
peer_id: self.peer_id,
583+
}
584+
}
521585
}
522586

523587
/// A peer that we have never heard of.
@@ -533,7 +597,9 @@ impl<'a> UnknownPeer<'a> {
533597
/// values using the `NotConnectedPeer` that this method returns.
534598
pub fn discover(self) -> NotConnectedPeer<'a> {
535599
self.parent.nodes.insert(self.peer_id.clone().into_owned(), Node {
536-
connection_state: ConnectionState::NotConnected,
600+
connection_state: ConnectionState::NotConnected {
601+
last_connected: Instant::now(),
602+
},
537603
reputation: 0,
538604
});
539605

0 commit comments

Comments
 (0)