diff --git a/clap-utils/src/input_parsers.rs b/clap-utils/src/input_parsers.rs index 1e9b1e697..24ed38f83 100644 --- a/clap-utils/src/input_parsers.rs +++ b/clap-utils/src/input_parsers.rs @@ -129,6 +129,22 @@ pub fn pubkey_of_signer( } } +pub fn pubkeys_of_multiple_signers( + matches: &ArgMatches<'_>, + name: &str, + wallet_manager: Option<&Arc>, +) -> Result>, Box> { + if let Some(pubkey_matches) = matches.values_of(name) { + let mut pubkeys: Vec = vec![]; + for signer in pubkey_matches { + pubkeys.push(pubkey_from_path(matches, signer, name, wallet_manager)?); + } + Ok(Some(pubkeys)) + } else { + Ok(None) + } +} + pub fn resolve_signer( matches: &ArgMatches<'_>, name: &str, diff --git a/clap-utils/src/input_validators.rs b/clap-utils/src/input_validators.rs index 88ec1c7b1..73a2a6a10 100644 --- a/clap-utils/src/input_validators.rs +++ b/clap-utils/src/input_validators.rs @@ -46,18 +46,27 @@ pub fn is_pubkey_or_keypair(string: String) -> Result<(), String> { is_pubkey(string.clone()).or_else(|_| is_keypair(string)) } -// Return an error if string cannot be parsed as pubkey or keypair file or keypair ask keyword -pub fn is_pubkey_or_keypair_or_ask_keyword(string: String) -> Result<(), String> { - is_pubkey(string.clone()).or_else(|_| is_keypair_or_ask_keyword(string)) -} - -pub fn is_valid_signer(string: String) -> Result<(), String> { +// Return an error if string cannot be parsed as a pubkey string, or a valid Signer that can +// produce a pubkey() +pub fn is_valid_pubkey(string: String) -> Result<(), String> { match parse_keypair_path(&string) { KeypairUrl::Filepath(path) => is_keypair(path), _ => Ok(()), } } +// Return an error if string cannot be parsed as a valid Signer. This is an alias of +// `is_valid_pubkey`, and does accept pubkey strings, even though a Pubkey is not by itself +// sufficient to sign a transaction. +// +// In the current offline-signing implementation, a pubkey is the valid input for a signer field +// when paired with an offline `--signer` argument to provide a Presigner (pubkey + signature). +// Clap validators can't check multiple fields at once, so the verification that a `--signer` is +// also provided and correct happens in parsing, not in validation. +pub fn is_valid_signer(string: String) -> Result<(), String> { + is_valid_pubkey(string) +} + // Return an error if string cannot be parsed as pubkey=signature string pub fn is_pubkey_sig(string: String) -> Result<(), String> { let mut signer = string.split('='); diff --git a/cli/src/cli.rs b/cli/src/cli.rs index ac21f7d13..e4c094a9a 100644 --- a/cli/src/cli.rs +++ b/cli/src/cli.rs @@ -569,7 +569,7 @@ pub fn parse_command( ) -> Result> { let response = match matches.subcommand() { // Cluster Query Commands - ("catchup", Some(matches)) => parse_catchup(matches), + ("catchup", Some(matches)) => parse_catchup(matches, wallet_manager), ("cluster-version", Some(_matches)) => Ok(CliCommandInfo { command: CliCommand::ClusterVersion, signers: vec![], @@ -604,7 +604,7 @@ pub fn parse_command( command: CliCommand::ShowGossip, signers: vec![], }), - ("stakes", Some(matches)) => parse_show_stakes(matches), + ("stakes", Some(matches)) => parse_show_stakes(matches, wallet_manager), ("validators", Some(matches)) => parse_show_validators(matches), // Nonce Commands ("authorize-nonce-account", Some(matches)) => { @@ -613,11 +613,11 @@ pub fn parse_command( ("create-nonce-account", Some(matches)) => { parse_nonce_create_account(matches, default_signer_path, wallet_manager) } - ("nonce", Some(matches)) => parse_get_nonce(matches), + ("nonce", Some(matches)) => parse_get_nonce(matches, wallet_manager), ("new-nonce", Some(matches)) => { parse_new_nonce(matches, default_signer_path, wallet_manager) } - ("nonce-account", Some(matches)) => parse_show_nonce_account(matches), + ("nonce-account", Some(matches)) => parse_show_nonce_account(matches, wallet_manager), ("withdraw-from-nonce-account", Some(matches)) => { parse_withdraw_from_nonce_account(matches, default_signer_path, wallet_manager) } @@ -662,7 +662,7 @@ pub fn parse_command( ("stake-set-lockup", Some(matches)) => { parse_stake_set_lockup(matches, default_signer_path, wallet_manager) } - ("stake-account", Some(matches)) => parse_show_stake_account(matches), + ("stake-account", Some(matches)) => parse_show_stake_account(matches, wallet_manager), ("stake-history", Some(matches)) => parse_show_stake_history(matches), // Storage Commands ("create-archiver-storage-account", Some(matches)) => { @@ -674,7 +674,9 @@ pub fn parse_command( ("claim-storage-reward", Some(matches)) => { parse_storage_claim_reward(matches, default_signer_path, wallet_manager) } - ("storage-account", Some(matches)) => parse_storage_get_account_command(matches), + ("storage-account", Some(matches)) => { + parse_storage_get_account_command(matches, wallet_manager) + } // Validator Info Commands ("validator-info", Some(matches)) => match matches.subcommand() { ("publish", Some(matches)) => { @@ -702,7 +704,7 @@ pub fn parse_command( wallet_manager, VoteAuthorize::Withdrawer, ), - ("vote-account", Some(matches)) => parse_vote_get_account_command(matches), + ("vote-account", Some(matches)) => parse_vote_get_account_command(matches, wallet_manager), ("withdraw-from-vote-account", Some(matches)) => { parse_withdraw_from_vote_account(matches, default_signer_path, wallet_manager) } @@ -738,7 +740,7 @@ pub fn parse_command( } else { None }; - let pubkey = pubkey_of(matches, "to"); + let pubkey = pubkey_of_signer(matches, "to", wallet_manager)?; let signers = if pubkey.is_some() { vec![] } else { @@ -761,7 +763,7 @@ pub fn parse_command( }) } ("balance", Some(matches)) => { - let pubkey = pubkey_of(matches, "pubkey"); + let pubkey = pubkey_of_signer(matches, "pubkey", wallet_manager)?; let signers = if pubkey.is_some() { vec![] } else { @@ -802,7 +804,7 @@ pub fn parse_command( }, ("pay", Some(matches)) => { let lamports = lamports_of_sol(matches, "amount").unwrap(); - let to = pubkey_of(matches, "to").unwrap(); + let to = pubkey_of_signer(matches, "to", wallet_manager)?.unwrap(); let timestamp = if matches.is_present("timestamp") { // Parse input for serde_json let date_string = if !matches.value_of("timestamp").unwrap().contains('Z') { @@ -819,7 +821,7 @@ pub fn parse_command( let cancelable = matches.is_present("cancelable"); let sign_only = matches.is_present(SIGN_ONLY_ARG.name); let blockhash_query = BlockhashQuery::new_from_matches(matches); - let nonce_account = pubkey_of(matches, NONCE_ARG.name); + let nonce_account = pubkey_of_signer(matches, NONCE_ARG.name, wallet_manager)?; let (nonce_authority, nonce_authority_pubkey) = signer_of(matches, NONCE_AUTHORITY_ARG.name, wallet_manager)?; @@ -852,7 +854,8 @@ pub fn parse_command( }) } ("account", Some(matches)) => { - let account_pubkey = pubkey_of(matches, "account_pubkey").unwrap(); + let account_pubkey = + pubkey_of_signer(matches, "account_pubkey", wallet_manager)?.unwrap(); let output_file = matches.value_of("output_file"); let use_lamports_unit = matches.is_present("lamports"); Ok(CliCommandInfo { @@ -907,10 +910,10 @@ pub fn parse_command( } ("transfer", Some(matches)) => { let lamports = lamports_of_sol(matches, "amount").unwrap(); - let to = pubkey_of(matches, "to").unwrap(); + let to = pubkey_of_signer(matches, "to", wallet_manager)?.unwrap(); let sign_only = matches.is_present(SIGN_ONLY_ARG.name); let blockhash_query = BlockhashQuery::new_from_matches(matches); - let nonce_account = pubkey_of(matches, NONCE_ARG.name); + let nonce_account = pubkey_of_signer(matches, NONCE_ARG.name, wallet_manager)?; let (nonce_authority, nonce_authority_pubkey) = signer_of(matches, NONCE_AUTHORITY_ARG.name, wallet_manager)?; let (fee_payer, fee_payer_pubkey) = @@ -2249,7 +2252,7 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, ' .index(2) .value_name("PUBKEY") .takes_value(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("The pubkey of airdrop recipient"), ), ) @@ -2261,7 +2264,7 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, ' .index(1) .value_name("PUBKEY") .takes_value(true) - .validator(is_valid_signer) + .validator(is_valid_pubkey) .help("The public key of the balance to check"), ) .arg( @@ -2324,7 +2327,7 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, ' .value_name("PUBKEY") .takes_value(true) .required(false) - .validator(is_valid_signer) + .validator(is_valid_pubkey) .help("From (base) key, [default: cli config keypair]"), ), ) @@ -2349,7 +2352,7 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, ' .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("The pubkey of recipient"), ) .arg( @@ -2467,7 +2470,7 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, ' .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("The pubkey of recipient"), ) .arg( @@ -2502,7 +2505,7 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, ' .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Account pubkey"), ) .arg( diff --git a/cli/src/cluster_query.rs b/cli/src/cluster_query.rs index 29cb7225c..47c96d712 100644 --- a/cli/src/cluster_query.rs +++ b/cli/src/cluster_query.rs @@ -58,7 +58,7 @@ impl ClusterQuerySubCommands for App<'_, '_> { .index(1) .takes_value(true) .value_name("PUBKEY") - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .required(true) .help("Identity pubkey of the validator"), ) @@ -224,7 +224,7 @@ impl ClusterQuerySubCommands for App<'_, '_> { .value_name("VOTE ACCOUNT PUBKEYS") .takes_value(true) .multiple(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Only show stake accounts delegated to the provided vote accounts"), ) .arg( @@ -256,8 +256,11 @@ impl ClusterQuerySubCommands for App<'_, '_> { } } -pub fn parse_catchup(matches: &ArgMatches<'_>) -> Result { - let node_pubkey = pubkey_of(matches, "node_pubkey").unwrap(); +pub fn parse_catchup( + matches: &ArgMatches<'_>, + wallet_manager: Option<&Arc>, +) -> Result { + let node_pubkey = pubkey_of_signer(matches, "node_pubkey", wallet_manager)?.unwrap(); let node_json_rpc_url = value_t!(matches, "node_json_rpc_url", String).ok(); Ok(CliCommandInfo { command: CliCommand::Catchup { @@ -359,9 +362,13 @@ pub fn parse_get_transaction_count(matches: &ArgMatches<'_>) -> Result) -> Result { +pub fn parse_show_stakes( + matches: &ArgMatches<'_>, + wallet_manager: Option<&Arc>, +) -> Result { let use_lamports_unit = matches.is_present("lamports"); - let vote_account_pubkeys = pubkeys_of(matches, "vote_account_pubkeys"); + let vote_account_pubkeys = + pubkeys_of_multiple_signers(matches, "vote_account_pubkeys", wallet_manager)?; Ok(CliCommandInfo { command: CliCommand::ShowStakes { diff --git a/cli/src/nonce.rs b/cli/src/nonce.rs index e5d6c9495..566f1f55d 100644 --- a/cli/src/nonce.rs +++ b/cli/src/nonce.rs @@ -74,7 +74,7 @@ pub fn nonce_arg<'a, 'b>() -> Arg<'a, 'b> { .takes_value(true) .value_name("PUBKEY") .requires(BLOCKHASH_ARG.name) - .validator(is_pubkey) + .validator(is_valid_pubkey) .help(NONCE_ARG.help) } @@ -98,7 +98,7 @@ impl NonceSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Address of the nonce account"), ) .arg( @@ -107,7 +107,7 @@ impl NonceSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Account to be granted authority of the nonce account"), ) .arg( @@ -125,10 +125,10 @@ impl NonceSubCommands for App<'_, '_> { .arg( Arg::with_name("nonce_account_keypair") .index(1) - .value_name("PUBKEY") + .value_name("KEYPAIR") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_signer) .help("Keypair of the nonce account to fund"), ) .arg( @@ -145,7 +145,7 @@ impl NonceSubCommands for App<'_, '_> { .long(NONCE_AUTHORITY_ARG.long) .takes_value(true) .value_name("PUBKEY") - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Assign noncing authority to another entity"), ), ) @@ -159,7 +159,7 @@ impl NonceSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Address of the nonce account to display"), ), ) @@ -167,12 +167,12 @@ impl NonceSubCommands for App<'_, '_> { SubCommand::with_name("new-nonce") .about("Generate a new nonce, rendering the existing nonce useless") .arg( - Arg::with_name("nonce_account_keypair") + Arg::with_name("nonce_account_pubkey") .index(1) - .value_name("KEYPAIR") + .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Address of the nonce account"), ) .arg(nonce_authority_arg()), @@ -187,7 +187,7 @@ impl NonceSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Address of the nonce account to display"), ) .arg( @@ -201,12 +201,12 @@ impl NonceSubCommands for App<'_, '_> { SubCommand::with_name("withdraw-from-nonce-account") .about("Withdraw SOL from the nonce account") .arg( - Arg::with_name("nonce_account_keypair") + Arg::with_name("nonce_account_pubkey") .index(1) - .value_name("KEYPAIR") + .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_valid_signer) + .validator(is_valid_pubkey) .help("Nonce account to withdraw from"), ) .arg( @@ -215,7 +215,7 @@ impl NonceSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("The account to which the SOL should be transferred"), ) .arg( @@ -279,8 +279,8 @@ pub fn parse_authorize_nonce_account( default_signer_path: &str, wallet_manager: Option<&Arc>, ) -> Result { - let nonce_account = pubkey_of(matches, "nonce_account_pubkey").unwrap(); - let new_authority = pubkey_of(matches, "new_authority").unwrap(); + let nonce_account = pubkey_of_signer(matches, "nonce_account_pubkey", wallet_manager)?.unwrap(); + let new_authority = pubkey_of_signer(matches, "new_authority", wallet_manager)?.unwrap(); let (nonce_authority, nonce_authority_pubkey) = signer_of(matches, NONCE_AUTHORITY_ARG.name, wallet_manager)?; @@ -311,7 +311,7 @@ pub fn parse_nonce_create_account( signer_of(matches, "nonce_account_keypair", wallet_manager)?; let seed = matches.value_of("seed").map(|s| s.to_string()); let lamports = lamports_of_sol(matches, "amount").unwrap(); - let nonce_authority = pubkey_of(matches, NONCE_AUTHORITY_ARG.name); + let nonce_authority = pubkey_of_signer(matches, NONCE_AUTHORITY_ARG.name, wallet_manager)?; let payer_provided = None; let signer_info = generate_unique_signers( @@ -332,8 +332,12 @@ pub fn parse_nonce_create_account( }) } -pub fn parse_get_nonce(matches: &ArgMatches<'_>) -> Result { - let nonce_account_pubkey = pubkey_of(matches, "nonce_account_pubkey").unwrap(); +pub fn parse_get_nonce( + matches: &ArgMatches<'_>, + wallet_manager: Option<&Arc>, +) -> Result { + let nonce_account_pubkey = + pubkey_of_signer(matches, "nonce_account_pubkey", wallet_manager)?.unwrap(); Ok(CliCommandInfo { command: CliCommand::GetNonce(nonce_account_pubkey), @@ -346,7 +350,7 @@ pub fn parse_new_nonce( default_signer_path: &str, wallet_manager: Option<&Arc>, ) -> Result { - let nonce_account = pubkey_of(matches, "nonce_account_keypair").unwrap(); + let nonce_account = pubkey_of_signer(matches, "nonce_account_pubkey", wallet_manager)?.unwrap(); let (nonce_authority, nonce_authority_pubkey) = signer_of(matches, NONCE_AUTHORITY_ARG.name, wallet_manager)?; @@ -367,8 +371,12 @@ pub fn parse_new_nonce( }) } -pub fn parse_show_nonce_account(matches: &ArgMatches<'_>) -> Result { - let nonce_account_pubkey = pubkey_of(matches, "nonce_account_pubkey").unwrap(); +pub fn parse_show_nonce_account( + matches: &ArgMatches<'_>, + wallet_manager: Option<&Arc>, +) -> Result { + let nonce_account_pubkey = + pubkey_of_signer(matches, "nonce_account_pubkey", wallet_manager)?.unwrap(); let use_lamports_unit = matches.is_present("lamports"); Ok(CliCommandInfo { @@ -385,8 +393,9 @@ pub fn parse_withdraw_from_nonce_account( default_signer_path: &str, wallet_manager: Option<&Arc>, ) -> Result { - let nonce_account = pubkey_of(matches, "nonce_account_keypair").unwrap(); - let destination_account_pubkey = pubkey_of(matches, "destination_account_pubkey").unwrap(); + let nonce_account = pubkey_of_signer(matches, "nonce_account_pubkey", wallet_manager)?.unwrap(); + let destination_account_pubkey = + pubkey_of_signer(matches, "destination_account_pubkey", wallet_manager)?.unwrap(); let lamports = lamports_of_sol(matches, "amount").unwrap(); let (nonce_authority, nonce_authority_pubkey) = signer_of(matches, NONCE_AUTHORITY_ARG.name, wallet_manager)?; diff --git a/cli/src/stake.rs b/cli/src/stake.rs index 5955c9b79..9abbda47f 100644 --- a/cli/src/stake.rs +++ b/cli/src/stake.rs @@ -93,7 +93,7 @@ impl StakeSubCommands for App<'_, '_> { .long("custodian") .value_name("PUBKEY") .takes_value(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Identity of the custodian (can withdraw before lockup expires)") ) .arg( @@ -123,7 +123,7 @@ impl StakeSubCommands for App<'_, '_> { .long(STAKE_AUTHORITY_ARG.long) .value_name("PUBKEY") .takes_value(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help(STAKE_AUTHORITY_ARG.help) ) .arg( @@ -131,7 +131,7 @@ impl StakeSubCommands for App<'_, '_> { .long(WITHDRAW_AUTHORITY_ARG.long) .value_name("PUBKEY") .takes_value(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help(WITHDRAW_AUTHORITY_ARG.help) ) .arg( @@ -163,7 +163,7 @@ impl StakeSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Stake account to delegate") ) .arg( @@ -172,7 +172,7 @@ impl StakeSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("The vote account to which the stake will be delegated") ) .arg(stake_authority_arg()) @@ -190,7 +190,7 @@ impl StakeSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Stake account in which to set the authorized staker") ) .arg( @@ -199,7 +199,7 @@ impl StakeSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("New authorized staker") ) .arg(stake_authority_arg()) @@ -217,7 +217,7 @@ impl StakeSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Stake account in which to set the authorized withdrawer") ) .arg( @@ -226,7 +226,7 @@ impl StakeSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("New authorized withdrawer") ) .arg(withdraw_authority_arg()) @@ -244,6 +244,7 @@ impl StakeSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) + .validator(is_valid_pubkey) .help("Stake account to be deactivated.") ) .arg(stake_authority_arg()) @@ -261,6 +262,7 @@ impl StakeSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) + .validator(is_valid_pubkey) .help("Stake account to be split") ) .arg( @@ -303,7 +305,7 @@ impl StakeSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Stake account from which to withdraw") ) .arg( @@ -312,7 +314,7 @@ impl StakeSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("The account to which the SOL should be transferred") ) .arg( @@ -339,7 +341,7 @@ impl StakeSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Stake account for which to set Lockup") ) .arg( @@ -362,7 +364,7 @@ impl StakeSubCommands for App<'_, '_> { .long("new-custodian") .value_name("PUBKEY") .takes_value(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Identity of the new lockup custodian (can withdraw before lockup expires)") ) .group(ArgGroup::with_name("lockup_details") @@ -391,7 +393,7 @@ impl StakeSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Address of the stake account to display") ) .arg( @@ -423,13 +425,13 @@ pub fn parse_stake_create_account( let seed = matches.value_of("seed").map(|s| s.to_string()); let epoch = value_of(matches, "lockup_epoch").unwrap_or(0); let unix_timestamp = unix_timestamp_from_rfc3339_datetime(matches, "lockup_date").unwrap_or(0); - let custodian = pubkey_of(matches, "custodian").unwrap_or_default(); - let staker = pubkey_of(matches, STAKE_AUTHORITY_ARG.name); - let withdrawer = pubkey_of(matches, WITHDRAW_AUTHORITY_ARG.name); + let custodian = pubkey_of_signer(matches, "custodian", wallet_manager)?.unwrap_or_default(); + let staker = pubkey_of_signer(matches, STAKE_AUTHORITY_ARG.name, wallet_manager)?; + let withdrawer = pubkey_of_signer(matches, WITHDRAW_AUTHORITY_ARG.name, wallet_manager)?; let lamports = lamports_of_sol(matches, "amount").unwrap(); let sign_only = matches.is_present(SIGN_ONLY_ARG.name); let blockhash_query = BlockhashQuery::new_from_matches(matches); - let nonce_account = pubkey_of(matches, NONCE_ARG.name); + let nonce_account = pubkey_of_signer(matches, NONCE_ARG.name, wallet_manager)?; let (nonce_authority, nonce_authority_pubkey) = signer_of(matches, NONCE_AUTHORITY_ARG.name, wallet_manager)?; let (fee_payer, fee_payer_pubkey) = signer_of(matches, FEE_PAYER_ARG.name, wallet_manager)?; @@ -472,8 +474,10 @@ pub fn parse_stake_delegate_stake( default_signer_path: &str, wallet_manager: Option<&Arc>, ) -> Result { - let stake_account_pubkey = pubkey_of(matches, "stake_account_pubkey").unwrap(); - let vote_account_pubkey = pubkey_of(matches, "vote_account_pubkey").unwrap(); + let stake_account_pubkey = + pubkey_of_signer(matches, "stake_account_pubkey", wallet_manager)?.unwrap(); + let vote_account_pubkey = + pubkey_of_signer(matches, "vote_account_pubkey", wallet_manager)?.unwrap(); let force = matches.is_present("force"); let sign_only = matches.is_present(SIGN_ONLY_ARG.name); let blockhash_query = BlockhashQuery::new_from_matches(matches); @@ -513,8 +517,10 @@ pub fn parse_stake_authorize( wallet_manager: Option<&Arc>, stake_authorize: StakeAuthorize, ) -> Result { - let stake_account_pubkey = pubkey_of(matches, "stake_account_pubkey").unwrap(); - let new_authorized_pubkey = pubkey_of(matches, "authorized_pubkey").unwrap(); + let stake_account_pubkey = + pubkey_of_signer(matches, "stake_account_pubkey", wallet_manager)?.unwrap(); + let new_authorized_pubkey = + pubkey_of_signer(matches, "authorized_pubkey", wallet_manager)?.unwrap(); let authority_flag = match stake_authorize { StakeAuthorize::Staker => STAKE_AUTHORITY_ARG.name, StakeAuthorize::Withdrawer => WITHDRAW_AUTHORITY_ARG.name, @@ -555,7 +561,8 @@ pub fn parse_split_stake( default_signer_path: &str, wallet_manager: Option<&Arc>, ) -> Result { - let stake_account_pubkey = pubkey_of(matches, "stake_account_pubkey").unwrap(); + let stake_account_pubkey = + pubkey_of_signer(matches, "stake_account_pubkey", wallet_manager)?.unwrap(); let (split_stake_account, split_stake_account_pubkey) = signer_of(matches, "split_stake_account", wallet_manager)?; let lamports = lamports_of_sol(matches, "amount").unwrap(); @@ -599,7 +606,8 @@ pub fn parse_stake_deactivate_stake( default_signer_path: &str, wallet_manager: Option<&Arc>, ) -> Result { - let stake_account_pubkey = pubkey_of(matches, "stake_account_pubkey").unwrap(); + let stake_account_pubkey = + pubkey_of_signer(matches, "stake_account_pubkey", wallet_manager)?.unwrap(); let sign_only = matches.is_present(SIGN_ONLY_ARG.name); let blockhash_query = BlockhashQuery::new_from_matches(matches); let nonce_account = pubkey_of(matches, NONCE_ARG.name); @@ -635,8 +643,10 @@ pub fn parse_stake_withdraw_stake( default_signer_path: &str, wallet_manager: Option<&Arc>, ) -> Result { - let stake_account_pubkey = pubkey_of(matches, "stake_account_pubkey").unwrap(); - let destination_account_pubkey = pubkey_of(matches, "destination_account_pubkey").unwrap(); + let stake_account_pubkey = + pubkey_of_signer(matches, "stake_account_pubkey", wallet_manager)?.unwrap(); + let destination_account_pubkey = + pubkey_of_signer(matches, "destination_account_pubkey", wallet_manager)?.unwrap(); let lamports = lamports_of_sol(matches, "amount").unwrap(); let sign_only = matches.is_present(SIGN_ONLY_ARG.name); let blockhash_query = BlockhashQuery::new_from_matches(matches); @@ -675,10 +685,11 @@ pub fn parse_stake_set_lockup( default_signer_path: &str, wallet_manager: Option<&Arc>, ) -> Result { - let stake_account_pubkey = pubkey_of(matches, "stake_account_pubkey").unwrap(); + let stake_account_pubkey = + pubkey_of_signer(matches, "stake_account_pubkey", wallet_manager)?.unwrap(); let epoch = value_of(matches, "lockup_epoch"); let unix_timestamp = unix_timestamp_from_rfc3339_datetime(matches, "lockup_date"); - let new_custodian = pubkey_of(matches, "new_custodian"); + let new_custodian = pubkey_of_signer(matches, "new_custodian", wallet_manager)?; let sign_only = matches.is_present(SIGN_ONLY_ARG.name); let blockhash_query = BlockhashQuery::new_from_matches(matches); @@ -715,8 +726,12 @@ pub fn parse_stake_set_lockup( }) } -pub fn parse_show_stake_account(matches: &ArgMatches<'_>) -> Result { - let stake_account_pubkey = pubkey_of(matches, "stake_account_pubkey").unwrap(); +pub fn parse_show_stake_account( + matches: &ArgMatches<'_>, + wallet_manager: Option<&Arc>, +) -> Result { + let stake_account_pubkey = + pubkey_of_signer(matches, "stake_account_pubkey", wallet_manager)?.unwrap(); let use_lamports_unit = matches.is_present("lamports"); Ok(CliCommandInfo { command: CliCommand::ShowStakeAccount { diff --git a/cli/src/storage.rs b/cli/src/storage.rs index 90ef0c0e0..3a20cb6a4 100644 --- a/cli/src/storage.rs +++ b/cli/src/storage.rs @@ -29,7 +29,7 @@ impl StorageSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair), + .validator(is_valid_pubkey), ) .arg( Arg::with_name("storage_account") @@ -49,7 +49,7 @@ impl StorageSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair), + .validator(is_valid_pubkey), ) .arg( Arg::with_name("storage_account") @@ -69,7 +69,7 @@ impl StorageSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("The node account to credit the rewards to"), ) .arg( @@ -78,7 +78,7 @@ impl StorageSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Storage account address to redeem credits for"), ), ) @@ -92,7 +92,7 @@ impl StorageSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Storage account pubkey"), ), ) @@ -104,7 +104,8 @@ pub fn parse_storage_create_archiver_account( default_signer_path: &str, wallet_manager: Option<&Arc>, ) -> Result { - let account_owner = pubkey_of(matches, "storage_account_owner").unwrap(); + let account_owner = + pubkey_of_signer(matches, "storage_account_owner", wallet_manager)?.unwrap(); let (storage_account, storage_account_pubkey) = signer_of(matches, "storage_account", wallet_manager)?; @@ -131,7 +132,8 @@ pub fn parse_storage_create_validator_account( default_signer_path: &str, wallet_manager: Option<&Arc>, ) -> Result { - let account_owner = pubkey_of(matches, "storage_account_owner").unwrap(); + let account_owner = + pubkey_of_signer(matches, "storage_account_owner", wallet_manager)?.unwrap(); let (storage_account, storage_account_pubkey) = signer_of(matches, "storage_account", wallet_manager)?; @@ -158,8 +160,10 @@ pub fn parse_storage_claim_reward( default_signer_path: &str, wallet_manager: Option<&Arc>, ) -> Result { - let node_account_pubkey = pubkey_of(matches, "node_account_pubkey").unwrap(); - let storage_account_pubkey = pubkey_of(matches, "storage_account_pubkey").unwrap(); + let node_account_pubkey = + pubkey_of_signer(matches, "node_account_pubkey", wallet_manager)?.unwrap(); + let storage_account_pubkey = + pubkey_of_signer(matches, "storage_account_pubkey", wallet_manager)?.unwrap(); Ok(CliCommandInfo { command: CliCommand::ClaimStorageReward { node_account_pubkey, @@ -176,8 +180,10 @@ pub fn parse_storage_claim_reward( pub fn parse_storage_get_account_command( matches: &ArgMatches<'_>, + wallet_manager: Option<&Arc>, ) -> Result { - let storage_account_pubkey = pubkey_of(matches, "storage_account_pubkey").unwrap(); + let storage_account_pubkey = + pubkey_of_signer(matches, "storage_account_pubkey", wallet_manager)?.unwrap(); Ok(CliCommandInfo { command: CliCommand::ShowStorageAccount(storage_account_pubkey), signers: vec![], diff --git a/cli/src/vote.rs b/cli/src/vote.rs index ac7a015de..cb8c96ed7 100644 --- a/cli/src/vote.rs +++ b/cli/src/vote.rs @@ -45,7 +45,7 @@ impl VoteSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Validator that will vote with this account"), ) .arg( @@ -61,7 +61,7 @@ impl VoteSubCommands for App<'_, '_> { .long("authorized-voter") .value_name("PUBKEY") .takes_value(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Public key of the authorized voter [default: validator identity pubkey]"), ) .arg( @@ -69,7 +69,7 @@ impl VoteSubCommands for App<'_, '_> { .long("authorized-withdrawer") .value_name("PUBKEY") .takes_value(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Public key of the authorized withdrawer [default: validator identity pubkey]"), ) .arg( @@ -80,37 +80,6 @@ impl VoteSubCommands for App<'_, '_> { .help("Seed for address generation; if specified, the resulting account will be at a derived address of the VOTE ACCOUNT pubkey") ), ) - .subcommand( - SubCommand::with_name("vote-update-validator") - .about("Update the vote account's validator identity") - .arg( - Arg::with_name("vote_account_pubkey") - .index(1) - .value_name("PUBKEY") - .takes_value(true) - .required(true) - .validator(is_pubkey_or_keypair) - .help("Vote account to update"), - ) - .arg( - Arg::with_name("new_identity_pubkey") - .index(2) - .value_name("PUBKEY") - .takes_value(true) - .required(true) - .validator(is_pubkey_or_keypair) - .help("New validator that will vote with this account"), - ) - .arg( - Arg::with_name("authorized_voter") - .index(3) - .value_name("KEYPAIR") - .takes_value(true) - .required(true) - .validator(is_valid_signer) - .help("Authorized voter keypair"), - ) - ) .subcommand( SubCommand::with_name("vote-authorize-voter") .about("Authorize a new vote signing keypair for the given vote account") @@ -120,7 +89,7 @@ impl VoteSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Vote account in which to set the authorized voter"), ) .arg( @@ -129,7 +98,7 @@ impl VoteSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("New vote signer to authorize"), ), ) @@ -142,7 +111,7 @@ impl VoteSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Vote account in which to set the authorized withdrawer"), ) .arg( @@ -151,10 +120,41 @@ impl VoteSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("New withdrawer to authorize"), ), ) + .subcommand( + SubCommand::with_name("vote-update-validator") + .about("Update the vote account's validator identity") + .arg( + Arg::with_name("vote_account_pubkey") + .index(1) + .value_name("PUBKEY") + .takes_value(true) + .required(true) + .validator(is_valid_pubkey) + .help("Vote account to update"), + ) + .arg( + Arg::with_name("new_identity_pubkey") + .index(2) + .value_name("PUBKEY") + .takes_value(true) + .required(true) + .validator(is_valid_pubkey) + .help("New validator that will vote with this account"), + ) + .arg( + Arg::with_name("authorized_voter") + .index(3) + .value_name("KEYPAIR") + .takes_value(true) + .required(true) + .validator(is_valid_signer) + .help("Authorized voter keypair"), + ) + ) .subcommand( SubCommand::with_name("vote-account") .about("Show the contents of a vote account") @@ -173,7 +173,7 @@ impl VoteSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Vote account pubkey"), ) .arg( @@ -192,7 +192,7 @@ impl VoteSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("Vote account from which to withdraw"), ) .arg( @@ -201,7 +201,7 @@ impl VoteSubCommands for App<'_, '_> { .value_name("PUBKEY") .takes_value(true) .required(true) - .validator(is_pubkey_or_keypair) + .validator(is_valid_pubkey) .help("The account to which the SOL should be transferred"), ) .arg( @@ -232,10 +232,10 @@ pub fn parse_create_vote_account( ) -> Result { let (vote_account, _) = signer_of(matches, "vote_account", wallet_manager)?; let seed = matches.value_of("seed").map(|s| s.to_string()); - let identity_pubkey = pubkey_of(matches, "identity_pubkey").unwrap(); + let identity_pubkey = pubkey_of_signer(matches, "identity_pubkey", wallet_manager)?.unwrap(); let commission = value_t_or_exit!(matches, "commission", u8); - let authorized_voter = pubkey_of(matches, "authorized_voter"); - let authorized_withdrawer = pubkey_of(matches, "authorized_withdrawer"); + let authorized_voter = pubkey_of_signer(matches, "authorized_voter", wallet_manager)?; + let authorized_withdrawer = pubkey_of_signer(matches, "authorized_withdrawer", wallet_manager)?; let payer_provided = None; let CliSignerInfo { signers } = generate_unique_signers( @@ -263,8 +263,10 @@ pub fn parse_vote_authorize( wallet_manager: Option<&Arc>, vote_authorize: VoteAuthorize, ) -> Result { - let vote_account_pubkey = pubkey_of(matches, "vote_account_pubkey").unwrap(); - let new_authorized_pubkey = pubkey_of(matches, "new_authorized_pubkey").unwrap(); + let vote_account_pubkey = + pubkey_of_signer(matches, "vote_account_pubkey", wallet_manager)?.unwrap(); + let new_authorized_pubkey = + pubkey_of_signer(matches, "new_authorized_pubkey", wallet_manager)?.unwrap(); let authorized_voter_provided = None; let CliSignerInfo { signers } = generate_unique_signers( @@ -289,8 +291,10 @@ pub fn parse_vote_update_validator( default_signer_path: &str, wallet_manager: Option<&Arc>, ) -> Result { - let vote_account_pubkey = pubkey_of(matches, "vote_account_pubkey").unwrap(); - let new_identity_pubkey = pubkey_of(matches, "new_identity_pubkey").unwrap(); + let vote_account_pubkey = + pubkey_of_signer(matches, "vote_account_pubkey", wallet_manager)?.unwrap(); + let new_identity_pubkey = + pubkey_of_signer(matches, "new_identity_pubkey", wallet_manager)?.unwrap(); let (authorized_voter, _) = signer_of(matches, "authorized_voter", wallet_manager)?; let payer_provided = None; @@ -312,8 +316,10 @@ pub fn parse_vote_update_validator( pub fn parse_vote_get_account_command( matches: &ArgMatches<'_>, + wallet_manager: Option<&Arc>, ) -> Result { - let vote_account_pubkey = pubkey_of(matches, "vote_account_pubkey").unwrap(); + let vote_account_pubkey = + pubkey_of_signer(matches, "vote_account_pubkey", wallet_manager)?.unwrap(); let use_lamports_unit = matches.is_present("lamports"); let commitment_config = if matches.is_present("confirmed") { CommitmentConfig::default() @@ -335,8 +341,10 @@ pub fn parse_withdraw_from_vote_account( default_signer_path: &str, wallet_manager: Option<&Arc>, ) -> Result { - let vote_account_pubkey = pubkey_of(matches, "vote_account_pubkey").unwrap(); - let destination_account_pubkey = pubkey_of(matches, "destination_account_pubkey").unwrap(); + let vote_account_pubkey = + pubkey_of_signer(matches, "vote_account_pubkey", wallet_manager)?.unwrap(); + let destination_account_pubkey = + pubkey_of_signer(matches, "destination_account_pubkey", wallet_manager)?.unwrap(); let lamports = lamports_of_sol(matches, "amount").unwrap(); let (withdraw_authority, withdraw_authority_pubkey) = signer_of(matches, "authorized_withdrawer", wallet_manager)?;