mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 19:09:54 +00:00
feat: add secret-key command line option (#1946)
This commit is contained in:
3
Cargo.lock
generated
3
Cargo.lock
generated
@ -4447,6 +4447,7 @@ dependencies = [
|
||||
"eyre",
|
||||
"fdlimit",
|
||||
"futures",
|
||||
"hex",
|
||||
"human_bytes",
|
||||
"hyper",
|
||||
"jsonrpsee",
|
||||
@ -4478,10 +4479,12 @@ dependencies = [
|
||||
"reth-tasks",
|
||||
"reth-tracing",
|
||||
"reth-transaction-pool",
|
||||
"secp256k1 0.26.0",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"shellexpand",
|
||||
"tempfile",
|
||||
"thiserror",
|
||||
"tokio",
|
||||
"tracing",
|
||||
"tui",
|
||||
|
||||
@ -34,6 +34,13 @@ reth-net-nat = { path = "../../crates/net/nat" }
|
||||
reth-miner = { path = "../../crates/miner" }
|
||||
reth-discv4 = { path = "../../crates/net/discv4" }
|
||||
|
||||
# crypto
|
||||
secp256k1 = { version = "0.26.0", features = [
|
||||
"global-context",
|
||||
"rand-std",
|
||||
"recovery",
|
||||
] }
|
||||
|
||||
# tracing
|
||||
tracing = "0.1"
|
||||
|
||||
@ -72,3 +79,5 @@ eyre = "0.6.8"
|
||||
clap = { version = "4", features = ["derive", "cargo"] }
|
||||
tempfile = { version = "3.3.0" }
|
||||
backon = "0.4"
|
||||
hex = "0.4"
|
||||
thiserror = "1.0"
|
||||
@ -11,3 +11,6 @@ pub use rpc_server_args::RpcServerArgs;
|
||||
/// DebugArgs struct for debugging purposes
|
||||
mod debug_args;
|
||||
pub use debug_args::DebugArgs;
|
||||
|
||||
mod secret_key;
|
||||
pub use secret_key::{get_secret_key, SecretKeyError};
|
||||
|
||||
@ -6,6 +6,7 @@ use reth_net_nat::NatResolver;
|
||||
use reth_network::NetworkConfigBuilder;
|
||||
use reth_primitives::{mainnet_nodes, ChainSpec, NodeRecord};
|
||||
use reth_staged_sync::Config;
|
||||
use secp256k1::SecretKey;
|
||||
use std::{path::PathBuf, sync::Arc};
|
||||
|
||||
/// Parameters for configuring the network more granularity via CLI
|
||||
@ -57,11 +58,12 @@ impl NetworkArgs {
|
||||
&self,
|
||||
config: &Config,
|
||||
chain_spec: Arc<ChainSpec>,
|
||||
secret_key: SecretKey,
|
||||
) -> NetworkConfigBuilder {
|
||||
let chain_bootnodes = chain_spec.chain.bootnodes().unwrap_or_else(mainnet_nodes);
|
||||
|
||||
let network_config_builder = config
|
||||
.network_config(self.nat, self.persistent_peers_file())
|
||||
.network_config(self.nat, self.persistent_peers_file(), secret_key)
|
||||
.boot_nodes(self.bootnodes.clone().unwrap_or(chain_bootnodes))
|
||||
.chain_spec(chain_spec);
|
||||
|
||||
|
||||
49
bin/reth/src/args/secret_key.rs
Normal file
49
bin/reth/src/args/secret_key.rs
Normal file
@ -0,0 +1,49 @@
|
||||
use crate::dirs::{PlatformPath, SecretKeyPath};
|
||||
use hex::encode as hex_encode;
|
||||
use reth_network::config::rng_secret_key;
|
||||
use secp256k1::{Error as SecretKeyBaseError, SecretKey};
|
||||
use std::fs::read_to_string;
|
||||
use thiserror::Error;
|
||||
|
||||
/// Errors returned by loading a [`SecretKey`][secp256k1::SecretKey], including IO errors.
|
||||
#[derive(Error, Debug)]
|
||||
#[allow(missing_docs)]
|
||||
pub enum SecretKeyError {
|
||||
#[error(transparent)]
|
||||
SecretKeyDecodeError(#[from] SecretKeyBaseError),
|
||||
#[error("An I/O error occurred: {0}")]
|
||||
IOError(#[from] std::io::Error),
|
||||
}
|
||||
|
||||
/// Attempts to load a [`SecretKey`] from a specified path. If no file exists
|
||||
/// there, then it generates a secret key and stores it in the default path. I/O
|
||||
/// errors might occur during write operations in the form of a
|
||||
/// [`SecretKeyError`]
|
||||
pub fn get_secret_key(
|
||||
secret_key_path: &PlatformPath<SecretKeyPath>,
|
||||
) -> Result<SecretKey, SecretKeyError> {
|
||||
let fpath = secret_key_path.as_ref();
|
||||
let exists = fpath.try_exists();
|
||||
|
||||
match exists {
|
||||
Ok(true) => {
|
||||
let contents = read_to_string(fpath)?;
|
||||
(contents.as_str().parse::<SecretKey>()).map_err(SecretKeyError::SecretKeyDecodeError)
|
||||
}
|
||||
Ok(false) => {
|
||||
let default_path = PlatformPath::<SecretKeyPath>::default();
|
||||
let fpath = default_path.as_ref();
|
||||
|
||||
if let Some(dir) = fpath.parent() {
|
||||
// Create parent directory
|
||||
std::fs::create_dir_all(dir)?
|
||||
}
|
||||
|
||||
let secret = rng_secret_key();
|
||||
let hex = hex_encode(secret.as_ref());
|
||||
std::fs::write(fpath, hex)?;
|
||||
Ok(secret)
|
||||
}
|
||||
Err(e) => Err(SecretKeyError::IOError(e)),
|
||||
}
|
||||
}
|
||||
@ -56,6 +56,13 @@ pub fn net_dir() -> Option<PathBuf> {
|
||||
data_dir().map(|root| root.join("net"))
|
||||
}
|
||||
|
||||
/// Returns the path to the reth secret key directory.
|
||||
///
|
||||
/// Refer to [dirs_next::data_dir] for cross-platform behavior.
|
||||
pub fn p2p_secret_key_dir() -> Option<PathBuf> {
|
||||
data_dir().map(|root| root.join("p2p"))
|
||||
}
|
||||
|
||||
/// Returns the path to the reth database.
|
||||
///
|
||||
/// Refer to [dirs_next::data_dir] for cross-platform behavior.
|
||||
@ -121,6 +128,19 @@ impl XdgPath for LogsDir {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the path to the default reth secret key directory.
|
||||
///
|
||||
/// Refer to [dirs_next::data_dir] for cross-platform behavior.
|
||||
#[derive(Default, Debug, Clone)]
|
||||
#[non_exhaustive]
|
||||
pub struct SecretKeyPath;
|
||||
|
||||
impl XdgPath for SecretKeyPath {
|
||||
fn resolve() -> Option<PathBuf> {
|
||||
p2p_secret_key_dir().map(|p| p.join("secret"))
|
||||
}
|
||||
}
|
||||
|
||||
/// A small helper trait for unit structs that represent a standard path following the XDG
|
||||
/// path specification.
|
||||
pub trait XdgPath {
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
//!
|
||||
//! Starts the client
|
||||
use crate::{
|
||||
args::{DebugArgs, NetworkArgs, RpcServerArgs},
|
||||
dirs::{ConfigPath, DbPath, PlatformPath},
|
||||
args::{get_secret_key, DebugArgs, NetworkArgs, RpcServerArgs},
|
||||
dirs::{ConfigPath, DbPath, PlatformPath, SecretKeyPath},
|
||||
prometheus_exporter,
|
||||
runner::CliContext,
|
||||
utils::get_single_header,
|
||||
@ -59,6 +59,7 @@ use reth_stages::{
|
||||
};
|
||||
use reth_tasks::TaskExecutor;
|
||||
use reth_transaction_pool::{EthTransactionValidator, TransactionPool};
|
||||
use secp256k1::SecretKey;
|
||||
use std::{
|
||||
net::{Ipv4Addr, SocketAddr, SocketAddrV4},
|
||||
path::PathBuf,
|
||||
@ -109,6 +110,12 @@ pub struct Command {
|
||||
)]
|
||||
chain: Arc<ChainSpec>,
|
||||
|
||||
/// Secret key to use for this node.
|
||||
///
|
||||
/// This also will deterministically set the peer ID.
|
||||
#[arg(long, value_name = "PATH", global = true, required = false, default_value_t)]
|
||||
p2p_secret_key: PlatformPath<SecretKeyPath>,
|
||||
|
||||
/// Enable Prometheus metrics.
|
||||
///
|
||||
/// The metrics will be served at the given interface and port.
|
||||
@ -168,8 +175,13 @@ impl Command {
|
||||
info!(target: "reth::cli", "Test transaction pool initialized");
|
||||
|
||||
info!(target: "reth::cli", "Connecting to P2P network");
|
||||
let network_config =
|
||||
self.load_network_config(&config, Arc::clone(&db), ctx.task_executor.clone());
|
||||
let secret_key = get_secret_key(&self.p2p_secret_key)?;
|
||||
let network_config = self.load_network_config(
|
||||
&config,
|
||||
Arc::clone(&db),
|
||||
ctx.task_executor.clone(),
|
||||
secret_key,
|
||||
);
|
||||
let network = self
|
||||
.start_network(network_config, &ctx.task_executor, transaction_pool.clone())
|
||||
.await?;
|
||||
@ -548,11 +560,12 @@ impl Command {
|
||||
config: &Config,
|
||||
db: Arc<Env<WriteMap>>,
|
||||
executor: TaskExecutor,
|
||||
secret_key: SecretKey,
|
||||
) -> NetworkConfig<ShareableDatabase<Arc<Env<WriteMap>>>> {
|
||||
let head = self.lookup_head(Arc::clone(&db)).expect("the head block is missing");
|
||||
|
||||
self.network
|
||||
.network_config(config, self.chain.clone())
|
||||
.network_config(config, self.chain.clone(), secret_key)
|
||||
.with_task_executor(Box::new(executor))
|
||||
.set_head(head)
|
||||
.listener_addr(SocketAddr::V4(SocketAddrV4::new(
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
//! P2P Debugging tool
|
||||
use crate::{
|
||||
args::DiscoveryArgs,
|
||||
dirs::{ConfigPath, PlatformPath},
|
||||
args::{get_secret_key, DiscoveryArgs},
|
||||
dirs::{ConfigPath, PlatformPath, SecretKeyPath},
|
||||
utils::get_single_header,
|
||||
};
|
||||
use backon::{ConstantBuilder, Retryable};
|
||||
@ -41,6 +41,12 @@ pub struct Command {
|
||||
)]
|
||||
chain: Arc<ChainSpec>,
|
||||
|
||||
/// Secret key to use for this node.
|
||||
///
|
||||
/// This also will deterministically set the peer ID.
|
||||
#[arg(long, value_name = "PATH", global = true, required = false, default_value_t)]
|
||||
p2p_secret_key: PlatformPath<SecretKeyPath>,
|
||||
|
||||
/// Disable the discovery service.
|
||||
#[command(flatten)]
|
||||
pub discovery: DiscoveryArgs,
|
||||
@ -98,8 +104,10 @@ impl Command {
|
||||
|
||||
config.peers.connect_trusted_nodes_only = self.trusted_only;
|
||||
|
||||
let p2p_secret_key = get_secret_key(&self.p2p_secret_key)?;
|
||||
|
||||
let mut network_config_builder =
|
||||
config.network_config(self.nat, None).chain_spec(self.chain.clone());
|
||||
config.network_config(self.nat, None, p2p_secret_key).chain_spec(self.chain.clone());
|
||||
|
||||
network_config_builder = self.discovery.apply_to_builder(network_config_builder);
|
||||
|
||||
|
||||
@ -2,8 +2,8 @@
|
||||
//!
|
||||
//! Stage debugging tool
|
||||
use crate::{
|
||||
args::NetworkArgs,
|
||||
dirs::{ConfigPath, DbPath, PlatformPath},
|
||||
args::{get_secret_key, NetworkArgs},
|
||||
dirs::{ConfigPath, DbPath, PlatformPath, SecretKeyPath},
|
||||
prometheus_exporter, StageEnum,
|
||||
};
|
||||
use clap::Parser;
|
||||
@ -56,6 +56,12 @@ pub struct Command {
|
||||
)]
|
||||
chain: Arc<ChainSpec>,
|
||||
|
||||
/// Secret key to use for this node.
|
||||
///
|
||||
/// This also will deterministically set the peer ID.
|
||||
#[arg(long, value_name = "PATH", global = true, required = false, default_value_t)]
|
||||
p2p_secret_key: PlatformPath<SecretKeyPath>,
|
||||
|
||||
/// Enable Prometheus metrics.
|
||||
///
|
||||
/// The metrics will be served at the given interface and port.
|
||||
@ -125,9 +131,11 @@ impl Command {
|
||||
});
|
||||
}
|
||||
|
||||
let p2p_secret_key = get_secret_key(&self.p2p_secret_key)?;
|
||||
|
||||
let network = self
|
||||
.network
|
||||
.network_config(&config, self.chain.clone())
|
||||
.network_config(&config, self.chain.clone(), p2p_secret_key)
|
||||
.build(Arc::new(ShareableDatabase::new(db.clone(), self.chain.clone())))
|
||||
.start_network()
|
||||
.await?;
|
||||
|
||||
@ -30,6 +30,11 @@ tracing = "0.1.37"
|
||||
|
||||
# crypto
|
||||
rand = { version = "0.8", optional = true }
|
||||
secp256k1 = { version = "0.26.0", features = [
|
||||
"global-context",
|
||||
"rand-std",
|
||||
"recovery",
|
||||
] }
|
||||
|
||||
# errors
|
||||
thiserror = "1"
|
||||
|
||||
@ -4,7 +4,8 @@ use reth_downloaders::{
|
||||
bodies::bodies::BodiesDownloaderBuilder,
|
||||
headers::reverse_headers::ReverseHeadersDownloaderBuilder,
|
||||
};
|
||||
use reth_network::{config::rng_secret_key, NetworkConfigBuilder, PeersConfig};
|
||||
use reth_network::{NetworkConfigBuilder, PeersConfig};
|
||||
use secp256k1::SecretKey;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
|
||||
@ -25,15 +26,17 @@ impl Config {
|
||||
&self,
|
||||
nat_resolution_method: reth_net_nat::NatResolver,
|
||||
peers_file: Option<PathBuf>,
|
||||
secret_key: SecretKey,
|
||||
) -> NetworkConfigBuilder {
|
||||
let peer_config = self
|
||||
.peers
|
||||
.clone()
|
||||
.with_basic_nodes_from_file(peers_file)
|
||||
.unwrap_or_else(|_| self.peers.clone());
|
||||
|
||||
let discv4 =
|
||||
Discv4Config::builder().external_ip_resolver(Some(nat_resolution_method)).clone();
|
||||
NetworkConfigBuilder::new(rng_secret_key()).peer_config(peer_config).discovery(discv4)
|
||||
NetworkConfigBuilder::new(secret_key).peer_config(peer_config).discovery(discv4)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user