Files
nanoreth/bin/reth/src/args/network_args.rs
2023-09-15 23:07:24 +00:00

217 lines
7.6 KiB
Rust

//! clap [Args](clap::Args) for network related arguments.
use crate::version::P2P_CLIENT_VERSION;
use clap::Args;
use reth_config::Config;
use reth_net_nat::NatResolver;
use reth_network::{HelloMessage, NetworkConfigBuilder};
use reth_primitives::{mainnet_nodes, ChainSpec, NodeRecord};
use secp256k1::SecretKey;
use std::{path::PathBuf, sync::Arc};
/// Parameters for configuring the network more granularity via CLI
#[derive(Debug, Args)]
#[command(next_help_heading = "Networking")]
pub struct NetworkArgs {
/// Disable the discovery service.
#[command(flatten)]
pub discovery: DiscoveryArgs,
/// Target trusted peer enodes
/// --trusted-peers enode://abcd@192.168.0.1:30303
#[arg(long, value_delimiter = ',')]
pub trusted_peers: Vec<NodeRecord>,
/// Connect only to trusted peers
#[arg(long)]
pub trusted_only: bool,
/// Bootnodes to connect to initially.
///
/// Will fall back to a network-specific default if not specified.
#[arg(long, value_delimiter = ',')]
pub bootnodes: Option<Vec<NodeRecord>>,
/// The path to the known peers file. Connected peers are dumped to this file on nodes
/// shutdown, and read on startup. Cannot be used with `--no-persist-peers`.
#[arg(long, value_name = "FILE", verbatim_doc_comment, conflicts_with = "no_persist_peers")]
pub peers_file: Option<PathBuf>,
/// Custom node identity
#[arg(long, value_name = "IDENTITY", default_value = P2P_CLIENT_VERSION)]
pub identity: String,
/// Secret key to use for this node.
///
/// This will also deterministically set the peer ID. If not specified, it will be set in the
/// data dir for the chain being used.
#[arg(long, value_name = "PATH")]
pub p2p_secret_key: Option<PathBuf>,
/// Do not persist peers.
#[arg(long, verbatim_doc_comment)]
pub no_persist_peers: bool,
#[allow(rustdoc::invalid_html_tags)]
/// NAT resolution method (any|none|upnp|publicip|extip:<IP>)
#[arg(long, default_value = "any")]
pub nat: NatResolver,
/// Network listening port. default: 30303
#[arg(long = "port", value_name = "PORT")]
pub port: Option<u16>,
/// Maximum number of outbound requests. default: 100
#[arg(long)]
pub max_outbound_peers: Option<usize>,
/// Maximum number of inbound requests. default: 30
#[arg(long)]
pub max_inbound_peers: Option<usize>,
}
impl NetworkArgs {
/// Build a [`NetworkConfigBuilder`] from a [`Config`] and a [`ChainSpec`], in addition to the
/// values in this option struct.
///
/// The `default_peers_file` will be used as the default location to store the persistent peers
/// file if `no_persist_peers` is false, and there is no provided `peers_file`.
pub fn network_config(
&self,
config: &Config,
chain_spec: Arc<ChainSpec>,
secret_key: SecretKey,
default_peers_file: PathBuf,
) -> NetworkConfigBuilder {
let chain_bootnodes = chain_spec.chain.bootnodes().unwrap_or_else(mainnet_nodes);
let peers_file = self.peers_file.clone().unwrap_or(default_peers_file);
// Configure peer connections
let peer_config = config
.peers
.clone()
.with_max_inbound_opt(self.max_inbound_peers)
.with_max_outbound_opt(self.max_outbound_peers);
// Configure basic network stack
let mut network_config_builder = config
.network_config(self.nat, self.persistent_peers_file(peers_file), secret_key)
.peer_config(peer_config)
.boot_nodes(self.bootnodes.clone().unwrap_or(chain_bootnodes))
.chain_spec(chain_spec);
// Configure node identity
let peer_id = network_config_builder.get_peer_id();
network_config_builder = network_config_builder
.hello_message(HelloMessage::builder(peer_id).client_version(&self.identity).build());
self.discovery.apply_to_builder(network_config_builder)
}
/// If `no_persist_peers` is true then this returns the path to the persistent peers file path.
pub fn persistent_peers_file(&self, peers_file: PathBuf) -> Option<PathBuf> {
if self.no_persist_peers {
return None
}
Some(peers_file)
}
}
/// Arguments to setup discovery
#[derive(Debug, Args)]
pub struct DiscoveryArgs {
/// Disable the discovery service.
#[arg(short, long, default_value_if("dev", "true", "true"))]
pub disable_discovery: bool,
/// Disable the DNS discovery.
#[arg(long, conflicts_with = "disable_discovery")]
pub disable_dns_discovery: bool,
/// Disable Discv4 discovery.
#[arg(long, conflicts_with = "disable_discovery")]
pub disable_discv4_discovery: bool,
/// The UDP port to use for P2P discovery/networking. default: 30303
#[arg(long = "discovery.port", name = "discovery.port", value_name = "DISCOVERY_PORT")]
pub port: Option<u16>,
}
impl DiscoveryArgs {
/// Apply the discovery settings to the given [NetworkConfigBuilder]
pub fn apply_to_builder(
&self,
mut network_config_builder: NetworkConfigBuilder,
) -> NetworkConfigBuilder {
if self.disable_discovery || self.disable_dns_discovery {
network_config_builder = network_config_builder.disable_dns_discovery();
}
if self.disable_discovery || self.disable_discv4_discovery {
network_config_builder = network_config_builder.disable_discv4_discovery();
}
network_config_builder
}
}
#[cfg(test)]
mod tests {
use super::*;
use clap::Parser;
/// A helper type to parse Args more easily
#[derive(Parser)]
struct CommandParser<T: Args> {
#[clap(flatten)]
args: T,
}
#[test]
fn parse_nat_args() {
let args = CommandParser::<NetworkArgs>::parse_from(["reth", "--nat", "none"]).args;
assert_eq!(args.nat, NatResolver::None);
let args =
CommandParser::<NetworkArgs>::parse_from(["reth", "--nat", "extip:0.0.0.0"]).args;
assert_eq!(args.nat, NatResolver::ExternalIp("0.0.0.0".parse().unwrap()));
}
#[test]
fn parse_peer_args() {
let args =
CommandParser::<NetworkArgs>::parse_from(["reth", "--max-outbound-peers", "50"]).args;
assert_eq!(args.max_outbound_peers, Some(50));
assert_eq!(args.max_inbound_peers, None);
let args = CommandParser::<NetworkArgs>::parse_from([
"reth",
"--max-outbound-peers",
"75",
"--max-inbound-peers",
"15",
])
.args;
assert_eq!(args.max_outbound_peers, Some(75));
assert_eq!(args.max_inbound_peers, Some(15));
}
#[test]
fn parse_trusted_peer_args() {
let args =
CommandParser::<NetworkArgs>::parse_from([
"reth",
"--trusted-peers",
"enode://d860a01f9722d78051619d1e2351aba3f43f943f6f00718d1b9baa4101932a1f5011f16bb2b1bb35db20d6fe28fa0bf09636d26a87d31de9ec6203eeedb1f666@18.138.108.67:30303,enode://22a8232c3abc76a16ae9d6c3b164f98775fe226f0917b0ca871128a74a8e9630b458460865bab457221f1d448dd9791d24c4e5d88786180ac185df813a68d4de@3.209.45.79:30303"
])
.args;
assert_eq!(
args.trusted_peers,
vec![
"enode://d860a01f9722d78051619d1e2351aba3f43f943f6f00718d1b9baa4101932a1f5011f16bb2b1bb35db20d6fe28fa0bf09636d26a87d31de9ec6203eeedb1f666@18.138.108.67:30303".parse().unwrap(),
"enode://22a8232c3abc76a16ae9d6c3b164f98775fe226f0917b0ca871128a74a8e9630b458460865bab457221f1d448dd9791d24c4e5d88786180ac185df813a68d4de@3.209.45.79:30303".parse().unwrap()
]
);
}
}