Skip to content

Commit

Permalink
feat(discv5): config via cli (paradigmxyz#7394)
Browse files Browse the repository at this point in the history
  • Loading branch information
emhane authored and Ruteri committed Apr 17, 2024
1 parent 5a18a74 commit 07af92a
Show file tree
Hide file tree
Showing 12 changed files with 149 additions and 16 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions crates/net/discv4/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,16 @@ pub const DEFAULT_DISCOVERY_ADDR: IpAddr = IpAddr::V4(Ipv4Addr::UNSPECIFIED);
/// Note: the default TCP port is the same.
pub const DEFAULT_DISCOVERY_PORT: u16 = 30303;

/// The default address for discv5 via UDP.
///
/// Note: the default TCP address is the same.
pub const DEFAULT_DISCOVERY_V5_ADDR: IpAddr = IpAddr::V4(Ipv4Addr::UNSPECIFIED);

/// The default port for discv5 via UDP.
///
/// Default is port 9000.
pub const DEFAULT_DISCOVERY_V5_PORT: u16 = 9000;

/// The default address for discv4 via UDP: "0.0.0.0:30303"
///
/// Note: The default TCP address is the same.
Expand Down
2 changes: 1 addition & 1 deletion crates/net/discv5/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ impl ConfigBuilder {
}

/// Adds boot nodes in the form a list of [`NodeRecord`]s, parsed enodes.
pub fn add_unsigned_boot_nodes(mut self, enodes: Vec<NodeRecord>) -> Self {
pub fn add_unsigned_boot_nodes(mut self, enodes: impl Iterator<Item = NodeRecord>) -> Self {
for node in enodes {
if let Ok(node) = BootNode::from_unsigned(node) {
self.bootstrap_nodes.insert(node);
Expand Down
4 changes: 2 additions & 2 deletions crates/net/discv5/src/enr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ impl From<EnrCombinedKeyWrapper> for Enr<SecretKey> {
mod tests {
use alloy_rlp::Encodable;
use discv5::enr::{CombinedKey, EnrKey};
use reth_primitives::{pk_to_id, Hardfork, NodeRecord, MAINNET};
use reth_primitives::{Hardfork, NodeRecord, MAINNET};

use super::*;

Expand Down Expand Up @@ -105,7 +105,7 @@ mod tests {
address: IP.parse().unwrap(),
tcp_port: TCP_PORT,
udp_port: UDP_PORT,
id: pk_to_id(&enr.public_key())
id: pk2id(&enr.public_key())
},
node_record
)
Expand Down
3 changes: 1 addition & 2 deletions crates/net/discv5/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -376,8 +376,7 @@ impl Discv5 {

// node has been inserted into kbuckets

// `replaced` covers `reth_discv4::DiscoveryUpdate::Removed(_)` .. but we can't get
// a `PeerId` from a `NodeId`
// `replaced` partly covers `reth_discv4::DiscoveryUpdate::Removed(_)`

self.metrics.discovered_peers.increment_kbucket_insertions(1);

Expand Down
2 changes: 2 additions & 0 deletions crates/net/network/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ reth-primitives.workspace = true
reth-net-common.workspace = true
reth-network-api.workspace = true
reth-discv4.workspace = true
reth-discv5.workspace = true
reth-dns-discovery.workspace = true
reth-eth-wire.workspace = true
reth-ecies.workspace = true
Expand All @@ -30,6 +31,7 @@ reth-tokio-util.workspace = true
# ethereum
enr = { workspace = true, features = ["rust-secp256k1"], optional = true }
alloy-rlp.workspace = true
discv5.workspace = true

# async/futures
futures.workspace = true
Expand Down
76 changes: 73 additions & 3 deletions crates/net/network/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ use crate::{
NetworkHandle, NetworkManager,
};
use reth_discv4::{Discv4Config, Discv4ConfigBuilder, DEFAULT_DISCOVERY_ADDRESS};
use reth_discv5::config::OPSTACK;
use reth_dns_discovery::DnsDiscoveryConfig;
use reth_eth_wire::{HelloMessage, HelloMessageWithProtocols, Status};
use reth_primitives::{
mainnet_nodes, pk2id, sepolia_nodes, ChainSpec, ForkFilter, Head, NodeRecord, PeerId, MAINNET,
mainnet_nodes, pk2id, sepolia_nodes, Chain, ChainSpec, ForkFilter, Head, NamedChain,
NodeRecord, PeerId, MAINNET,
};
use reth_provider::{BlockReader, HeaderProvider};
use reth_tasks::{TaskSpawner, TokioTaskExecutor};
Expand Down Expand Up @@ -43,6 +45,8 @@ pub struct NetworkConfig<C> {
pub dns_discovery_config: Option<DnsDiscoveryConfig>,
/// How to set up discovery.
pub discovery_v4_config: Option<Discv4Config>,
/// How to set up discovery version 5.
pub discovery_v5_config: Option<reth_discv5::Config>,
/// Address to use for discovery
pub discovery_addr: SocketAddr,
/// Address to listen for incoming connections
Expand Down Expand Up @@ -110,6 +114,54 @@ impl<C> NetworkConfig<C> {
self
}

/// Sets the config to use for the discovery v5 protocol, with help of the
/// [`reth_discv5::ConfigBuilder`].
/// ```
/// use reth_network::NetworkConfigBuilder;
/// use secp256k1::{rand::thread_rng, SecretKey};
///
/// let sk = SecretKey::new(&mut thread_rng());
/// let network_config = NetworkConfigBuilder::new(sk).build(());
/// let fork_id = network_config.status.forkid;
/// let network_config = network_config
/// .discovery_v5_with_config_builder(|builder| builder.fork(b"eth", fork_id).build());
/// ```
pub fn discovery_v5_with_config_builder(
self,
f: impl FnOnce(reth_discv5::ConfigBuilder) -> reth_discv5::Config,
) -> Self {
let rlpx_port = self.listener_addr.port();
let chain = self.chain_spec.chain;
let fork_id = self.status.forkid;
let boot_nodes = self.boot_nodes.clone();

let mut builder =
reth_discv5::Config::builder(rlpx_port).add_unsigned_boot_nodes(boot_nodes.into_iter()); // todo: store discv5 peers in separate file

if chain.is_optimism() {
builder = builder.fork(OPSTACK, fork_id)
}

if chain == Chain::optimism_mainnet() || chain == Chain::base_mainnet() {
builder = builder.add_optimism_mainnet_boot_nodes()
} else if chain == Chain::from_named(NamedChain::OptimismSepolia) ||
chain == Chain::from_named(NamedChain::BaseSepolia)
{
builder = builder.add_optimism_sepolia_boot_nodes()
}

self.set_discovery_v5(f(builder))
}

/// Sets the config to use for the discovery v5 protocol.
pub fn set_discovery_v5(mut self, discv5_config: reth_discv5::Config) -> Self {
self.discovery_v5_config = Some(discv5_config);
self.discovery_addr = self.discovery_v5_config.as_ref().unwrap().discovery_socket();
self
}

/// Sets the address for the incoming connection listener.
pub fn set_listener_addr(mut self, listener_addr: SocketAddr) -> Self {
self.listener_addr = listener_addr;
Expand Down Expand Up @@ -142,8 +194,10 @@ pub struct NetworkConfigBuilder {
secret_key: SecretKey,
/// How to configure discovery over DNS.
dns_discovery_config: Option<DnsDiscoveryConfig>,
/// How to set up discovery.
/// How to set up discovery version 4.
discovery_v4_builder: Option<Discv4ConfigBuilder>,
/// Whether to enable discovery version 5. Disabled by default.
enable_discovery_v5: bool,
/// All boot nodes to start network discovery with.
boot_nodes: HashSet<NodeRecord>,
/// Address to use for discovery
Expand Down Expand Up @@ -198,6 +252,7 @@ impl NetworkConfigBuilder {
secret_key,
dns_discovery_config: Some(Default::default()),
discovery_v4_builder: Some(Default::default()),
enable_discovery_v5: false,
boot_nodes: Default::default(),
discovery_addr: None,
listener_addr: None,
Expand Down Expand Up @@ -326,11 +381,18 @@ impl NetworkConfigBuilder {
}

/// Sets the discv4 config to use.
//
pub fn discovery(mut self, builder: Discv4ConfigBuilder) -> Self {
self.discovery_v4_builder = Some(builder);
self
}

/// Allows discv5 discovery.
pub fn discovery_v5(mut self) -> Self {
self.enable_discovery_v5 = true;
self
}

/// Sets the dns discovery config to use.
pub fn dns_discovery(mut self, config: DnsDiscoveryConfig) -> Self {
self.dns_discovery_config = Some(config);
Expand Down Expand Up @@ -379,6 +441,12 @@ impl NetworkConfigBuilder {
self
}

/// Enable the Discv5 discovery.
pub fn enable_discv5_discovery(mut self) -> Self {
self.enable_discovery_v5 = true;
self
}

/// Disable the DNS discovery if the given condition is true.
pub fn disable_dns_discovery_if(self, disable: bool) -> Self {
if disable {
Expand Down Expand Up @@ -442,6 +510,7 @@ impl NetworkConfigBuilder {
secret_key,
mut dns_discovery_config,
discovery_v4_builder,
enable_discovery_v5: _,
boot_nodes,
discovery_addr,
listener_addr,
Expand Down Expand Up @@ -497,6 +566,7 @@ impl NetworkConfigBuilder {
boot_nodes,
dns_discovery_config,
discovery_v4_config: discovery_v4_builder.map(|builder| builder.build()),
discovery_v5_config: None,
discovery_addr: discovery_addr.unwrap_or(DEFAULT_DISCOVERY_ADDRESS),
listener_addr,
peers_config: peers_config.unwrap_or_default(),
Expand Down Expand Up @@ -546,7 +616,7 @@ mod tests {
use super::*;
use rand::thread_rng;
use reth_dns_discovery::tree::LinkEntry;
use reth_primitives::{Chain, ForkHash};
use reth_primitives::ForkHash;
use reth_provider::test_utils::NoopProvider;
use std::collections::BTreeMap;

Expand Down
3 changes: 3 additions & 0 deletions crates/node-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ reth-prune.workspace = true
reth-blockchain-tree.workspace = true
reth-static-file.workspace = true

# ethereum
discv5.workspace = true

# async
tokio.workspace = true

Expand Down
32 changes: 29 additions & 3 deletions crates/node-core/src/args/network_args.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@
use crate::version::P2P_CLIENT_VERSION;
use clap::Args;
use reth_config::Config;
use reth_discv4::{DEFAULT_DISCOVERY_ADDR, DEFAULT_DISCOVERY_PORT};
use reth_discv4::{
DEFAULT_DISCOVERY_ADDR, DEFAULT_DISCOVERY_PORT, DEFAULT_DISCOVERY_V5_ADDR,
DEFAULT_DISCOVERY_V5_PORT,
};
use reth_net_nat::NatResolver;
use reth_network::{
transactions::{
Expand Down Expand Up @@ -211,13 +214,27 @@ pub struct DiscoveryArgs {
#[arg(long, conflicts_with = "disable_discovery")]
pub disable_discv4_discovery: bool,

/// The UDP address to use for P2P discovery/networking
/// Enable Discv5 discovery.
#[arg(long, conflicts_with = "disable_discovery")]
pub enable_discv5_discovery: bool,

/// The UDP address to use for devp2p peer discovery version 4.
#[arg(id = "discovery.addr", long = "discovery.addr", value_name = "DISCOVERY_ADDR", default_value_t = DEFAULT_DISCOVERY_ADDR)]
pub addr: IpAddr,

/// The UDP port to use for P2P discovery/networking
/// The UDP port to use for devp2p peer discovery version 4.
#[arg(id = "discovery.port", long = "discovery.port", value_name = "DISCOVERY_PORT", default_value_t = DEFAULT_DISCOVERY_PORT)]
pub port: u16,

/// The UDP address to use for devp2p peer discovery version 5.
#[arg(id = "discovery.v5.addr", long = "discovery.v5.addr", value_name = "DISCOVERY_V5_ADDR",
default_value_t = DEFAULT_DISCOVERY_V5_ADDR)]
pub discv5_addr: IpAddr,

/// The UDP port to use for devp2p peer discovery version 5.
#[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,
}

impl DiscoveryArgs {
Expand All @@ -233,6 +250,11 @@ impl DiscoveryArgs {
if self.disable_discovery || self.disable_discv4_discovery {
network_config_builder = network_config_builder.disable_discv4_discovery();
}

if !self.disable_discovery && (self.enable_discv5_discovery || cfg!(feature = "optimism")) {
network_config_builder = network_config_builder.enable_discv5_discovery();
}

network_config_builder
}

Expand All @@ -250,8 +272,11 @@ impl Default for DiscoveryArgs {
disable_discovery: false,
disable_dns_discovery: false,
disable_discv4_discovery: false,
enable_discv5_discovery: cfg!(feature = "optimism"),
addr: DEFAULT_DISCOVERY_ADDR,
port: DEFAULT_DISCOVERY_PORT,
discv5_addr: DEFAULT_DISCOVERY_V5_ADDR,
discv5_port: DEFAULT_DISCOVERY_V5_PORT,
}
}
}
Expand Down Expand Up @@ -315,6 +340,7 @@ mod tests {
);
}

#[cfg(not(feature = "optimism"))]
#[test]
fn network_args_default_sanity_test() {
let default_args = NetworkArgs::default();
Expand Down
26 changes: 23 additions & 3 deletions crates/node-core/src/node_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,15 @@
use crate::{
args::{
get_secret_key, DatabaseArgs, DebugArgs, DevArgs, NetworkArgs, PayloadBuilderArgs,
PruningArgs, RpcServerArgs, TxPoolArgs,
get_secret_key, DatabaseArgs, DebugArgs, DevArgs, DiscoveryArgs, NetworkArgs,
PayloadBuilderArgs, PruningArgs, RpcServerArgs, TxPoolArgs,
},
cli::config::RethTransactionPoolConfig,
dirs::{ChainPath, DataDirPath},
metrics::prometheus_exporter,
utils::{get_single_header, write_peers_to_file},
};
use discv5::ListenConfig;
use metrics_exporter_prometheus::PrometheusHandle;
use once_cell::sync::Lazy;
use reth_auto_seal_consensus::{AutoSealConsensus, MiningMode};
Expand Down Expand Up @@ -162,6 +163,7 @@ pub struct NodeConfig {
///
/// Changes to the following port numbers:
/// - DISCOVERY_PORT: default + `instance` - 1
/// - DISCOVERY_V5_PORT: default + `instance` - 1
/// - AUTH_PORT: default + `instance` * 100 - 100
/// - HTTP_RPC_PORT: default - `instance` + 1
/// - WS_RPC_PORT: default + `instance` * 2 - 2
Expand Down Expand Up @@ -768,7 +770,25 @@ impl NodeConfig {
self.network.discovery.port + self.instance - 1,
));

cfg_builder.build(client)
let config = cfg_builder.build(client);

if !self.network.discovery.enable_discv5_discovery {
return config
}
// 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;
builder
.discv5_config(
discv5::ConfigBuilder::new(ListenConfig::from(Into::<SocketAddr>::into((
discv5_addr,
discv5_port + self.instance - 1,
))))
.build(),
)
.build()
})
}

/// Builds the [Pipeline] with the given [ProviderFactory] and downloaders.
Expand Down
2 changes: 1 addition & 1 deletion crates/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ pub use header::{Header, HeaderValidationError, HeadersDirection, SealedHeader};
pub use integer_list::IntegerList;
pub use log::{logs_bloom, Log};
pub use net::{
goerli_nodes, holesky_nodes, mainnet_nodes, parse_nodes, pk_to_id, sepolia_nodes, NodeRecord,
goerli_nodes, holesky_nodes, mainnet_nodes, parse_nodes, sepolia_nodes, NodeRecord,
NodeRecordParseError, GOERLI_BOOTNODES, HOLESKY_BOOTNODES, MAINNET_BOOTNODES,
SEPOLIA_BOOTNODES,
};
Expand Down
Loading

0 comments on commit 07af92a

Please sign in to comment.