Add instructions and processor for stake deactivation (#4781)
automerge
This commit is contained in:
committed by
Michael Vines
parent
2ec73db6bd
commit
36eda29fc9
@ -42,6 +42,13 @@ pub enum StakeInstruction {
|
||||
/// The u64 is the portion of the Stake account balance to be withdrawn,
|
||||
/// must be <= StakeAccount.lamports - staked lamports
|
||||
Withdraw(u64),
|
||||
|
||||
/// Deactivates the stake in the account
|
||||
///
|
||||
/// Expects 2 Accounts:
|
||||
/// 0 - Delegate StakeAccount
|
||||
/// 1 - Syscall Account that carries epoch
|
||||
Deactivate,
|
||||
}
|
||||
|
||||
pub fn create_stake_account(
|
||||
@ -97,6 +104,14 @@ pub fn withdraw(stake_pubkey: &Pubkey, to_pubkey: &Pubkey, lamports: u64) -> Ins
|
||||
Instruction::new(id(), &StakeInstruction::Withdraw(lamports), account_metas)
|
||||
}
|
||||
|
||||
pub fn deactivate_stake(stake_pubkey: &Pubkey) -> Instruction {
|
||||
let account_metas = vec![
|
||||
AccountMeta::new(*stake_pubkey, true),
|
||||
AccountMeta::new(syscall::current::id(), false),
|
||||
];
|
||||
Instruction::new(id(), &StakeInstruction::Deactivate, account_metas)
|
||||
}
|
||||
|
||||
pub fn process_instruction(
|
||||
_program_id: &Pubkey,
|
||||
keyed_accounts: &mut [KeyedAccount],
|
||||
@ -156,6 +171,14 @@ pub fn process_instruction(
|
||||
&syscall::current::from_keyed_account(&syscall[0])?,
|
||||
)
|
||||
}
|
||||
StakeInstruction::Deactivate => {
|
||||
if rest.len() != 1 {
|
||||
Err(InstructionError::InvalidInstructionData)?;
|
||||
}
|
||||
let syscall = &rest[0];
|
||||
|
||||
me.deactivate_stake(&syscall::current::from_keyed_account(&syscall)?)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,6 +228,10 @@ mod tests {
|
||||
process_instruction(&withdraw(&Pubkey::default(), &Pubkey::new_rand(), 100)),
|
||||
Err(InstructionError::InvalidAccountData),
|
||||
);
|
||||
assert_eq!(
|
||||
process_instruction(&deactivate_stake(&Pubkey::default())),
|
||||
Err(InstructionError::InvalidAccountData),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -322,6 +349,41 @@ mod tests {
|
||||
),
|
||||
Err(InstructionError::InvalidInstructionData),
|
||||
);
|
||||
|
||||
// Tests 2nd keyed account is of correct type (Current instead of rewards) in deactivate
|
||||
assert_eq!(
|
||||
super::process_instruction(
|
||||
&Pubkey::default(),
|
||||
&mut [
|
||||
KeyedAccount::new(&Pubkey::default(), false, &mut Account::default()),
|
||||
KeyedAccount::new(
|
||||
&syscall::rewards::id(),
|
||||
false,
|
||||
&mut syscall::rewards::create_account(1, 0.0, 0.0)
|
||||
),
|
||||
],
|
||||
&serialize(&StakeInstruction::Deactivate).unwrap(),
|
||||
),
|
||||
Err(InstructionError::InvalidArgument),
|
||||
);
|
||||
|
||||
// Tests correct number of accounts are provided in deactivate
|
||||
assert_eq!(
|
||||
super::process_instruction(
|
||||
&Pubkey::default(),
|
||||
&mut [
|
||||
KeyedAccount::new(&Pubkey::default(), false, &mut Account::default()),
|
||||
KeyedAccount::new(&Pubkey::default(), false, &mut Account::default()),
|
||||
KeyedAccount::new(
|
||||
&syscall::current::id(),
|
||||
false,
|
||||
&mut syscall::rewards::create_account(1, 0.0, 0.0)
|
||||
),
|
||||
],
|
||||
&serialize(&StakeInstruction::Deactivate).unwrap(),
|
||||
),
|
||||
Err(InstructionError::InvalidInstructionData),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -464,6 +464,44 @@ mod tests {
|
||||
assert_eq!(stake.stake(STAKE_WARMUP_EPOCHS * 42), 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_deactivate_stake() {
|
||||
let stake_pubkey = Pubkey::new_rand();
|
||||
let stake_lamports = 42;
|
||||
let mut stake_account =
|
||||
Account::new(stake_lamports, std::mem::size_of::<StakeState>(), &id());
|
||||
|
||||
let current = syscall::current::Current::default();
|
||||
|
||||
// unsigned keyed account
|
||||
let mut stake_keyed_account = KeyedAccount::new(&stake_pubkey, false, &mut stake_account);
|
||||
assert_eq!(
|
||||
stake_keyed_account.deactivate_stake(¤t),
|
||||
Err(InstructionError::MissingRequiredSignature)
|
||||
);
|
||||
|
||||
// signed keyed account but not staked yet
|
||||
let mut stake_keyed_account = KeyedAccount::new(&stake_pubkey, true, &mut stake_account);
|
||||
assert_eq!(
|
||||
stake_keyed_account.deactivate_stake(¤t),
|
||||
Err(InstructionError::InvalidAccountData)
|
||||
);
|
||||
|
||||
// Staking
|
||||
let vote_pubkey = Pubkey::new_rand();
|
||||
let mut vote_account =
|
||||
vote_state::create_account(&vote_pubkey, &Pubkey::new_rand(), 0, 100);
|
||||
let mut vote_keyed_account = KeyedAccount::new(&vote_pubkey, false, &mut vote_account);
|
||||
vote_keyed_account.set_state(&VoteState::default()).unwrap();
|
||||
assert_eq!(
|
||||
stake_keyed_account.delegate_stake(&vote_keyed_account, stake_lamports, ¤t),
|
||||
Ok(())
|
||||
);
|
||||
|
||||
// Deactivate after staking
|
||||
assert_eq!(stake_keyed_account.deactivate_stake(¤t), Ok(()));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_withdraw_stake() {
|
||||
let stake_pubkey = Pubkey::new_rand();
|
||||
|
Reference in New Issue
Block a user