feat(discv5): bootstrap cli (#8004)

This commit is contained in:
Emilia Hane
2024-05-02 13:16:22 +02:00
committed by GitHub
parent 10ef202d7c
commit 7428573d7c
7 changed files with 125 additions and 20 deletions

View File

@ -16,7 +16,18 @@ use crate::{enr::discv4_id_to_multiaddr_id, filter::MustNotIncludeKeys, NetworkS
/// Default interval in seconds at which to run a lookup up query.
///
/// Default is 60 seconds.
const DEFAULT_SECONDS_LOOKUP_INTERVAL: u64 = 60;
pub const DEFAULT_SECONDS_LOOKUP_INTERVAL: u64 = 60;
/// Default number of times to do pulse lookup queries, at bootstrap (pulse intervals, defaulting
/// to 5 seconds).
///
/// Default is 100 counts.
pub const DEFAULT_COUNT_BOOTSTRAP_LOOKUPS: u64 = 100;
/// Default duration of look up interval, for pulse look ups at bootstrap.
///
/// Default is 5 seconds.
pub const DEFAULT_SECONDS_BOOTSTRAP_LOOKUP_INTERVAL: u64 = 5;
/// Builds a [`Config`].
#[derive(Debug, Default)]
@ -39,6 +50,11 @@ pub struct ConfigBuilder {
other_enr_kv_pairs: Vec<(&'static [u8], Bytes)>,
/// Interval in seconds at which to run a lookup up query to populate kbuckets.
lookup_interval: Option<u64>,
/// Interval in seconds at which to run pulse lookup queries at bootstrap to boost kbucket
/// population.
bootstrap_lookup_interval: Option<u64>,
/// Number of times to run boost lookup queries at start up.
bootstrap_lookup_countdown: Option<u64>,
/// Custom filter rules to apply to a discovered peer in order to determine if it should be
/// passed up to rlpx or dropped.
discovered_peer_filter: Option<MustNotIncludeKeys>,
@ -54,6 +70,8 @@ impl ConfigBuilder {
tcp_port,
other_enr_kv_pairs,
lookup_interval,
bootstrap_lookup_interval,
bootstrap_lookup_countdown,
discovered_peer_filter,
} = discv5_config;
@ -64,6 +82,8 @@ impl ConfigBuilder {
tcp_port,
other_enr_kv_pairs,
lookup_interval: Some(lookup_interval),
bootstrap_lookup_interval: Some(bootstrap_lookup_interval),
bootstrap_lookup_countdown: Some(bootstrap_lookup_countdown),
discovered_peer_filter: Some(discovered_peer_filter),
}
}
@ -135,6 +155,26 @@ impl ConfigBuilder {
self
}
/// Sets the interval at which to run lookup queries, in order to fill kbuckets. Lookup queries
/// are done periodically at the given interval for the whole run of the program.
pub fn lookup_interval(mut self, seconds: u64) -> Self {
self.lookup_interval = Some(seconds);
self
}
/// Sets the interval at which to run boost lookup queries at start up. Queries will be started
/// at this interval for the configured number of times after start up.
pub fn bootstrap_lookup_interval(mut self, seconds: u64) -> Self {
self.bootstrap_lookup_interval = Some(seconds);
self
}
/// Sets the the number of times at which to run boost lookup queries to bootstrap the node.
pub fn bootstrap_lookup_countdown(mut self, counts: u64) -> Self {
self.bootstrap_lookup_countdown = Some(counts);
self
}
/// Adds keys to disallow when filtering a discovered peer, to determine whether or not it
/// should be passed to rlpx. The discovered node record is scanned for any kv-pairs where the
/// key matches the disallowed keys. If not explicitly set, b"eth2" key will be disallowed.
@ -154,6 +194,8 @@ impl ConfigBuilder {
tcp_port,
other_enr_kv_pairs,
lookup_interval,
bootstrap_lookup_interval,
bootstrap_lookup_countdown,
discovered_peer_filter,
} = self;
@ -163,6 +205,10 @@ impl ConfigBuilder {
let fork = fork.map(|(key, fork_id)| (key, fork_id.into()));
let lookup_interval = lookup_interval.unwrap_or(DEFAULT_SECONDS_LOOKUP_INTERVAL);
let bootstrap_lookup_interval =
bootstrap_lookup_interval.unwrap_or(DEFAULT_SECONDS_BOOTSTRAP_LOOKUP_INTERVAL);
let bootstrap_lookup_countdown =
bootstrap_lookup_countdown.unwrap_or(DEFAULT_COUNT_BOOTSTRAP_LOOKUPS);
let discovered_peer_filter = discovered_peer_filter
.unwrap_or_else(|| MustNotIncludeKeys::new(&[NetworkStackId::ETH2]));
@ -174,6 +220,8 @@ impl ConfigBuilder {
tcp_port,
other_enr_kv_pairs,
lookup_interval,
bootstrap_lookup_interval,
bootstrap_lookup_countdown,
discovered_peer_filter,
}
}
@ -197,6 +245,11 @@ pub struct Config {
pub(super) other_enr_kv_pairs: Vec<(&'static [u8], Bytes)>,
/// Interval in seconds at which to run a lookup up query with to populate kbuckets.
pub(super) lookup_interval: u64,
/// Interval in seconds at which to run pulse lookup queries at bootstrap to boost kbucket
/// population.
pub(super) bootstrap_lookup_interval: u64,
/// Number of times to run boost lookup queries at start up.
pub(super) bootstrap_lookup_countdown: u64,
/// Custom filter rules to apply to a discovered peer in order to determine if it should be
/// passed up to rlpx or dropped.
pub(super) discovered_peer_filter: MustNotIncludeKeys,

View File

@ -37,7 +37,10 @@ pub mod network_stack_id;
pub use discv5::{self, IpMode};
pub use config::{BootNode, Config, ConfigBuilder};
pub use config::{
BootNode, Config, ConfigBuilder, DEFAULT_COUNT_BOOTSTRAP_LOOKUPS,
DEFAULT_SECONDS_BOOTSTRAP_LOOKUP_INTERVAL, DEFAULT_SECONDS_LOOKUP_INTERVAL,
};
pub use enr::enr_to_discv4_id;
pub use error::Error;
pub use filter::{FilterOutcome, MustNotIncludeKeys};
@ -45,17 +48,6 @@ pub use network_stack_id::NetworkStackId;
use metrics::{DiscoveredPeersMetrics, Discv5Metrics};
/// Default number of times to do pulse lookup queries, at bootstrap (pulse intervals, defaulting
/// to 5 seconds).
///
/// Default is 100 counts.
pub const DEFAULT_COUNT_PULSE_LOOKUPS_AT_BOOTSTRAP: u64 = 100;
/// Default duration of look up interval, for pulse look ups at bootstrap.
///
/// Default is 5 seconds.
pub const DEFAULT_SECONDS_PULSE_LOOKUP_INTERVAL: u64 = 5;
/// Max kbucket index is 255.
///
/// This is the max log2distance for 32 byte [`NodeId`](discv5::enr::NodeId) - 1. See <https://github.com/sigp/discv5/blob/e9e0d4f93ec35591832a9a8d937b4161127da87b/src/kbucket.rs#L586-L587>.
@ -180,7 +172,13 @@ impl Discv5 {
// 2. start discv5
//
let Config {
discv5_config, bootstrap_nodes, lookup_interval, discovered_peer_filter, ..
discv5_config,
bootstrap_nodes,
lookup_interval,
bootstrap_lookup_interval,
bootstrap_lookup_countdown,
discovered_peer_filter,
..
} = discv5_config;
let EnrCombinedKeyWrapper(enr) = enr.into();
@ -206,7 +204,13 @@ impl Discv5 {
//
// 4. start bg kbuckets maintenance
//
Self::spawn_populate_kbuckets_bg(lookup_interval, metrics.clone(), discv5.clone());
Self::spawn_populate_kbuckets_bg(
lookup_interval,
bootstrap_lookup_interval,
bootstrap_lookup_countdown,
metrics.clone(),
discv5.clone(),
);
Ok((
Self { discv5, ip_mode, fork_key, discovered_peer_filter, metrics },
@ -319,6 +323,8 @@ impl Discv5 {
/// Backgrounds regular look up queries, in order to keep kbuckets populated.
fn spawn_populate_kbuckets_bg(
lookup_interval: u64,
bootstrap_lookup_interval: u64,
bootstrap_lookup_countdown: u64,
metrics: Discv5Metrics,
discv5: Arc<discv5::Discv5>,
) {
@ -327,18 +333,18 @@ impl Discv5 {
let lookup_interval = Duration::from_secs(lookup_interval);
let metrics = metrics.discovered_peers;
let mut kbucket_index = MAX_KBUCKET_INDEX;
let pulse_lookup_interval = Duration::from_secs(DEFAULT_SECONDS_PULSE_LOOKUP_INTERVAL);
let pulse_lookup_interval = Duration::from_secs(bootstrap_lookup_interval);
// todo: graceful shutdown
async move {
// make many fast lookup queries at bootstrap, trying to fill kbuckets at furthest
// log2distance from local node
for i in (0..DEFAULT_COUNT_PULSE_LOOKUPS_AT_BOOTSTRAP).rev() {
for i in (0..bootstrap_lookup_countdown).rev() {
let target = discv5::enr::NodeId::random();
trace!(target: "net::discv5",
%target,
bootstrap_boost_runs_count_down=i,
bootstrap_boost_runs_countdown=i,
lookup_interval=format!("{:#?}", pulse_lookup_interval),
"starting bootstrap boost lookup query"
);

View File

@ -27,6 +27,7 @@ reth-transaction-pool.workspace = true
reth-tracing.workspace = true
reth-config.workspace = true
reth-discv4.workspace = true
reth-discv5.workspace = true
reth-net-nat.workspace = true
reth-network-api.workspace = true
reth-evm.workspace = true

View File

@ -7,6 +7,10 @@ use reth_discv4::{
DEFAULT_DISCOVERY_ADDR, DEFAULT_DISCOVERY_PORT, DEFAULT_DISCOVERY_V5_ADDR,
DEFAULT_DISCOVERY_V5_PORT,
};
use reth_discv5::{
DEFAULT_COUNT_BOOTSTRAP_LOOKUPS, DEFAULT_SECONDS_BOOTSTRAP_LOOKUP_INTERVAL,
DEFAULT_SECONDS_LOOKUP_INTERVAL,
};
use reth_net_nat::NatResolver;
use reth_network::{
transactions::{
@ -235,6 +239,23 @@ pub struct DiscoveryArgs {
#[arg(id = "discovery.v5.port", long = "discovery.v5.port", value_name = "DISCOVERY_V5_PORT",
default_value_t = DEFAULT_DISCOVERY_V5_PORT)]
pub discv5_port: u16,
/// The interval in seconds at which to carry out periodic lookup queries, for the whole
/// run of the program.
#[arg(id = "discovery.v5.lookup-interval", long = "discovery.v5.lookup-interval", value_name = "DISCOVERY_V5_LOOKUP_INTERVAL",
default_value_t = DEFAULT_SECONDS_LOOKUP_INTERVAL)]
pub discv5_lookup_interval: u64,
/// The interval in seconds at which to carry out boost lookup queries, for a fixed number of
/// times, at bootstrap.
#[arg(id = "discovery.v5.bootstrap.lookup-interval", long = "discovery.v5.bootstrap.lookup-interval", value_name = "DISCOVERY_V5_bootstrap_lookup_interval",
default_value_t = DEFAULT_SECONDS_BOOTSTRAP_LOOKUP_INTERVAL)]
pub discv5_bootstrap_lookup_interval: u64,
/// The number of times to carry out boost lookup queries at bootstrap.
#[arg(id = "discovery.v5.bootstrap.lookup-countdown", long = "discovery.v5.bootstrap.lookup-countdown", value_name = "DISCOVERY_V5_bootstrap_lookup_countdown",
default_value_t = DEFAULT_COUNT_BOOTSTRAP_LOOKUPS)]
pub discv5_bootstrap_lookup_countdown: u64,
}
impl DiscoveryArgs {
@ -278,6 +299,9 @@ impl Default for DiscoveryArgs {
port: DEFAULT_DISCOVERY_PORT,
discv5_addr: DEFAULT_DISCOVERY_V5_ADDR,
discv5_port: DEFAULT_DISCOVERY_V5_PORT,
discv5_lookup_interval: DEFAULT_SECONDS_LOOKUP_INTERVAL,
discv5_bootstrap_lookup_interval: DEFAULT_SECONDS_BOOTSTRAP_LOOKUP_INTERVAL,
discv5_bootstrap_lookup_countdown: DEFAULT_COUNT_BOOTSTRAP_LOOKUPS,
}
}
}

View File

@ -476,7 +476,14 @@ impl NodeConfig {
// work around since discv5 config builder can't be integrated into network config builder
// due to unsatisfied trait bounds
config.discovery_v5_with_config_builder(|builder| {
let DiscoveryArgs { discv5_addr, discv5_port, .. } = self.network.discovery;
let DiscoveryArgs {
discv5_addr,
discv5_port,
discv5_lookup_interval,
discv5_bootstrap_lookup_interval,
discv5_bootstrap_lookup_countdown,
..
} = self.network.discovery;
builder
.discv5_config(
discv5::ConfigBuilder::new(ListenConfig::from(Into::<SocketAddr>::into((
@ -485,6 +492,9 @@ impl NodeConfig {
))))
.build(),
)
.lookup_interval(discv5_lookup_interval)
.bootstrap_lookup_interval(discv5_bootstrap_lookup_interval)
.bootstrap_lookup_countdown(discv5_bootstrap_lookup_countdown)
.build()
})
}