|
1 | 1 | use std::{env, ffi::OsString, fmt, net::SocketAddr, path::PathBuf, str::FromStr}; |
2 | 2 |
|
| 3 | +use clap::{arg, Parser}; |
3 | 4 | use ethereum_types::H256; |
4 | | -use structopt::StructOpt; |
5 | 5 | use url::Url; |
6 | 6 |
|
7 | 7 | use crate::bootnodes::Bootnodes; |
@@ -34,142 +34,129 @@ impl fmt::Display for Web3TransportType { |
34 | 34 | } |
35 | 35 | } |
36 | 36 |
|
37 | | -#[derive(Debug, PartialEq, Eq)] |
38 | | -pub struct ParseWeb3TransportError; |
39 | | - |
40 | | -impl fmt::Display for ParseWeb3TransportError { |
41 | | - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
42 | | - write!( |
43 | | - f, |
44 | | - "Invalid web3-transport arg. Expected either 'http' or 'ipc'" |
45 | | - ) |
46 | | - } |
47 | | -} |
48 | | - |
49 | 37 | impl FromStr for Web3TransportType { |
50 | | - type Err = ParseWeb3TransportError; |
| 38 | + type Err = &'static str; |
51 | 39 |
|
52 | 40 | fn from_str(s: &str) -> Result<Self, Self::Err> { |
53 | 41 | match s { |
54 | 42 | "http" => Ok(Web3TransportType::HTTP), |
55 | 43 | "ipc" => Ok(Web3TransportType::IPC), |
56 | | - _ => Err(ParseWeb3TransportError), |
| 44 | + _ => Err("Invalid web3-transport arg. Expected either 'http' or 'ipc'"), |
57 | 45 | } |
58 | 46 | } |
59 | 47 | } |
60 | 48 |
|
61 | | -#[derive(StructOpt, Debug, PartialEq, Clone)] |
62 | | -#[structopt( |
| 49 | +#[derive(Parser, Debug, PartialEq, Clone)] |
| 50 | +#[command( |
63 | 51 | name = "trin", |
64 | 52 | version = "0.0.1", |
65 | 53 | author = "carver", |
66 | 54 | about = "Run an eth portal client" |
67 | 55 | )] |
68 | 56 | pub struct TrinConfig { |
69 | | - #[structopt( |
70 | | - default_value(DEFAULT_WEB3_TRANSPORT), |
| 57 | + #[arg( |
| 58 | + default_value = DEFAULT_WEB3_TRANSPORT, |
71 | 59 | long = "web3-transport", |
72 | 60 | help = "select transport protocol to serve json-rpc endpoint" |
73 | 61 | )] |
74 | 62 | pub web3_transport: Web3TransportType, |
75 | 63 |
|
76 | | - #[structopt( |
77 | | - default_value(DEFAULT_WEB3_HTTP_ADDRESS), |
| 64 | + #[arg( |
| 65 | + default_value = DEFAULT_WEB3_HTTP_ADDRESS, |
78 | 66 | long = "web3-http-address", |
79 | 67 | help = "address to accept json-rpc http connections" |
80 | 68 | )] |
81 | 69 | pub web3_http_address: Url, |
82 | 70 |
|
83 | | - #[structopt( |
84 | | - default_value(DEFAULT_WEB3_IPC_PATH), |
| 71 | + #[arg( |
| 72 | + default_value = DEFAULT_WEB3_IPC_PATH, |
85 | 73 | long = "web3-ipc-path", |
86 | 74 | help = "path to json-rpc endpoint over IPC" |
87 | 75 | )] |
88 | 76 | pub web3_ipc_path: PathBuf, |
89 | 77 |
|
90 | | - #[structopt( |
91 | | - default_value(DEFAULT_DISCOVERY_PORT), |
| 78 | + #[arg( |
| 79 | + default_value = DEFAULT_DISCOVERY_PORT, |
92 | 80 | long = "discovery-port", |
93 | 81 | help = "The UDP port to listen on." |
94 | 82 | )] |
95 | 83 | pub discovery_port: u16, |
96 | 84 |
|
97 | | - #[structopt( |
98 | | - default_value("default"), |
| 85 | + #[arg( |
| 86 | + default_value = "default", |
99 | 87 | long = "bootnodes", |
100 | 88 | help = "One or more comma-delimited base64-encoded ENR's or multiaddr strings of peers to initially add to the local routing table" |
101 | 89 | )] |
102 | 90 | pub bootnodes: Bootnodes, |
103 | 91 |
|
104 | | - #[structopt( |
| 92 | + #[arg( |
105 | 93 | long = "external-address", |
106 | 94 | group = "external-ips", |
107 | 95 | 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" |
108 | 96 | )] |
109 | 97 | pub external_addr: Option<SocketAddr>, |
110 | 98 |
|
111 | | - #[structopt( |
| 99 | + #[arg( |
112 | 100 | long = "no-stun", |
113 | 101 | group = "external-ips", |
114 | 102 | help = "Do not use STUN to determine an external IP. Leaves ENR entry for IP blank. Some users report better connections over VPN." |
115 | 103 | )] |
116 | 104 | pub no_stun: bool, |
117 | 105 |
|
118 | | - #[structopt( |
119 | | - validator(check_private_key_length), |
| 106 | + #[arg( |
120 | 107 | long = "unsafe-private-key", |
| 108 | + value_parser = check_private_key_length, |
121 | 109 | help = "Hex encoded 32 byte private key (with 0x prefix) (considered unsafe as it's stored in terminal history - keyfile support coming soon)" |
122 | 110 | )] |
123 | 111 | pub private_key: Option<H256>, |
124 | 112 |
|
125 | | - #[structopt( |
126 | | - long = "networks", |
| 113 | + #[arg( |
| 114 | + long = "networks", |
127 | 115 | help = "Comma-separated list of which portal subnetworks to activate", |
128 | 116 | default_value = DEFAULT_SUBNETWORKS, |
129 | | - use_delimiter = true |
| 117 | + use_value_delimiter = true |
130 | 118 | )] |
131 | 119 | pub networks: Vec<String>, |
132 | 120 |
|
133 | 121 | /// Storage capacity specified in megabytes. |
134 | | - #[structopt( |
| 122 | + #[arg( |
135 | 123 | default_value(DEFAULT_STORAGE_CAPACITY_MB), |
136 | 124 | long, |
137 | 125 | help = "Maximum number of megabytes of total data to store in the DB (actual usage will exceed limit due to overhead)" |
138 | 126 | )] |
139 | 127 | pub mb: u32, |
140 | 128 |
|
141 | | - #[structopt( |
| 129 | + #[arg( |
142 | 130 | long = "enable-metrics-with-url", |
143 | 131 | help = "Enable prometheus metrics reporting (provide local IP/Port from which your Prometheus server is configured to fetch metrics)" |
144 | 132 | )] |
145 | 133 | pub enable_metrics_with_url: Option<SocketAddr>, |
146 | 134 |
|
147 | | - #[structopt( |
148 | | - short = "e", |
| 135 | + #[arg( |
| 136 | + short = 'e', |
149 | 137 | long = "ephemeral", |
150 | 138 | help = "Use temporary data storage that is deleted on exit." |
151 | 139 | )] |
152 | 140 | pub ephemeral: bool, |
153 | 141 |
|
154 | | - #[structopt( |
| 142 | + #[arg( |
155 | 143 | long = "trusted-provider", |
156 | 144 | help = "Trusted provider to use. (options: 'infura' (default), 'pandaops' (devops) or 'custom')", |
157 | 145 | default_value(DEFAULT_TRUSTED_PROVIDER) |
158 | 146 | )] |
159 | 147 | pub trusted_provider: TrustedProviderType, |
160 | 148 |
|
161 | | - #[structopt( |
| 149 | + #[arg( |
162 | 150 | long = "trusted-provider-url", |
163 | | - help = "URL for a trusted http provider. Must include a base, host and port (e.g., '<base>://<host>:<port>').", |
164 | | - validator(check_url_format) |
| 151 | + value_parser = check_url_format, |
| 152 | + help = "URL for a trusted http provider. Must include a base, host and port (e.g., '<base>://<host>:<port>')." |
165 | 153 | )] |
166 | 154 | pub trusted_provider_url: Option<Url>, |
167 | 155 |
|
168 | | - #[structopt( |
| 156 | + #[arg( |
169 | 157 | long = "master-accumulator-path", |
170 | 158 | help = "Path to master accumulator for validation", |
171 | | - default_value(DEFAULT_MASTER_ACC_PATH), |
172 | | - parse(from_os_str) |
| 159 | + default_value(DEFAULT_MASTER_ACC_PATH) |
173 | 160 | )] |
174 | 161 | pub master_acc_path: PathBuf, |
175 | 162 | } |
@@ -214,7 +201,7 @@ impl TrinConfig { |
214 | 201 | I: Iterator<Item = T>, |
215 | 202 | T: Into<OsString> + Clone, |
216 | 203 | { |
217 | | - let config = Self::from_iter_safe(args)?; |
| 204 | + let config = Self::try_parse_from(args)?; |
218 | 205 |
|
219 | 206 | match config.web3_transport { |
220 | 207 | Web3TransportType::HTTP => match &config.web3_ipc_path.as_path().display().to_string()[..] { |
@@ -260,16 +247,16 @@ impl TrinConfig { |
260 | 247 | } |
261 | 248 |
|
262 | 249 | /// A validator function for CLI URL arguments. |
263 | | -fn check_url_format(url: String) -> Result<(), String> { |
264 | | - match Url::parse(&url) { |
265 | | - Ok(_) => Ok(()), |
| 250 | +fn check_url_format(url: &str) -> Result<Url, String> { |
| 251 | + match Url::parse(url) { |
| 252 | + Ok(val) => Ok(val), |
266 | 253 | Err(e) => panic!("Invalid URL '{url}', {e}"), |
267 | 254 | } |
268 | 255 | } |
269 | 256 |
|
270 | | -fn check_private_key_length(private_key: String) -> Result<(), String> { |
| 257 | +fn check_private_key_length(private_key: &str) -> Result<H256, String> { |
271 | 258 | if private_key.len() == 66 { |
272 | | - return Ok(()); |
| 259 | + return H256::from_str(private_key).map_err(|err| format!("HexError: {}", err)); |
273 | 260 | } |
274 | 261 | panic!( |
275 | 262 | "Invalid private key length: {}, expected 66 (0x-prefixed 32 byte hexstring)", |
|
0 commit comments