CLI: Support offline authorities (#7905) (#7920)

automerge
This commit is contained in:
mergify[bot]
2020-01-22 10:57:16 -08:00
committed by Grimes
parent 8ffd2c12a3
commit e401bc6997
6 changed files with 301 additions and 114 deletions

View File

@@ -3,7 +3,7 @@ use crate::{
build_balance_message, check_account_for_fee, check_unique_pubkeys,
get_blockhash_fee_calculator, log_instruction_custom_error, replace_signatures,
required_lamports_from, return_signers, CliCommand, CliCommandInfo, CliConfig, CliError,
ProcessResult,
ProcessResult, SigningAuthority,
},
nonce::{check_nonce_account, NONCE_ARG, NONCE_AUTHORITY_ARG},
};
@@ -49,7 +49,7 @@ fn stake_authority_arg<'a, 'b>() -> Arg<'a, 'b> {
.long(STAKE_AUTHORITY_ARG.long)
.takes_value(true)
.value_name("KEYPAIR")
.validator(is_keypair_or_ask_keyword)
.validator(is_pubkey_or_keypair_or_ask_keyword)
.help(STAKE_AUTHORITY_ARG.help)
}
@@ -58,7 +58,7 @@ fn withdraw_authority_arg<'a, 'b>() -> Arg<'a, 'b> {
.long(WITHDRAW_AUTHORITY_ARG.long)
.takes_value(true)
.value_name("KEYPAIR")
.validator(is_keypair_or_ask_keyword)
.validator(is_pubkey_or_keypair_or_ask_keyword)
.help(WITHDRAW_AUTHORITY_ARG.help)
}
@@ -508,23 +508,27 @@ pub fn parse_stake_create_account(matches: &ArgMatches<'_>) -> Result<CliCommand
pub fn parse_stake_delegate_stake(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
let stake_account_pubkey = pubkey_of(matches, "stake_account_pubkey").unwrap();
let vote_account_pubkey = pubkey_of(matches, "vote_account_pubkey").unwrap();
let stake_authority = if matches.is_present(STAKE_AUTHORITY_ARG.name) {
let authority = keypair_of(&matches, STAKE_AUTHORITY_ARG.name)
.ok_or_else(|| CliError::BadParameter("Invalid keypair for stake-authority".into()))?;
Some(authority.into())
} else {
None
};
let force = matches.is_present("force");
let sign_only = matches.is_present("sign_only");
let signers = pubkeys_sigs_of(&matches, "signer");
let blockhash = value_of(matches, "blockhash");
let require_keypair = signers.is_none();
let nonce_account = pubkey_of(&matches, NONCE_ARG.name);
let stake_authority = if matches.is_present(STAKE_AUTHORITY_ARG.name) {
Some(SigningAuthority::new_from_matches(
&matches,
STAKE_AUTHORITY_ARG.name,
signers.as_deref(),
)?)
} else {
None
};
let nonce_authority = if matches.is_present(NONCE_AUTHORITY_ARG.name) {
let authority = keypair_of(&matches, NONCE_AUTHORITY_ARG.name)
.ok_or_else(|| CliError::BadParameter("Invalid keypair for nonce-authority".into()))?;
Some(authority.into())
Some(SigningAuthority::new_from_matches(
&matches,
NONCE_AUTHORITY_ARG.name,
signers.as_deref(),
)?)
} else {
None
};
@@ -555,22 +559,25 @@ pub fn parse_stake_authorize(
StakeAuthorize::Staker => STAKE_AUTHORITY_ARG.name,
StakeAuthorize::Withdrawer => WITHDRAW_AUTHORITY_ARG.name,
};
let sign_only = matches.is_present("sign_only");
let signers = pubkeys_sigs_of(&matches, "signer");
let authority = if matches.is_present(authority_flag) {
let authority = keypair_of(&matches, authority_flag).ok_or_else(|| {
CliError::BadParameter(format!("Invalid keypair for {}", authority_flag))
})?;
Some(authority.into())
Some(SigningAuthority::new_from_matches(
&matches,
authority_flag,
signers.as_deref(),
)?)
} else {
None
};
let sign_only = matches.is_present("sign_only");
let signers = pubkeys_sigs_of(&matches, "signer");
let blockhash = value_of(matches, "blockhash");
let nonce_account = pubkey_of(&matches, NONCE_ARG.name);
let nonce_authority = if matches.is_present(NONCE_AUTHORITY_ARG.name) {
let authority = keypair_of(&matches, NONCE_AUTHORITY_ARG.name)
.ok_or_else(|| CliError::BadParameter("Invalid keypair for nonce-authority".into()))?;
Some(authority.into())
Some(SigningAuthority::new_from_matches(
&matches,
NONCE_AUTHORITY_ARG.name,
signers.as_deref(),
)?)
} else {
None
};
@@ -603,22 +610,26 @@ pub fn parse_redeem_vote_credits(matches: &ArgMatches<'_>) -> Result<CliCommandI
pub fn parse_stake_deactivate_stake(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
let stake_account_pubkey = pubkey_of(matches, "stake_account_pubkey").unwrap();
let stake_authority = if matches.is_present(STAKE_AUTHORITY_ARG.name) {
let authority = keypair_of(&matches, STAKE_AUTHORITY_ARG.name)
.ok_or_else(|| CliError::BadParameter("Invalid keypair for stake-authority".into()))?;
Some(authority.into())
} else {
None
};
let sign_only = matches.is_present("sign_only");
let signers = pubkeys_sigs_of(&matches, "signer");
let blockhash = value_of(matches, "blockhash");
let require_keypair = signers.is_none();
let nonce_account = pubkey_of(&matches, NONCE_ARG.name);
let stake_authority = if matches.is_present(STAKE_AUTHORITY_ARG.name) {
Some(SigningAuthority::new_from_matches(
&matches,
STAKE_AUTHORITY_ARG.name,
signers.as_deref(),
)?)
} else {
None
};
let nonce_authority = if matches.is_present(NONCE_AUTHORITY_ARG.name) {
let authority = keypair_of(&matches, NONCE_AUTHORITY_ARG.name)
.ok_or_else(|| CliError::BadParameter("Invalid keypair for nonce-authority".into()))?;
Some(authority.into())
Some(SigningAuthority::new_from_matches(
&matches,
NONCE_AUTHORITY_ARG.name,
signers.as_deref(),
)?)
} else {
None
};
@@ -642,10 +653,11 @@ pub fn parse_stake_withdraw_stake(matches: &ArgMatches<'_>) -> Result<CliCommand
let destination_account_pubkey = pubkey_of(matches, "destination_account_pubkey").unwrap();
let lamports = required_lamports_from(matches, "amount", "unit")?;
let withdraw_authority = if matches.is_present(WITHDRAW_AUTHORITY_ARG.name) {
let authority = keypair_of(&matches, WITHDRAW_AUTHORITY_ARG.name).ok_or_else(|| {
CliError::BadParameter("Invalid keypair for withdraw-authority".into())
})?;
Some(authority.into())
Some(SigningAuthority::new_from_matches(
&matches,
WITHDRAW_AUTHORITY_ARG.name,
None,
)?)
} else {
None
};
@@ -756,18 +768,18 @@ pub fn process_stake_authorize(
stake_account_pubkey: &Pubkey,
authorized_pubkey: &Pubkey,
stake_authorize: StakeAuthorize,
authority: Option<&Keypair>,
authority: Option<&SigningAuthority>,
sign_only: bool,
signers: &Option<Vec<(Pubkey, Signature)>>,
blockhash: Option<Hash>,
nonce_account: Option<Pubkey>,
nonce_authority: Option<&Keypair>,
nonce_authority: Option<&SigningAuthority>,
) -> ProcessResult {
check_unique_pubkeys(
(stake_account_pubkey, "stake_account_pubkey".to_string()),
(authorized_pubkey, "new_authorized_pubkey".to_string()),
)?;
let authority = authority.unwrap_or(&config.keypair);
let authority = authority.map(|a| a.keypair()).unwrap_or(&config.keypair);
let (recent_blockhash, fee_calculator) =
get_blockhash_fee_calculator(rpc_client, sign_only, blockhash)?;
let ixs = vec![stake_instruction::authorize(
@@ -777,12 +789,14 @@ pub fn process_stake_authorize(
stake_authorize, // stake or withdraw
)];
let (nonce_authority, nonce_authority_pubkey) = nonce_authority
.map(|a| (a.keypair(), a.pubkey()))
.unwrap_or((&config.keypair, config.keypair.pubkey()));
let mut tx = if let Some(nonce_account) = &nonce_account {
let nonce_authority: &Keypair = nonce_authority.unwrap_or(&config.keypair);
Transaction::new_signed_with_nonce(
ixs,
Some(&config.keypair.pubkey()),
&[&config.keypair, authority, nonce_authority],
&[&config.keypair, nonce_authority, authority],
nonce_account,
&nonce_authority.pubkey(),
recent_blockhash,
@@ -802,9 +816,8 @@ pub fn process_stake_authorize(
return_signers(&tx)
} else {
if let Some(nonce_account) = &nonce_account {
let nonce_authority: &Keypair = nonce_authority.unwrap_or(&config.keypair);
let nonce_account = rpc_client.get_account(nonce_account)?;
check_nonce_account(&nonce_account, &nonce_authority.pubkey(), &recent_blockhash)?;
check_nonce_account(&nonce_account, &nonce_authority_pubkey, &recent_blockhash)?;
}
check_account_for_fee(
rpc_client,
@@ -821,22 +834,26 @@ pub fn process_deactivate_stake_account(
rpc_client: &RpcClient,
config: &CliConfig,
stake_account_pubkey: &Pubkey,
stake_authority: Option<&Keypair>,
stake_authority: Option<&SigningAuthority>,
sign_only: bool,
signers: &Option<Vec<(Pubkey, Signature)>>,
blockhash: Option<Hash>,
nonce_account: Option<Pubkey>,
nonce_authority: Option<&Keypair>,
nonce_authority: Option<&SigningAuthority>,
) -> ProcessResult {
let (recent_blockhash, fee_calculator) =
get_blockhash_fee_calculator(rpc_client, sign_only, blockhash)?;
let stake_authority = stake_authority.unwrap_or(&config.keypair);
let stake_authority = stake_authority
.map(|a| a.keypair())
.unwrap_or(&config.keypair);
let ixs = vec![stake_instruction::deactivate_stake(
stake_account_pubkey,
&stake_authority.pubkey(),
)];
let (nonce_authority, nonce_authority_pubkey) = nonce_authority
.map(|a| (a.keypair(), a.pubkey()))
.unwrap_or((&config.keypair, config.keypair.pubkey()));
let mut tx = if let Some(nonce_account) = &nonce_account {
let nonce_authority: &Keypair = nonce_authority.unwrap_or(&config.keypair);
Transaction::new_signed_with_nonce(
ixs,
Some(&config.keypair.pubkey()),
@@ -860,9 +877,8 @@ pub fn process_deactivate_stake_account(
return_signers(&tx)
} else {
if let Some(nonce_account) = &nonce_account {
let nonce_authority: &Keypair = nonce_authority.unwrap_or(&config.keypair);
let nonce_account = rpc_client.get_account(nonce_account)?;
check_nonce_account(&nonce_account, &nonce_authority.pubkey(), &recent_blockhash)?;
check_nonce_account(&nonce_account, &nonce_authority_pubkey, &recent_blockhash)?;
}
check_account_for_fee(
rpc_client,
@@ -881,10 +897,12 @@ pub fn process_withdraw_stake(
stake_account_pubkey: &Pubkey,
destination_account_pubkey: &Pubkey,
lamports: u64,
withdraw_authority: Option<&Keypair>,
withdraw_authority: Option<&SigningAuthority>,
) -> ProcessResult {
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let withdraw_authority = withdraw_authority.unwrap_or(&config.keypair);
let withdraw_authority = withdraw_authority
.map(|a| a.keypair())
.unwrap_or(&config.keypair);
let ixs = vec![stake_instruction::withdraw(
stake_account_pubkey,
@@ -1052,19 +1070,21 @@ pub fn process_delegate_stake(
config: &CliConfig,
stake_account_pubkey: &Pubkey,
vote_account_pubkey: &Pubkey,
stake_authority: Option<&Keypair>,
stake_authority: Option<&SigningAuthority>,
force: bool,
sign_only: bool,
signers: &Option<Vec<(Pubkey, Signature)>>,
blockhash: Option<Hash>,
nonce_account: Option<Pubkey>,
nonce_authority: Option<&Keypair>,
nonce_authority: Option<&SigningAuthority>,
) -> ProcessResult {
check_unique_pubkeys(
(&config.keypair.pubkey(), "cli keypair".to_string()),
(stake_account_pubkey, "stake_account_pubkey".to_string()),
)?;
let stake_authority = stake_authority.unwrap_or(&config.keypair);
let stake_authority = stake_authority
.map(|a| a.keypair())
.unwrap_or(&config.keypair);
// Sanity check the vote account to ensure it is attached to a validator that has recently
// voted at the tip of the ledger
@@ -1114,8 +1134,10 @@ pub fn process_delegate_stake(
&stake_authority.pubkey(),
vote_account_pubkey,
)];
let (nonce_authority, nonce_authority_pubkey) = nonce_authority
.map(|a| (a.keypair(), a.pubkey()))
.unwrap_or((&config.keypair, config.keypair.pubkey()));
let mut tx = if let Some(nonce_account) = &nonce_account {
let nonce_authority: &Keypair = nonce_authority.unwrap_or(&config.keypair);
Transaction::new_signed_with_nonce(
ixs,
Some(&config.keypair.pubkey()),
@@ -1139,9 +1161,8 @@ pub fn process_delegate_stake(
return_signers(&tx)
} else {
if let Some(nonce_account) = &nonce_account {
let nonce_authority: &Keypair = nonce_authority.unwrap_or(&config.keypair);
let nonce_account = rpc_client.get_account(nonce_account)?;
check_nonce_account(&nonce_account, &nonce_authority.pubkey(), &recent_blockhash)?;
check_nonce_account(&nonce_account, &nonce_authority_pubkey, &recent_blockhash)?;
}
check_account_for_fee(
rpc_client,