mirror of
https://github.com/hl-archive-node/nanoreth.git
synced 2025-12-06 10:59:55 +00:00
chore(cli): move utils to reth-cli-utils crate (#9297)
This commit is contained in:
@ -46,6 +46,7 @@ reth-consensus.workspace = true
|
||||
reth-consensus-debug-client.workspace = true
|
||||
reth-rpc-types.workspace = true
|
||||
reth-engine-util.workspace = true
|
||||
reth-cli-util.workspace = true
|
||||
|
||||
## async
|
||||
futures.workspace = true
|
||||
|
||||
@ -11,6 +11,7 @@ use crate::{
|
||||
};
|
||||
use futures::Future;
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_cli_util::get_secret_key;
|
||||
use reth_db::{
|
||||
test_utils::{create_test_rw_db_with_path, tempdir_path, TempDatabase},
|
||||
DatabaseEnv,
|
||||
@ -25,7 +26,7 @@ use reth_network::{
|
||||
};
|
||||
use reth_node_api::{FullNodeTypes, FullNodeTypesAdapter, NodeTypes};
|
||||
use reth_node_core::{
|
||||
args::{get_secret_key, DatadirArgs},
|
||||
args::DatadirArgs,
|
||||
cli::config::{PayloadBuilderConfig, RethTransactionPoolConfig},
|
||||
dirs::{ChainPath, DataDirPath, MaybePlatformPath},
|
||||
node_config::NodeConfig,
|
||||
|
||||
@ -14,6 +14,7 @@ workspace = true
|
||||
# reth
|
||||
reth-chainspec.workspace = true
|
||||
reth-primitives.workspace = true
|
||||
reth-cli-util.workspace = true
|
||||
reth-fs-util.workspace = true
|
||||
reth-db = { workspace = true, features = ["mdbx"] }
|
||||
reth-db-api.workspace = true
|
||||
@ -57,7 +58,6 @@ metrics-util.workspace = true
|
||||
eyre.workspace = true
|
||||
clap = { workspace = true, features = ["derive"] }
|
||||
humantime.workspace = true
|
||||
thiserror.workspace = true
|
||||
const_format.workspace = true
|
||||
rand.workspace = true
|
||||
derive_more.workspace = true
|
||||
|
||||
@ -24,9 +24,6 @@ pub use database::DatabaseArgs;
|
||||
mod log;
|
||||
pub use log::{ColorMode, LogArgs};
|
||||
|
||||
mod secret_key;
|
||||
pub use secret_key::{get_secret_key, SecretKeyError};
|
||||
|
||||
/// `PayloadBuilderArgs` struct for configuring the payload builder
|
||||
mod payload_builder;
|
||||
pub use payload_builder::PayloadBuilderArgs;
|
||||
|
||||
@ -1,11 +1,9 @@
|
||||
use crate::{
|
||||
args::utils::parse_duration_from_secs, cli::config::PayloadBuilderConfig,
|
||||
version::default_extradata,
|
||||
};
|
||||
use crate::{cli::config::PayloadBuilderConfig, version::default_extradata};
|
||||
use clap::{
|
||||
builder::{RangedU64ValueParser, TypedValueParser},
|
||||
Arg, Args, Command,
|
||||
};
|
||||
use reth_cli_util::parse_duration_from_secs;
|
||||
use reth_primitives::constants::{
|
||||
ETHEREUM_BLOCK_GAS_LIMIT, MAXIMUM_EXTRA_DATA_SIZE, SLOT_DURATION,
|
||||
};
|
||||
|
||||
@ -1,62 +0,0 @@
|
||||
use reth_fs_util::{self as fs, FsPathError};
|
||||
use reth_network::config::rng_secret_key;
|
||||
use reth_primitives::hex::encode as hex_encode;
|
||||
use secp256k1::{Error as SecretKeyBaseError, SecretKey};
|
||||
use std::{
|
||||
io,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use thiserror::Error;
|
||||
|
||||
/// Errors returned by loading a [`SecretKey`], including IO errors.
|
||||
#[derive(Error, Debug)]
|
||||
pub enum SecretKeyError {
|
||||
/// Error encountered during decoding of the secret key.
|
||||
#[error(transparent)]
|
||||
SecretKeyDecodeError(#[from] SecretKeyBaseError),
|
||||
|
||||
/// Error related to file system path operations.
|
||||
#[error(transparent)]
|
||||
SecretKeyFsPathError(#[from] FsPathError),
|
||||
|
||||
/// Represents an error when failed to access the key file.
|
||||
#[error("failed to access key file {secret_file:?}: {error}")]
|
||||
FailedToAccessKeyFile {
|
||||
/// The encountered IO error.
|
||||
error: io::Error,
|
||||
/// Path to the secret key file.
|
||||
secret_file: PathBuf,
|
||||
},
|
||||
}
|
||||
|
||||
/// 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 provided path. I/O errors might occur during write
|
||||
/// operations in the form of a [`SecretKeyError`]
|
||||
pub fn get_secret_key(secret_key_path: &Path) -> Result<SecretKey, SecretKeyError> {
|
||||
let exists = secret_key_path.try_exists();
|
||||
|
||||
match exists {
|
||||
Ok(true) => {
|
||||
let contents = fs::read_to_string(secret_key_path)?;
|
||||
Ok(contents
|
||||
.as_str()
|
||||
.parse::<SecretKey>()
|
||||
.map_err(SecretKeyError::SecretKeyDecodeError)?)
|
||||
}
|
||||
Ok(false) => {
|
||||
if let Some(dir) = secret_key_path.parent() {
|
||||
// Create parent directory
|
||||
fs::create_dir_all(dir)?;
|
||||
}
|
||||
|
||||
let secret = rng_secret_key();
|
||||
let hex = hex_encode(secret.as_ref());
|
||||
fs::write(secret_key_path, hex)?;
|
||||
Ok(secret)
|
||||
}
|
||||
Err(error) => Err(SecretKeyError::FailedToAccessKeyFile {
|
||||
error,
|
||||
secret_file: secret_key_path.to_path_buf(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
@ -3,14 +3,7 @@
|
||||
use alloy_genesis::Genesis;
|
||||
use reth_chainspec::ChainSpec;
|
||||
use reth_fs_util as fs;
|
||||
use reth_primitives::{BlockHashOrNumber, B256};
|
||||
use std::{
|
||||
net::{IpAddr, Ipv4Addr, SocketAddr, ToSocketAddrs},
|
||||
path::PathBuf,
|
||||
str::FromStr,
|
||||
sync::Arc,
|
||||
time::Duration,
|
||||
};
|
||||
use std::{path::PathBuf, sync::Arc};
|
||||
|
||||
use reth_chainspec::DEV;
|
||||
|
||||
@ -27,12 +20,6 @@ pub const SUPPORTED_CHAINS: &[&str] = &["optimism", "optimism-sepolia", "base",
|
||||
/// Chains supported by reth. First value should be used as the default.
|
||||
pub const SUPPORTED_CHAINS: &[&str] = &["mainnet", "sepolia", "goerli", "holesky", "dev"];
|
||||
|
||||
/// Helper to parse a [Duration] from seconds
|
||||
pub fn parse_duration_from_secs(arg: &str) -> eyre::Result<Duration, std::num::ParseIntError> {
|
||||
let seconds = arg.parse()?;
|
||||
Ok(Duration::from_secs(seconds))
|
||||
}
|
||||
|
||||
/// The help info for the --chain flag
|
||||
pub fn chain_help() -> String {
|
||||
format!("The chain this node is running.\nPossible values are either a built-in chain or the path to a chain specification file.\n\nBuilt-in chains:\n {}", SUPPORTED_CHAINS.join(", "))
|
||||
@ -83,64 +70,9 @@ pub fn chain_value_parser(s: &str) -> eyre::Result<Arc<ChainSpec>, eyre::Error>
|
||||
})
|
||||
}
|
||||
|
||||
/// Parse [`BlockHashOrNumber`]
|
||||
pub fn hash_or_num_value_parser(value: &str) -> eyre::Result<BlockHashOrNumber, eyre::Error> {
|
||||
match B256::from_str(value) {
|
||||
Ok(hash) => Ok(BlockHashOrNumber::Hash(hash)),
|
||||
Err(_) => Ok(BlockHashOrNumber::Number(value.parse()?)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Error thrown while parsing a socket address.
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum SocketAddressParsingError {
|
||||
/// Failed to convert the string into a socket addr
|
||||
#[error("could not parse socket address: {0}")]
|
||||
Io(#[from] std::io::Error),
|
||||
/// Input must not be empty
|
||||
#[error("cannot parse socket address from empty string")]
|
||||
Empty,
|
||||
/// Failed to parse the address
|
||||
#[error("could not parse socket address from {0}")]
|
||||
Parse(String),
|
||||
/// Failed to parse port
|
||||
#[error("could not parse port: {0}")]
|
||||
Port(#[from] std::num::ParseIntError),
|
||||
}
|
||||
|
||||
/// Parse a [`SocketAddr`] from a `str`.
|
||||
///
|
||||
/// The following formats are checked:
|
||||
///
|
||||
/// - If the value can be parsed as a `u16` or starts with `:` it is considered a port, and the
|
||||
/// hostname is set to `localhost`.
|
||||
/// - If the value contains `:` it is assumed to be the format `<host>:<port>`
|
||||
/// - Otherwise it is assumed to be a hostname
|
||||
///
|
||||
/// An error is returned if the value is empty.
|
||||
pub fn parse_socket_address(value: &str) -> eyre::Result<SocketAddr, SocketAddressParsingError> {
|
||||
if value.is_empty() {
|
||||
return Err(SocketAddressParsingError::Empty)
|
||||
}
|
||||
|
||||
if let Some(port) = value.strip_prefix(':').or_else(|| value.strip_prefix("localhost:")) {
|
||||
let port: u16 = port.parse()?;
|
||||
return Ok(SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), port))
|
||||
}
|
||||
if let Ok(port) = value.parse::<u16>() {
|
||||
return Ok(SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), port))
|
||||
}
|
||||
value
|
||||
.to_socket_addrs()?
|
||||
.next()
|
||||
.ok_or_else(|| SocketAddressParsingError::Parse(value.to_string()))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use proptest::prelude::Rng;
|
||||
use secp256k1::rand::thread_rng;
|
||||
|
||||
#[test]
|
||||
fn parse_known_chain_spec() {
|
||||
@ -148,28 +80,4 @@ mod tests {
|
||||
chain_value_parser(chain).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_socket_addresses() {
|
||||
for value in ["localhost:9000", ":9000", "9000"] {
|
||||
let socket_addr = parse_socket_address(value)
|
||||
.unwrap_or_else(|_| panic!("could not parse socket address: {value}"));
|
||||
|
||||
assert!(socket_addr.ip().is_loopback());
|
||||
assert_eq!(socket_addr.port(), 9000);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parse_socket_address_random() {
|
||||
let port: u16 = thread_rng().gen();
|
||||
|
||||
for value in [format!("localhost:{port}"), format!(":{port}"), port.to_string()] {
|
||||
let socket_addr = parse_socket_address(&value)
|
||||
.unwrap_or_else(|_| panic!("could not parse socket address: {value}"));
|
||||
|
||||
assert!(socket_addr.ip().is_loopback());
|
||||
assert_eq!(socket_addr.port(), port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user