* 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
(cherry picked from commit 7042f11791
)
# Conflicts:
# programs/stake/src/stake_instruction.rs
# sdk/src/feature_set.rs
* Fix conflicts
Co-authored-by: Tyera Eulberg <teulberg@gmail.com>
Co-authored-by: Tyera Eulberg <tyera@solana.com>
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
@ -569,8 +588,15 @@ mod tests {
|
||||
let mut account = Account::default();
|
||||
account.owner = solana_vote_program::id();
|
||||
account
|
||||
} else if meta.pubkey == spoofed_stake_state_pubkey() {
|
||||
let mut account = Account::default();
|
||||
account.owner = spoofed_stake_program_id();
|
||||
account
|
||||
} else {
|
||||
Account::default()
|
||||
Account {
|
||||
owner: id(),
|
||||
..Account::default()
|
||||
}
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
@ -676,6 +702,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
|
||||
@ -702,7 +837,7 @@ mod tests {
|
||||
&[KeyedAccount::new(
|
||||
&Pubkey::default(),
|
||||
false,
|
||||
&create_default_account(),
|
||||
&create_default_stake_account(),
|
||||
)],
|
||||
&serialize(&StakeInstruction::Initialize(
|
||||
Authorized::default(),
|
||||
@ -719,8 +854,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(),
|
||||
@ -737,7 +872,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,
|
||||
@ -761,7 +896,7 @@ mod tests {
|
||||
&[KeyedAccount::new(
|
||||
&Pubkey::default(),
|
||||
false,
|
||||
&create_default_account()
|
||||
&create_default_stake_account()
|
||||
),],
|
||||
&serialize(&StakeInstruction::DelegateStake).unwrap(),
|
||||
&mut MockInvokeContext::default()
|
||||
@ -776,7 +911,7 @@ mod tests {
|
||||
&[KeyedAccount::new(
|
||||
&Pubkey::default(),
|
||||
false,
|
||||
&create_default_account()
|
||||
&create_default_stake_account()
|
||||
)],
|
||||
&serialize(&StakeInstruction::DelegateStake).unwrap(),
|
||||
&mut MockInvokeContext::default()
|
||||
@ -791,7 +926,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(),
|
||||
@ -823,7 +958,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(),
|
||||
@ -852,7 +987,7 @@ mod tests {
|
||||
&[KeyedAccount::new(
|
||||
&Pubkey::default(),
|
||||
false,
|
||||
&create_default_account()
|
||||
&create_default_stake_account()
|
||||
)],
|
||||
&serialize(&StakeInstruction::Withdraw(42)).unwrap(),
|
||||
&mut MockInvokeContext::default()
|
||||
@ -865,7 +1000,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,
|
||||
|
@ -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,
|
||||
|
@ -104,11 +104,11 @@ fn feature_builtins() -> Vec<(Builtin, Pubkey, ActivationType)> {
|
||||
),
|
||||
(
|
||||
Builtin::new(
|
||||
"stake_program_v2",
|
||||
"stake_program_v3",
|
||||
solana_stake_program::id(),
|
||||
solana_stake_program::stake_instruction::process_instruction,
|
||||
),
|
||||
feature_set::stake_program_v2::id(),
|
||||
feature_set::stake_program_v3::id(),
|
||||
ActivationType::NewVersion,
|
||||
),
|
||||
]
|
||||
|
@ -102,6 +102,10 @@ pub mod simple_capitalization {
|
||||
solana_sdk::declare_id!("9r69RnnxABmpcPFfj1yhg4n9YFR2MNaLdKJCC6v3Speb");
|
||||
}
|
||||
|
||||
pub mod stake_program_v3 {
|
||||
solana_sdk::declare_id!("Ego6nTu7WsBcZBvVqJQKp6Yku2N3mrfG8oYCfaLZkAeK");
|
||||
}
|
||||
|
||||
lazy_static! {
|
||||
/// Map of feature identifiers to user-visible description
|
||||
pub static ref FEATURE_NAMES: HashMap<Pubkey, &'static str> = [
|
||||
@ -129,6 +133,7 @@ lazy_static! {
|
||||
(rewrite_stake::id(), "rewrite stake"),
|
||||
(filter_stake_delegation_accounts::id(), "filter stake_delegation_accounts #14062"),
|
||||
(simple_capitalization::id(), "simple capitalization"),
|
||||
(stake_program_v3::id(), "solana_stake_program v3"),
|
||||
/*************** ADD NEW FEATURES HERE ***************/
|
||||
]
|
||||
.iter()
|
||||
|
Reference in New Issue
Block a user