diff --git a/client/cli/src/params/network_params.rs b/client/cli/src/params/network_params.rs index 6b7b2680513c3..86060486144ac 100644 --- a/client/cli/src/params/network_params.rs +++ b/client/cli/src/params/network_params.rs @@ -86,9 +86,12 @@ pub struct NetworkParams { #[structopt(long = "out-peers", value_name = "COUNT", default_value = "25")] pub out_peers: u32, - /// Specify the maximum number of incoming connections we're accepting. + /// Maximum number of inbound full nodes peers. #[structopt(long = "in-peers", value_name = "COUNT", default_value = "25")] pub in_peers: u32, + /// Maximum number of inbound light nodes peers. + #[structopt(long = "in-peers-light", value_name = "COUNT", default_value = "100")] + pub in_peers_light: u32, /// Disable mDNS discovery. /// @@ -203,7 +206,7 @@ impl NetworkParams { boot_nodes, net_config_path, default_peers_set: SetConfig { - in_peers: self.in_peers, + in_peers: self.in_peers + self.in_peers_light, out_peers: self.out_peers, reserved_nodes: self.reserved_nodes.clone(), non_reserved_mode: if self.reserved_only { @@ -212,6 +215,7 @@ impl NetworkParams { NonReservedPeerMode::Accept }, }, + default_peers_set_num_full: self.in_peers + self.out_peers, listen_addresses, public_addresses, extra_sets: Vec::new(), diff --git a/client/network/src/config.rs b/client/network/src/config.rs index 14411ef2aa18a..3b9c864c37927 100644 --- a/client/network/src/config.rs +++ b/client/network/src/config.rs @@ -416,6 +416,11 @@ pub struct NetworkConfiguration { pub request_response_protocols: Vec, /// Configuration for the default set of nodes used for block syncing and transactions. pub default_peers_set: SetConfig, + /// Number of substreams to reserve for full nodes for block syncing and transactions. + /// Any other slot will be dedicated to light nodes. + /// + /// This value is implicitly capped to `default_set.out_peers + default_set.in_peers`. + pub default_peers_set_num_full: u32, /// Configuration for extra sets of nodes. pub extra_sets: Vec, /// Client identifier. Sent over the wire for debugging purposes. @@ -473,6 +478,7 @@ impl NetworkConfiguration { node_key: NodeKeyConfig, net_config_path: Option, ) -> Self { + let default_peers_set = SetConfig::default(); Self { net_config_path, listen_addresses: Vec::new(), @@ -480,7 +486,8 @@ impl NetworkConfiguration { boot_nodes: Vec::new(), node_key, request_response_protocols: Vec::new(), - default_peers_set: Default::default(), + default_peers_set_num_full: default_peers_set.in_peers + default_peers_set.out_peers, + default_peers_set, extra_sets: Vec::new(), client_version: client_version.into(), node_name: node_name.into(), diff --git a/client/network/src/protocol.rs b/client/network/src/protocol.rs index a5a826ed4748c..3fb40b7199d68 100644 --- a/client/network/src/protocol.rs +++ b/client/network/src/protocol.rs @@ -166,13 +166,19 @@ pub struct Protocol { pending_messages: VecDeque>, config: ProtocolConfig, genesis_hash: B::Hash, + /// State machine that handles the list of in-progress requests. Only full node peers are + /// registered. sync: ChainSync, - // All connected peers + // All connected peers. Contains both full and light node peers. peers: HashMap>, chain: Arc>, /// List of nodes for which we perform additional logging because they are important for the /// user. important_peers: HashSet, + /// Value that was passed as part of the configuration. Used to cap the number of full nodes. + default_peers_set_num_full: usize, + /// Number of slots to allocate to light nodes. + default_peers_set_num_light: usize, /// Used to report reputation changes. peerset_handle: sc_peerset::PeersetHandle, /// Handles opening the unique substream and sending and receiving raw messages. @@ -428,6 +434,12 @@ impl Protocol { genesis_hash: info.genesis_hash, sync, important_peers, + default_peers_set_num_full: network_config.default_peers_set_num_full as usize, + default_peers_set_num_light: { + let total = network_config.default_peers_set.out_peers + + network_config.default_peers_set.in_peers; + total.saturating_sub(network_config.default_peers_set_num_full) as usize + }, peerset_handle: peerset_handle.clone(), behaviour, notification_protocols: network_config @@ -808,6 +820,21 @@ impl Protocol { } } + if status.roles.is_full() && self.sync.num_peers() >= self.default_peers_set_num_full { + debug!(target: "sync", "Too many full nodes, rejecting {}", who); + self.behaviour.disconnect_peer(&who, HARDCODED_PEERSETS_SYNC); + return Err(()) + } + + if status.roles.is_light() && + (self.peers.len() - self.sync.num_peers()) < self.default_peers_set_num_light + { + // Make sure that not all slots are occupied by light clients. + debug!(target: "sync", "Too many light nodes, rejecting {}", who); + self.behaviour.disconnect_peer(&who, HARDCODED_PEERSETS_SYNC); + return Err(()) + } + let peer = Peer { info: PeerInfo { roles: status.roles, diff --git a/client/network/src/protocol/sync.rs b/client/network/src/protocol/sync.rs index af65dec1c3fe9..d6513ca2e5b9d 100644 --- a/client/network/src/protocol/sync.rs +++ b/client/network/src/protocol/sync.rs @@ -648,6 +648,11 @@ impl ChainSync { self.downloaded_blocks } + /// Returns the current number of peers stored within this state machine. + pub fn num_peers(&self) -> usize { + self.peers.len() + } + /// Handle a new connected peer. /// /// Call this method whenever we connect to a new peer. diff --git a/client/service/src/builder.rs b/client/service/src/builder.rs index 269b7be720be0..bf681aec94c7d 100644 --- a/client/service/src/builder.rs +++ b/client/service/src/builder.rs @@ -808,8 +808,7 @@ where let (handler, protocol_config) = StateRequestHandler::new( &protocol_id, client.clone(), - config.network.default_peers_set.in_peers as usize + - config.network.default_peers_set.out_peers as usize, + config.network.default_peers_set_num_full as usize, ); spawn_handle.spawn("state-request-handler", Some("networking"), handler.run()); protocol_config