add vote withdraw (#5284)
This commit is contained in:
parent
8537da19bb
commit
f4554be72c
|
@ -89,7 +89,7 @@ pub fn redeem_vote_credits(stake_pubkey: &Pubkey, vote_pubkey: &Pubkey) -> Instr
|
||||||
pub fn delegate_stake(stake_pubkey: &Pubkey, vote_pubkey: &Pubkey, stake: u64) -> Instruction {
|
pub fn delegate_stake(stake_pubkey: &Pubkey, vote_pubkey: &Pubkey, stake: u64) -> Instruction {
|
||||||
let account_metas = vec![
|
let account_metas = vec![
|
||||||
AccountMeta::new(*stake_pubkey, true),
|
AccountMeta::new(*stake_pubkey, true),
|
||||||
AccountMeta::new(*vote_pubkey, false),
|
AccountMeta::new_credit_only(*vote_pubkey, false),
|
||||||
AccountMeta::new_credit_only(sysvar::clock::id(), false),
|
AccountMeta::new_credit_only(sysvar::clock::id(), false),
|
||||||
];
|
];
|
||||||
Instruction::new(id(), &StakeInstruction::DelegateStake(stake), account_metas)
|
Instruction::new(id(), &StakeInstruction::DelegateStake(stake), account_metas)
|
||||||
|
@ -98,7 +98,7 @@ pub fn delegate_stake(stake_pubkey: &Pubkey, vote_pubkey: &Pubkey, stake: u64) -
|
||||||
pub fn withdraw(stake_pubkey: &Pubkey, to_pubkey: &Pubkey, lamports: u64) -> Instruction {
|
pub fn withdraw(stake_pubkey: &Pubkey, to_pubkey: &Pubkey, lamports: u64) -> Instruction {
|
||||||
let account_metas = vec![
|
let account_metas = vec![
|
||||||
AccountMeta::new(*stake_pubkey, true),
|
AccountMeta::new(*stake_pubkey, true),
|
||||||
AccountMeta::new(*to_pubkey, false),
|
AccountMeta::new_credit_only(*to_pubkey, false),
|
||||||
AccountMeta::new_credit_only(sysvar::clock::id(), false),
|
AccountMeta::new_credit_only(sysvar::clock::id(), false),
|
||||||
];
|
];
|
||||||
Instruction::new(id(), &StakeInstruction::Withdraw(lamports), account_metas)
|
Instruction::new(id(), &StakeInstruction::Withdraw(lamports), account_metas)
|
||||||
|
|
|
@ -24,6 +24,9 @@ pub enum VoteInstruction {
|
||||||
|
|
||||||
/// A Vote instruction with recent votes
|
/// A Vote instruction with recent votes
|
||||||
Vote(Vec<Vote>),
|
Vote(Vec<Vote>),
|
||||||
|
|
||||||
|
/// Withdraw some amount of funds
|
||||||
|
Withdraw(u64),
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initialize_account(vote_pubkey: &Pubkey, node_pubkey: &Pubkey, commission: u8) -> Instruction {
|
fn initialize_account(vote_pubkey: &Pubkey, node_pubkey: &Pubkey, commission: u8) -> Instruction {
|
||||||
|
@ -71,7 +74,7 @@ fn metas_for_authorized_signer(
|
||||||
|
|
||||||
// append signer at the end
|
// append signer at the end
|
||||||
if !is_own_signer {
|
if !is_own_signer {
|
||||||
account_metas.push(AccountMeta::new(*authorized_voter_pubkey, true)) // signer
|
account_metas.push(AccountMeta::new_credit_only(*authorized_voter_pubkey, true)) // signer
|
||||||
}
|
}
|
||||||
|
|
||||||
account_metas
|
account_metas
|
||||||
|
@ -110,6 +113,15 @@ pub fn vote(
|
||||||
Instruction::new(id(), &VoteInstruction::Vote(recent_votes), account_metas)
|
Instruction::new(id(), &VoteInstruction::Vote(recent_votes), account_metas)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn withdraw(vote_pubkey: &Pubkey, lamports: u64, to_pubkey: &Pubkey) -> Instruction {
|
||||||
|
let account_metas = vec![
|
||||||
|
AccountMeta::new(*vote_pubkey, true),
|
||||||
|
AccountMeta::new_credit_only(*to_pubkey, false),
|
||||||
|
];
|
||||||
|
|
||||||
|
Instruction::new(id(), &VoteInstruction::Withdraw(lamports), account_metas)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn process_instruction(
|
pub fn process_instruction(
|
||||||
_program_id: &Pubkey,
|
_program_id: &Pubkey,
|
||||||
keyed_accounts: &mut [KeyedAccount],
|
keyed_accounts: &mut [KeyedAccount],
|
||||||
|
@ -151,6 +163,12 @@ pub fn process_instruction(
|
||||||
&votes,
|
&votes,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
VoteInstruction::Withdraw(lamports) => {
|
||||||
|
if rest.is_empty() {
|
||||||
|
Err(InstructionError::InvalidInstructionData)?;
|
||||||
|
}
|
||||||
|
vote_state::withdraw(me, lamports, &mut rest[0])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -300,6 +300,23 @@ pub fn authorize_voter(
|
||||||
vote_account.set_state(&vote_state)
|
vote_account.set_state(&vote_state)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Withdraw funds from the vote account
|
||||||
|
pub fn withdraw(
|
||||||
|
vote_account: &mut KeyedAccount,
|
||||||
|
lamports: u64,
|
||||||
|
to_account: &mut KeyedAccount,
|
||||||
|
) -> Result<(), InstructionError> {
|
||||||
|
if vote_account.signer_key().is_none() {
|
||||||
|
return Err(InstructionError::MissingRequiredSignature);
|
||||||
|
}
|
||||||
|
if vote_account.account.lamports < lamports {
|
||||||
|
return Err(InstructionError::InsufficientFunds);
|
||||||
|
}
|
||||||
|
vote_account.account.lamports -= lamports;
|
||||||
|
to_account.account.lamports += lamports;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Initialize the vote_state for a vote account
|
/// Initialize the vote_state for a vote account
|
||||||
/// Assumes that the account is being init as part of a account creation or balance transfer and
|
/// Assumes that the account is being init as part of a account creation or balance transfer and
|
||||||
/// that the transaction must be signed by the staker's keys
|
/// that the transaction must be signed by the staker's keys
|
||||||
|
@ -811,6 +828,39 @@ mod tests {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_vote_state_withdraw() {
|
||||||
|
let (vote_pubkey, mut vote_account) = create_test_account();
|
||||||
|
|
||||||
|
// unsigned
|
||||||
|
let res = withdraw(
|
||||||
|
&mut KeyedAccount::new(&vote_pubkey, false, &mut vote_account),
|
||||||
|
0,
|
||||||
|
&mut KeyedAccount::new(&Pubkey::new_rand(), false, &mut Account::default()),
|
||||||
|
);
|
||||||
|
assert_eq!(res, Err(InstructionError::MissingRequiredSignature));
|
||||||
|
|
||||||
|
// insufficient funds
|
||||||
|
let res = withdraw(
|
||||||
|
&mut KeyedAccount::new(&vote_pubkey, true, &mut vote_account),
|
||||||
|
101,
|
||||||
|
&mut KeyedAccount::new(&Pubkey::new_rand(), false, &mut Account::default()),
|
||||||
|
);
|
||||||
|
assert_eq!(res, Err(InstructionError::InsufficientFunds));
|
||||||
|
|
||||||
|
// all good
|
||||||
|
let mut to_account = Account::default();
|
||||||
|
let lamports = vote_account.lamports;
|
||||||
|
let res = withdraw(
|
||||||
|
&mut KeyedAccount::new(&vote_pubkey, true, &mut vote_account),
|
||||||
|
lamports,
|
||||||
|
&mut KeyedAccount::new(&Pubkey::new_rand(), false, &mut to_account),
|
||||||
|
);
|
||||||
|
assert_eq!(res, Ok(()));
|
||||||
|
assert_eq!(vote_account.lamports, 0);
|
||||||
|
assert_eq!(to_account.lamports, lamports);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_vote_state_epoch_credits() {
|
fn test_vote_state_epoch_credits() {
|
||||||
let mut vote_state = VoteState::default();
|
let mut vote_state = VoteState::default();
|
||||||
|
|
Loading…
Reference in New Issue