Feature-gate stake-program-v3 (#14232)

* Remove deprecated legacy stake program

* Add legacy stake program

* Strip out duplicative legacy code

* Feature-deploy stake-program-v3

* Add ownership check in stake processor
This commit is contained in:
Tyera Eulberg
2020-12-22 11:20:38 -07:00
committed by GitHub
parent bfcfdcf0ee
commit 7042f11791
5 changed files with 2513 additions and 338 deletions

File diff suppressed because it is too large Load Diff

View File

@ -457,6 +457,10 @@ pub fn process_instruction(
let keyed_accounts = &mut keyed_accounts.iter();
let me = &next_keyed_account(keyed_accounts)?;
if me.owner()? != id() {
return Err(InstructionError::IncorrectProgramId);
}
match limited_deserialize(data)? {
StakeInstruction::Initialize(authorized, lockup) => me.initialize(
&authorized,
@ -538,6 +542,13 @@ mod tests {
RefCell::new(Account::default())
}
fn create_default_stake_account() -> RefCell<Account> {
RefCell::new(Account {
owner: id(),
..Account::default()
})
}
fn invalid_stake_state_pubkey() -> Pubkey {
Pubkey::from_str("BadStake11111111111111111111111111111111111").unwrap()
}
@ -546,6 +557,14 @@ mod tests {
Pubkey::from_str("BadVote111111111111111111111111111111111111").unwrap()
}
fn spoofed_stake_state_pubkey() -> Pubkey {
Pubkey::from_str("SpoofedStake1111111111111111111111111111111").unwrap()
}
fn spoofed_stake_program_id() -> Pubkey {
Pubkey::from_str("Spoofed111111111111111111111111111111111111").unwrap()
}
fn process_instruction(instruction: &Instruction) -> Result<(), InstructionError> {
let accounts: Vec<_> = instruction
.accounts
@ -571,8 +590,16 @@ mod tests {
owner: solana_vote_program::id(),
..Account::default()
}
} else if meta.pubkey == spoofed_stake_state_pubkey() {
Account {
owner: spoofed_stake_program_id(),
..Account::default()
}
} else {
Account::default()
Account {
owner: id(),
..Account::default()
}
})
})
.collect();
@ -678,6 +705,115 @@ mod tests {
);
}
#[test]
fn test_spoofed_stake_accounts() {
assert_eq!(
process_instruction(&initialize(
&spoofed_stake_state_pubkey(),
&Authorized::default(),
&Lockup::default()
)),
Err(InstructionError::IncorrectProgramId),
);
assert_eq!(
process_instruction(&authorize(
&spoofed_stake_state_pubkey(),
&Pubkey::default(),
&Pubkey::default(),
StakeAuthorize::Staker
)),
Err(InstructionError::IncorrectProgramId),
);
assert_eq!(
process_instruction(
&split(
&spoofed_stake_state_pubkey(),
&Pubkey::default(),
100,
&Pubkey::default(),
)[1]
),
Err(InstructionError::IncorrectProgramId),
);
assert_eq!(
process_instruction(
&split(
&Pubkey::default(),
&Pubkey::default(),
100,
&spoofed_stake_state_pubkey(),
)[1]
),
Err(InstructionError::IncorrectProgramId),
);
assert_eq!(
process_instruction(
&merge(
&spoofed_stake_state_pubkey(),
&Pubkey::default(),
&Pubkey::default(),
)[0]
),
Err(InstructionError::IncorrectProgramId),
);
assert_eq!(
process_instruction(
&merge(
&Pubkey::default(),
&spoofed_stake_state_pubkey(),
&Pubkey::default(),
)[0]
),
Err(InstructionError::IncorrectProgramId),
);
assert_eq!(
process_instruction(
&split_with_seed(
&spoofed_stake_state_pubkey(),
&Pubkey::default(),
100,
&Pubkey::default(),
&Pubkey::default(),
"seed"
)[1]
),
Err(InstructionError::IncorrectProgramId),
);
assert_eq!(
process_instruction(&delegate_stake(
&spoofed_stake_state_pubkey(),
&Pubkey::default(),
&Pubkey::default(),
)),
Err(InstructionError::IncorrectProgramId),
);
assert_eq!(
process_instruction(&withdraw(
&spoofed_stake_state_pubkey(),
&Pubkey::default(),
&solana_sdk::pubkey::new_rand(),
100,
None,
)),
Err(InstructionError::IncorrectProgramId),
);
assert_eq!(
process_instruction(&deactivate_stake(
&spoofed_stake_state_pubkey(),
&Pubkey::default()
)),
Err(InstructionError::IncorrectProgramId),
);
assert_eq!(
process_instruction(&set_lockup(
&spoofed_stake_state_pubkey(),
&LockupArgs::default(),
&Pubkey::default()
)),
Err(InstructionError::IncorrectProgramId),
);
}
#[test]
fn test_stake_process_instruction_decode_bail() {
// these will not call stake_state, have bogus contents
@ -704,7 +840,7 @@ mod tests {
&[KeyedAccount::new(
&Pubkey::default(),
false,
&create_default_account(),
&create_default_stake_account(),
)],
&serialize(&StakeInstruction::Initialize(
Authorized::default(),
@ -721,8 +857,8 @@ mod tests {
super::process_instruction(
&Pubkey::default(),
&[
KeyedAccount::new(&Pubkey::default(), false, &create_default_account(),),
KeyedAccount::new(&sysvar::rent::id(), false, &create_default_account(),)
KeyedAccount::new(&Pubkey::default(), false, &create_default_stake_account()),
KeyedAccount::new(&sysvar::rent::id(), false, &create_default_account())
],
&serialize(&StakeInstruction::Initialize(
Authorized::default(),
@ -739,7 +875,7 @@ mod tests {
super::process_instruction(
&Pubkey::default(),
&[
KeyedAccount::new(&Pubkey::default(), false, &create_default_account()),
KeyedAccount::new(&Pubkey::default(), false, &create_default_stake_account()),
KeyedAccount::new(
&sysvar::rent::id(),
false,
@ -763,7 +899,7 @@ mod tests {
&[KeyedAccount::new(
&Pubkey::default(),
false,
&create_default_account()
&create_default_stake_account()
),],
&serialize(&StakeInstruction::DelegateStake).unwrap(),
&mut MockInvokeContext::default()
@ -778,7 +914,7 @@ mod tests {
&[KeyedAccount::new(
&Pubkey::default(),
false,
&create_default_account()
&create_default_stake_account()
)],
&serialize(&StakeInstruction::DelegateStake).unwrap(),
&mut MockInvokeContext::default()
@ -793,7 +929,7 @@ mod tests {
super::process_instruction(
&Pubkey::default(),
&[
KeyedAccount::new(&Pubkey::default(), true, &create_default_account()),
KeyedAccount::new(&Pubkey::default(), true, &create_default_stake_account()),
KeyedAccount::new(&Pubkey::default(), false, &bad_vote_account),
KeyedAccount::new(
&sysvar::clock::id(),
@ -825,7 +961,7 @@ mod tests {
super::process_instruction(
&Pubkey::default(),
&[
KeyedAccount::new(&Pubkey::default(), false, &create_default_account()),
KeyedAccount::new(&Pubkey::default(), false, &create_default_stake_account()),
KeyedAccount::new(&Pubkey::default(), false, &create_default_account()),
KeyedAccount::new(
&sysvar::rewards::id(),
@ -854,7 +990,7 @@ mod tests {
&[KeyedAccount::new(
&Pubkey::default(),
false,
&create_default_account()
&create_default_stake_account()
)],
&serialize(&StakeInstruction::Withdraw(42)).unwrap(),
&mut MockInvokeContext::default()
@ -867,7 +1003,7 @@ mod tests {
super::process_instruction(
&Pubkey::default(),
&[
KeyedAccount::new(&Pubkey::default(), false, &create_default_account()),
KeyedAccount::new(&Pubkey::default(), false, &create_default_stake_account()),
KeyedAccount::new(
&sysvar::rewards::id(),
false,

View File

@ -42,7 +42,7 @@ pub enum InflationPointCalculationEvent {
CreditsObserved(u64, u64),
}
fn null_tracer() -> Option<impl FnMut(&InflationPointCalculationEvent)> {
pub(crate) fn null_tracer() -> Option<impl FnMut(&InflationPointCalculationEvent)> {
None::<fn(&_)>
}
@ -415,7 +415,7 @@ impl Delegation {
}
}
fn rewrite_stake(
pub(crate) fn rewrite_stake(
&mut self,
account_balance: u64,
rent_exempt_balance: u64,