From 324cce3461c2a93438beb381878782544e385de7 Mon Sep 17 00:00:00 2001 From: Andrea Simeoni Date: Wed, 24 Sep 2025 14:14:59 +0200 Subject: [PATCH] feat(bootnode): Persists the discovery secret key (#18643) --- crates/cli/commands/src/node.rs | 1 + crates/cli/commands/src/p2p/bootnode.rs | 33 ++++++++++++------- .../vocs/docs/pages/cli/reth/p2p/bootnode.mdx | 11 ++----- 3 files changed, 26 insertions(+), 19 deletions(-) diff --git a/crates/cli/commands/src/node.rs b/crates/cli/commands/src/node.rs index 86e59ce28b..bafb1b72f1 100644 --- a/crates/cli/commands/src/node.rs +++ b/crates/cli/commands/src/node.rs @@ -213,6 +213,7 @@ impl NodeCommand { Some(&self.chain) } } + /// No Additional arguments #[derive(Debug, Clone, Copy, Default, Args)] #[non_exhaustive] diff --git a/crates/cli/commands/src/p2p/bootnode.rs b/crates/cli/commands/src/p2p/bootnode.rs index 5db54ddf80..8e4fb5ad2d 100644 --- a/crates/cli/commands/src/p2p/bootnode.rs +++ b/crates/cli/commands/src/p2p/bootnode.rs @@ -1,11 +1,13 @@ //! Standalone bootnode command use clap::Parser; +use reth_cli_util::{get_secret_key, load_secret_key::rng_secret_key}; use reth_discv4::{DiscoveryUpdate, Discv4, Discv4Config}; use reth_discv5::{discv5::Event, Config, Discv5}; use reth_net_nat::NatResolver; use reth_network_peers::NodeRecord; -use std::net::SocketAddr; +use secp256k1::SecretKey; +use std::{net::SocketAddr, path::PathBuf}; use tokio::select; use tokio_stream::StreamExt; use tracing::info; @@ -17,13 +19,14 @@ pub struct Command { #[arg(long, default_value = "0.0.0.0:30301")] pub addr: SocketAddr, - /// Generate a new node key and save it to the specified file. - #[arg(long, default_value = "")] - pub gen_key: String, - - /// Private key filename for the node. - #[arg(long, default_value = "")] - pub node_key: String, + /// Secret key to use for the bootnode. + /// + /// This will also deterministically set the peer ID. + /// If a path is provided but no key exists at that path, + /// a new random secret will be generated and stored there. + /// If no path is specified, a new ephemeral random secret will be used. + #[arg(long, value_name = "PATH")] + pub p2p_secret_key: Option, /// NAT resolution method (any|none|upnp|publicip|extip:\) #[arg(long, default_value = "any")] @@ -37,15 +40,16 @@ pub struct Command { impl Command { /// Execute the bootnode command. pub async fn execute(self) -> eyre::Result<()> { - info!("Bootnode started with config: {:?}", self); - let sk = reth_network::config::rng_secret_key(); + info!("Bootnode started with config: {self:?}"); + + let sk = self.network_secret()?; let local_enr = NodeRecord::from_secret_key(self.addr, &sk); let config = Discv4Config::builder().external_ip_resolver(Some(self.nat)).build(); let (_discv4, mut discv4_service) = Discv4::bind(self.addr, local_enr, sk, config).await?; - info!("Started discv4 at address:{:?}", self.addr); + info!("Started discv4 at address: {local_enr:?}"); let mut discv4_updates = discv4_service.update_stream(); discv4_service.spawn(); @@ -102,4 +106,11 @@ impl Command { Ok(()) } + + fn network_secret(&self) -> eyre::Result { + match &self.p2p_secret_key { + Some(path) => Ok(get_secret_key(path)?), + None => Ok(rng_secret_key()), + } + } } diff --git a/docs/vocs/docs/pages/cli/reth/p2p/bootnode.mdx b/docs/vocs/docs/pages/cli/reth/p2p/bootnode.mdx index 859fec8597..2a0a5b6a80 100644 --- a/docs/vocs/docs/pages/cli/reth/p2p/bootnode.mdx +++ b/docs/vocs/docs/pages/cli/reth/p2p/bootnode.mdx @@ -14,15 +14,10 @@ Options: [default: 0.0.0.0:30301] - --gen-key - Generate a new node key and save it to the specified file + --p2p-secret-key + Secret key to use for the bootnode. - [default: ] - - --node-key - Private key filename for the node - - [default: ] + This will also deterministically set the peer ID. If a path is provided but no key exists at that path, a new random secret will be generated and stored there. If no path is specified, a new ephemeral random secret will be used. --nat NAT resolution method (any|none|upnp|publicip|extip:\)