Disable Kademlia random walk when --reserved-nodes is passed (#7999)

* Disable Kademlia random walk when --reserved-nodes is passed

* Update client/network/src/discovery.rs

Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>

Co-authored-by: Roman Borschel <romanb@users.noreply.github.com>
This commit is contained in:
Pierre Krieger
2021-02-02 14:52:09 +01:00
committed by GitHub
parent de4cf4c380
commit eeff8f3204
4 changed files with 68 additions and 35 deletions
@@ -36,10 +36,14 @@ pub struct NetworkParams {
#[structopt(long = "reserved-nodes", value_name = "ADDR")] #[structopt(long = "reserved-nodes", value_name = "ADDR")]
pub reserved_nodes: Vec<MultiaddrWithPeerId>, pub reserved_nodes: Vec<MultiaddrWithPeerId>,
/// Whether to only allow connections to/from reserved nodes. /// Whether to only synchronize the chain with reserved nodes.
/// ///
/// If you are a validator your node might still connect to other validator /// Also disables automatic peer discovery.
/// nodes regardless of whether they are defined as reserved nodes. ///
/// TCP connections might still be established with non-reserved nodes.
/// In particular, if you are a validator your node might still connect to other
/// validator nodes and collator nodes regardless of whether they are defined as
/// reserved nodes.
#[structopt(long = "reserved-only")] #[structopt(long = "reserved-only")]
pub reserved_only: bool, pub reserved_only: bool,
@@ -173,6 +177,7 @@ impl NetworkParams {
wasm_external_transport: None, wasm_external_transport: None,
}, },
max_parallel_downloads: self.max_parallel_downloads, max_parallel_downloads: self.max_parallel_downloads,
enable_dht_random_walk: !self.reserved_only,
allow_non_globals_in_dht, allow_non_globals_in_dht,
kademlia_disjoint_query_paths: self.kademlia_disjoint_query_paths, kademlia_disjoint_query_paths: self.kademlia_disjoint_query_paths,
yamux_window_size: None, yamux_window_size: None,
+10 -2
View File
@@ -408,10 +408,17 @@ pub struct NetworkConfiguration {
pub transport: TransportConfig, pub transport: TransportConfig,
/// Maximum number of peers to ask the same blocks in parallel. /// Maximum number of peers to ask the same blocks in parallel.
pub max_parallel_downloads: u32, pub max_parallel_downloads: u32,
/// True if Kademlia random discovery should be enabled.
///
/// If true, the node will automatically randomly walk the DHT in order to find new peers.
pub enable_dht_random_walk: bool,
/// Should we insert non-global addresses into the DHT? /// Should we insert non-global addresses into the DHT?
pub allow_non_globals_in_dht: bool, pub allow_non_globals_in_dht: bool,
/// Require iterative Kademlia DHT queries to use disjoint paths for increased resiliency in the
/// presence of potentially adversarial nodes. /// Require iterative Kademlia DHT queries to use disjoint paths for increased resiliency in
/// the presence of potentially adversarial nodes.
pub kademlia_disjoint_query_paths: bool, pub kademlia_disjoint_query_paths: bool,
/// Size of Yamux receive window of all substreams. `None` for the default (256kiB). /// Size of Yamux receive window of all substreams. `None` for the default (256kiB).
@@ -461,6 +468,7 @@ impl NetworkConfiguration {
wasm_external_transport: None, wasm_external_transport: None,
}, },
max_parallel_downloads: 5, max_parallel_downloads: 5,
enable_dht_random_walk: true,
allow_non_globals_in_dht: false, allow_non_globals_in_dht: false,
kademlia_disjoint_query_paths: false, kademlia_disjoint_query_paths: false,
yamux_window_size: None, yamux_window_size: None,
+49 -30
View File
@@ -80,6 +80,7 @@ const MAX_KNOWN_EXTERNAL_ADDRESSES: usize = 32;
pub struct DiscoveryConfig { pub struct DiscoveryConfig {
local_peer_id: PeerId, local_peer_id: PeerId,
user_defined: Vec<(PeerId, Multiaddr)>, user_defined: Vec<(PeerId, Multiaddr)>,
dht_random_walk: bool,
allow_private_ipv4: bool, allow_private_ipv4: bool,
allow_non_globals_in_dht: bool, allow_non_globals_in_dht: bool,
discovery_only_if_under_num: u64, discovery_only_if_under_num: u64,
@@ -94,6 +95,7 @@ impl DiscoveryConfig {
DiscoveryConfig { DiscoveryConfig {
local_peer_id: local_public_key.into_peer_id(), local_peer_id: local_public_key.into_peer_id(),
user_defined: Vec::new(), user_defined: Vec::new(),
dht_random_walk: true,
allow_private_ipv4: true, allow_private_ipv4: true,
allow_non_globals_in_dht: false, allow_non_globals_in_dht: false,
discovery_only_if_under_num: std::u64::MAX, discovery_only_if_under_num: std::u64::MAX,
@@ -118,6 +120,13 @@ impl DiscoveryConfig {
self self
} }
/// Whether the discovery behaviour should periodically perform a random
/// walk on the DHT to discover peers.
pub fn with_dht_random_walk(&mut self, value: bool) -> &mut Self {
self.dht_random_walk = value;
self
}
/// Should private IPv4 addresses be reported? /// Should private IPv4 addresses be reported?
pub fn allow_private_ipv4(&mut self, value: bool) -> &mut Self { pub fn allow_private_ipv4(&mut self, value: bool) -> &mut Self {
self.allow_private_ipv4 = value; self.allow_private_ipv4 = value;
@@ -163,6 +172,7 @@ impl DiscoveryConfig {
let DiscoveryConfig { let DiscoveryConfig {
local_peer_id, local_peer_id,
user_defined, user_defined,
dht_random_walk,
allow_private_ipv4, allow_private_ipv4,
allow_non_globals_in_dht, allow_non_globals_in_dht,
discovery_only_if_under_num, discovery_only_if_under_num,
@@ -197,7 +207,11 @@ impl DiscoveryConfig {
DiscoveryBehaviour { DiscoveryBehaviour {
user_defined, user_defined,
kademlias, kademlias,
next_kad_random_query: Delay::new(Duration::new(0, 0)), next_kad_random_query: if dht_random_walk {
Some(Delay::new(Duration::new(0, 0)))
} else {
None
},
duration_to_next_kad: Duration::from_secs(1), duration_to_next_kad: Duration::from_secs(1),
pending_events: VecDeque::new(), pending_events: VecDeque::new(),
local_peer_id, local_peer_id,
@@ -229,8 +243,9 @@ pub struct DiscoveryBehaviour {
/// Discovers nodes on the local network. /// Discovers nodes on the local network.
#[cfg(not(target_os = "unknown"))] #[cfg(not(target_os = "unknown"))]
mdns: MdnsWrapper, mdns: MdnsWrapper,
/// Stream that fires when we need to perform the next random Kademlia query. /// Stream that fires when we need to perform the next random Kademlia query. `None` if
next_kad_random_query: Delay, /// random walking is disabled.
next_kad_random_query: Option<Delay>,
/// After `next_kad_random_query` triggers, the next one triggers after this duration. /// After `next_kad_random_query` triggers, the next one triggers after this duration.
duration_to_next_kad: Duration, duration_to_next_kad: Duration,
/// Events to return in priority when polled. /// Events to return in priority when polled.
@@ -434,6 +449,8 @@ pub enum DiscoveryOut {
ValuePutFailed(record::Key, Duration), ValuePutFailed(record::Key, Duration),
/// Started a random Kademlia query for each DHT identified by the given `ProtocolId`s. /// Started a random Kademlia query for each DHT identified by the given `ProtocolId`s.
///
/// Only happens if [`DiscoveryConfig::with_dht_random_walk`] has been configured to `true`.
RandomKademliaStarted(Vec<ProtocolId>), RandomKademliaStarted(Vec<ProtocolId>),
} }
@@ -602,34 +619,36 @@ impl NetworkBehaviour for DiscoveryBehaviour {
} }
// Poll the stream that fires when we need to start a random Kademlia query. // Poll the stream that fires when we need to start a random Kademlia query.
while let Poll::Ready(_) = self.next_kad_random_query.poll_unpin(cx) { if let Some(next_kad_random_query) = self.next_kad_random_query.as_mut() {
let actually_started = if self.num_connections < self.discovery_only_if_under_num { while let Poll::Ready(_) = next_kad_random_query.poll_unpin(cx) {
let random_peer_id = PeerId::random(); let actually_started = if self.num_connections < self.discovery_only_if_under_num {
debug!(target: "sub-libp2p", let random_peer_id = PeerId::random();
"Libp2p <= Starting random Kademlia request for {:?}", debug!(target: "sub-libp2p",
random_peer_id); "Libp2p <= Starting random Kademlia request for {:?}",
for k in self.kademlias.values_mut() { random_peer_id);
k.get_closest_peers(random_peer_id.clone()); for k in self.kademlias.values_mut() {
k.get_closest_peers(random_peer_id.clone());
}
true
} else {
debug!(
target: "sub-libp2p",
"Kademlia paused due to high number of connections ({})",
self.num_connections
);
false
};
// Schedule the next random query with exponentially increasing delay,
// capped at 60 seconds.
*next_kad_random_query = Delay::new(self.duration_to_next_kad);
self.duration_to_next_kad = cmp::min(self.duration_to_next_kad * 2,
Duration::from_secs(60));
if actually_started {
let ev = DiscoveryOut::RandomKademliaStarted(self.kademlias.keys().cloned().collect());
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev));
} }
true
} else {
debug!(
target: "sub-libp2p",
"Kademlia paused due to high number of connections ({})",
self.num_connections
);
false
};
// Schedule the next random query with exponentially increasing delay,
// capped at 60 seconds.
self.next_kad_random_query = Delay::new(self.duration_to_next_kad);
self.duration_to_next_kad = cmp::min(self.duration_to_next_kad * 2,
Duration::from_secs(60));
if actually_started {
let ev = DiscoveryOut::RandomKademliaStarted(self.kademlias.keys().cloned().collect());
return Poll::Ready(NetworkBehaviourAction::GenerateEvent(ev));
} }
} }
+1
View File
@@ -268,6 +268,7 @@ impl<B: BlockT + 'static, H: ExHashT> NetworkWorker<B, H> {
config.with_user_defined(known_addresses); config.with_user_defined(known_addresses);
config.discovery_limit(u64::from(params.network_config.default_peers_set.out_peers) + 15); config.discovery_limit(u64::from(params.network_config.default_peers_set.out_peers) + 15);
config.add_protocol(params.protocol_id.clone()); config.add_protocol(params.protocol_id.clone());
config.with_dht_random_walk(params.network_config.enable_dht_random_walk);
config.allow_non_globals_in_dht(params.network_config.allow_non_globals_in_dht); config.allow_non_globals_in_dht(params.network_config.allow_non_globals_in_dht);
config.use_kademlia_disjoint_query_paths(params.network_config.kademlia_disjoint_query_paths); config.use_kademlia_disjoint_query_paths(params.network_config.kademlia_disjoint_query_paths);