diff --git a/prdoc/pr_9315.prdoc b/prdoc/pr_9315.prdoc new file mode 100644 index 0000000000000..ac30287b309a3 --- /dev/null +++ b/prdoc/pr_9315.prdoc @@ -0,0 +1,15 @@ +title: 'network/kad: Increase memory store capacity for providers' +doc: +- audience: Node Dev + description: |- + Increase Kademlia memory store capacity for DHT content providers (used by parachain DHT-based bootnodes) and reduce provider republish interval & TTL. This is needed to support testnets with 1-minute fast runtime and up to 13 parachains. + + Parameters set: + - 10000 provider keys per node + - 10h provider record TTL + - 3.5h provider republish interval + + Closes https://github.com/paritytech/litep2p/issues/405. +crates: +- name: sc-network + bump: minor diff --git a/substrate/client/network/src/config.rs b/substrate/client/network/src/config.rs index 5f90a7bfe15ee..fc316e382bb15 100644 --- a/substrate/client/network/src/config.rs +++ b/substrate/client/network/src/config.rs @@ -74,6 +74,21 @@ use std::{ /// are possible in custom nodes through [`NetworkConfiguration`]. pub const DEFAULT_IDLE_CONNECTION_TIMEOUT: Duration = Duration::from_secs(10); +/// Maximum number of locally kept Kademlia provider keys. +/// +/// 10000 keys is enough for a testnet with fast runtime (1-minute epoch) and 13 parachains. +pub const KADEMLIA_MAX_PROVIDER_KEYS: usize = 10000; + +/// Time to keep Kademlia content provider records. +/// +/// 10 h is enough time to keep the parachain bootnode record for two 4-hour epochs. +pub const KADEMLIA_PROVIDER_RECORD_TTL: Duration = Duration::from_secs(10 * 3600); + +/// Interval of republishing Kademlia provider records. +/// +/// 3.5 h means we refresh next epoch provider record 30 minutes before next 4-hour epoch comes. +pub const KADEMLIA_PROVIDER_REPUBLISH_INTERVAL: Duration = Duration::from_secs(12600); + /// Protocol name prefix, transmitted on the wire for legacy protocol names. /// I.e., `dot` in `/dot/sync/2`. Should be unique for each chain. Always UTF-8. /// Deprecated in favour of genesis hash & fork ID based protocol names. diff --git a/substrate/client/network/src/discovery.rs b/substrate/client/network/src/discovery.rs index b0917ed363b65..a5d693f699443 100644 --- a/substrate/client/network/src/discovery.rs +++ b/substrate/client/network/src/discovery.rs @@ -46,7 +46,13 @@ //! active mechanism that asks nodes for the addresses they are listening on. Whenever we learn //! of a node's address, you must call `add_self_reported_address`. -use crate::{config::ProtocolId, utils::LruHashSet}; +use crate::{ + config::{ + ProtocolId, KADEMLIA_MAX_PROVIDER_KEYS, KADEMLIA_PROVIDER_RECORD_TTL, + KADEMLIA_PROVIDER_REPUBLISH_INTERVAL, + }, + utils::LruHashSet, +}; use array_bytes::bytes2hex; use futures::prelude::*; @@ -56,7 +62,7 @@ use libp2p::{ core::{transport::PortUse, Endpoint, Multiaddr}, kad::{ self, - store::{MemoryStore, RecordStore}, + store::{MemoryStore, MemoryStoreConfig, RecordStore}, Behaviour as Kademlia, BucketInserts, Config as KademliaConfig, Event as KademliaEvent, Event, GetClosestPeersError, GetClosestPeersOk, GetProvidersError, GetProvidersOk, GetRecordOk, PeerRecord, QueryId, QueryResult, Quorum, Record, RecordKey, @@ -239,7 +245,18 @@ impl DiscoveryConfig { // auto-insertion and instead add peers manually. config.set_kbucket_inserts(BucketInserts::Manual); config.disjoint_query_paths(kademlia_disjoint_query_paths); - let store = MemoryStore::new(local_peer_id); + + config.set_provider_record_ttl(Some(KADEMLIA_PROVIDER_RECORD_TTL)); + config.set_provider_publication_interval(Some(KADEMLIA_PROVIDER_REPUBLISH_INTERVAL)); + + let store = MemoryStore::with_config( + local_peer_id, + MemoryStoreConfig { + max_provided_keys: KADEMLIA_MAX_PROVIDER_KEYS, + ..Default::default() + }, + ); + let mut kad = Kademlia::with_config(local_peer_id, store, config); kad.set_mode(Some(kad::Mode::Server)); diff --git a/substrate/client/network/src/litep2p/discovery.rs b/substrate/client/network/src/litep2p/discovery.rs index 0db4b5d623b22..4a9b84b3a215a 100644 --- a/substrate/client/network/src/litep2p/discovery.rs +++ b/substrate/client/network/src/litep2p/discovery.rs @@ -19,7 +19,10 @@ //! libp2p-related discovery code for litep2p backend. use crate::{ - config::{NetworkConfiguration, ProtocolId}, + config::{ + NetworkConfiguration, ProtocolId, KADEMLIA_MAX_PROVIDER_KEYS, KADEMLIA_PROVIDER_RECORD_TTL, + KADEMLIA_PROVIDER_REPUBLISH_INTERVAL, + }, peer_store::PeerStoreProvider, }; @@ -299,6 +302,9 @@ impl Discovery { .with_known_peers(known_peers) .with_protocol_names(protocol_names) .with_incoming_records_validation_mode(IncomingRecordValidationMode::Manual) + .with_provider_record_ttl(KADEMLIA_PROVIDER_RECORD_TTL) + .with_provider_refresh_interval(KADEMLIA_PROVIDER_REPUBLISH_INTERVAL) + .with_max_provider_keys(KADEMLIA_MAX_PROVIDER_KEYS) .build() };