Add --seed support to delegate-stake and withdraw-stake commands (#16717)

(cherry picked from commit ba9a502e7e)

Co-authored-by: Michael Vines <mvines@gmail.com>
This commit is contained in:
mergify[bot]
2021-04-21 21:49:39 +00:00
committed by GitHub
parent ae605f8f02
commit a2395e8730
3 changed files with 73 additions and 9 deletions

View File

@ -214,6 +214,7 @@ pub enum CliCommand {
nonce_account: Option<Pubkey>, nonce_account: Option<Pubkey>,
nonce_authority: SignerIndex, nonce_authority: SignerIndex,
memo: Option<String>, memo: Option<String>,
seed: Option<String>,
fee_payer: SignerIndex, fee_payer: SignerIndex,
}, },
DelegateStake { DelegateStake {
@ -300,6 +301,7 @@ pub enum CliCommand {
nonce_account: Option<Pubkey>, nonce_account: Option<Pubkey>,
nonce_authority: SignerIndex, nonce_authority: SignerIndex,
memo: Option<String>, memo: Option<String>,
seed: Option<String>,
fee_payer: SignerIndex, fee_payer: SignerIndex,
}, },
// Validator Info Commands // Validator Info Commands
@ -1556,6 +1558,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
nonce_account, nonce_account,
nonce_authority, nonce_authority,
memo, memo,
seed,
fee_payer, fee_payer,
} => process_deactivate_stake_account( } => process_deactivate_stake_account(
&rpc_client, &rpc_client,
@ -1568,6 +1571,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
*nonce_account, *nonce_account,
*nonce_authority, *nonce_authority,
memo.as_ref(), memo.as_ref(),
seed.as_ref(),
*fee_payer, *fee_payer,
), ),
CliCommand::DelegateStake { CliCommand::DelegateStake {
@ -1728,6 +1732,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
ref nonce_account, ref nonce_account,
nonce_authority, nonce_authority,
memo, memo,
seed,
fee_payer, fee_payer,
} => process_withdraw_stake( } => process_withdraw_stake(
&rpc_client, &rpc_client,
@ -1743,6 +1748,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
nonce_account.as_ref(), nonce_account.as_ref(),
*nonce_authority, *nonce_authority,
memo.as_ref(), memo.as_ref(),
seed.as_ref(),
*fee_payer, *fee_payer,
), ),
@ -2709,6 +2715,7 @@ mod tests {
nonce_account: None, nonce_account: None,
nonce_authority: 0, nonce_authority: 0,
memo: None, memo: None,
seed: None,
fee_payer: 0, fee_payer: 0,
}; };
config.signers = vec![&keypair]; config.signers = vec![&keypair];
@ -2725,6 +2732,7 @@ mod tests {
nonce_account: None, nonce_account: None,
nonce_authority: 0, nonce_authority: 0,
memo: None, memo: None,
seed: None,
fee_payer: 0, fee_payer: 0,
}; };
let result = process_command(&config); let result = process_command(&config);

View File

@ -8,7 +8,7 @@ use crate::{
nonce::check_nonce_account, nonce::check_nonce_account,
spend_utils::{resolve_spend_tx_and_check_account_balances, SpendAmount}, spend_utils::{resolve_spend_tx_and_check_account_balances, SpendAmount},
}; };
use clap::{App, Arg, ArgGroup, ArgMatches, SubCommand}; use clap::{value_t, App, Arg, ArgGroup, ArgMatches, SubCommand};
use solana_clap_utils::{ use solana_clap_utils::{
fee_payer::{fee_payer_arg, FEE_PAYER_ARG}, fee_payer::{fee_payer_arg, FEE_PAYER_ARG},
input_parsers::*, input_parsers::*,
@ -107,7 +107,7 @@ impl StakeSubCommands for App<'_, '_> {
.arg( .arg(
Arg::with_name("stake_account") Arg::with_name("stake_account")
.index(1) .index(1)
.value_name("ACCOUNT_KEYPAIR") .value_name("STAKE_ACCOUNT_KEYPAIR")
.takes_value(true) .takes_value(true)
.required(true) .required(true)
.validator(is_valid_signer) .validator(is_valid_signer)
@ -133,7 +133,8 @@ impl StakeSubCommands for App<'_, '_> {
.long("seed") .long("seed")
.value_name("STRING") .value_name("STRING")
.takes_value(true) .takes_value(true)
.help("Seed for address generation; if specified, the resulting account will be at a derived address of the stake_account pubkey") .help("Seed for address generation; if specified, the resulting account \
will be at a derived address of the STAKE_ACCOUNT_KEYPAIR pubkey")
) )
.arg( .arg(
Arg::with_name("lockup_epoch") Arg::with_name("lockup_epoch")
@ -246,7 +247,15 @@ impl StakeSubCommands for App<'_, '_> {
.index(1) .index(1)
.value_name("STAKE_ACCOUNT_ADDRESS") .value_name("STAKE_ACCOUNT_ADDRESS")
.required(true), .required(true),
"Stake account to be deactivated. ") "Stake account to be deactivated (or base of derived address if --seed is used). ")
)
.arg(
Arg::with_name("seed")
.long("seed")
.value_name("STRING")
.takes_value(true)
.help("Seed for address generation; if specified, the resulting account \
will be at a derived address of STAKE_ACCOUNT_ADDRESS")
) )
.arg(stake_authority_arg()) .arg(stake_authority_arg())
.offline_args() .offline_args()
@ -286,7 +295,8 @@ impl StakeSubCommands for App<'_, '_> {
.long("seed") .long("seed")
.value_name("STRING") .value_name("STRING")
.takes_value(true) .takes_value(true)
.help("Seed for address generation; if specified, the resulting account will be at a derived address of the SPLIT_STAKE_ACCOUNT pubkey") .help("Seed for address generation; if specified, the resulting account \
will be at a derived address of SPLIT_STAKE_ACCOUNT")
) )
.arg(stake_authority_arg()) .arg(stake_authority_arg())
.offline_args() .offline_args()
@ -308,7 +318,8 @@ impl StakeSubCommands for App<'_, '_> {
.index(2) .index(2)
.value_name("SOURCE_STAKE_ACCOUNT_ADDRESS") .value_name("SOURCE_STAKE_ACCOUNT_ADDRESS")
.required(true), .required(true),
"Source stake account for the merge. If successful, this stake account will no longer exist after the merge") "Source stake account for the merge. If successful, this stake account \
will no longer exist after the merge")
) )
.arg(stake_authority_arg()) .arg(stake_authority_arg())
.offline_args() .offline_args()
@ -323,7 +334,7 @@ impl StakeSubCommands for App<'_, '_> {
.index(1) .index(1)
.value_name("STAKE_ACCOUNT_ADDRESS") .value_name("STAKE_ACCOUNT_ADDRESS")
.required(true), .required(true),
"Stake account from which to withdraw") "Stake account from which to withdraw (or base of derived address if --seed is used). ")
) )
.arg( .arg(
pubkey!(Arg::with_name("destination_account_pubkey") pubkey!(Arg::with_name("destination_account_pubkey")
@ -341,6 +352,14 @@ impl StakeSubCommands for App<'_, '_> {
.required(true) .required(true)
.help("The amount to withdraw from the stake account, in SOL") .help("The amount to withdraw from the stake account, in SOL")
) )
.arg(
Arg::with_name("seed")
.long("seed")
.value_name("STRING")
.takes_value(true)
.help("Seed for address generation; if specified, the resulting account \
will be at a derived address of STAKE_ACCOUNT_ADDRESS")
)
.arg(withdraw_authority_arg()) .arg(withdraw_authority_arg())
.offline_args() .offline_args()
.nonce_args(false) .nonce_args(false)
@ -755,6 +774,7 @@ pub fn parse_stake_deactivate_stake(
let blockhash_query = BlockhashQuery::new_from_matches(matches); let blockhash_query = BlockhashQuery::new_from_matches(matches);
let nonce_account = pubkey_of(matches, NONCE_ARG.name); let nonce_account = pubkey_of(matches, NONCE_ARG.name);
let memo = matches.value_of(MEMO_ARG.name).map(String::from); let memo = matches.value_of(MEMO_ARG.name).map(String::from);
let seed = value_t!(matches, "seed", String).ok();
let (stake_authority, stake_authority_pubkey) = let (stake_authority, stake_authority_pubkey) =
signer_of(matches, STAKE_AUTHORITY_ARG.name, wallet_manager)?; signer_of(matches, STAKE_AUTHORITY_ARG.name, wallet_manager)?;
let (nonce_authority, nonce_authority_pubkey) = let (nonce_authority, nonce_authority_pubkey) =
@ -778,6 +798,7 @@ pub fn parse_stake_deactivate_stake(
nonce_account, nonce_account,
nonce_authority: signer_info.index_of(nonce_authority_pubkey).unwrap(), nonce_authority: signer_info.index_of(nonce_authority_pubkey).unwrap(),
memo, memo,
seed,
fee_payer: signer_info.index_of(fee_payer_pubkey).unwrap(), fee_payer: signer_info.index_of(fee_payer_pubkey).unwrap(),
}, },
signers: signer_info.signers, signers: signer_info.signers,
@ -799,6 +820,7 @@ pub fn parse_stake_withdraw_stake(
let blockhash_query = BlockhashQuery::new_from_matches(matches); let blockhash_query = BlockhashQuery::new_from_matches(matches);
let nonce_account = pubkey_of(matches, NONCE_ARG.name); let nonce_account = pubkey_of(matches, NONCE_ARG.name);
let memo = matches.value_of(MEMO_ARG.name).map(String::from); let memo = matches.value_of(MEMO_ARG.name).map(String::from);
let seed = value_t!(matches, "seed", String).ok();
let (withdraw_authority, withdraw_authority_pubkey) = let (withdraw_authority, withdraw_authority_pubkey) =
signer_of(matches, WITHDRAW_AUTHORITY_ARG.name, wallet_manager)?; signer_of(matches, WITHDRAW_AUTHORITY_ARG.name, wallet_manager)?;
let (nonce_authority, nonce_authority_pubkey) = let (nonce_authority, nonce_authority_pubkey) =
@ -828,6 +850,7 @@ pub fn parse_stake_withdraw_stake(
nonce_account, nonce_account,
nonce_authority: signer_info.index_of(nonce_authority_pubkey).unwrap(), nonce_authority: signer_info.index_of(nonce_authority_pubkey).unwrap(),
memo, memo,
seed,
fee_payer: signer_info.index_of(fee_payer_pubkey).unwrap(), fee_payer: signer_info.index_of(fee_payer_pubkey).unwrap(),
custodian: custodian_pubkey.and_then(|_| signer_info.index_of(custodian_pubkey)), custodian: custodian_pubkey.and_then(|_| signer_info.index_of(custodian_pubkey)),
}, },
@ -1151,13 +1174,21 @@ pub fn process_deactivate_stake_account(
nonce_account: Option<Pubkey>, nonce_account: Option<Pubkey>,
nonce_authority: SignerIndex, nonce_authority: SignerIndex,
memo: Option<&String>, memo: Option<&String>,
seed: Option<&String>,
fee_payer: SignerIndex, fee_payer: SignerIndex,
) -> ProcessResult { ) -> ProcessResult {
let (recent_blockhash, fee_calculator) = let (recent_blockhash, fee_calculator) =
blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?; blockhash_query.get_blockhash_and_fee_calculator(rpc_client, config.commitment)?;
let stake_authority = config.signers[stake_authority]; let stake_authority = config.signers[stake_authority];
let stake_account_address = if let Some(seed) = seed {
Pubkey::create_with_seed(&stake_account_pubkey, seed, &solana_stake_program::id())?
} else {
*stake_account_pubkey
};
let ixs = vec![stake_instruction::deactivate_stake( let ixs = vec![stake_instruction::deactivate_stake(
stake_account_pubkey, &stake_account_address,
&stake_authority.pubkey(), &stake_authority.pubkey(),
)] )]
.with_memo(memo); .with_memo(memo);
@ -1222,6 +1253,7 @@ pub fn process_withdraw_stake(
nonce_account: Option<&Pubkey>, nonce_account: Option<&Pubkey>,
nonce_authority: SignerIndex, nonce_authority: SignerIndex,
memo: Option<&String>, memo: Option<&String>,
seed: Option<&String>,
fee_payer: SignerIndex, fee_payer: SignerIndex,
) -> ProcessResult { ) -> ProcessResult {
let (recent_blockhash, fee_calculator) = let (recent_blockhash, fee_calculator) =
@ -1229,8 +1261,14 @@ pub fn process_withdraw_stake(
let withdraw_authority = config.signers[withdraw_authority]; let withdraw_authority = config.signers[withdraw_authority];
let custodian = custodian.map(|index| config.signers[index]); let custodian = custodian.map(|index| config.signers[index]);
let stake_account_address = if let Some(seed) = seed {
Pubkey::create_with_seed(&stake_account_pubkey, seed, &solana_stake_program::id())?
} else {
*stake_account_pubkey
};
let ixs = vec![stake_instruction::withdraw( let ixs = vec![stake_instruction::withdraw(
stake_account_pubkey, &stake_account_address,
&withdraw_authority.pubkey(), &withdraw_authority.pubkey(),
destination_account_pubkey, destination_account_pubkey,
lamports, lamports,
@ -3067,6 +3105,7 @@ mod tests {
nonce_account: None, nonce_account: None,
nonce_authority: 0, nonce_authority: 0,
memo: None, memo: None,
seed: None,
fee_payer: 0, fee_payer: 0,
}, },
signers: vec![read_keypair_file(&default_keypair_file).unwrap().into()], signers: vec![read_keypair_file(&default_keypair_file).unwrap().into()],
@ -3099,6 +3138,7 @@ mod tests {
nonce_account: None, nonce_account: None,
nonce_authority: 0, nonce_authority: 0,
memo: None, memo: None,
seed: None,
fee_payer: 0, fee_payer: 0,
}, },
signers: vec![ signers: vec![
@ -3136,6 +3176,7 @@ mod tests {
nonce_account: None, nonce_account: None,
nonce_authority: 0, nonce_authority: 0,
memo: None, memo: None,
seed: None,
fee_payer: 0, fee_payer: 0,
}, },
signers: vec![ signers: vec![
@ -3184,6 +3225,7 @@ mod tests {
nonce_account: Some(nonce_account), nonce_account: Some(nonce_account),
nonce_authority: 1, nonce_authority: 1,
memo: None, memo: None,
seed: None,
fee_payer: 1, fee_payer: 1,
}, },
signers: vec![ signers: vec![
@ -3213,6 +3255,7 @@ mod tests {
nonce_account: None, nonce_account: None,
nonce_authority: 0, nonce_authority: 0,
memo: None, memo: None,
seed: None,
fee_payer: 0, fee_payer: 0,
}, },
signers: vec![read_keypair_file(&default_keypair_file).unwrap().into()], signers: vec![read_keypair_file(&default_keypair_file).unwrap().into()],
@ -3239,6 +3282,7 @@ mod tests {
nonce_account: None, nonce_account: None,
nonce_authority: 0, nonce_authority: 0,
memo: None, memo: None,
seed: None,
fee_payer: 0, fee_payer: 0,
}, },
signers: vec![ signers: vec![
@ -3275,6 +3319,7 @@ mod tests {
nonce_account: None, nonce_account: None,
nonce_authority: 0, nonce_authority: 0,
memo: None, memo: None,
seed: None,
fee_payer: 0, fee_payer: 0,
}, },
signers: vec![read_keypair_file(&default_keypair_file).unwrap().into()], signers: vec![read_keypair_file(&default_keypair_file).unwrap().into()],
@ -3301,6 +3346,7 @@ mod tests {
nonce_account: None, nonce_account: None,
nonce_authority: 0, nonce_authority: 0,
memo: None, memo: None,
seed: None,
fee_payer: 0, fee_payer: 0,
}, },
signers: vec![read_keypair_file(&default_keypair_file).unwrap().into()], signers: vec![read_keypair_file(&default_keypair_file).unwrap().into()],
@ -3337,6 +3383,7 @@ mod tests {
nonce_account: None, nonce_account: None,
nonce_authority: 0, nonce_authority: 0,
memo: None, memo: None,
seed: None,
fee_payer: 1, fee_payer: 1,
}, },
signers: vec![ signers: vec![
@ -3382,6 +3429,7 @@ mod tests {
nonce_account: Some(nonce_account), nonce_account: Some(nonce_account),
nonce_authority: 2, nonce_authority: 2,
memo: None, memo: None,
seed: None,
fee_payer: 1, fee_payer: 1,
}, },
signers: vec![ signers: vec![
@ -3412,6 +3460,7 @@ mod tests {
nonce_account: None, nonce_account: None,
nonce_authority: 0, nonce_authority: 0,
memo: None, memo: None,
seed: None,
fee_payer: 1, fee_payer: 1,
}, },
signers: vec![ signers: vec![

View File

@ -189,6 +189,7 @@ fn test_seed_stake_delegation_and_deactivation() {
nonce_account: None, nonce_account: None,
nonce_authority: 0, nonce_authority: 0,
memo: None, memo: None,
seed: None,
fee_payer: 0, fee_payer: 0,
}; };
process_command(&config_validator).unwrap(); process_command(&config_validator).unwrap();
@ -269,6 +270,7 @@ fn test_stake_delegation_and_deactivation() {
nonce_account: None, nonce_account: None,
nonce_authority: 0, nonce_authority: 0,
memo: None, memo: None,
seed: None,
fee_payer: 0, fee_payer: 0,
}; };
process_command(&config_validator).unwrap(); process_command(&config_validator).unwrap();
@ -391,6 +393,7 @@ fn test_offline_stake_delegation_and_deactivation() {
nonce_account: None, nonce_account: None,
nonce_authority: 0, nonce_authority: 0,
memo: None, memo: None,
seed: None,
fee_payer: 0, fee_payer: 0,
}; };
let sig_response = process_command(&config_offline).unwrap(); let sig_response = process_command(&config_offline).unwrap();
@ -409,6 +412,7 @@ fn test_offline_stake_delegation_and_deactivation() {
nonce_account: None, nonce_account: None,
nonce_authority: 0, nonce_authority: 0,
memo: None, memo: None,
seed: None,
fee_payer: 0, fee_payer: 0,
}; };
process_command(&config_payer).unwrap(); process_command(&config_payer).unwrap();
@ -524,6 +528,7 @@ fn test_nonced_stake_delegation_and_deactivation() {
nonce_account: Some(nonce_account.pubkey()), nonce_account: Some(nonce_account.pubkey()),
nonce_authority: 0, nonce_authority: 0,
memo: None, memo: None,
seed: None,
fee_payer: 0, fee_payer: 0,
}; };
process_command(&config).unwrap(); process_command(&config).unwrap();
@ -1459,6 +1464,7 @@ fn test_offline_nonced_create_stake_account_and_withdraw() {
nonce_account: Some(nonce_pubkey), nonce_account: Some(nonce_pubkey),
nonce_authority: 0, nonce_authority: 0,
memo: None, memo: None,
seed: None,
fee_payer: 0, fee_payer: 0,
}; };
let sig_response = process_command(&config_offline).unwrap(); let sig_response = process_command(&config_offline).unwrap();
@ -1480,6 +1486,7 @@ fn test_offline_nonced_create_stake_account_and_withdraw() {
nonce_account: Some(nonce_pubkey), nonce_account: Some(nonce_pubkey),
nonce_authority: 0, nonce_authority: 0,
memo: None, memo: None,
seed: None,
fee_payer: 0, fee_payer: 0,
}; };
process_command(&config).unwrap(); process_command(&config).unwrap();