diff --git a/client/cli/src/params/network_params.rs b/client/cli/src/params/network_params.rs index a974b86026116..84db218cc51da 100644 --- a/client/cli/src/params/network_params.rs +++ b/client/cli/src/params/network_params.rs @@ -28,7 +28,7 @@ use sc_service::{ config::{Multiaddr, MultiaddrWithPeerId}, ChainSpec, ChainType, }; -use std::{borrow::Cow, path::PathBuf}; +use std::{borrow::Cow, num::NonZeroUsize, path::PathBuf}; /// Parameters used to create the network configuration. #[derive(Debug, Clone, Args)] @@ -121,6 +121,13 @@ pub struct NetworkParams { #[arg(long)] pub kademlia_disjoint_query_paths: bool, + /// Kademlia replication factor determines to how many closest peers a record is replicated to. + /// + /// Discovery mechanism requires successful replication to all + /// `kademlia_replication_factor` peers to consider record successfully put. + #[arg(long, default_value = "20")] + pub kademlia_replication_factor: NonZeroUsize, + /// Join the IPFS network and serve transactions over bitswap protocol. #[arg(long)] pub ipfs_server: bool, @@ -233,6 +240,7 @@ impl NetworkParams { enable_dht_random_walk: !self.reserved_only, allow_non_globals_in_dht, kademlia_disjoint_query_paths: self.kademlia_disjoint_query_paths, + kademlia_replication_factor: self.kademlia_replication_factor, yamux_window_size: None, ipfs_server: self.ipfs_server, sync_mode: self.sync.into(), diff --git a/client/network/src/config.rs b/client/network/src/config.rs index 17ca8335653de..78b064a690541 100644 --- a/client/network/src/config.rs +++ b/client/network/src/config.rs @@ -22,6 +22,7 @@ //! See the documentation of [`Params`]. pub use crate::{ + discovery::DEFAULT_KADEMLIA_REPLICATION_FACTOR, protocol::NotificationsSink, request_responses::{ IncomingRequest, OutgoingResponse, ProtocolConfig as RequestResponseConfig, @@ -50,6 +51,7 @@ use std::{ io::{self, Write}, iter, net::Ipv4Addr, + num::NonZeroUsize, path::{Path, PathBuf}, pin::Pin, str::{self, FromStr}, @@ -605,6 +607,12 @@ pub struct NetworkConfiguration { /// the presence of potentially adversarial nodes. pub kademlia_disjoint_query_paths: bool, + /// Kademlia replication factor determines to how many closest peers a record is replicated to. + /// + /// Discovery mechanism requires successful replication to all + /// `kademlia_replication_factor` peers to consider record successfully put. + pub kademlia_replication_factor: NonZeroUsize, + /// Enable serving block data over IPFS bitswap. pub ipfs_server: bool, @@ -656,6 +664,8 @@ impl NetworkConfiguration { enable_dht_random_walk: true, allow_non_globals_in_dht: false, kademlia_disjoint_query_paths: false, + kademlia_replication_factor: NonZeroUsize::new(DEFAULT_KADEMLIA_REPLICATION_FACTOR) + .expect("value is a constant; constant is non-zero; qed."), yamux_window_size: None, ipfs_server: false, } diff --git a/client/network/src/discovery.rs b/client/network/src/discovery.rs index 708406bd15340..42dc934ef7776 100644 --- a/client/network/src/discovery.rs +++ b/client/network/src/discovery.rs @@ -87,6 +87,10 @@ use std::{ /// a given address. const MAX_KNOWN_EXTERNAL_ADDRESSES: usize = 32; +/// Default value for Kademlia replication factor which determines to how many closest peers a +/// record is replicated to. +pub const DEFAULT_KADEMLIA_REPLICATION_FACTOR: usize = 20; + /// `DiscoveryBehaviour` configuration. /// /// Note: In order to discover nodes or load and store values via Kademlia one has to add @@ -101,6 +105,7 @@ pub struct DiscoveryConfig { enable_mdns: bool, kademlia_disjoint_query_paths: bool, kademlia_protocols: Vec>, + kademlia_replication_factor: NonZeroUsize, } impl DiscoveryConfig { @@ -116,6 +121,8 @@ impl DiscoveryConfig { enable_mdns: false, kademlia_disjoint_query_paths: false, kademlia_protocols: Vec::new(), + kademlia_replication_factor: NonZeroUsize::new(DEFAULT_KADEMLIA_REPLICATION_FACTOR) + .expect("value is a constant; constant is non-zero; qed."), } } @@ -182,6 +189,12 @@ impl DiscoveryConfig { self } + /// Sets Kademlia replication factor. + pub fn with_kademlia_replication_factor(&mut self, value: NonZeroUsize) -> &mut Self { + self.kademlia_replication_factor = value; + self + } + /// Create a `DiscoveryBehaviour` from this config. pub fn finish(self) -> DiscoveryBehaviour { let Self { @@ -194,10 +207,13 @@ impl DiscoveryConfig { enable_mdns, kademlia_disjoint_query_paths, kademlia_protocols, + kademlia_replication_factor, } = self; let kademlia = if !kademlia_protocols.is_empty() { let mut config = KademliaConfig::default(); + + config.set_replication_factor(kademlia_replication_factor); config.set_protocol_names(kademlia_protocols.into_iter().map(Into::into).collect()); // By default Kademlia attempts to insert all peers into its routing table once a // dialing attempt succeeds. In order to control which peer is added, disable the diff --git a/client/network/src/service.rs b/client/network/src/service.rs index 62ff5ae42466b..94927b5edf921 100644 --- a/client/network/src/service.rs +++ b/client/network/src/service.rs @@ -320,6 +320,7 @@ where config.use_kademlia_disjoint_query_paths( network_config.kademlia_disjoint_query_paths, ); + config.with_kademlia_replication_factor(network_config.kademlia_replication_factor); match network_config.transport { TransportConfig::MemoryOnly => {