diff --git a/cli/src/wallet.rs b/cli/src/wallet.rs index 7e5cf217b7..c8d783779d 100644 --- a/cli/src/wallet.rs +++ b/cli/src/wallet.rs @@ -1661,7 +1661,7 @@ fn is_pubkey(string: String) -> Result<(), String> { } } -// Return an error if a pubkey cannot be parsed. +// Return an error if a keypair file cannot be parsed. fn is_keypair(string: String) -> Result<(), String> { read_keypair(&string) .map(|_| ()) diff --git a/gossip/src/main.rs b/gossip/src/main.rs index eac4aab703..cc7aee5e9f 100644 --- a/gossip/src/main.rs +++ b/gossip/src/main.rs @@ -15,7 +15,7 @@ use std::error; use std::net::SocketAddr; use std::process::exit; -fn pubkey_validator(pubkey: String) -> Result<(), String> { +fn is_pubkey(pubkey: String) -> Result<(), String> { match pubkey.parse::() { Ok(_) => Ok(()), Err(err) => Err(format!("{:?}", err)), @@ -38,6 +38,7 @@ fn main() -> Result<(), Box> { .value_name("HOST:PORT") .takes_value(true) .default_value(&entrypoint_string) + .validator(solana_netutil::is_host_port) .global(true) .help("Rendezvous with the cluster at this entry point"), ) @@ -81,7 +82,7 @@ fn main() -> Result<(), Box> { .long("pubkey") .value_name("PUBKEY") .takes_value(true) - .validator(pubkey_validator) + .validator(is_pubkey) .help("Public key of a specific node to wait for"), ) .arg( @@ -101,7 +102,7 @@ fn main() -> Result<(), Box> { .index(1) .required(true) .value_name("PUBKEY") - .validator(pubkey_validator) + .validator(is_pubkey) .help("Public key of a specific node to stop"), ), ) diff --git a/replicator/src/main.rs b/replicator/src/main.rs index 33eff5a0e3..024e56ff6e 100644 --- a/replicator/src/main.rs +++ b/replicator/src/main.rs @@ -8,6 +8,13 @@ use std::path::PathBuf; use std::process::exit; use std::sync::Arc; +// Return an error if a keypair file cannot be parsed. +fn is_keypair(string: String) -> Result<(), String> { + read_keypair(&string) + .map(|_| ()) + .map_err(|err| format!("{:?}", err)) +} + fn main() { solana_logger::setup(); @@ -20,6 +27,7 @@ fn main() { .long("identity") .value_name("PATH") .takes_value(true) + .validator(is_keypair) .help("File containing an identity (keypair)"), ) .arg( @@ -29,6 +37,7 @@ fn main() { .value_name("HOST:PORT") .takes_value(true) .required(true) + .validator(solana_netutil::is_host_port) .help("Rendezvous with the cluster at this entry point"), ) .arg( @@ -47,6 +56,7 @@ fn main() { .value_name("PATH") .takes_value(true) .required(true) + .validator(is_keypair) .help("File containing the storage account keypair"), ) .get_matches(); diff --git a/utils/netutil/src/lib.rs b/utils/netutil/src/lib.rs index 5871ae5513..67851b73a3 100644 --- a/utils/netutil/src/lib.rs +++ b/utils/netutil/src/lib.rs @@ -104,6 +104,11 @@ pub fn parse_host_port(host_port: &str) -> Result { } } +pub fn is_host_port(string: String) -> Result<(), String> { + parse_host_port(&string)?; + Ok(()) +} + #[cfg(windows)] fn udp_socket(_reuseaddr: bool) -> io::Result { let sock = Socket::new(Domain::ipv4(), Type::dgram(), None)?; diff --git a/validator-info/src/validator_info.rs b/validator-info/src/validator_info.rs index 39a111e80b..023570738f 100644 --- a/validator-info/src/validator_info.rs +++ b/validator-info/src/validator_info.rs @@ -50,6 +50,13 @@ fn is_pubkey(string: String) -> Result<(), String> { } } +// Return an error if a keypair file cannot be parsed. +fn is_keypair(string: String) -> Result<(), String> { + read_keypair(&string) + .map(|_| ()) + .map_err(|err| format!("{:?}", err)) +} + // Return an error if a url cannot be parsed. fn is_url(string: String) -> Result<(), String> { match url::Url::parse(&string) { @@ -187,6 +194,7 @@ fn main() -> Result<(), Box> { .value_name("KEYPAIR") .takes_value(true) .required(true) + .validator(is_keypair) .help("/path/to/validator-keypair.json"), ) .arg( diff --git a/validator/src/main.rs b/validator/src/main.rs index b91f854237..e4fe8ac99e 100644 --- a/validator/src/main.rs +++ b/validator/src/main.rs @@ -211,6 +211,13 @@ fn initialize_ledger_path( Ok(genesis_blockhash) } +// Return an error if a keypair file cannot be parsed. +fn is_keypair(string: String) -> Result<(), String> { + read_keypair(&string) + .map(|_| ()) + .map_err(|err| format!("{:?}", err)) +} + fn main() { solana_logger::setup_with_filter("solana=info"); solana_metrics::set_panic_hook("validator"); @@ -233,6 +240,7 @@ fn main() { .long("identity") .value_name("PATH") .takes_value(true) + .validator(is_keypair) .help("File containing the identity keypair for the validator"), ) .arg( @@ -240,6 +248,7 @@ fn main() { .long("voting-keypair") .value_name("PATH") .takes_value(true) + .validator(is_keypair) .help("File containing the authorized voting keypair. Default is an ephemeral keypair"), ) .arg( @@ -247,6 +256,7 @@ fn main() { .long("vote-account") .value_name("PUBKEY") .takes_value(true) + .validator(is_keypair) .help("Public key of the vote account to vote with. Default is the public key of the voting keypair"), ) .arg( @@ -254,6 +264,7 @@ fn main() { .long("storage-keypair") .value_name("PATH") .takes_value(true) + .validator(is_keypair) .help("File containing the storage account keypair. Default is an ephemeral keypair"), ) .arg( @@ -278,6 +289,7 @@ fn main() { .long("entrypoint") .value_name("HOST:PORT") .takes_value(true) + .validator(solana_netutil::is_host_port) .help("Rendezvous with the cluster at this entry point"), ) .arg( @@ -324,6 +336,7 @@ fn main() { .long("rpc-drone-address") .value_name("HOST:PORT") .takes_value(true) + .validator(solana_netutil::is_host_port) .help("Enable the JSON RPC 'requestAirdrop' API with this drone address."), ) .arg( @@ -332,6 +345,7 @@ fn main() { .value_name("HOST:PORT") .takes_value(true) .hidden(true) // Don't document this argument to discourage its use + .validator(solana_netutil::is_host_port) .help("Rendezvous with the vote signer at this RPC end point"), ) .arg(