diff --git a/Cargo.lock b/Cargo.lock index b44e85313..af28c9c22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6879,6 +6879,7 @@ dependencies = [ "tokio", "tracing", "tracing-subscriber", + "trin-beacon", "trin-bridge", "trin-history", "trin-state", @@ -7012,7 +7013,7 @@ dependencies = [ "anyhow", "base64 0.13.1", "bytes 1.4.0", - "clap 2.34.0", + "clap 4.2.4", "discv5", "env_logger 0.9.3", "eth2_ssz", @@ -7036,7 +7037,6 @@ dependencies = [ "sha3 0.9.1", "snap", "stremio-serde-hex", - "structopt", "test-log", "thiserror", "tokio", diff --git a/newsfragments/740.fixed.md b/newsfragments/740.fixed.md new file mode 100644 index 000000000..6cd6580d2 --- /dev/null +++ b/newsfragments/740.fixed.md @@ -0,0 +1 @@ +Replace `structopt` with `clap` when parsing command line arguments in ``trin-types``. \ No newline at end of file diff --git a/trin-types/Cargo.toml b/trin-types/Cargo.toml index 34673f2be..32a69003c 100644 --- a/trin-types/Cargo.toml +++ b/trin-types/Cargo.toml @@ -14,7 +14,7 @@ authors = ["https://github.com/ethereum/trin/graphs/contributors"] anyhow = "1.0.68" base64 = "0.13.0" bytes = "1.3.0" -clap = "2.33.3" +clap = { version = "4.2.1", features = ["derive"] } discv5 = { version = "0.2.1", features = ["serde"]} eth_trie = "0.1.0" ethereum-types = "0.12.1" @@ -35,7 +35,6 @@ serde_yaml = "0.9.17" sha2 = "0.10.1" sha3 = "0.9.1" snap = "1.1.0" -structopt = "0.3.26" stremio-serde-hex = "0.1.0" tree_hash = "0.4.0" tree_hash_derive = "0.4.0" diff --git a/trin-types/src/cli.rs b/trin-types/src/cli.rs index 98d499ef8..1dab6742d 100644 --- a/trin-types/src/cli.rs +++ b/trin-types/src/cli.rs @@ -1,7 +1,7 @@ use std::{env, ffi::OsString, fmt, net::SocketAddr, path::PathBuf, str::FromStr}; +use clap::{arg, Parser}; use ethereum_types::H256; -use structopt::StructOpt; use url::Url; use crate::bootnodes::Bootnodes; @@ -34,142 +34,129 @@ impl fmt::Display for Web3TransportType { } } -#[derive(Debug, PartialEq, Eq)] -pub struct ParseWeb3TransportError; - -impl fmt::Display for ParseWeb3TransportError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!( - f, - "Invalid web3-transport arg. Expected either 'http' or 'ipc'" - ) - } -} - impl FromStr for Web3TransportType { - type Err = ParseWeb3TransportError; + type Err = &'static str; fn from_str(s: &str) -> Result { match s { "http" => Ok(Web3TransportType::HTTP), "ipc" => Ok(Web3TransportType::IPC), - _ => Err(ParseWeb3TransportError), + _ => Err("Invalid web3-transport arg. Expected either 'http' or 'ipc'"), } } } -#[derive(StructOpt, Debug, PartialEq, Clone)] -#[structopt( +#[derive(Parser, Debug, PartialEq, Clone)] +#[command( name = "trin", version = "0.0.1", author = "carver", about = "Run an eth portal client" )] pub struct TrinConfig { - #[structopt( - default_value(DEFAULT_WEB3_TRANSPORT), + #[arg( + default_value = DEFAULT_WEB3_TRANSPORT, long = "web3-transport", help = "select transport protocol to serve json-rpc endpoint" )] pub web3_transport: Web3TransportType, - #[structopt( - default_value(DEFAULT_WEB3_HTTP_ADDRESS), + #[arg( + default_value = DEFAULT_WEB3_HTTP_ADDRESS, long = "web3-http-address", help = "address to accept json-rpc http connections" )] pub web3_http_address: Url, - #[structopt( - default_value(DEFAULT_WEB3_IPC_PATH), + #[arg( + default_value = DEFAULT_WEB3_IPC_PATH, long = "web3-ipc-path", help = "path to json-rpc endpoint over IPC" )] pub web3_ipc_path: PathBuf, - #[structopt( - default_value(DEFAULT_DISCOVERY_PORT), + #[arg( + default_value = DEFAULT_DISCOVERY_PORT, long = "discovery-port", help = "The UDP port to listen on." )] pub discovery_port: u16, - #[structopt( - default_value("default"), + #[arg( + default_value = "default", long = "bootnodes", help = "One or more comma-delimited base64-encoded ENR's or multiaddr strings of peers to initially add to the local routing table" )] pub bootnodes: Bootnodes, - #[structopt( + #[arg( long = "external-address", group = "external-ips", help = "(Only use this if you are behind a NAT) The address which will be advertised to peers (in an ENR). Changing it does not change which port or address trin binds to. Port number is required, ex: 127.0.0.1:9001" )] pub external_addr: Option, - #[structopt( + #[arg( long = "no-stun", group = "external-ips", help = "Do not use STUN to determine an external IP. Leaves ENR entry for IP blank. Some users report better connections over VPN." )] pub no_stun: bool, - #[structopt( - validator(check_private_key_length), + #[arg( long = "unsafe-private-key", + value_parser = check_private_key_length, help = "Hex encoded 32 byte private key (with 0x prefix) (considered unsafe as it's stored in terminal history - keyfile support coming soon)" )] pub private_key: Option, - #[structopt( - long = "networks", + #[arg( + long = "networks", help = "Comma-separated list of which portal subnetworks to activate", default_value = DEFAULT_SUBNETWORKS, - use_delimiter = true + use_value_delimiter = true )] pub networks: Vec, /// Storage capacity specified in megabytes. - #[structopt( + #[arg( default_value(DEFAULT_STORAGE_CAPACITY_MB), long, help = "Maximum number of megabytes of total data to store in the DB (actual usage will exceed limit due to overhead)" )] pub mb: u32, - #[structopt( + #[arg( long = "enable-metrics-with-url", help = "Enable prometheus metrics reporting (provide local IP/Port from which your Prometheus server is configured to fetch metrics)" )] pub enable_metrics_with_url: Option, - #[structopt( - short = "e", + #[arg( + short = 'e', long = "ephemeral", help = "Use temporary data storage that is deleted on exit." )] pub ephemeral: bool, - #[structopt( + #[arg( long = "trusted-provider", help = "Trusted provider to use. (options: 'infura' (default), 'pandaops' (devops) or 'custom')", default_value(DEFAULT_TRUSTED_PROVIDER) )] pub trusted_provider: TrustedProviderType, - #[structopt( + #[arg( long = "trusted-provider-url", - help = "URL for a trusted http provider. Must include a base, host and port (e.g., '://:').", - validator(check_url_format) + value_parser = check_url_format, + help = "URL for a trusted http provider. Must include a base, host and port (e.g., '://:')." )] pub trusted_provider_url: Option, - #[structopt( + #[arg( long = "master-accumulator-path", help = "Path to master accumulator for validation", - default_value(DEFAULT_MASTER_ACC_PATH), - parse(from_os_str) + default_value(DEFAULT_MASTER_ACC_PATH) )] pub master_acc_path: PathBuf, } @@ -214,7 +201,7 @@ impl TrinConfig { I: Iterator, T: Into + Clone, { - let config = Self::from_iter_safe(args)?; + let config = Self::try_parse_from(args)?; match config.web3_transport { Web3TransportType::HTTP => match &config.web3_ipc_path.as_path().display().to_string()[..] { @@ -260,16 +247,16 @@ impl TrinConfig { } /// A validator function for CLI URL arguments. -fn check_url_format(url: String) -> Result<(), String> { - match Url::parse(&url) { - Ok(_) => Ok(()), +fn check_url_format(url: &str) -> Result { + match Url::parse(url) { + Ok(val) => Ok(val), Err(e) => panic!("Invalid URL '{url}', {e}"), } } -fn check_private_key_length(private_key: String) -> Result<(), String> { +fn check_private_key_length(private_key: &str) -> Result { if private_key.len() == 66 { - return Ok(()); + return H256::from_str(private_key).map_err(|err| format!("HexError: {}", err)); } panic!( "Invalid private key length: {}, expected 66 (0x-prefixed 32 byte hexstring)",