Restore ALL behavior; add enum variant, comments, and help text to make behavior clearer (#21854)

This commit is contained in:
Tyera Eulberg 2021-12-13 19:00:29 -07:00 committed by GitHub
parent a8ba979360
commit bed1b143a5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 3 deletions

View File

@ -16,6 +16,7 @@ use {
pub enum SpendAmount {
All,
Some(u64),
RentExempt,
}
impl Default for SpendAmount {
@ -90,6 +91,7 @@ where
0,
from_pubkey,
fee_pubkey,
0,
build_message,
)?;
Ok((message, spend))
@ -97,6 +99,12 @@ where
let from_balance = rpc_client
.get_balance_with_commitment(from_pubkey, commitment)?
.value;
let from_rent_exempt_minimum = if amount == SpendAmount::RentExempt {
let data = rpc_client.get_account_data(from_pubkey)?;
rpc_client.get_minimum_balance_for_rent_exemption(data.len())?
} else {
0
};
let (message, SpendAndFee { spend, fee }) = resolve_spend_message(
rpc_client,
amount,
@ -104,6 +112,7 @@ where
from_balance,
from_pubkey,
fee_pubkey,
from_rent_exempt_minimum,
build_message,
)?;
if from_pubkey == fee_pubkey {
@ -140,6 +149,7 @@ fn resolve_spend_message<F>(
from_balance: u64,
from_pubkey: &Pubkey,
fee_pubkey: &Pubkey,
from_rent_exempt_minimum: u64,
build_message: F,
) -> Result<(Message, SpendAndFee), CliError>
where
@ -176,5 +186,20 @@ where
},
))
}
SpendAmount::RentExempt => {
let mut lamports = if from_pubkey == fee_pubkey {
from_balance.saturating_sub(fee)
} else {
from_balance
};
lamports = lamports.saturating_sub(from_rent_exempt_minimum);
Ok((
build_message(lamports),
SpendAndFee {
spend: lamports,
fee,
},
))
}
}
}

View File

@ -359,7 +359,7 @@ impl VoteSubCommands for App<'_, '_> {
.takes_value(true)
.required(true)
.validator(is_amount_or_all)
.help("The amount to withdraw, in SOL; accepts keyword ALL"),
.help("The amount to withdraw, in SOL; accepts keyword ALL, which for this command means account balance minus rent-exempt minimum"),
)
.arg(
Arg::with_name("authorized_withdrawer")
@ -653,7 +653,13 @@ pub fn parse_withdraw_from_vote_account(
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 withdraw_amount = SpendAmount::new_from_matches(matches, "amount");
let mut withdraw_amount = SpendAmount::new_from_matches(matches, "amount");
// As a safeguard for vote accounts for running validators, `ALL` withdraws only the amount in
// excess of the rent-exempt minimum. In order to close the account with this subcommand, a
// validator must specify the withdrawal amount precisely.
if withdraw_amount == SpendAmount::All {
withdraw_amount = SpendAmount::RentExempt;
}
let (withdraw_authority, withdraw_authority_pubkey) =
signer_of(matches, "authorized_withdrawer", wallet_manager)?;
@ -1990,7 +1996,7 @@ mod tests {
vote_account_pubkey: read_keypair_file(&keypair_file).unwrap().pubkey(),
destination_account_pubkey: pubkey,
withdraw_authority: 0,
withdraw_amount: SpendAmount::All,
withdraw_amount: SpendAmount::RentExempt,
sign_only: false,
dump_transaction_message: false,
blockhash_query: BlockhashQuery::All(blockhash_query::Source::Cluster),