mirror of
https://github.com/paradigmxyz/reth.git
synced 2026-01-10 15:58:27 -05:00
feat: add --p2p-secret-key-hex which is similiar nodekeyhex in geth (#19670)
Co-authored-by: weixie.cui <weixie.cui@okg.com>
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -9058,7 +9058,6 @@ dependencies = [
|
||||
"reth-basic-payload-builder",
|
||||
"reth-chain-state",
|
||||
"reth-chainspec",
|
||||
"reth-cli-util",
|
||||
"reth-config",
|
||||
"reth-consensus",
|
||||
"reth-consensus-debug-client",
|
||||
|
||||
@@ -8,7 +8,7 @@ use backon::{ConstantBuilder, Retryable};
|
||||
use clap::{Parser, Subcommand};
|
||||
use reth_chainspec::{EthChainSpec, EthereumHardforks, Hardforks};
|
||||
use reth_cli::chainspec::ChainSpecParser;
|
||||
use reth_cli_util::{get_secret_key, hash_or_num_value_parser};
|
||||
use reth_cli_util::hash_or_num_value_parser;
|
||||
use reth_config::Config;
|
||||
use reth_network::{BlockDownloaderProvider, NetworkConfigBuilder};
|
||||
use reth_network_p2p::bodies::client::BodiesClient;
|
||||
@@ -183,9 +183,7 @@ impl<C: ChainSpecParser> DownloadArgs<C> {
|
||||
config.peers.trusted_nodes_only = self.network.trusted_only;
|
||||
|
||||
let default_secret_key_path = data_dir.p2p_secret();
|
||||
let secret_key_path =
|
||||
self.network.p2p_secret_key.clone().unwrap_or(default_secret_key_path);
|
||||
let p2p_secret_key = get_secret_key(&secret_key_path)?;
|
||||
let p2p_secret_key = self.network.secret_key(default_secret_key_path)?;
|
||||
let rlpx_socket = (self.network.addr, self.network.port).into();
|
||||
let boot_nodes = self.chain.bootnodes().unwrap_or_default();
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ pub mod allocator;
|
||||
|
||||
/// Helper function to load a secret key from a file.
|
||||
pub mod load_secret_key;
|
||||
pub use load_secret_key::get_secret_key;
|
||||
pub use load_secret_key::{get_secret_key, parse_secret_key_from_hex};
|
||||
|
||||
/// Cli parsers functions.
|
||||
pub mod parsers;
|
||||
|
||||
@@ -30,6 +30,10 @@ pub enum SecretKeyError {
|
||||
/// Path to the secret key file.
|
||||
secret_file: PathBuf,
|
||||
},
|
||||
|
||||
/// Invalid hex string format.
|
||||
#[error("invalid hex string: {0}")]
|
||||
InvalidHexString(String),
|
||||
}
|
||||
|
||||
/// Attempts to load a [`SecretKey`] from a specified path. If no file exists there, then it
|
||||
@@ -60,3 +64,75 @@ pub fn get_secret_key(secret_key_path: &Path) -> Result<SecretKey, SecretKeyErro
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
/// Parses a [`SecretKey`] from a hex string.
|
||||
///
|
||||
/// The hex string can optionally start with "0x".
|
||||
pub fn parse_secret_key_from_hex(hex_str: &str) -> Result<SecretKey, SecretKeyError> {
|
||||
// Remove "0x" prefix if present
|
||||
let hex_str = hex_str.strip_prefix("0x").unwrap_or(hex_str);
|
||||
|
||||
// Decode the hex string
|
||||
let bytes = alloy_primitives::hex::decode(hex_str)
|
||||
.map_err(|e| SecretKeyError::InvalidHexString(e.to_string()))?;
|
||||
|
||||
// Parse into SecretKey
|
||||
SecretKey::from_slice(&bytes).map_err(SecretKeyError::SecretKeyDecodeError)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_parse_secret_key_from_hex_without_prefix() {
|
||||
// Valid 32-byte hex string (64 characters)
|
||||
let hex = "4c0883a69102937d6231471b5dbb6204fe512961708279f8c5c58b3b9c4e8b8f";
|
||||
let result = parse_secret_key_from_hex(hex);
|
||||
assert!(result.is_ok());
|
||||
|
||||
let secret_key = result.unwrap();
|
||||
assert_eq!(alloy_primitives::hex::encode(secret_key.secret_bytes()), hex);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_secret_key_from_hex_with_0x_prefix() {
|
||||
// Valid 32-byte hex string with 0x prefix
|
||||
let hex = "0x4c0883a69102937d6231471b5dbb6204fe512961708279f8c5c58b3b9c4e8b8f";
|
||||
let result = parse_secret_key_from_hex(hex);
|
||||
assert!(result.is_ok());
|
||||
|
||||
let secret_key = result.unwrap();
|
||||
let expected = "4c0883a69102937d6231471b5dbb6204fe512961708279f8c5c58b3b9c4e8b8f";
|
||||
assert_eq!(alloy_primitives::hex::encode(secret_key.secret_bytes()), expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_secret_key_from_hex_invalid_length() {
|
||||
// Invalid length (not 32 bytes)
|
||||
let hex = "4c0883a69102937d";
|
||||
let result = parse_secret_key_from_hex(hex);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_secret_key_from_hex_invalid_chars() {
|
||||
// Invalid hex characters
|
||||
let hex = "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz";
|
||||
let result = parse_secret_key_from_hex(hex);
|
||||
assert!(result.is_err());
|
||||
|
||||
if let Err(SecretKeyError::InvalidHexString(_)) = result {
|
||||
// Expected error type
|
||||
} else {
|
||||
panic!("Expected InvalidHexString error");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_secret_key_from_hex_empty() {
|
||||
let hex = "";
|
||||
let result = parse_secret_key_from_hex(hex);
|
||||
assert!(result.is_err());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@ workspace = true
|
||||
## reth
|
||||
reth-chain-state.workspace = true
|
||||
reth-chainspec.workspace = true
|
||||
reth-cli-util.workspace = true
|
||||
reth-config.workspace = true
|
||||
reth-consensus-debug-client.workspace = true
|
||||
reth-consensus.workspace = true
|
||||
|
||||
@@ -12,7 +12,6 @@ use crate::{
|
||||
use alloy_eips::eip4844::env_settings::EnvKzgSettings;
|
||||
use futures::Future;
|
||||
use reth_chainspec::{EthChainSpec, EthereumHardforks, Hardforks};
|
||||
use reth_cli_util::get_secret_key;
|
||||
use reth_db_api::{database::Database, database_metrics::DatabaseMetrics};
|
||||
use reth_exex::ExExContext;
|
||||
use reth_network::{
|
||||
@@ -869,9 +868,7 @@ impl<Node: FullNodeTypes> BuilderContext<Node> {
|
||||
|
||||
/// Get the network secret from the given data dir
|
||||
fn network_secret(&self, data_dir: &ChainPath<DataDirPath>) -> eyre::Result<SecretKey> {
|
||||
let network_secret_path =
|
||||
self.config().network.p2p_secret_key.clone().unwrap_or_else(|| data_dir.p2p_secret());
|
||||
let secret_key = get_secret_key(&network_secret_path)?;
|
||||
let secret_key = self.config().network.secret_key(data_dir.p2p_secret())?;
|
||||
Ok(secret_key)
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ use std::{
|
||||
use crate::version::version_metadata;
|
||||
use clap::Args;
|
||||
use reth_chainspec::EthChainSpec;
|
||||
use reth_cli_util::{get_secret_key, load_secret_key::SecretKeyError};
|
||||
use reth_config::Config;
|
||||
use reth_discv4::{NodeRecord, DEFAULT_DISCOVERY_ADDR, DEFAULT_DISCOVERY_PORT};
|
||||
use reth_discv5::{
|
||||
@@ -81,9 +82,16 @@ pub struct NetworkArgs {
|
||||
///
|
||||
/// 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")]
|
||||
#[arg(long, value_name = "PATH", conflicts_with = "p2p_secret_key_hex")]
|
||||
pub p2p_secret_key: Option<PathBuf>,
|
||||
|
||||
/// Hex encoded secret key to use for this node.
|
||||
///
|
||||
/// This will also deterministically set the peer ID. Cannot be used together with
|
||||
/// `--p2p-secret-key`.
|
||||
#[arg(long, value_name = "HEX", conflicts_with = "p2p_secret_key")]
|
||||
pub p2p_secret_key_hex: Option<B256>,
|
||||
|
||||
/// Do not persist peers.
|
||||
#[arg(long, verbatim_doc_comment)]
|
||||
pub no_persist_peers: bool,
|
||||
@@ -351,6 +359,25 @@ impl NetworkArgs {
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Load the p2p secret key from the provided options.
|
||||
///
|
||||
/// If `p2p_secret_key_hex` is provided, it will be used directly.
|
||||
/// If `p2p_secret_key` is provided, it will be loaded from the file.
|
||||
/// If neither is provided, the `default_secret_key_path` will be used.
|
||||
pub fn secret_key(
|
||||
&self,
|
||||
default_secret_key_path: PathBuf,
|
||||
) -> Result<SecretKey, SecretKeyError> {
|
||||
if let Some(b256) = &self.p2p_secret_key_hex {
|
||||
// Use the B256 value directly (already validated as 32 bytes)
|
||||
SecretKey::from_slice(b256.as_slice()).map_err(SecretKeyError::SecretKeyDecodeError)
|
||||
} else {
|
||||
// Load from file (either provided path or default)
|
||||
let secret_key_path = self.p2p_secret_key.clone().unwrap_or(default_secret_key_path);
|
||||
get_secret_key(&secret_key_path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for NetworkArgs {
|
||||
@@ -364,6 +391,7 @@ impl Default for NetworkArgs {
|
||||
peers_file: None,
|
||||
identity: version_metadata().p2p_client_version.to_string(),
|
||||
p2p_secret_key: None,
|
||||
p2p_secret_key_hex: None,
|
||||
no_persist_peers: false,
|
||||
nat: NatResolver::Any,
|
||||
addr: DEFAULT_DISCOVERY_ADDR,
|
||||
@@ -698,4 +726,53 @@ mod tests {
|
||||
let args = CommandParser::<NetworkArgs>::parse_from(["reth"]).args;
|
||||
assert!(args.required_block_hashes.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_p2p_secret_key_hex() {
|
||||
let hex = "4c0883a69102937d6231471b5dbb6204fe512961708279f8c5c58b3b9c4e8b8f";
|
||||
let args =
|
||||
CommandParser::<NetworkArgs>::parse_from(["reth", "--p2p-secret-key-hex", hex]).args;
|
||||
|
||||
let expected: B256 = hex.parse().unwrap();
|
||||
assert_eq!(args.p2p_secret_key_hex, Some(expected));
|
||||
assert_eq!(args.p2p_secret_key, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_p2p_secret_key_hex_with_0x_prefix() {
|
||||
let hex = "0x4c0883a69102937d6231471b5dbb6204fe512961708279f8c5c58b3b9c4e8b8f";
|
||||
let args =
|
||||
CommandParser::<NetworkArgs>::parse_from(["reth", "--p2p-secret-key-hex", hex]).args;
|
||||
|
||||
let expected: B256 = hex.parse().unwrap();
|
||||
assert_eq!(args.p2p_secret_key_hex, Some(expected));
|
||||
assert_eq!(args.p2p_secret_key, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_p2p_secret_key_and_hex_are_mutually_exclusive() {
|
||||
let result = CommandParser::<NetworkArgs>::try_parse_from([
|
||||
"reth",
|
||||
"--p2p-secret-key",
|
||||
"/path/to/key",
|
||||
"--p2p-secret-key-hex",
|
||||
"4c0883a69102937d6231471b5dbb6204fe512961708279f8c5c58b3b9c4e8b8f",
|
||||
]);
|
||||
|
||||
assert!(result.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_secret_key_method_with_hex() {
|
||||
let hex = "4c0883a69102937d6231471b5dbb6204fe512961708279f8c5c58b3b9c4e8b8f";
|
||||
let args =
|
||||
CommandParser::<NetworkArgs>::parse_from(["reth", "--p2p-secret-key-hex", hex]).args;
|
||||
|
||||
let temp_dir = std::env::temp_dir();
|
||||
let default_path = temp_dir.join("default_key");
|
||||
let secret_key = args.secret_key(default_path).unwrap();
|
||||
|
||||
// Verify the secret key matches the hex input
|
||||
assert_eq!(alloy_primitives::hex::encode(secret_key.secret_bytes()), hex);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,6 +160,11 @@ Networking:
|
||||
|
||||
This will also deterministically set the peer ID. If not specified, it will be set in the data dir for the chain being used.
|
||||
|
||||
--p2p-secret-key-hex <HEX>
|
||||
Hex encoded secret key to use for this node.
|
||||
|
||||
This will also deterministically set the peer ID. Cannot be used together with `--p2p-secret-key`.
|
||||
|
||||
--no-persist-peers
|
||||
Do not persist peers.
|
||||
|
||||
|
||||
@@ -106,6 +106,11 @@ Networking:
|
||||
|
||||
This will also deterministically set the peer ID. If not specified, it will be set in the data dir for the chain being used.
|
||||
|
||||
--p2p-secret-key-hex <HEX>
|
||||
Hex encoded secret key to use for this node.
|
||||
|
||||
This will also deterministically set the peer ID. Cannot be used together with `--p2p-secret-key`.
|
||||
|
||||
--no-persist-peers
|
||||
Do not persist peers.
|
||||
|
||||
|
||||
@@ -106,6 +106,11 @@ Networking:
|
||||
|
||||
This will also deterministically set the peer ID. If not specified, it will be set in the data dir for the chain being used.
|
||||
|
||||
--p2p-secret-key-hex <HEX>
|
||||
Hex encoded secret key to use for this node.
|
||||
|
||||
This will also deterministically set the peer ID. Cannot be used together with `--p2p-secret-key`.
|
||||
|
||||
--no-persist-peers
|
||||
Do not persist peers.
|
||||
|
||||
|
||||
@@ -210,6 +210,11 @@ Networking:
|
||||
|
||||
This will also deterministically set the peer ID. If not specified, it will be set in the data dir for the chain being used.
|
||||
|
||||
--p2p-secret-key-hex <HEX>
|
||||
Hex encoded secret key to use for this node.
|
||||
|
||||
This will also deterministically set the peer ID. Cannot be used together with `--p2p-secret-key`.
|
||||
|
||||
--no-persist-peers
|
||||
Do not persist peers.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user