From 8e4a9a94eddda22351deda9b9bd4aa9aef28ddba Mon Sep 17 00:00:00 2001 From: Jon Cinque Date: Wed, 9 Aug 2023 00:05:40 +0200 Subject: [PATCH] sdk: Add new version of `StakeState` to avoid breaking downstream users (#32736) * sdk: Rename `StakeState` -> `StakeStateWithFlags` * Add back `StakeFlags` with a deprecation warning --- account-decoder/src/parse_stake.rs | 20 +- cli/src/cluster_query.rs | 10 +- cli/src/stake.rs | 31 +- cli/tests/stake.rs | 60 +- docs/art/passive-staking-callflow.msc | 4 +- .../cluster/stake-delegation-and-rewards.md | 26 +- genesis/src/main.rs | 6 +- genesis/src/stakes.rs | 12 +- ledger-tool/src/main.rs | 14 +- program-test/tests/warp.rs | 12 +- programs/stake/src/stake_instruction.rs | 533 ++++++++++-------- programs/stake/src/stake_state.rs | 162 +++--- rpc/src/rpc.rs | 4 +- rpc/src/rpc_pubsub.rs | 4 +- runtime/src/bank.rs | 6 +- runtime/src/bank/tests.rs | 4 +- runtime/src/genesis_utils.rs | 4 +- runtime/src/non_circulating_supply.rs | 10 +- runtime/src/stake_account.rs | 14 +- runtime/src/stakes.rs | 2 +- runtime/tests/stake.rs | 16 +- sdk/program/src/stake/instruction.rs | 21 +- sdk/program/src/stake/state.rs | 268 ++++++++- stake-accounts/src/stake_accounts.rs | 5 +- 24 files changed, 782 insertions(+), 466 deletions(-) diff --git a/account-decoder/src/parse_stake.rs b/account-decoder/src/parse_stake.rs index f870789777..36c8988278 100644 --- a/account-decoder/src/parse_stake.rs +++ b/account-decoder/src/parse_stake.rs @@ -6,24 +6,24 @@ use { bincode::deserialize, solana_sdk::{ clock::{Epoch, UnixTimestamp}, - stake::state::{Authorized, Delegation, Lockup, Meta, Stake, StakeState}, + stake::state::{Authorized, Delegation, Lockup, Meta, Stake, StakeStateWithFlags}, }, }; pub fn parse_stake(data: &[u8]) -> Result { - let stake_state: StakeState = deserialize(data) + let stake_state: StakeStateWithFlags = deserialize(data) .map_err(|_| ParseAccountError::AccountNotParsable(ParsableAccount::Stake))?; let parsed_account = match stake_state { - StakeState::Uninitialized => StakeAccountType::Uninitialized, - StakeState::Initialized(meta) => StakeAccountType::Initialized(UiStakeAccount { + StakeStateWithFlags::Uninitialized => StakeAccountType::Uninitialized, + StakeStateWithFlags::Initialized(meta) => StakeAccountType::Initialized(UiStakeAccount { meta: meta.into(), stake: None, }), - StakeState::Stake(meta, stake, _) => StakeAccountType::Delegated(UiStakeAccount { + StakeStateWithFlags::Stake(meta, stake, _) => StakeAccountType::Delegated(UiStakeAccount { meta: meta.into(), stake: Some(stake.into()), }), - StakeState::RewardsPool => StakeAccountType::RewardsPool, + StakeStateWithFlags::RewardsPool => StakeAccountType::RewardsPool, }; Ok(parsed_account) } @@ -146,7 +146,7 @@ mod test { #[test] #[allow(deprecated)] fn test_parse_stake() { - let stake_state = StakeState::Uninitialized; + let stake_state = StakeStateWithFlags::Uninitialized; let stake_data = serialize(&stake_state).unwrap(); assert_eq!( parse_stake(&stake_data).unwrap(), @@ -167,7 +167,7 @@ mod test { lockup, }; - let stake_state = StakeState::Initialized(meta); + let stake_state = StakeStateWithFlags::Initialized(meta); let stake_data = serialize(&stake_state).unwrap(); assert_eq!( parse_stake(&stake_data).unwrap(), @@ -200,7 +200,7 @@ mod test { credits_observed: 10, }; - let stake_state = StakeState::Stake(meta, stake, StakeFlags::empty()); + let stake_state = StakeStateWithFlags::Stake(meta, stake, StakeFlags::empty()); let stake_data = serialize(&stake_state).unwrap(); assert_eq!( parse_stake(&stake_data).unwrap(), @@ -230,7 +230,7 @@ mod test { }) ); - let stake_state = StakeState::RewardsPool; + let stake_state = StakeStateWithFlags::RewardsPool; let stake_data = serialize(&stake_state).unwrap(); assert_eq!( parse_stake(&stake_data).unwrap(), diff --git a/cli/src/cluster_query.rs b/cli/src/cluster_query.rs index ad8758b3e7..17e5d80869 100644 --- a/cli/src/cluster_query.rs +++ b/cli/src/cluster_query.rs @@ -54,7 +54,7 @@ use { rpc_port::DEFAULT_RPC_PORT_STR, signature::Signature, slot_history, - stake::{self, state::StakeState}, + stake::{self, state::StakeStateWithFlags}, system_instruction, sysvar::{ self, @@ -1768,7 +1768,7 @@ pub fn process_show_stakes( // Use server-side filtering if only one vote account is provided if vote_account_pubkeys.len() == 1 { program_accounts_config.filters = Some(vec![ - // Filter by `StakeState::Stake(_, _)` + // Filter by `StakeStateWithFlags::Stake(_, _)` RpcFilterType::Memcmp(Memcmp::new_base58_encoded(0, &[2, 0, 0, 0])), // Filter by `Delegation::voter_pubkey`, which begins at byte offset 124 RpcFilterType::Memcmp(Memcmp::new_base58_encoded( @@ -1809,7 +1809,7 @@ pub fn process_show_stakes( for (stake_pubkey, stake_account) in all_stake_accounts { if let Ok(stake_state) = stake_account.state() { match stake_state { - StakeState::Initialized(_) => { + StakeStateWithFlags::Initialized(_) => { if vote_account_pubkeys.is_none() { stake_accounts.push(CliKeyedStakeState { stake_pubkey: stake_pubkey.to_string(), @@ -1824,7 +1824,7 @@ pub fn process_show_stakes( }); } } - StakeState::Stake(_, stake, _) => { + StakeStateWithFlags::Stake(_, stake, _) => { if vote_account_pubkeys.is_none() || vote_account_pubkeys .unwrap() @@ -2157,7 +2157,7 @@ impl RentLengthValue { pub fn length(&self) -> usize { match self { Self::Nonce => NonceState::size(), - Self::Stake => StakeState::size_of(), + Self::Stake => StakeStateWithFlags::size_of(), Self::System => 0, Self::Vote => VoteState::size_of(), Self::Bytes(l) => *l, diff --git a/cli/src/stake.rs b/cli/src/stake.rs index 58d65aa1c2..5526e889be 100644 --- a/cli/src/stake.rs +++ b/cli/src/stake.rs @@ -47,7 +47,10 @@ use { stake::{ self, instruction::{self as stake_instruction, LockupArgs, StakeError}, - state::{Authorized, Lockup, Meta, StakeActivationStatus, StakeAuthorize, StakeState}, + state::{ + Authorized, Lockup, Meta, StakeActivationStatus, StakeAuthorize, + StakeStateWithFlags, + }, tools::{acceptable_reference_epoch_credits, eligible_for_deactivate_delinquent}, }, stake_history::{Epoch, StakeHistory}, @@ -1422,7 +1425,7 @@ pub fn process_create_stake_account( } let minimum_balance = - rpc_client.get_minimum_balance_for_rent_exemption(StakeState::size_of())?; + rpc_client.get_minimum_balance_for_rent_exemption(StakeStateWithFlags::size_of())?; if lamports < minimum_balance { return Err(CliError::BadParameter(format!( @@ -1500,8 +1503,8 @@ pub fn process_stake_authorize( let authority = config.signers[*authority]; if let Some(current_stake_account) = current_stake_account { let authorized = match current_stake_account { - StakeState::Stake(Meta { authorized, .. }, ..) => Some(authorized), - StakeState::Initialized(Meta { authorized, .. }) => Some(authorized), + StakeStateWithFlags::Stake(Meta { authorized, .. }, ..) => Some(authorized), + StakeStateWithFlags::Initialized(Meta { authorized, .. }) => Some(authorized), _ => None, }; if let Some(authorized) = authorized { @@ -1630,7 +1633,7 @@ pub fn process_deactivate_stake_account( let vote_account_address = match stake_account.state() { Ok(stake_state) => match stake_state { - StakeState::Stake(_, stake, _) => stake.delegation.voter_pubkey, + StakeStateWithFlags::Stake(_, stake, _) => stake.delegation.voter_pubkey, _ => { return Err(CliError::BadParameter(format!( "{stake_account_address} is not a delegated stake account", @@ -1895,7 +1898,7 @@ pub fn process_split_stake( } let minimum_balance = - rpc_client.get_minimum_balance_for_rent_exemption(StakeState::size_of())?; + rpc_client.get_minimum_balance_for_rent_exemption(StakeStateWithFlags::size_of())?; if lamports < minimum_balance { return Err(CliError::BadParameter(format!( @@ -2116,8 +2119,8 @@ pub fn process_stake_set_lockup( if !sign_only { let state = get_stake_account_state(rpc_client, stake_account_pubkey, config.commitment)?; let lockup = match state { - StakeState::Stake(Meta { lockup, .. }, ..) => Some(lockup), - StakeState::Initialized(Meta { lockup, .. }) => Some(lockup), + StakeStateWithFlags::Stake(Meta { lockup, .. }, ..) => Some(lockup), + StakeStateWithFlags::Initialized(Meta { lockup, .. }) => Some(lockup), _ => None, }; if let Some(lockup) = lockup { @@ -2184,14 +2187,14 @@ fn u64_some_if_not_zero(n: u64) -> Option { pub fn build_stake_state( account_balance: u64, - stake_state: &StakeState, + stake_state: &StakeStateWithFlags, use_lamports_unit: bool, stake_history: &StakeHistory, clock: &Clock, new_rate_activation_epoch: Option, ) -> CliStakeState { match stake_state { - StakeState::Stake( + StakeStateWithFlags::Stake( Meta { rent_exempt_reserve, authorized, @@ -2248,16 +2251,16 @@ pub fn build_stake_state( ..CliStakeState::default() } } - StakeState::RewardsPool => CliStakeState { + StakeStateWithFlags::RewardsPool => CliStakeState { stake_type: CliStakeType::RewardsPool, account_balance, ..CliStakeState::default() }, - StakeState::Uninitialized => CliStakeState { + StakeStateWithFlags::Uninitialized => CliStakeState { account_balance, ..CliStakeState::default() }, - StakeState::Initialized(Meta { + StakeStateWithFlags::Initialized(Meta { rent_exempt_reserve, authorized, lockup, @@ -2285,7 +2288,7 @@ fn get_stake_account_state( rpc_client: &RpcClient, stake_account_pubkey: &Pubkey, commitment_config: CommitmentConfig, -) -> Result> { +) -> Result> { let stake_account = rpc_client .get_account_with_commitment(stake_account_pubkey, commitment_config)? .value diff --git a/cli/tests/stake.rs b/cli/tests/stake.rs index 481c163c68..beb19678ff 100644 --- a/cli/tests/stake.rs +++ b/cli/tests/stake.rs @@ -26,7 +26,7 @@ use { stake::{ self, instruction::LockupArgs, - state::{Lockup, StakeAuthorize, StakeState}, + state::{Lockup, StakeAuthorize, StakeStateWithFlags}, }, }, solana_streamer::socket::SocketAddrSpace, @@ -162,10 +162,10 @@ fn test_stake_redelegation() { // `stake_keypair` should now be delegated to `vote_keypair` and fully activated let stake_account = rpc_client.get_account(&stake_keypair.pubkey()).unwrap(); - let stake_state: StakeState = stake_account.state().unwrap(); + let stake_state: StakeStateWithFlags = stake_account.state().unwrap(); let rent_exempt_reserve = match stake_state { - StakeState::Stake(meta, stake, _) => { + StakeStateWithFlags::Stake(meta, stake, _) => { assert_eq!(stake.delegation.voter_pubkey, vote_keypair.pubkey()); meta.rent_exempt_reserve } @@ -268,10 +268,10 @@ fn test_stake_redelegation() { // `stake2_keypair` should now be delegated to `vote2_keypair` and fully activated let stake2_account = rpc_client.get_account(&stake2_keypair.pubkey()).unwrap(); - let stake2_state: StakeState = stake2_account.state().unwrap(); + let stake2_state: StakeStateWithFlags = stake2_account.state().unwrap(); match stake2_state { - StakeState::Stake(_meta, stake, _) => { + StakeStateWithFlags::Stake(_meta, stake, _) => { assert_eq!(stake.delegation.voter_pubkey, vote2_keypair.pubkey()); } _ => panic!("Unexpected stake2 state!"), @@ -966,9 +966,9 @@ fn test_stake_authorize() { }; process_command(&config).unwrap(); let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap(); - let stake_state: StakeState = stake_account.state().unwrap(); + let stake_state: StakeStateWithFlags = stake_account.state().unwrap(); let current_authority = match stake_state { - StakeState::Initialized(meta) => meta.authorized.staker, + StakeStateWithFlags::Initialized(meta) => meta.authorized.staker, _ => panic!("Unexpected stake state!"), }; assert_eq!(current_authority, online_authority_pubkey); @@ -1008,9 +1008,11 @@ fn test_stake_authorize() { }; process_command(&config).unwrap(); let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap(); - let stake_state: StakeState = stake_account.state().unwrap(); + let stake_state: StakeStateWithFlags = stake_account.state().unwrap(); let (current_staker, current_withdrawer) = match stake_state { - StakeState::Initialized(meta) => (meta.authorized.staker, meta.authorized.withdrawer), + StakeStateWithFlags::Initialized(meta) => { + (meta.authorized.staker, meta.authorized.withdrawer) + } _ => panic!("Unexpected stake state!"), }; assert_eq!(current_staker, online_authority2_pubkey); @@ -1040,9 +1042,9 @@ fn test_stake_authorize() { }; process_command(&config).unwrap(); let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap(); - let stake_state: StakeState = stake_account.state().unwrap(); + let stake_state: StakeStateWithFlags = stake_account.state().unwrap(); let current_authority = match stake_state { - StakeState::Initialized(meta) => meta.authorized.staker, + StakeStateWithFlags::Initialized(meta) => meta.authorized.staker, _ => panic!("Unexpected stake state!"), }; assert_eq!(current_authority, offline_authority_pubkey); @@ -1097,9 +1099,9 @@ fn test_stake_authorize() { }; process_command(&config).unwrap(); let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap(); - let stake_state: StakeState = stake_account.state().unwrap(); + let stake_state: StakeStateWithFlags = stake_account.state().unwrap(); let current_authority = match stake_state { - StakeState::Initialized(meta) => meta.authorized.staker, + StakeStateWithFlags::Initialized(meta) => meta.authorized.staker, _ => panic!("Unexpected stake state!"), }; assert_eq!(current_authority, nonced_authority_pubkey); @@ -1184,9 +1186,9 @@ fn test_stake_authorize() { }; process_command(&config).unwrap(); let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap(); - let stake_state: StakeState = stake_account.state().unwrap(); + let stake_state: StakeStateWithFlags = stake_account.state().unwrap(); let current_authority = match stake_state { - StakeState::Initialized(meta) => meta.authorized.staker, + StakeStateWithFlags::Initialized(meta) => meta.authorized.staker, _ => panic!("Unexpected stake state!"), }; assert_eq!(current_authority, online_authority_pubkey); @@ -1434,7 +1436,7 @@ fn test_stake_split() { // Create stake account, identity is authority let stake_balance = rpc_client - .get_minimum_balance_for_rent_exemption(StakeState::size_of()) + .get_minimum_balance_for_rent_exemption(StakeStateWithFlags::size_of()) .unwrap() + 10_000_000_000; let stake_keypair = keypair_from_seed(&[0u8; 32]).unwrap(); @@ -1587,7 +1589,7 @@ fn test_stake_set_lockup() { // Create stake account, identity is authority let stake_balance = rpc_client - .get_minimum_balance_for_rent_exemption(StakeState::size_of()) + .get_minimum_balance_for_rent_exemption(StakeStateWithFlags::size_of()) .unwrap() + 10_000_000_000; @@ -1645,9 +1647,9 @@ fn test_stake_set_lockup() { }; process_command(&config).unwrap(); let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap(); - let stake_state: StakeState = stake_account.state().unwrap(); + let stake_state: StakeStateWithFlags = stake_account.state().unwrap(); let current_lockup = match stake_state { - StakeState::Initialized(meta) => meta.lockup, + StakeStateWithFlags::Initialized(meta) => meta.lockup, _ => panic!("Unexpected stake state!"), }; assert_eq!( @@ -1704,9 +1706,9 @@ fn test_stake_set_lockup() { }; process_command(&config).unwrap(); let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap(); - let stake_state: StakeState = stake_account.state().unwrap(); + let stake_state: StakeStateWithFlags = stake_account.state().unwrap(); let current_lockup = match stake_state { - StakeState::Initialized(meta) => meta.lockup, + StakeStateWithFlags::Initialized(meta) => meta.lockup, _ => panic!("Unexpected stake state!"), }; assert_eq!( @@ -1811,9 +1813,9 @@ fn test_stake_set_lockup() { }; process_command(&config).unwrap(); let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap(); - let stake_state: StakeState = stake_account.state().unwrap(); + let stake_state: StakeStateWithFlags = stake_account.state().unwrap(); let current_lockup = match stake_state { - StakeState::Initialized(meta) => meta.lockup, + StakeStateWithFlags::Initialized(meta) => meta.lockup, _ => panic!("Unexpected stake state!"), }; assert_eq!( @@ -2187,9 +2189,9 @@ fn test_stake_checked_instructions() { }; process_command(&config).unwrap(); let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap(); - let stake_state: StakeState = stake_account.state().unwrap(); + let stake_state: StakeStateWithFlags = stake_account.state().unwrap(); let current_authority = match stake_state { - StakeState::Initialized(meta) => meta.authorized.staker, + StakeStateWithFlags::Initialized(meta) => meta.authorized.staker, _ => panic!("Unexpected stake state!"), }; assert_eq!(current_authority, staker_pubkey); @@ -2244,9 +2246,9 @@ fn test_stake_checked_instructions() { }; process_command(&config).unwrap(); let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap(); - let stake_state: StakeState = stake_account.state().unwrap(); + let stake_state: StakeStateWithFlags = stake_account.state().unwrap(); let current_authority = match stake_state { - StakeState::Initialized(meta) => meta.authorized.withdrawer, + StakeStateWithFlags::Initialized(meta) => meta.authorized.withdrawer, _ => panic!("Unexpected stake state!"), }; assert_eq!(current_authority, new_withdrawer_pubkey); @@ -2293,9 +2295,9 @@ fn test_stake_checked_instructions() { }; process_command(&config).unwrap(); let stake_account = rpc_client.get_account(&stake_account_pubkey).unwrap(); - let stake_state: StakeState = stake_account.state().unwrap(); + let stake_state: StakeStateWithFlags = stake_account.state().unwrap(); let current_lockup = match stake_state { - StakeState::Initialized(meta) => meta.lockup, + StakeStateWithFlags::Initialized(meta) => meta.lockup, _ => panic!("Unexpected stake state!"), }; assert_eq!( diff --git a/docs/art/passive-staking-callflow.msc b/docs/art/passive-staking-callflow.msc index 8383b0b6cf..e830cde5d8 100644 --- a/docs/art/passive-staking-callflow.msc +++ b/docs/art/passive-staking-callflow.msc @@ -11,8 +11,8 @@ msc { VoteSigner <:> Validator [label="register\n\n(optional)"]; Validator => Cluster [label="VoteState::Initialize(VoteSigner)"]; - StakerX => Cluster [label="StakeState::Delegate(Validator)"]; - StakerY => Cluster [label="StakeState::Delegate(Validator)"]; + StakerX => Cluster [label="StakeStateWithFlags::Delegate(Validator)"]; + StakerY => Cluster [label="StakeStateWithFlags::Delegate(Validator)"]; |||; Validator box Cluster [label="\nvalidate\n"]; diff --git a/docs/src/cluster/stake-delegation-and-rewards.md b/docs/src/cluster/stake-delegation-and-rewards.md index 344774c920..8523414805 100644 --- a/docs/src/cluster/stake-delegation-and-rewards.md +++ b/docs/src/cluster/stake-delegation-and-rewards.md @@ -14,7 +14,7 @@ A separate Stake account \(created by a staker\) names a Vote account to which t Any number of Stake accounts can delegate to a single Vote account without an interactive action from the identity controlling the Vote account or submitting votes to the account. -The total stake allocated to a Vote account can be calculated by the sum of all the Stake accounts that have the Vote account pubkey as the `StakeState::Stake::voter_pubkey`. +The total stake allocated to a Vote account can be calculated by the sum of all the Stake accounts that have the Vote account pubkey as the `StakeStateWithFlags::Stake::voter_pubkey`. ## Vote and Stake accounts @@ -62,13 +62,13 @@ Updates the account with a new authorized voter or withdrawer, according to the - `account[1]` - RO - `sysvar::slot_hashes` A list of some N most recent slots and their hashes for the vote to be verified against. - `account[2]` - RO - `sysvar::clock` The current network time, expressed in slots, epochs. -### StakeState +### StakeStateWithFlags -A StakeState takes one of four forms, StakeState::Uninitialized, StakeState::Initialized, StakeState::Stake, and StakeState::RewardsPool. Only the first three forms are used in staking, but only StakeState::Stake is interesting. All RewardsPools are created at genesis. +A StakeStateWithFlags takes one of four forms, StakeStateWithFlags::Uninitialized, StakeStateWithFlags::Initialized, StakeStateWithFlags::Stake, and StakeStateWithFlags::RewardsPool. Only the first three forms are used in staking, but only StakeStateWithFlags::Stake is interesting. All RewardsPools are created at genesis. -### StakeState::Stake +### StakeStateWithFlags::Stake -StakeState::Stake is the current delegation preference of the **staker** and contains the following state information: +StakeStateWithFlags::Stake is the current delegation preference of the **staker** and contains the following state information: - Account::lamports - The lamports available for staking. - `stake` - the staked amount \(subject to warmup and cooldown\) for generating rewards, always less than or equal to Account::lamports. @@ -79,7 +79,7 @@ StakeState::Stake is the current delegation preference of the **staker** and con - `authorized_staker` - the pubkey of the entity that must sign delegation, activation, and deactivation transactions. - `authorized_withdrawer` - the identity of the entity in charge of the lamports of this account, separate from the account's address, and the authorized staker. -### StakeState::RewardsPool +### StakeStateWithFlags::RewardsPool To avoid a single network-wide lock or contention in redemption, 256 RewardsPools are part of genesis under pre-determined keys, each with std::u64::MAX credits to be able to satisfy redemptions according to point value. @@ -87,9 +87,9 @@ The Stakes and the RewardsPool are accounts that are owned by the same `Stake` p ### StakeInstruction::DelegateStake -The Stake account is moved from Initialized to StakeState::Stake form, or from a deactivated (i.e. fully cooled-down) StakeState::Stake to activated StakeState::Stake. This is how stakers choose the vote account and validator node to which their stake account lamports are delegated. The transaction must be signed by the stake's `authorized_staker`. +The Stake account is moved from Initialized to StakeStateWithFlags::Stake form, or from a deactivated (i.e. fully cooled-down) StakeStateWithFlags::Stake to activated StakeStateWithFlags::Stake. This is how stakers choose the vote account and validator node to which their stake account lamports are delegated. The transaction must be signed by the stake's `authorized_staker`. -- `account[0]` - RW - The StakeState::Stake instance. `StakeState::Stake::credits_observed` is initialized to `VoteState::credits`, `StakeState::Stake::voter_pubkey` is initialized to `account[1]`. If this is the initial delegation of stake, `StakeState::Stake::stake` is initialized to the account's balance in lamports, `StakeState::Stake::activated` is initialized to the current Bank epoch, and `StakeState::Stake::deactivated` is initialized to std::u64::MAX +- `account[0]` - RW - The StakeStateWithFlags::Stake instance. `StakeStateWithFlags::Stake::credits_observed` is initialized to `VoteState::credits`, `StakeStateWithFlags::Stake::voter_pubkey` is initialized to `account[1]`. If this is the initial delegation of stake, `StakeStateWithFlags::Stake::stake` is initialized to the account's balance in lamports, `StakeStateWithFlags::Stake::activated` is initialized to the current Bank epoch, and `StakeStateWithFlags::Stake::deactivated` is initialized to std::u64::MAX - `account[1]` - R - The VoteState instance. - `account[2]` - R - sysvar::clock account, carries information about current Bank epoch. - `account[3]` - R - sysvar::stakehistory account, carries information about stake history. @@ -99,25 +99,25 @@ The Stake account is moved from Initialized to StakeState::Stake form, or from a Updates the account with a new authorized staker or withdrawer, according to the StakeAuthorize parameter \(`Staker` or `Withdrawer`\). The transaction must be by signed by the Stakee account's current `authorized_staker` or `authorized_withdrawer`. Any stake lock-up must have expired, or the lock-up custodian must also sign the transaction. -- `account[0]` - RW - The StakeState. +- `account[0]` - RW - The StakeStateWithFlags. - `StakeState::authorized_staker` or `authorized_withdrawer` is set to to `Pubkey`. + `StakeStateWithFlags::authorized_staker` or `authorized_withdrawer` is set to to `Pubkey`. ### StakeInstruction::Deactivate A staker may wish to withdraw from the network. To do so he must first deactivate his stake, and wait for cooldown. The transaction must be signed by the stake's `authorized_staker`. -- `account[0]` - RW - The StakeState::Stake instance that is deactivating. +- `account[0]` - RW - The StakeStateWithFlags::Stake instance that is deactivating. - `account[1]` - R - sysvar::clock account from the Bank that carries current epoch. -StakeState::Stake::deactivated is set to the current epoch + cooldown. The account's stake will ramp down to zero by that epoch, and Account::lamports will be available for withdrawal. +StakeStateWithFlags::Stake::deactivated is set to the current epoch + cooldown. The account's stake will ramp down to zero by that epoch, and Account::lamports will be available for withdrawal. ### StakeInstruction::Withdraw\(u64\) Lamports build up over time in a Stake account and any excess over activated stake can be withdrawn. The transaction must be signed by the stake's `authorized_withdrawer`. -- `account[0]` - RW - The StakeState::Stake from which to withdraw. +- `account[0]` - RW - The StakeStateWithFlags::Stake from which to withdraw. - `account[1]` - RW - Account that should be credited with the withdrawn lamports. - `account[2]` - R - sysvar::clock account from the Bank that carries current epoch, to calculate stake. - `account[3]` - R - sysvar::stake_history account from the Bank that carries stake warmup/cooldown history. diff --git a/genesis/src/main.rs b/genesis/src/main.rs index 875655d42b..85136fd759 100644 --- a/genesis/src/main.rs +++ b/genesis/src/main.rs @@ -31,7 +31,7 @@ use { rent::Rent, signature::{Keypair, Signer}, signer::keypair::read_keypair_file, - stake::state::StakeState, + stake::state::StakeStateWithFlags, system_program, timing, }, solana_stake_program::stake_state, @@ -141,7 +141,7 @@ fn main() -> Result<(), Box> { .to_string(); // stake account let default_bootstrap_validator_stake_lamports = &sol_to_lamports(0.5) - .max(rent.minimum_balance(StakeState::size_of())) + .max(rent.minimum_balance(StakeStateWithFlags::size_of())) .to_string(); let default_target_tick_duration = @@ -444,7 +444,7 @@ fn main() -> Result<(), Box> { let bootstrap_validator_stake_lamports = rent_exempt_check( &matches, "bootstrap_validator_stake_lamports", - rent.minimum_balance(StakeState::size_of()), + rent.minimum_balance(StakeStateWithFlags::size_of()), )?; let bootstrap_stake_authorized_pubkey = diff --git a/genesis/src/stakes.rs b/genesis/src/stakes.rs index c48a3ec863..73f7856b60 100644 --- a/genesis/src/stakes.rs +++ b/genesis/src/stakes.rs @@ -11,7 +11,7 @@ use { pubkey::Pubkey, stake::{ self, - state::{Authorized, Lockup, StakeState}, + state::{Authorized, Lockup, StakeStateWithFlags}, }, system_program, timing::years_as_slots, @@ -107,7 +107,9 @@ pub fn create_and_add_stakes( let mut address_generator = AddressGenerator::new(&authorized.staker, &stake::program::id()); - let stake_rent_reserve = genesis_config.rent.minimum_balance(StakeState::size_of()); + let stake_rent_reserve = genesis_config + .rent + .minimum_balance(StakeStateWithFlags::size_of()); for unlock in unlocks { let lamports = unlock.amount(stakes_lamports); @@ -193,7 +195,9 @@ mod tests { .iter() .all(|(_pubkey, account)| account.lamports <= granularity || account.lamports - granularity - <= genesis_config.rent.minimum_balance(StakeState::size_of()))); + <= genesis_config + .rent + .minimum_balance(StakeStateWithFlags::size_of()))); } // #[ignore] @@ -238,7 +242,7 @@ mod tests { ..Rent::default() }; - let reserve = rent.minimum_balance(StakeState::size_of()); + let reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let staker_reserve = rent.minimum_balance(0); // verify that a small remainder ends up in the last stake diff --git a/ledger-tool/src/main.rs b/ledger-tool/src/main.rs index 6cb85bba68..835e4e63bb 100644 --- a/ledger-tool/src/main.rs +++ b/ledger-tool/src/main.rs @@ -74,7 +74,7 @@ use { pubkey::Pubkey, rent::Rent, shred_version::compute_shred_version, - stake::{self, state::StakeState}, + stake::{self, state::StakeStateWithFlags}, system_program, transaction::{ MessageHash, SanitizedTransaction, SimpleAddressLoader, VersionedTransaction, @@ -1293,7 +1293,7 @@ fn main() { .max(VoteState::get_rent_exempt_reserve(&rent)) .to_string(); let default_bootstrap_validator_stake_lamports = &sol_to_lamports(0.5) - .max(rent.minimum_balance(StakeState::size_of())) + .max(rent.minimum_balance(StakeStateWithFlags::size_of())) .to_string(); let default_graph_vote_account_mode = GraphVoteAccountMode::default(); @@ -2768,7 +2768,7 @@ fn main() { value_t_or_exit!(arg_matches, "bootstrap_validator_lamports", u64); let bootstrap_validator_stake_lamports = value_t_or_exit!(arg_matches, "bootstrap_validator_stake_lamports", u64); - let minimum_stake_lamports = rent.minimum_balance(StakeState::size_of()); + let minimum_stake_lamports = rent.minimum_balance(StakeStateWithFlags::size_of()); if bootstrap_validator_stake_lamports < minimum_stake_lamports { eprintln!( "Error: insufficient --bootstrap-validator-stake-lamports. \ @@ -2996,7 +2996,9 @@ fn main() { .unwrap() .into_iter() { - if let Ok(StakeState::Stake(meta, stake, _)) = account.state() { + if let Ok(StakeStateWithFlags::Stake(meta, stake, _)) = + account.state() + { if vote_accounts_to_destake .contains(&stake.delegation.voter_pubkey) { @@ -3006,7 +3008,9 @@ fn main() { address, stake.delegation.voter_pubkey, ); } - account.set_state(&StakeState::Initialized(meta)).unwrap(); + account + .set_state(&StakeStateWithFlags::Initialized(meta)) + .unwrap(); bank.store_account(&address, &account); } } diff --git a/program-test/tests/warp.rs b/program-test/tests/warp.rs index 7ab151dd63..bfafd11f0f 100644 --- a/program-test/tests/warp.rs +++ b/program-test/tests/warp.rs @@ -18,7 +18,7 @@ use { signature::{Keypair, Signer}, stake::{ instruction as stake_instruction, - state::{Authorized, Lockup, StakeActivationStatus, StakeState}, + state::{Authorized, Lockup, StakeActivationStatus, StakeStateWithFlags}, }, system_instruction, system_program, sysvar::{ @@ -271,7 +271,7 @@ async fn stake_rewards_from_warp() { .expect("account exists") .unwrap(); - let stake_state: StakeState = deserialize(&account.data).unwrap(); + let stake_state: StakeStateWithFlags = deserialize(&account.data).unwrap(); let stake_history: StakeHistory = deserialize(&stake_history_account.data).unwrap(); let clock: Clock = deserialize(&clock_account.data).unwrap(); let stake = stake_state.stake().unwrap(); @@ -387,7 +387,7 @@ async fn stake_rewards_filter_bench_core(num_stake_accounts: u64) { .expect("account exists") .unwrap(); - let stake_state: StakeState = deserialize(&account.data).unwrap(); + let stake_state: StakeStateWithFlags = deserialize(&account.data).unwrap(); let stake_history: StakeHistory = deserialize(&stake_history_account.data).unwrap(); let clock: Clock = deserialize(&clock_account.data).unwrap(); let stake = stake_state.stake().unwrap(); @@ -409,7 +409,7 @@ async fn check_credits_observed( .await .unwrap() .unwrap(); - let stake_state: StakeState = deserialize(&stake_account.data).unwrap(); + let stake_state: StakeStateWithFlags = deserialize(&stake_account.data).unwrap(); assert_eq!( stake_state.stake().unwrap().credits_observed, expected_credits @@ -465,7 +465,7 @@ async fn stake_merge_immediately_after_activation() { .await .unwrap() .unwrap(); - let stake_state: StakeState = deserialize(&stake_account.data).unwrap(); + let stake_state: StakeStateWithFlags = deserialize(&stake_account.data).unwrap(); assert_eq!(stake_state.stake().unwrap().credits_observed, 300); assert!(stake_account.lamports > stake_lamports); @@ -476,7 +476,7 @@ async fn stake_merge_immediately_after_activation() { .await .unwrap() .unwrap(); - let stake_state: StakeState = deserialize(&stake_account.data).unwrap(); + let stake_state: StakeStateWithFlags = deserialize(&stake_account.data).unwrap(); assert_eq!(stake_state.stake().unwrap().credits_observed, 300); assert_eq!(stake_account.lamports, stake_lamports); diff --git a/programs/stake/src/stake_instruction.rs b/programs/stake/src/stake_instruction.rs index 21e982fb4b..9e348baa2f 100644 --- a/programs/stake/src/stake_instruction.rs +++ b/programs/stake/src/stake_instruction.rs @@ -467,7 +467,7 @@ mod tests { config, stake_state::{ authorized_from, create_stake_history_from_delegations, from, new_stake, - stake_from, Delegation, Meta, Stake, StakeState, + stake_from, Delegation, Meta, Stake, StakeStateWithFlags, }, }, assert_matches::assert_matches, @@ -626,8 +626,8 @@ mod tests { ) } - fn just_stake(meta: Meta, stake: u64) -> StakeState { - StakeState::Stake( + fn just_stake(meta: Meta, stake: u64) -> StakeStateWithFlags { + StakeStateWithFlags::Stake( meta, Stake { delegation: Delegation { @@ -909,7 +909,7 @@ mod tests { let config_address = stake_config::id(); #[allow(deprecated)] let config_account = config::create_account(0, &stake_config::Config::default()); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let minimum_delegation = crate::get_minimum_delegation(&feature_set); let withdrawal_amount = rent_exempt_reserve + minimum_delegation; @@ -1175,7 +1175,7 @@ mod tests { let rent = Rent::default(); let rent_address = rent::id(); let rent_account = create_account_shared_data_for_test(&rent); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let minimum_delegation = crate::get_minimum_delegation(&feature_set); // Test InitializeChecked with non-signing withdrawer @@ -1191,7 +1191,7 @@ mod tests { // Test InitializeChecked with withdrawer signer let stake_account = AccountSharedData::new( rent_exempt_reserve + minimum_delegation, - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ); process_instruction( @@ -1260,8 +1260,8 @@ mod tests { // Test AuthorizeChecked with authority signer let stake_account = AccountSharedData::new_data_with_space( 42, - &StakeState::Initialized(Meta::auto(&authorized_address)), - StakeState::size_of(), + &StakeStateWithFlags::Initialized(Meta::auto(&authorized_address)), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -1376,8 +1376,8 @@ mod tests { // Test AuthorizeCheckedWithSeed with authority signer let stake_account = AccountSharedData::new_data_with_space( 42, - &StakeState::Initialized(Meta::auto(&address_with_seed)), - StakeState::size_of(), + &StakeStateWithFlags::Initialized(Meta::auto(&address_with_seed)), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -1483,8 +1483,8 @@ mod tests { // Test SetLockupChecked with lockup custodian signer let stake_account = AccountSharedData::new_data_with_space( 42, - &StakeState::Initialized(Meta::auto(&withdrawer)), - StakeState::size_of(), + &StakeStateWithFlags::Initialized(Meta::auto(&withdrawer)), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -1524,10 +1524,11 @@ mod tests { #[test_case(feature_set_all_enabled(); "all_enabled")] fn test_stake_initialize(feature_set: Arc) { let rent = Rent::default(); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let stake_lamports = rent_exempt_reserve; let stake_address = solana_sdk::pubkey::new_rand(); - let stake_account = AccountSharedData::new(stake_lamports, StakeState::size_of(), &id()); + let stake_account = + AccountSharedData::new(stake_lamports, StakeStateWithFlags::size_of(), &id()); let custodian_address = solana_sdk::pubkey::new_rand(); let lockup = Lockup { epoch: 1, @@ -1567,7 +1568,7 @@ mod tests { // check that we see what we expect assert_eq!( from(&accounts[0]).unwrap(), - StakeState::Initialized(Meta { + StakeStateWithFlags::Initialized(Meta { authorized: Authorized::auto(&stake_address), rent_exempt_reserve, lockup, @@ -1603,7 +1604,7 @@ mod tests { // incorrect account sizes let stake_account = - AccountSharedData::new(stake_lamports, StakeState::size_of() + 1, &id()); + AccountSharedData::new(stake_lamports, StakeStateWithFlags::size_of() + 1, &id()); transaction_accounts[0] = (stake_address, stake_account); process_instruction( Arc::clone(&feature_set), @@ -1614,7 +1615,7 @@ mod tests { ); let stake_account = - AccountSharedData::new(stake_lamports, StakeState::size_of() - 1, &id()); + AccountSharedData::new(stake_lamports, StakeStateWithFlags::size_of() - 1, &id()); transaction_accounts[0] = (stake_address, stake_account); process_instruction( Arc::clone(&feature_set), @@ -1635,8 +1636,8 @@ mod tests { let stake_lamports = 42; let stake_account = AccountSharedData::new_data_with_space( stake_lamports, - &StakeState::default(), - StakeState::size_of(), + &StakeStateWithFlags::default(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -1693,8 +1694,8 @@ mod tests { // should pass let stake_account = AccountSharedData::new_data_with_space( stake_lamports, - &StakeState::Initialized(Meta::auto(&stake_address)), - StakeState::size_of(), + &StakeStateWithFlags::Initialized(Meta::auto(&stake_address)), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -1723,7 +1724,9 @@ mod tests { Ok(()), ); transaction_accounts[0] = (stake_address, accounts[0].clone()); - if let StakeState::Initialized(Meta { authorized, .. }) = from(&accounts[0]).unwrap() { + if let StakeStateWithFlags::Initialized(Meta { authorized, .. }) = + from(&accounts[0]).unwrap() + { assert_eq!(authorized.staker, authority_address); assert_eq!(authorized.withdrawer, authority_address); } else { @@ -1757,7 +1760,9 @@ mod tests { instruction_accounts.clone(), Ok(()), ); - if let StakeState::Initialized(Meta { authorized, .. }) = from(&accounts[0]).unwrap() { + if let StakeStateWithFlags::Initialized(Meta { authorized, .. }) = + from(&accounts[0]).unwrap() + { assert_eq!(authorized.staker, authority_address_2); } else { panic!(); @@ -1798,7 +1803,10 @@ mod tests { instruction_accounts.clone(), Ok(()), ); - assert_eq!(from(&accounts[0]).unwrap(), StakeState::Uninitialized); + assert_eq!( + from(&accounts[0]).unwrap(), + StakeStateWithFlags::Uninitialized + ); // Test that withdrawal to account fails without authorized withdrawer instruction_accounts[4].is_signer = false; @@ -1821,8 +1829,8 @@ mod tests { let stake_lamports = 42; let stake_account = AccountSharedData::new_data_with_space( stake_lamports, - &StakeState::Initialized(Meta::auto(&stake_address)), - StakeState::size_of(), + &StakeStateWithFlags::Initialized(Meta::auto(&stake_address)), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -1942,8 +1950,8 @@ mod tests { let stake_lamports = 42; let stake_account = AccountSharedData::new_data_with_space( stake_lamports, - &StakeState::Initialized(Meta::auto(&stake_address)), - StakeState::size_of(), + &StakeStateWithFlags::Initialized(Meta::auto(&stake_address)), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -2059,8 +2067,8 @@ mod tests { let stake_lamports = minimum_delegation; let stake_account = AccountSharedData::new_data_with_space( stake_lamports, - &StakeState::Initialized(Meta::auto(&stake_address)), - StakeState::size_of(), + &StakeStateWithFlags::Initialized(Meta::auto(&stake_address)), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -2273,14 +2281,14 @@ mod tests { let stake_address = solana_sdk::pubkey::new_rand(); let mut stake_account = AccountSharedData::new_data_with_space( stake_lamports, - &StakeState::Initialized(Meta { + &StakeStateWithFlags::Initialized(Meta { authorized: Authorized { staker: stake_address, withdrawer: stake_address, }, ..Meta::default() }), - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -2483,7 +2491,7 @@ mod tests { ); // verify that non-stakes fail delegate() - let stake_state = StakeState::RewardsPool; + let stake_state = StakeStateWithFlags::RewardsPool; stake_account.set_state(&stake_state).unwrap(); transaction_accounts[0] = (stake_address, stake_account); process_instruction( @@ -2501,7 +2509,7 @@ mod tests { fn test_redelegate_consider_balance_changes(feature_set: Arc) { let mut clock = Clock::default(); let rent = Rent::default(); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let initial_lamports = 4242424242; let stake_lamports = rent_exempt_reserve + initial_lamports; let recipient_address = solana_sdk::pubkey::new_rand(); @@ -2512,11 +2520,11 @@ mod tests { let stake_address = solana_sdk::pubkey::new_rand(); let stake_account = AccountSharedData::new_data_with_space( stake_lamports, - &StakeState::Initialized(Meta { + &StakeStateWithFlags::Initialized(Meta { rent_exempt_reserve, ..Meta::auto(&authority_address) }), - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -2712,8 +2720,8 @@ mod tests { let split_to_address = solana_sdk::pubkey::new_rand(); let split_to_account = AccountSharedData::new_data_with_space( 0, - &StakeState::Uninitialized, - StakeState::size_of(), + &StakeStateWithFlags::Uninitialized, + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -2744,13 +2752,13 @@ mod tests { let feature_set = Arc::new(feature_set); for state in [ - StakeState::Initialized(Meta::auto(&stake_address)), + StakeStateWithFlags::Initialized(Meta::auto(&stake_address)), just_stake(Meta::auto(&stake_address), stake_lamports), ] { let stake_account = AccountSharedData::new_data_with_space( stake_lamports, &state, - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -2781,10 +2789,10 @@ mod tests { assert_eq!(from(&accounts[0]).unwrap(), from(&accounts[1]).unwrap()); match state { - StakeState::Initialized(_meta) => { + StakeStateWithFlags::Initialized(_meta) => { assert_eq!(from(&accounts[0]).unwrap(), state); } - StakeState::Stake(_meta, _stake, _) => { + StakeStateWithFlags::Stake(_meta, _stake, _) => { let stake_0 = from(&accounts[0]).unwrap().stake(); assert_eq!(stake_0.unwrap().delegation.stake, stake_lamports / 2); } @@ -2795,8 +2803,8 @@ mod tests { // should fail, fake owner of destination let split_to_account = AccountSharedData::new_data_with_space( 0, - &StakeState::Uninitialized, - StakeState::size_of(), + &StakeStateWithFlags::Uninitialized, + StakeStateWithFlags::size_of(), &solana_sdk::pubkey::new_rand(), ) .unwrap(); @@ -2822,8 +2830,8 @@ mod tests { let stake_lamports = minimum_delegation; let stake_account = AccountSharedData::new_data_with_space( stake_lamports, - &StakeState::Uninitialized, - StakeState::size_of(), + &StakeStateWithFlags::Uninitialized, + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -2912,7 +2920,10 @@ mod tests { Ok(()), ); assert_eq!(accounts[0].lamports(), 0); - assert_eq!(from(&accounts[0]).unwrap(), StakeState::Uninitialized); + assert_eq!( + from(&accounts[0]).unwrap(), + StakeStateWithFlags::Uninitialized + ); // initialize stake let lockup = Lockup { @@ -3057,14 +3068,17 @@ mod tests { Ok(()), ); assert_eq!(accounts[0].lamports(), 0); - assert_eq!(from(&accounts[0]).unwrap(), StakeState::Uninitialized); + assert_eq!( + from(&accounts[0]).unwrap(), + StakeStateWithFlags::Uninitialized + ); // overflow let rent = Rent::default(); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let stake_account = AccountSharedData::new_data_with_space( 1_000_000_000, - &StakeState::Initialized(Meta { + &StakeStateWithFlags::Initialized(Meta { rent_exempt_reserve, authorized: Authorized { staker: authority_address, @@ -3072,7 +3086,7 @@ mod tests { }, lockup: Lockup::default(), }), - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -3090,8 +3104,8 @@ mod tests { // should fail, invalid state let stake_account = AccountSharedData::new_data_with_space( stake_lamports, - &StakeState::RewardsPool, - StakeState::size_of(), + &StakeStateWithFlags::RewardsPool, + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -3116,8 +3130,8 @@ mod tests { let total_lamports = stake_lamports + 33; let stake_account = AccountSharedData::new_data_with_space( total_lamports, - &StakeState::Initialized(Meta::auto(&stake_address)), - StakeState::size_of(), + &StakeStateWithFlags::Initialized(Meta::auto(&stake_address)), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -3258,8 +3272,8 @@ mod tests { }; let stake_account = AccountSharedData::new_data_with_space( total_lamports, - &StakeState::Initialized(meta), - StakeState::size_of(), + &StakeStateWithFlags::Initialized(meta), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -3328,15 +3342,18 @@ mod tests { instruction_accounts.clone(), Ok(()), ); - assert_eq!(from(&accounts[0]).unwrap(), StakeState::Uninitialized); + assert_eq!( + from(&accounts[0]).unwrap(), + StakeStateWithFlags::Uninitialized + ); // should pass, custodian is the same as the withdraw authority instruction_accounts[5].pubkey = stake_address; meta.lockup.custodian = stake_address; let stake_account_self_as_custodian = AccountSharedData::new_data_with_space( total_lamports, - &StakeState::Initialized(meta), - StakeState::size_of(), + &StakeStateWithFlags::Initialized(meta), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -3348,7 +3365,10 @@ mod tests { instruction_accounts.clone(), Ok(()), ); - assert_eq!(from(&accounts[0]).unwrap(), StakeState::Uninitialized); + assert_eq!( + from(&accounts[0]).unwrap(), + StakeStateWithFlags::Uninitialized + ); transaction_accounts[0] = (stake_address, stake_account); // should pass, lockup has expired @@ -3362,7 +3382,10 @@ mod tests { instruction_accounts, Ok(()), ); - assert_eq!(from(&accounts[0]).unwrap(), StakeState::Uninitialized); + assert_eq!( + from(&accounts[0]).unwrap(), + StakeStateWithFlags::Uninitialized + ); } #[test_case(feature_set_old_warmup_cooldown_no_minimum_delegation(); "old_warmup_cooldown_no_min_delegation")] @@ -3373,16 +3396,16 @@ mod tests { let custodian_address = solana_sdk::pubkey::new_rand(); let stake_address = solana_sdk::pubkey::new_rand(); let rent = Rent::default(); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let minimum_delegation = crate::get_minimum_delegation(&feature_set); let stake_lamports = 7 * minimum_delegation; let stake_account = AccountSharedData::new_data_with_space( stake_lamports + rent_exempt_reserve, - &StakeState::Initialized(Meta { + &StakeStateWithFlags::Initialized(Meta { rent_exempt_reserve, ..Meta::auto(&stake_address) }), - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -3471,8 +3494,8 @@ mod tests { let stake_lamports = minimum_delegation; let stake_account = AccountSharedData::new_data_with_space( stake_lamports, - &StakeState::Initialized(Meta::auto(&stake_address)), - StakeState::size_of(), + &StakeStateWithFlags::Initialized(Meta::auto(&stake_address)), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -3604,8 +3627,8 @@ mod tests { let stake_lamports = minimum_delegation; let stake_account = AccountSharedData::new_data_with_space( stake_lamports, - &StakeState::Uninitialized, - StakeState::size_of(), + &StakeStateWithFlags::Uninitialized, + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -3888,7 +3911,7 @@ mod tests { #[test_case(feature_set_all_enabled(); "all_enabled")] fn test_initialize_minimum_balance(feature_set: Arc) { let rent = Rent::default(); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let stake_address = solana_sdk::pubkey::new_rand(); let instruction_data = serialize(&StakeInstruction::Initialize( Authorized::auto(&stake_address), @@ -3914,7 +3937,8 @@ mod tests { Err(InstructionError::InsufficientFunds), ), ] { - let stake_account = AccountSharedData::new(lamports, StakeState::size_of(), &id()); + let stake_account = + AccountSharedData::new(lamports, StakeStateWithFlags::size_of(), &id()); process_instruction( Arc::clone(&feature_set), &instruction_data, @@ -3931,7 +3955,7 @@ mod tests { /// Ensure that `delegate()` respects the minimum delegation requirements /// - Assert 1: delegating an amount equal-to the minimum succeeds /// - Assert 2: delegating an amount less-than the minimum fails - /// Also test both asserts above over both StakeState::{Initialized and Stake}, since the logic + /// Also test both asserts above over both StakeStateWithFlags::{Initialized and Stake}, since the logic /// is slightly different for the variants. /// /// NOTE: Even though new stake accounts must have a minimum balance that is at least @@ -3945,7 +3969,7 @@ mod tests { fn test_delegate_minimum_stake_delegation(feature_set: Arc) { let minimum_delegation = crate::get_minimum_delegation(&feature_set); let rent = Rent::default(); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let stake_address = solana_sdk::pubkey::new_rand(); let meta = Meta { rent_exempt_reserve, @@ -3990,13 +4014,13 @@ mod tests { ), ] { for stake_state in &[ - StakeState::Initialized(meta), + StakeStateWithFlags::Initialized(meta), just_stake(meta, *stake_delegation), ] { let stake_account = AccountSharedData::new_data_with_space( stake_delegation + rent_exempt_reserve, stake_state, - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -4047,7 +4071,7 @@ mod tests { fn test_split_minimum_stake_delegation(feature_set: Arc) { let minimum_delegation = crate::get_minimum_delegation(&feature_set); let rent = Rent::default(); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let source_address = Pubkey::new_unique(); let source_meta = Meta { rent_exempt_reserve, @@ -4056,8 +4080,8 @@ mod tests { let dest_address = Pubkey::new_unique(); let dest_account = AccountSharedData::new_data_with_space( 0, - &StakeState::Uninitialized, - StakeState::size_of(), + &StakeStateWithFlags::Uninitialized, + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -4095,7 +4119,7 @@ mod tests { // accounts' *final* balance let mut source_starting_balance = source_reserve + dest_reserve; for (delegation, source_stake_state) in &[ - (0, StakeState::Initialized(source_meta)), + (0, StakeStateWithFlags::Initialized(source_meta)), ( minimum_delegation, just_stake( @@ -4108,7 +4132,7 @@ mod tests { let source_account = AccountSharedData::new_data_with_space( source_starting_balance, source_stake_state, - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -4140,7 +4164,7 @@ mod tests { fn test_split_full_amount_minimum_stake_delegation(feature_set: Arc) { let minimum_delegation = crate::get_minimum_delegation(&feature_set); let rent = Rent::default(); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let source_address = Pubkey::new_unique(); let source_meta = Meta { rent_exempt_reserve, @@ -4149,8 +4173,8 @@ mod tests { let dest_address = Pubkey::new_unique(); let dest_account = AccountSharedData::new_data_with_space( 0, - &StakeState::Uninitialized, - StakeState::size_of(), + &StakeStateWithFlags::Uninitialized, + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -4174,7 +4198,7 @@ mod tests { ), ] { for (stake_delegation, source_stake_state) in &[ - (0, StakeState::Initialized(source_meta)), + (0, StakeStateWithFlags::Initialized(source_meta)), ( minimum_delegation, just_stake(source_meta, minimum_delegation), @@ -4183,7 +4207,7 @@ mod tests { let source_account = AccountSharedData::new_data_with_space( stake_delegation + reserve, source_stake_state, - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -4210,7 +4234,7 @@ mod tests { #[test_case(feature_set_all_enabled(); "all_enabled")] fn test_initialized_split_destination_minimum_balance(feature_set: Arc) { let rent = Rent::default(); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let source_address = Pubkey::new_unique(); let destination_address = Pubkey::new_unique(); let instruction_accounts = vec![ @@ -4270,15 +4294,15 @@ mod tests { }; let source_account = AccountSharedData::new_data_with_space( source_balance, - &StakeState::Initialized(source_meta), - StakeState::size_of(), + &StakeStateWithFlags::Initialized(source_meta), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); let destination_account = AccountSharedData::new_data_with_space( destination_starting_balance, - &StakeState::Uninitialized, - StakeState::size_of(), + &StakeStateWithFlags::Uninitialized, + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -4309,7 +4333,7 @@ mod tests { ) { let minimum_delegation = crate::get_minimum_delegation(&feature_set); let rent = Rent::default(); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let source_address = Pubkey::new_unique(); let destination_address = Pubkey::new_unique(); let instruction_accounts = vec![ @@ -4401,14 +4425,14 @@ mod tests { let source_account = AccountSharedData::new_data_with_space( source_balance, &just_stake(source_meta, source_stake_delegation), - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); let destination_account = AccountSharedData::new_data_with_space( destination_starting_balance, - &StakeState::Uninitialized, - StakeState::size_of(), + &StakeStateWithFlags::Uninitialized, + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -4423,15 +4447,20 @@ mod tests { instruction_accounts.clone(), expected_result.clone(), ); - // For the expected OK cases, when the source's StakeState is Stake, then the - // destination's StakeState *must* also end up as Stake as well. Additionally, + // For the expected OK cases, when the source's StakeStateWithFlags is Stake, then the + // destination's StakeStateWithFlags *must* also end up as Stake as well. Additionally, // check to ensure the destination's delegation amount is correct. If the // destination is already rent exempt, then the destination's stake delegation // *must* equal the split amount. Otherwise, the split amount must first be used to // make the destination rent exempt, and then the leftover lamports are delegated. if expected_result.is_ok() { - assert_matches!(accounts[0].state().unwrap(), StakeState::Stake(_, _, _)); - if let StakeState::Stake(_, destination_stake, _) = accounts[1].state().unwrap() { + assert_matches!( + accounts[0].state().unwrap(), + StakeStateWithFlags::Stake(_, _, _) + ); + if let StakeStateWithFlags::Stake(_, destination_stake, _) = + accounts[1].state().unwrap() + { let destination_initial_rent_deficit = rent_exempt_reserve.saturating_sub(destination_starting_balance); let expected_destination_stake_delegation = @@ -4442,7 +4471,7 @@ mod tests { ); assert!(destination_stake.delegation.stake >= minimum_delegation,); } else { - panic!("destination state must be StakeStake::Stake after successful split when source is also StakeState::Stake!"); + panic!("destination state must be StakeStake::Stake after successful split when source is also StakeStateWithFlags::Stake!"); } } } @@ -4457,7 +4486,7 @@ mod tests { fn test_withdraw_minimum_stake_delegation(feature_set: Arc) { let minimum_delegation = crate::get_minimum_delegation(&feature_set); let rent = Rent::default(); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let stake_address = solana_sdk::pubkey::new_rand(); let meta = Meta { rent_exempt_reserve, @@ -4500,14 +4529,14 @@ mod tests { ), ] { for (stake_delegation, stake_state) in &[ - (0, StakeState::Initialized(meta)), + (0, StakeStateWithFlags::Initialized(meta)), (minimum_delegation, just_stake(meta, minimum_delegation)), ] { let rewards_balance = 123; let stake_account = AccountSharedData::new_data_with_space( stake_delegation + rent_exempt_reserve + rewards_balance, stake_state, - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -4567,11 +4596,11 @@ mod tests { let feature_set = feature_set_all_enabled(); let minimum_delegation = crate::get_minimum_delegation(&feature_set); let rent = Rent::default(); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let stake_address = solana_sdk::pubkey::new_rand(); let stake_account = AccountSharedData::new( rent_exempt_reserve + minimum_delegation, - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ); let vote_address = solana_sdk::pubkey::new_rand(); @@ -4740,22 +4769,22 @@ mod tests { #[test_case(feature_set_all_enabled(); "all_enabled")] fn test_split_source_uninitialized(feature_set: Arc) { let rent = Rent::default(); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let minimum_delegation = crate::get_minimum_delegation(&feature_set); let stake_lamports = (rent_exempt_reserve + minimum_delegation) * 2; let stake_address = solana_sdk::pubkey::new_rand(); let stake_account = AccountSharedData::new_data_with_space( stake_lamports, - &StakeState::Uninitialized, - StakeState::size_of(), + &StakeStateWithFlags::Uninitialized, + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); let split_to_address = solana_sdk::pubkey::new_rand(); let split_to_account = AccountSharedData::new_data_with_space( 0, - &StakeState::Uninitialized, - StakeState::size_of(), + &StakeStateWithFlags::Uninitialized, + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -4845,7 +4874,7 @@ mod tests { let stake_account = AccountSharedData::new_data_with_space( stake_lamports, &just_stake(Meta::auto(&stake_address), stake_lamports), - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -4864,14 +4893,14 @@ mod tests { ]; for split_to_state in &[ - StakeState::Initialized(Meta::default()), - StakeState::Stake(Meta::default(), Stake::default(), StakeFlags::default()), - StakeState::RewardsPool, + StakeStateWithFlags::Initialized(Meta::default()), + StakeStateWithFlags::Stake(Meta::default(), Stake::default(), StakeFlags::default()), + StakeStateWithFlags::RewardsPool, ] { let split_to_account = AccountSharedData::new_data_with_space( 0, split_to_state, - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -4893,7 +4922,7 @@ mod tests { #[test_case(feature_set_all_enabled(); "all_enabled")] fn test_split_more_than_staked(feature_set: Arc) { let rent = Rent::default(); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let minimum_delegation = crate::get_minimum_delegation(&feature_set); let stake_lamports = (rent_exempt_reserve + minimum_delegation) * 2; let stake_address = solana_sdk::pubkey::new_rand(); @@ -4906,15 +4935,15 @@ mod tests { }, stake_lamports / 2 - 1, ), - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); let split_to_address = solana_sdk::pubkey::new_rand(); let split_to_account = AccountSharedData::new_data_with_space( 0, - &StakeState::Uninitialized, - StakeState::size_of(), + &StakeStateWithFlags::Uninitialized, + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -4950,14 +4979,14 @@ mod tests { #[test_case(feature_set_all_enabled(); "all_enabled")] fn test_split_with_rent(feature_set: Arc) { let rent = Rent::default(); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let minimum_delegation = crate::get_minimum_delegation(&feature_set); let stake_address = solana_sdk::pubkey::new_rand(); let split_to_address = solana_sdk::pubkey::new_rand(); let split_to_account = AccountSharedData::new_data_with_space( 0, - &StakeState::Uninitialized, - StakeState::size_of(), + &StakeStateWithFlags::Uninitialized, + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -4981,7 +5010,7 @@ mod tests { // test splitting both an Initialized stake and a Staked stake for (minimum_balance, state) in &[ - (rent_exempt_reserve, StakeState::Initialized(meta)), + (rent_exempt_reserve, StakeStateWithFlags::Initialized(meta)), ( rent_exempt_reserve + minimum_delegation, just_stake(meta, minimum_delegation * 2 + rent_exempt_reserve), @@ -4991,7 +5020,7 @@ mod tests { let stake_account = AccountSharedData::new_data_with_space( stake_lamports, state, - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -5033,10 +5062,10 @@ mod tests { ); // verify no stake leakage in the case of a stake - if let StakeState::Stake(meta, stake, stake_flags) = state { + if let StakeStateWithFlags::Stake(meta, stake, stake_flags) = state { assert_eq!( accounts[1].state(), - Ok(StakeState::Stake( + Ok(StakeStateWithFlags::Stake( *meta, Stake { delegation: Delegation { @@ -5059,7 +5088,7 @@ mod tests { #[test_case(feature_set_all_enabled(); "all_enabled")] fn test_split_to_account_with_rent_exempt_reserve(feature_set: Arc) { let rent = Rent::default(); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let minimum_delegation = crate::get_minimum_delegation(&feature_set); let stake_lamports = (rent_exempt_reserve + minimum_delegation) * 2; let stake_address = solana_sdk::pubkey::new_rand(); @@ -5072,7 +5101,7 @@ mod tests { let stake_account = AccountSharedData::new_data_with_space( stake_lamports, &state, - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -5103,8 +5132,8 @@ mod tests { for initial_balance in split_lamport_balances { let split_to_account = AccountSharedData::new_data_with_space( initial_balance, - &StakeState::Uninitialized, - StakeState::size_of(), + &StakeStateWithFlags::Uninitialized, + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -5137,11 +5166,11 @@ mod tests { stake_lamports + initial_balance, ); - if let StakeState::Stake(meta, stake, stake_flags) = state { + if let StakeStateWithFlags::Stake(meta, stake, stake_flags) = state { let expected_stake = stake_lamports / 2 - (rent_exempt_reserve.saturating_sub(initial_balance)); assert_eq!( - Ok(StakeState::Stake( + Ok(StakeStateWithFlags::Stake( meta, Stake { delegation: Delegation { @@ -5162,7 +5191,7 @@ mod tests { + initial_balance.saturating_sub(rent_exempt_reserve), ); assert_eq!( - Ok(StakeState::Stake( + Ok(StakeStateWithFlags::Stake( meta, Stake { delegation: Delegation { @@ -5184,8 +5213,9 @@ mod tests { #[test_case(feature_set_all_enabled(); "all_enabled")] fn test_split_from_larger_sized_account(feature_set: Arc) { let rent = Rent::default(); - let source_larger_rent_exempt_reserve = rent.minimum_balance(StakeState::size_of() + 100); - let split_rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let source_larger_rent_exempt_reserve = + rent.minimum_balance(StakeStateWithFlags::size_of() + 100); + let split_rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let minimum_delegation = crate::get_minimum_delegation(&feature_set); let stake_lamports = (source_larger_rent_exempt_reserve + minimum_delegation) * 2; let stake_address = solana_sdk::pubkey::new_rand(); @@ -5198,7 +5228,7 @@ mod tests { let stake_account = AccountSharedData::new_data_with_space( stake_lamports, &state, - StakeState::size_of() + 100, + StakeStateWithFlags::size_of() + 100, &id(), ) .unwrap(); @@ -5229,8 +5259,8 @@ mod tests { for initial_balance in split_lamport_balances { let split_to_account = AccountSharedData::new_data_with_space( initial_balance, - &StakeState::Uninitialized, - StakeState::size_of(), + &StakeStateWithFlags::Uninitialized, + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -5263,7 +5293,7 @@ mod tests { stake_lamports + initial_balance ); - if let StakeState::Stake(meta, stake, stake_flags) = state { + if let StakeStateWithFlags::Stake(meta, stake, stake_flags) = state { let expected_split_meta = Meta { authorized: Authorized::auto(&stake_address), rent_exempt_reserve: split_rent_exempt_reserve, @@ -5273,7 +5303,7 @@ mod tests { - (split_rent_exempt_reserve.saturating_sub(initial_balance)); assert_eq!( - Ok(StakeState::Stake( + Ok(StakeStateWithFlags::Stake( expected_split_meta, Stake { delegation: Delegation { @@ -5293,7 +5323,7 @@ mod tests { + initial_balance.saturating_sub(split_rent_exempt_reserve) ); assert_eq!( - Ok(StakeState::Stake( + Ok(StakeStateWithFlags::Stake( meta, Stake { delegation: Delegation { @@ -5315,8 +5345,9 @@ mod tests { #[test_case(feature_set_all_enabled(); "all_enabled")] fn test_split_from_smaller_sized_account(feature_set: Arc) { let rent = Rent::default(); - let source_smaller_rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); - let split_rent_exempt_reserve = rent.minimum_balance(StakeState::size_of() + 100); + let source_smaller_rent_exempt_reserve = + rent.minimum_balance(StakeStateWithFlags::size_of()); + let split_rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of() + 100); let stake_lamports = split_rent_exempt_reserve + 1; let stake_address = solana_sdk::pubkey::new_rand(); let meta = Meta { @@ -5328,7 +5359,7 @@ mod tests { let stake_account = AccountSharedData::new_data_with_space( stake_lamports, &state, - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -5356,8 +5387,8 @@ mod tests { for initial_balance in split_lamport_balances { let split_to_account = AccountSharedData::new_data_with_space( initial_balance, - &StakeState::Uninitialized, - StakeState::size_of() + 100, + &StakeStateWithFlags::Uninitialized, + StakeStateWithFlags::size_of() + 100, &id(), ) .unwrap(); @@ -5392,7 +5423,7 @@ mod tests { #[test_case(feature_set_all_enabled(); "all_enabled")] fn test_split_100_percent_of_source(feature_set: Arc) { let rent = Rent::default(); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let minimum_delegation = crate::get_minimum_delegation(&feature_set); let stake_lamports = rent_exempt_reserve + minimum_delegation; let stake_address = solana_sdk::pubkey::new_rand(); @@ -5404,8 +5435,8 @@ mod tests { let split_to_address = solana_sdk::pubkey::new_rand(); let split_to_account = AccountSharedData::new_data_with_space( 0, - &StakeState::Uninitialized, - StakeState::size_of(), + &StakeStateWithFlags::Uninitialized, + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -5424,13 +5455,13 @@ mod tests { // test splitting both an Initialized stake and a Staked stake for state in &[ - StakeState::Initialized(meta), + StakeStateWithFlags::Initialized(meta), just_stake(meta, stake_lamports - rent_exempt_reserve), ] { let stake_account = AccountSharedData::new_data_with_space( stake_lamports, &state, - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -5456,13 +5487,13 @@ mod tests { ); match state { - StakeState::Initialized(_) => { + StakeStateWithFlags::Initialized(_) => { assert_eq!(Ok(*state), accounts[1].state()); - assert_eq!(Ok(StakeState::Uninitialized), accounts[0].state()); + assert_eq!(Ok(StakeStateWithFlags::Uninitialized), accounts[0].state()); } - StakeState::Stake(meta, stake, stake_flags) => { + StakeStateWithFlags::Stake(meta, stake, stake_flags) => { assert_eq!( - Ok(StakeState::Stake( + Ok(StakeStateWithFlags::Stake( *meta, Stake { delegation: Delegation { @@ -5475,7 +5506,7 @@ mod tests { )), accounts[1].state() ); - assert_eq!(Ok(StakeState::Uninitialized), accounts[0].state()); + assert_eq!(Ok(StakeStateWithFlags::Uninitialized), accounts[0].state()); } _ => unreachable!(), } @@ -5487,7 +5518,7 @@ mod tests { #[test_case(feature_set_all_enabled(); "all_enabled")] fn test_split_100_percent_of_source_to_account_with_lamports(feature_set: Arc) { let rent = Rent::default(); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let minimum_delegation = crate::get_minimum_delegation(&feature_set); let stake_lamports = rent_exempt_reserve + minimum_delegation; let stake_address = solana_sdk::pubkey::new_rand(); @@ -5500,7 +5531,7 @@ mod tests { let stake_account = AccountSharedData::new_data_with_space( stake_lamports, &state, - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -5531,8 +5562,8 @@ mod tests { for initial_balance in split_lamport_balances { let split_to_account = AccountSharedData::new_data_with_space( initial_balance, - &StakeState::Uninitialized, - StakeState::size_of(), + &StakeStateWithFlags::Uninitialized, + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -5557,9 +5588,9 @@ mod tests { stake_lamports + initial_balance ); - if let StakeState::Stake(meta, stake, stake_flags) = state { + if let StakeStateWithFlags::Stake(meta, stake, stake_flags) = state { assert_eq!( - Ok(StakeState::Stake( + Ok(StakeStateWithFlags::Stake( meta, Stake { delegation: Delegation { @@ -5572,7 +5603,7 @@ mod tests { )), accounts[1].state() ); - assert_eq!(Ok(StakeState::Uninitialized), accounts[0].state()); + assert_eq!(Ok(StakeStateWithFlags::Uninitialized), accounts[0].state()); } } } @@ -5582,8 +5613,8 @@ mod tests { #[test_case(feature_set_all_enabled(); "all_enabled")] fn test_split_rent_exemptness(feature_set: Arc) { let rent = Rent::default(); - let source_rent_exempt_reserve = rent.minimum_balance(StakeState::size_of() + 100); - let split_rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let source_rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of() + 100); + let split_rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let minimum_delegation = crate::get_minimum_delegation(&feature_set); let stake_lamports = source_rent_exempt_reserve + minimum_delegation; let stake_address = solana_sdk::pubkey::new_rand(); @@ -5607,21 +5638,21 @@ mod tests { ]; for state in &[ - StakeState::Initialized(meta), + StakeStateWithFlags::Initialized(meta), just_stake(meta, stake_lamports - source_rent_exempt_reserve), ] { // Test that splitting to a larger account fails let stake_account = AccountSharedData::new_data_with_space( stake_lamports, &state, - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); let split_to_account = AccountSharedData::new_data_with_space( 0, - &StakeState::Uninitialized, - StakeState::size_of() + 10000, + &StakeStateWithFlags::Uninitialized, + StakeStateWithFlags::size_of() + 10000, &id(), ) .unwrap(); @@ -5643,14 +5674,14 @@ mod tests { let stake_account = AccountSharedData::new_data_with_space( stake_lamports, &state, - StakeState::size_of() + 100, + StakeStateWithFlags::size_of() + 100, &id(), ) .unwrap(); let split_to_account = AccountSharedData::new_data_with_space( 0, - &StakeState::Uninitialized, - StakeState::size_of(), + &StakeStateWithFlags::Uninitialized, + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -5674,20 +5705,20 @@ mod tests { ..Meta::default() }; match state { - StakeState::Initialized(_) => { + StakeStateWithFlags::Initialized(_) => { assert_eq!( - Ok(StakeState::Initialized(expected_split_meta)), + Ok(StakeStateWithFlags::Initialized(expected_split_meta)), accounts[1].state() ); - assert_eq!(Ok(StakeState::Uninitialized), accounts[0].state()); + assert_eq!(Ok(StakeStateWithFlags::Uninitialized), accounts[0].state()); } - StakeState::Stake(_meta, stake, stake_flags) => { + StakeStateWithFlags::Stake(_meta, stake, stake_flags) => { // Expected stake should reflect original stake amount so that extra lamports // from the rent_exempt_reserve inequality do not magically activate let expected_stake = stake_lamports - source_rent_exempt_reserve; assert_eq!( - Ok(StakeState::Stake( + Ok(StakeStateWithFlags::Stake( expected_split_meta, Stake { delegation: Delegation { @@ -5704,7 +5735,7 @@ mod tests { accounts[1].lamports(), expected_stake + source_rent_exempt_reserve, ); - assert_eq!(Ok(StakeState::Uninitialized), accounts[0].state()); + assert_eq!(Ok(StakeStateWithFlags::Uninitialized), accounts[0].state()); } _ => unreachable!(), } @@ -5749,24 +5780,24 @@ mod tests { ]; for state in &[ - StakeState::Initialized(meta), + StakeStateWithFlags::Initialized(meta), just_stake(meta, stake_lamports), ] { let stake_account = AccountSharedData::new_data_with_space( stake_lamports, state, - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); for merge_from_state in &[ - StakeState::Initialized(meta), + StakeStateWithFlags::Initialized(meta), just_stake(meta, stake_lamports), ] { let merge_from_account = AccountSharedData::new_data_with_space( stake_lamports, merge_from_state, - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -5813,10 +5844,13 @@ mod tests { // check state match state { - StakeState::Initialized(meta) => { - assert_eq!(accounts[0].state(), Ok(StakeState::Initialized(*meta)),); + StakeStateWithFlags::Initialized(meta) => { + assert_eq!( + accounts[0].state(), + Ok(StakeStateWithFlags::Initialized(*meta)), + ); } - StakeState::Stake(meta, stake, stake_flags) => { + StakeStateWithFlags::Stake(meta, stake, stake_flags) => { let expected_stake = stake.delegation.stake + merge_from_state .stake() @@ -5827,7 +5861,7 @@ mod tests { }); assert_eq!( accounts[0].state(), - Ok(StakeState::Stake( + Ok(StakeStateWithFlags::Stake( *meta, Stake { delegation: Delegation { @@ -5842,7 +5876,7 @@ mod tests { } _ => unreachable!(), } - assert_eq!(accounts[1].state(), Ok(StakeState::Uninitialized)); + assert_eq!(accounts[1].state(), Ok(StakeStateWithFlags::Uninitialized)); } } } @@ -5854,7 +5888,7 @@ mod tests { let stake_address = solana_sdk::pubkey::new_rand(); let authorized_address = solana_sdk::pubkey::new_rand(); let rent = Rent::default(); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let stake_amount = 4242424242; let stake_lamports = rent_exempt_reserve + stake_amount; let meta = Meta { @@ -5871,8 +5905,8 @@ mod tests { }; let stake_account = AccountSharedData::new_data_with_space( stake_lamports, - &StakeState::Stake(meta, stake, StakeFlags::empty()), - StakeState::size_of(), + &StakeStateWithFlags::Stake(meta, stake, StakeFlags::empty()), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -5963,24 +5997,24 @@ mod tests { ]; for state in &[ - StakeState::Initialized(Meta::auto(&authorized_address)), + StakeStateWithFlags::Initialized(Meta::auto(&authorized_address)), just_stake(Meta::auto(&authorized_address), stake_lamports), ] { let stake_account = AccountSharedData::new_data_with_space( stake_lamports, state, - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); for merge_from_state in &[ - StakeState::Initialized(Meta::auto(&wrong_authorized_address)), + StakeStateWithFlags::Initialized(Meta::auto(&wrong_authorized_address)), just_stake(Meta::auto(&wrong_authorized_address), stake_lamports), ] { let merge_from_account = AccountSharedData::new_data_with_space( stake_lamports, merge_from_state, - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -6061,23 +6095,26 @@ mod tests { ]; for state in &[ - StakeState::Uninitialized, - StakeState::RewardsPool, - StakeState::Initialized(Meta::auto(&authorized_address)), + StakeStateWithFlags::Uninitialized, + StakeStateWithFlags::RewardsPool, + StakeStateWithFlags::Initialized(Meta::auto(&authorized_address)), just_stake(Meta::auto(&authorized_address), stake_lamports), ] { let stake_account = AccountSharedData::new_data_with_space( stake_lamports, state, - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); - for merge_from_state in &[StakeState::Uninitialized, StakeState::RewardsPool] { + for merge_from_state in &[ + StakeStateWithFlags::Uninitialized, + StakeStateWithFlags::RewardsPool, + ] { let merge_from_account = AccountSharedData::new_data_with_space( stake_lamports, merge_from_state, - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -6121,14 +6158,14 @@ mod tests { let stake_account = AccountSharedData::new_data_with_space( stake_lamports, &just_stake(Meta::auto(&authorized_address), stake_lamports), - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); let merge_from_account = AccountSharedData::new_data_with_space( stake_lamports, &just_stake(Meta::auto(&authorized_address), stake_lamports), - StakeState::size_of(), + StakeStateWithFlags::size_of(), &solana_sdk::pubkey::new_rand(), ) .unwrap(); @@ -6191,7 +6228,7 @@ mod tests { let authorized_address = solana_sdk::pubkey::new_rand(); let base_lamports = 4242424242; let rent = Rent::default(); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let stake_amount = base_lamports; let stake_lamports = rent_exempt_reserve + stake_amount; let merge_from_amount = base_lamports; @@ -6210,8 +6247,8 @@ mod tests { }; let stake_account = AccountSharedData::new_data_with_space( stake_lamports, - &StakeState::Stake(meta, stake, StakeFlags::empty()), - StakeState::size_of(), + &StakeStateWithFlags::Stake(meta, stake, StakeFlags::empty()), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -6226,8 +6263,8 @@ mod tests { }; let merge_from_account = AccountSharedData::new_data_with_space( merge_from_lamports, - &StakeState::Stake(meta, merge_from_stake, StakeFlags::empty()), - StakeState::size_of(), + &StakeStateWithFlags::Stake(meta, merge_from_stake, StakeFlags::empty()), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -6306,7 +6343,7 @@ mod tests { if expected_result.is_ok() { assert_eq!( accounts[1 - iteration].state(), - Ok(StakeState::Uninitialized) + Ok(StakeStateWithFlags::Uninitialized) ); } } @@ -6405,7 +6442,11 @@ mod tests { }; transaction_accounts[0] .1 - .set_state(&StakeState::Stake(meta, stake, StakeFlags::empty())) + .set_state(&StakeStateWithFlags::Stake( + meta, + stake, + StakeFlags::empty(), + )) .unwrap(); } if clock.epoch == merge_from_deactivation_epoch { @@ -6419,7 +6460,7 @@ mod tests { }; transaction_accounts[1] .1 - .set_state(&StakeState::Stake( + .set_state(&StakeStateWithFlags::Stake( meta, merge_from_stake, StakeFlags::empty(), @@ -6518,7 +6559,8 @@ mod tests { let rent_account = create_account_shared_data_for_test(&rent); let good_stake_address = Pubkey::new_unique(); - let good_stake_account = AccountSharedData::new(u64::MAX, StakeState::size_of(), &id()); + let good_stake_account = + AccountSharedData::new(u64::MAX, StakeStateWithFlags::size_of(), &id()); let good_instruction = instruction::initialize( &good_stake_address, &Authorized::auto(&good_stake_address), @@ -6586,7 +6628,7 @@ mod tests { let vote_address = Pubkey::new_unique(); let stake_address = Pubkey::new_unique(); - let initial_stake_state = StakeState::Stake( + let initial_stake_state = StakeStateWithFlags::Stake( Meta::default(), new_stake( 1, /* stake */ @@ -6600,7 +6642,7 @@ mod tests { let stake_account = AccountSharedData::new_data_with_space( 1, /* lamports */ &initial_stake_state, - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap(); @@ -6785,7 +6827,7 @@ mod tests { let mut unrelated_stake_account = stake_account.clone(); assert_ne!(unrelated_vote_address, vote_address); unrelated_stake_account - .serialize_data(&StakeState::Stake( + .serialize_data(&StakeStateWithFlags::Stake( Meta::default(), new_stake( 1, /* stake */ @@ -6852,7 +6894,7 @@ mod tests { let minimum_delegation = crate::get_minimum_delegation(&feature_set); let rent = Rent::default(); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let stake_history = StakeHistory::default(); let current_epoch = 100; @@ -6872,7 +6914,7 @@ mod tests { let prepare_stake_account = |activation_epoch, expected_stake_activation_status| { let initial_stake_delegation = minimum_delegation + rent_exempt_reserve; - let initial_stake_state = StakeState::Stake( + let initial_stake_state = StakeStateWithFlags::Stake( Meta { authorized: Authorized { staker: authorized_staker, @@ -6907,7 +6949,7 @@ mod tests { AccountSharedData::new_data_with_space( rent_exempt_reserve + initial_stake_delegation, /* lamports */ &initial_stake_state, - StakeState::size_of(), + StakeStateWithFlags::size_of(), &id(), ) .unwrap() @@ -6999,7 +7041,7 @@ mod tests { // let stake_account = prepare_stake_account(0 /*activation_epoch*/, None); let uninitialized_stake_account = - AccountSharedData::new(0 /* lamports */, StakeState::size_of(), &id()); + AccountSharedData::new(0 /* lamports */, StakeStateWithFlags::size_of(), &id()); let _ = process_instruction_redelegate( &stake_address, @@ -7027,7 +7069,9 @@ mod tests { ); assert_eq!(output_accounts[0].lamports(), rent_exempt_reserve); - if let StakeState::Stake(meta, stake, _) = output_accounts[0].deserialize_data().unwrap() { + if let StakeStateWithFlags::Stake(meta, stake, _) = + output_accounts[0].deserialize_data().unwrap() + { assert_eq!(meta.rent_exempt_reserve, rent_exempt_reserve); assert_eq!( stake.delegation.stake, @@ -7042,7 +7086,9 @@ mod tests { output_accounts[1].lamports(), minimum_delegation + rent_exempt_reserve ); - if let StakeState::Stake(meta, stake, _) = output_accounts[1].deserialize_data().unwrap() { + if let StakeStateWithFlags::Stake(meta, stake, _) = + output_accounts[1].deserialize_data().unwrap() + { assert_eq!(meta.rent_exempt_reserve, rent_exempt_reserve); assert_eq!(stake.delegation.stake, minimum_delegation); assert_eq!(stake.delegation.activation_epoch, current_epoch); @@ -7172,8 +7218,11 @@ mod tests { // // Success: `uninitialized_stake_account` starts with 42 extra lamports // - let uninitialized_stake_account_with_extra_lamports = - AccountSharedData::new(42 /* lamports */, StakeState::size_of(), &id()); + let uninitialized_stake_account_with_extra_lamports = AccountSharedData::new( + 42, /* lamports */ + StakeStateWithFlags::size_of(), + &id(), + ); let output_accounts = process_instruction_redelegate( &stake_address, &stake_account, @@ -7190,7 +7239,9 @@ mod tests { output_accounts[1].lamports(), minimum_delegation + rent_exempt_reserve + 42 ); - if let StakeState::Stake(meta, stake, _) = output_accounts[1].deserialize_data().unwrap() { + if let StakeStateWithFlags::Stake(meta, stake, _) = + output_accounts[1].deserialize_data().unwrap() + { assert_eq!(meta.rent_exempt_reserve, rent_exempt_reserve); assert_eq!(stake.delegation.stake, minimum_delegation + 42); assert_eq!(stake.delegation.activation_epoch, current_epoch); @@ -7204,12 +7255,12 @@ mod tests { // let mut stake_account_over_allocated = prepare_stake_account(0 /*activation_epoch:*/, None); - if let StakeState::Stake(mut meta, stake, stake_flags) = + if let StakeStateWithFlags::Stake(mut meta, stake, stake_flags) = stake_account_over_allocated.deserialize_data().unwrap() { meta.rent_exempt_reserve += 42; stake_account_over_allocated - .set_state(&StakeState::Stake(meta, stake, stake_flags)) + .set_state(&StakeStateWithFlags::Stake(meta, stake, stake_flags)) .unwrap(); } stake_account_over_allocated @@ -7232,7 +7283,9 @@ mod tests { ); assert_eq!(output_accounts[0].lamports(), rent_exempt_reserve + 42); - if let StakeState::Stake(meta, _stake, _) = output_accounts[0].deserialize_data().unwrap() { + if let StakeStateWithFlags::Stake(meta, _stake, _) = + output_accounts[0].deserialize_data().unwrap() + { assert_eq!(meta.rent_exempt_reserve, rent_exempt_reserve + 42); } else { panic!("Invalid output_accounts[0] data"); @@ -7241,7 +7294,9 @@ mod tests { output_accounts[1].lamports(), minimum_delegation + rent_exempt_reserve, ); - if let StakeState::Stake(meta, stake, _) = output_accounts[1].deserialize_data().unwrap() { + if let StakeStateWithFlags::Stake(meta, stake, _) = + output_accounts[1].deserialize_data().unwrap() + { assert_eq!(meta.rent_exempt_reserve, rent_exempt_reserve); assert_eq!(stake.delegation.stake, minimum_delegation); } else { @@ -7260,7 +7315,7 @@ mod tests { &uninitialized_stake_address, &AccountSharedData::new( 0, /* lamports */ - StakeState::size_of(), + StakeStateWithFlags::size_of(), &Pubkey::new_unique(), // <-- Invalid program id ), Err(InstructionError::IncorrectProgramId), @@ -7276,7 +7331,11 @@ mod tests { &new_vote_address, &new_vote_account, &uninitialized_stake_address, - &AccountSharedData::new(0 /* lamports */, StakeState::size_of() - 1, &id()), // <-- size too small + &AccountSharedData::new( + 0, /* lamports */ + StakeStateWithFlags::size_of() - 1, + &id(), + ), // <-- size too small Err(InstructionError::InvalidAccountData), ); @@ -7290,7 +7349,11 @@ mod tests { &new_vote_address, &new_vote_account, &uninitialized_stake_address, - &AccountSharedData::new(0 /* lamports */, StakeState::size_of() + 1, &id()), // <-- size too large + &AccountSharedData::new( + 0, /* lamports */ + StakeStateWithFlags::size_of() + 1, + &id(), + ), // <-- size too large Err(InstructionError::InvalidAccountData), ); @@ -7379,7 +7442,7 @@ mod tests { let mut deactivating_stake_account = prepare_stake_account(0 /*activation_epoch:*/, None); - if let StakeState::Stake(meta, mut stake, _stake_flags) = + if let StakeStateWithFlags::Stake(meta, mut stake, _stake_flags) = deactivating_stake_account.deserialize_data().unwrap() { stake.deactivate(current_epoch).unwrap(); @@ -7397,7 +7460,11 @@ mod tests { ); deactivating_stake_account - .set_state(&StakeState::Stake(meta, stake, StakeFlags::empty())) + .set_state(&StakeStateWithFlags::Stake( + meta, + stake, + StakeFlags::empty(), + )) .unwrap(); } let _ = process_instruction_redelegate( @@ -7416,7 +7483,7 @@ mod tests { // (less than `minimum_delegation + rent_exempt_reserve`) // let mut stake_account_too_few_lamports = stake_account.clone(); - if let StakeState::Stake(meta, mut stake, stake_flags) = + if let StakeStateWithFlags::Stake(meta, mut stake, stake_flags) = stake_account_too_few_lamports.deserialize_data().unwrap() { stake.delegation.stake -= 1; @@ -7425,7 +7492,7 @@ mod tests { minimum_delegation + rent_exempt_reserve - 1 ); stake_account_too_few_lamports - .set_state(&StakeState::Stake(meta, stake, stake_flags)) + .set_state(&StakeStateWithFlags::Stake(meta, stake, stake_flags)) .unwrap(); } else { panic!("Invalid stake_account"); diff --git a/programs/stake/src/stake_state.rs b/programs/stake/src/stake_state.rs index eaf7b2bff0..23c8ab12a9 100644 --- a/programs/stake/src/stake_state.rs +++ b/programs/stake/src/stake_state.rs @@ -73,28 +73,34 @@ pub(crate) fn null_tracer() -> Option } // utility function, used by Stakes, tests -pub fn from>(account: &T) -> Option { +pub fn from>( + account: &T, +) -> Option { account.state().ok() } -pub fn stake_from>(account: &T) -> Option { - from(account).and_then(|state: StakeState| state.stake()) +pub fn stake_from>( + account: &T, +) -> Option { + from(account).and_then(|state: StakeStateWithFlags| state.stake()) } pub fn delegation_from(account: &AccountSharedData) -> Option { - from(account).and_then(|state: StakeState| state.delegation()) + from(account).and_then(|state: StakeStateWithFlags| state.delegation()) } pub fn authorized_from(account: &AccountSharedData) -> Option { - from(account).and_then(|state: StakeState| state.authorized()) + from(account).and_then(|state: StakeStateWithFlags| state.authorized()) } -pub fn lockup_from>(account: &T) -> Option { - from(account).and_then(|state: StakeState| state.lockup()) +pub fn lockup_from>( + account: &T, +) -> Option { + from(account).and_then(|state: StakeStateWithFlags| state.lockup()) } pub fn meta_from(account: &AccountSharedData) -> Option { - from(account).and_then(|state: StakeState| state.meta()) + from(account).and_then(|state: StakeStateWithFlags| state.meta()) } pub(crate) fn new_warmup_cooldown_rate_epoch(invoke_context: &InvokeContext) -> Option { @@ -470,13 +476,13 @@ pub fn initialize( lockup: &Lockup, rent: &Rent, ) -> Result<(), InstructionError> { - if stake_account.get_data().len() != StakeState::size_of() { + if stake_account.get_data().len() != StakeStateWithFlags::size_of() { return Err(InstructionError::InvalidAccountData); } - if let StakeState::Uninitialized = stake_account.get_state()? { + if let StakeStateWithFlags::Uninitialized = stake_account.get_state()? { let rent_exempt_reserve = rent.minimum_balance(stake_account.get_data().len()); if stake_account.get_lamports() >= rent_exempt_reserve { - stake_account.set_state(&StakeState::Initialized(Meta { + stake_account.set_state(&StakeStateWithFlags::Initialized(Meta { rent_exempt_reserve, authorized: *authorized, lockup: *lockup, @@ -502,7 +508,7 @@ pub fn authorize( custodian: Option<&Pubkey>, ) -> Result<(), InstructionError> { match stake_account.get_state()? { - StakeState::Stake(mut meta, stake, stake_flags) => { + StakeStateWithFlags::Stake(mut meta, stake, stake_flags) => { meta.authorized.authorize( signers, new_authority, @@ -513,9 +519,9 @@ pub fn authorize( None }, )?; - stake_account.set_state(&StakeState::Stake(meta, stake, stake_flags)) + stake_account.set_state(&StakeStateWithFlags::Stake(meta, stake, stake_flags)) } - StakeState::Initialized(mut meta) => { + StakeStateWithFlags::Initialized(mut meta) => { meta.authorized.authorize( signers, new_authority, @@ -526,7 +532,7 @@ pub fn authorize( None }, )?; - stake_account.set_state(&StakeState::Initialized(meta)) + stake_account.set_state(&StakeStateWithFlags::Initialized(meta)) } _ => Err(InstructionError::InvalidAccountData), } @@ -593,7 +599,7 @@ pub fn delegate( let mut stake_account = instruction_context .try_borrow_instruction_account(transaction_context, stake_account_index)?; match stake_account.get_state()? { - StakeState::Initialized(meta) => { + StakeStateWithFlags::Initialized(meta) => { meta.authorized.check(signers, StakeAuthorize::Staker)?; let ValidatedDelegatedInfo { stake_amount } = validate_delegated_amount(&stake_account, &meta, feature_set)?; @@ -603,9 +609,13 @@ pub fn delegate( &vote_state?.convert_to_current(), clock.epoch, ); - stake_account.set_state(&StakeState::Stake(meta, stake, StakeFlags::empty())) + stake_account.set_state(&StakeStateWithFlags::Stake( + meta, + stake, + StakeFlags::empty(), + )) } - StakeState::Stake(meta, mut stake, stake_flags) => { + StakeStateWithFlags::Stake(meta, mut stake, stake_flags) => { meta.authorized.check(signers, StakeAuthorize::Staker)?; let ValidatedDelegatedInfo { stake_amount } = validate_delegated_amount(&stake_account, &meta, feature_set)?; @@ -618,7 +628,7 @@ pub fn delegate( clock, stake_history, )?; - stake_account.set_state(&StakeState::Stake(meta, stake, stake_flags)) + stake_account.set_state(&StakeStateWithFlags::Stake(meta, stake, stake_flags)) } _ => Err(InstructionError::InvalidAccountData), } @@ -629,11 +639,11 @@ pub fn deactivate( clock: &Clock, signers: &HashSet, ) -> Result<(), InstructionError> { - if let StakeState::Stake(meta, mut stake, stake_flags) = stake_account.get_state()? { + if let StakeStateWithFlags::Stake(meta, mut stake, stake_flags) = stake_account.get_state()? { meta.authorized.check(signers, StakeAuthorize::Staker)?; stake.deactivate(clock.epoch)?; - stake_account.set_state(&StakeState::Stake(meta, stake, stake_flags)) + stake_account.set_state(&StakeStateWithFlags::Stake(meta, stake, stake_flags)) } else { Err(InstructionError::InvalidAccountData) } @@ -646,13 +656,13 @@ pub fn set_lockup( clock: &Clock, ) -> Result<(), InstructionError> { match stake_account.get_state()? { - StakeState::Initialized(mut meta) => { + StakeStateWithFlags::Initialized(mut meta) => { meta.set_lockup(lockup, signers, clock)?; - stake_account.set_state(&StakeState::Initialized(meta)) + stake_account.set_state(&StakeStateWithFlags::Initialized(meta)) } - StakeState::Stake(mut meta, stake, stake_flags) => { + StakeStateWithFlags::Stake(mut meta, stake, stake_flags) => { meta.set_lockup(lockup, signers, clock)?; - stake_account.set_state(&StakeState::Stake(meta, stake, stake_flags)) + stake_account.set_state(&StakeStateWithFlags::Stake(meta, stake, stake_flags)) } _ => Err(InstructionError::InvalidAccountData), } @@ -672,10 +682,10 @@ pub fn split( if *split.get_owner() != id() { return Err(InstructionError::IncorrectProgramId); } - if split.get_data().len() != StakeState::size_of() { + if split.get_data().len() != StakeStateWithFlags::size_of() { return Err(InstructionError::InvalidAccountData); } - if !matches!(split.get_state()?, StakeState::Uninitialized) { + if !matches!(split.get_state()?, StakeStateWithFlags::Uninitialized) { return Err(InstructionError::InvalidAccountData); } let split_lamport_balance = split.get_lamports(); @@ -689,7 +699,7 @@ pub fn split( drop(stake_account); match stake_state { - StakeState::Stake(meta, mut stake, stake_flags) => { + StakeStateWithFlags::Stake(meta, mut stake, stake_flags) => { meta.authorized.check(signers, StakeAuthorize::Staker)?; let minimum_delegation = crate::get_minimum_delegation(&invoke_context.feature_set); let validated_split_info = validate_split_amount( @@ -759,13 +769,17 @@ pub fn split( let mut stake_account = instruction_context .try_borrow_instruction_account(transaction_context, stake_account_index)?; - stake_account.set_state(&StakeState::Stake(meta, stake, stake_flags))?; + stake_account.set_state(&StakeStateWithFlags::Stake(meta, stake, stake_flags))?; drop(stake_account); let mut split = instruction_context .try_borrow_instruction_account(transaction_context, split_index)?; - split.set_state(&StakeState::Stake(split_meta, split_stake, stake_flags))?; + split.set_state(&StakeStateWithFlags::Stake( + split_meta, + split_stake, + stake_flags, + ))?; } - StakeState::Initialized(meta) => { + StakeStateWithFlags::Initialized(meta) => { meta.authorized.check(signers, StakeAuthorize::Staker)?; let validated_split_info = validate_split_amount( invoke_context, @@ -782,9 +796,9 @@ pub fn split( split_meta.rent_exempt_reserve = validated_split_info.destination_rent_exempt_reserve; let mut split = instruction_context .try_borrow_instruction_account(transaction_context, split_index)?; - split.set_state(&StakeState::Initialized(split_meta))?; + split.set_state(&StakeStateWithFlags::Initialized(split_meta))?; } - StakeState::Uninitialized => { + StakeStateWithFlags::Uninitialized => { let stake_pubkey = transaction_context.get_key_of_account_at_index( instruction_context .get_index_of_instruction_account_in_transaction(stake_account_index)?, @@ -800,7 +814,7 @@ pub fn split( let mut stake_account = instruction_context .try_borrow_instruction_account(transaction_context, stake_account_index)?; if lamports == stake_account.get_lamports() { - stake_account.set_state(&StakeState::Uninitialized)?; + stake_account.set_state(&StakeStateWithFlags::Uninitialized)?; } drop(stake_account); @@ -870,7 +884,7 @@ pub fn merge( } // Source is about to be drained, deinitialize its state - source_account.set_state(&StakeState::Uninitialized)?; + source_account.set_state(&StakeStateWithFlags::Uninitialized)?; // Drain the source stake account let lamports = source_account.get_lamports(); @@ -902,18 +916,18 @@ pub fn redelegate( ); return Err(InstructionError::IncorrectProgramId); } - if uninitialized_stake_account.get_data().len() != StakeState::size_of() { + if uninitialized_stake_account.get_data().len() != StakeStateWithFlags::size_of() { ic_msg!( invoke_context, "expected uninitialized stake account data len to be {}, not {}", - StakeState::size_of(), + StakeStateWithFlags::size_of(), uninitialized_stake_account.get_data().len() ); return Err(InstructionError::InvalidAccountData); } if !matches!( uninitialized_stake_account.get_state()?, - StakeState::Uninitialized + StakeStateWithFlags::Uninitialized ) { ic_msg!( invoke_context, @@ -938,7 +952,7 @@ pub fn redelegate( let vote_state = vote_account.get_state::()?; let (stake_meta, effective_stake) = - if let StakeState::Stake(meta, stake, _stake_flags) = stake_account.get_state()? { + if let StakeStateWithFlags::Stake(meta, stake, _stake_flags) = stake_account.get_state()? { let stake_history = invoke_context.get_sysvar_cache().get_stake_history()?; let status = stake.delegation.stake_activating_and_deactivating( clock.epoch, @@ -987,7 +1001,7 @@ pub fn redelegate( &uninitialized_stake_meta, &invoke_context.feature_set, )?; - uninitialized_stake_account.set_state(&StakeState::Stake( + uninitialized_stake_account.set_state(&StakeStateWithFlags::Stake( uninitialized_stake_meta, new_stake( stake_amount, @@ -1027,7 +1041,7 @@ pub fn withdraw( let mut stake_account = instruction_context .try_borrow_instruction_account(transaction_context, stake_account_index)?; let (lockup, reserve, is_staked) = match stake_account.get_state()? { - StakeState::Stake(meta, stake, _stake_flag) => { + StakeStateWithFlags::Stake(meta, stake, _stake_flag) => { meta.authorized .check(&signers, StakeAuthorize::Withdrawer)?; // if we have a deactivation epoch and we're in cooldown @@ -1045,13 +1059,13 @@ pub fn withdraw( let staked_and_reserve = checked_add(staked, meta.rent_exempt_reserve)?; (meta.lockup, staked_and_reserve, staked != 0) } - StakeState::Initialized(meta) => { + StakeStateWithFlags::Initialized(meta) => { meta.authorized .check(&signers, StakeAuthorize::Withdrawer)?; // stake accounts must have a balance >= rent_exempt_reserve (meta.lockup, meta.rent_exempt_reserve, false) } - StakeState::Uninitialized => { + StakeStateWithFlags::Uninitialized => { if !signers.contains(stake_account.get_key()) { return Err(InstructionError::MissingRequiredSignature); } @@ -1097,7 +1111,7 @@ pub fn withdraw( // Deinitialize state upon zero balance if lamports == stake_account.get_lamports() { - stake_account.set_state(&StakeState::Uninitialized)?; + stake_account.set_state(&StakeStateWithFlags::Uninitialized)?; } stake_account.checked_sub_lamports(lamports)?; @@ -1142,7 +1156,7 @@ pub(crate) fn deactivate_delinquent( return Err(StakeError::InsufficientReferenceVotes.into()); } - if let StakeState::Stake(meta, mut stake, stake_flags) = stake_account.get_state()? { + if let StakeStateWithFlags::Stake(meta, mut stake, stake_flags) = stake_account.get_state()? { if stake.delegation.voter_pubkey != *delinquent_vote_account_pubkey { return Err(StakeError::VoteAddressMismatch.into()); } @@ -1151,7 +1165,7 @@ pub(crate) fn deactivate_delinquent( // voted in the last `MINIMUM_DELINQUENT_EPOCHS_FOR_DEACTIVATION` if eligible_for_deactivate_delinquent(&delinquent_vote_state.epoch_credits, current_epoch) { stake.deactivate(current_epoch)?; - stake_account.set_state(&StakeState::Stake(meta, stake, stake_flags)) + stake_account.set_state(&StakeStateWithFlags::Stake(meta, stake, stake_flags)) } else { Err(StakeError::MinimumDelinquentEpochsForDeactivationNotMet.into()) } @@ -1312,13 +1326,13 @@ impl MergeKind { fn get_if_mergeable( invoke_context: &InvokeContext, - stake_state: &StakeState, + stake_state: &StakeStateWithFlags, stake_lamports: u64, clock: &Clock, stake_history: &StakeHistory, ) -> Result { match stake_state { - StakeState::Stake(meta, stake, stake_flags) => { + StakeStateWithFlags::Stake(meta, stake, stake_flags) => { // stake must not be in a transient state. Transient here meaning // activating or deactivating with non-zero effective stake. let status = stake.delegation.stake_activating_and_deactivating( @@ -1338,7 +1352,7 @@ impl MergeKind { } } } - StakeState::Initialized(meta) => { + StakeStateWithFlags::Initialized(meta) => { Ok(Self::Inactive(*meta, stake_lamports, StakeFlags::empty())) } _ => Err(InstructionError::InvalidAccountData), @@ -1412,7 +1426,7 @@ impl MergeKind { invoke_context: &InvokeContext, source: Self, clock: &Clock, - ) -> Result, InstructionError> { + ) -> Result, InstructionError> { Self::metas_can_merge(invoke_context, self.meta(), source.meta(), clock)?; self.active_stake() .zip(source.active_stake()) @@ -1439,7 +1453,7 @@ impl MergeKind { Self::Inactive(_, source_lamports, source_stake_flags), ) => { stake.delegation.stake = checked_add(stake.delegation.stake, source_lamports)?; - Some(StakeState::Stake( + Some(StakeStateWithFlags::Stake( meta, stake, stake_flags.union(source_stake_flags), @@ -1459,7 +1473,7 @@ impl MergeKind { source_lamports, source_stake.credits_observed, )?; - Some(StakeState::Stake( + Some(StakeStateWithFlags::Stake( meta, stake, stake_flags.union(source_stake_flags), @@ -1476,7 +1490,7 @@ impl MergeKind { source_stake.delegation.stake, source_stake.credits_observed, )?; - Some(StakeState::Stake(meta, stake, StakeFlags::empty())) + Some(StakeStateWithFlags::Stake(meta, stake, StakeFlags::empty())) } _ => return Err(StakeError::MergeMismatch.into()), }; @@ -1555,7 +1569,7 @@ fn stake_weighted_credits_observed( #[doc(hidden)] pub fn redeem_rewards( rewarded_epoch: Epoch, - stake_state: StakeState, + stake_state: StakeStateWithFlags, stake_account: &mut AccountSharedData, vote_state: &VoteState, point_value: &PointValue, @@ -1563,7 +1577,7 @@ pub fn redeem_rewards( inflation_point_calc_tracer: Option, new_rate_activation_epoch: Option, ) -> Result<(u64, u64), InstructionError> { - if let StakeState::Stake(meta, mut stake, stake_flags) = stake_state { + if let StakeStateWithFlags::Stake(meta, mut stake, stake_flags) = stake_state { if let Some(inflation_point_calc_tracer) = inflation_point_calc_tracer.as_ref() { inflation_point_calc_tracer( &InflationPointCalculationEvent::EffectiveStakeAtRewardedEpoch(stake.stake( @@ -1590,7 +1604,7 @@ pub fn redeem_rewards( new_rate_activation_epoch, ) { stake_account.checked_add_lamports(stakers_reward)?; - stake_account.set_state(&StakeState::Stake(meta, stake, stake_flags))?; + stake_account.set_state(&StakeStateWithFlags::Stake(meta, stake, stake_flags))?; Ok((stakers_reward, voters_reward)) } else { @@ -1604,12 +1618,12 @@ pub fn redeem_rewards( // utility function, used by runtime #[doc(hidden)] pub fn calculate_points( - stake_state: &StakeState, + stake_state: &StakeStateWithFlags, vote_state: &VoteState, stake_history: Option<&StakeHistory>, new_rate_activation_epoch: Option, ) -> Result { - if let StakeState::Stake(_meta, stake, _stake_flags) = stake_state { + if let StakeStateWithFlags::Stake(_meta, stake, _stake_flags) = stake_state { Ok(calculate_stake_points( stake, vote_state, @@ -1678,7 +1692,7 @@ pub fn create_lockup_stake_account( rent: &Rent, lamports: u64, ) -> AccountSharedData { - let mut stake_account = AccountSharedData::new(lamports, StakeState::size_of(), &id()); + let mut stake_account = AccountSharedData::new(lamports, StakeStateWithFlags::size_of(), &id()); let rent_exempt_reserve = rent.minimum_balance(stake_account.data().len()); assert!( @@ -1687,7 +1701,7 @@ pub fn create_lockup_stake_account( ); stake_account - .set_state(&StakeState::Initialized(Meta { + .set_state(&StakeStateWithFlags::Initialized(Meta { authorized: *authorized, lockup: *lockup, rent_exempt_reserve, @@ -1742,14 +1756,14 @@ fn do_create_account( lamports: u64, activation_epoch: Epoch, ) -> AccountSharedData { - let mut stake_account = AccountSharedData::new(lamports, StakeState::size_of(), &id()); + let mut stake_account = AccountSharedData::new(lamports, StakeStateWithFlags::size_of(), &id()); let vote_state = vote_state::from(vote_account).expect("vote_state"); let rent_exempt_reserve = rent.minimum_balance(stake_account.data().len()); stake_account - .set_state(&StakeState::Stake( + .set_state(&StakeStateWithFlags::Stake( Meta { authorized: Authorized::auto(authorized), rent_exempt_reserve, @@ -1925,10 +1939,10 @@ mod tests { #[test] fn test_stake_state_stake_from_fail() { - let mut stake_account = AccountSharedData::new(0, StakeState::size_of(), &id()); + let mut stake_account = AccountSharedData::new(0, StakeStateWithFlags::size_of(), &id()); stake_account - .set_state(&StakeState::default()) + .set_state(&StakeStateWithFlags::default()) .expect("set_state"); assert_eq!(stake_from(&stake_account), None); @@ -2985,7 +2999,7 @@ mod tests { #[ignore] #[should_panic] fn test_dbg_stake_minimum_balance() { - let minimum_balance = Rent::default().minimum_balance(StakeState::size_of()); + let minimum_balance = Rent::default().minimum_balance(StakeStateWithFlags::size_of()); panic!( "stake minimum_balance: {} lamports, {} SOL", minimum_balance, @@ -3230,7 +3244,7 @@ mod tests { let authority_pubkey = Pubkey::new_unique(); let initial_lamports = 4242424242; let rent = Rent::default(); - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let stake_lamports = rent_exempt_reserve + initial_lamports; let new_rate_activation_epoch = Some(0); @@ -3240,8 +3254,8 @@ mod tests { }; let mut stake_account = AccountSharedData::new_data_with_space( stake_lamports, - &StakeState::Uninitialized, - StakeState::size_of(), + &StakeStateWithFlags::Uninitialized, + StakeStateWithFlags::size_of(), &id(), ) .expect("stake_account"); @@ -3262,7 +3276,9 @@ mod tests { ); // RewardsPool state fails - stake_account.set_state(&StakeState::RewardsPool).unwrap(); + stake_account + .set_state(&StakeStateWithFlags::RewardsPool) + .unwrap(); assert_eq!( MergeKind::get_if_mergeable( &invoke_context, @@ -3277,7 +3293,7 @@ mod tests { // Initialized state succeeds stake_account - .set_state(&StakeState::Initialized(meta)) + .set_state(&StakeStateWithFlags::Initialized(meta)) .unwrap(); assert_eq!( MergeKind::get_if_mergeable( @@ -3325,7 +3341,11 @@ mod tests { ..Stake::default() }; stake_account - .set_state(&StakeState::Stake(meta, stake, StakeFlags::empty())) + .set_state(&StakeStateWithFlags::Stake( + meta, + stake, + StakeFlags::empty(), + )) .unwrap(); // activation_epoch succeeds assert_eq!( diff --git a/rpc/src/rpc.rs b/rpc/src/rpc.rs index f4c4668b00..7ac0dac986 100644 --- a/rpc/src/rpc.rs +++ b/rpc/src/rpc.rs @@ -68,7 +68,7 @@ use { message::SanitizedMessage, pubkey::{Pubkey, PUBKEY_BYTES}, signature::{Keypair, Signature, Signer}, - stake::state::{StakeActivationStatus, StakeState}, + stake::state::{StakeActivationStatus, StakeStateWithFlags}, stake_history::StakeHistory, system_instruction, sysvar::stake_history, @@ -1731,7 +1731,7 @@ impl JsonRpcRequestProcessor { let stake_account = bank .get_account(pubkey) .ok_or_else(|| Error::invalid_params("Invalid param: account not found".to_string()))?; - let stake_state: StakeState = stake_account + let stake_state: StakeStateWithFlags = stake_account .state() .map_err(|_| Error::invalid_params("Invalid param: not a stake account".to_string()))?; let delegation = stake_state.delegation(); diff --git a/rpc/src/rpc_pubsub.rs b/rpc/src/rpc_pubsub.rs index 59911a248b..64f1b38066 100644 --- a/rpc/src/rpc_pubsub.rs +++ b/rpc/src/rpc_pubsub.rs @@ -635,7 +635,7 @@ mod tests { signature::{Keypair, Signer}, stake::{ self, instruction as stake_instruction, - state::{Authorized, Lockup, StakeAuthorize, StakeState}, + state::{Authorized, Lockup, StakeAuthorize, StakeStateWithFlags}, }, system_instruction, system_program, system_transaction, transaction::{self, Transaction}, @@ -907,7 +907,7 @@ mod tests { let balance = { let bank = bank_forks.read().unwrap().working_bank(); let rent = &bank.rent_collector().rent; - rent.minimum_balance(StakeState::size_of()) + rent.minimum_balance(StakeStateWithFlags::size_of()) }; let tx = system_transaction::transfer(&alice, &from.pubkey(), balance, blockhash); diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 6d3632be7a..8d3a5e8610 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -174,7 +174,7 @@ use { }, }, solana_stake_program::stake_state::{ - self, InflationPointCalculationEvent, PointValue, StakeState, + self, InflationPointCalculationEvent, PointValue, StakeStateWithFlags, }, solana_system_program::{get_system_account_kind, SystemAccountKind}, solana_vote_program::vote_state::VoteState, @@ -3122,7 +3122,7 @@ impl Bank { let delegation = stake_account.delegation(); let (mut stake_account, stake_state) = - <(AccountSharedData, StakeState)>::from(stake_account); + <(AccountSharedData, StakeStateWithFlags)>::from(stake_account); let vote_pubkey = delegation.voter_pubkey; let Some(vote_account) = get_vote_account(&vote_pubkey) else { return None; @@ -3253,7 +3253,7 @@ impl Bank { } }); let (mut stake_account, stake_state) = - <(AccountSharedData, StakeState)>::from(stake_account); + <(AccountSharedData, StakeStateWithFlags)>::from(stake_account); let redeemed = stake_state::redeem_rewards( rewarded_epoch, stake_state, diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index 5d3a1c2151..9882a48d9e 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -96,7 +96,7 @@ use { }, transaction_context::{TransactionAccount, TransactionContext}, }, - solana_stake_program::stake_state::{self, StakeState}, + solana_stake_program::stake_state::{self, StakeStateWithFlags}, solana_vote_program::{ vote_instruction, vote_state::{ @@ -4417,7 +4417,7 @@ fn test_bank_cloned_stake_delegations() { let (vote_balance, stake_balance) = { let rent = &bank.rent_collector().rent; let vote_rent_exempt_reserve = rent.minimum_balance(VoteState::size_of()); - let stake_rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let stake_rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let minimum_delegation = solana_stake_program::get_minimum_delegation(&bank.feature_set); ( vote_rent_exempt_reserve, diff --git a/runtime/src/genesis_utils.rs b/runtime/src/genesis_utils.rs index a4193db229..bc9412a1ad 100644 --- a/runtime/src/genesis_utils.rs +++ b/runtime/src/genesis_utils.rs @@ -10,7 +10,7 @@ use { pubkey::Pubkey, rent::Rent, signature::{Keypair, Signer}, - stake::state::StakeState, + stake::state::StakeStateWithFlags, system_program, }, solana_stake_program::stake_state, @@ -23,7 +23,7 @@ const VALIDATOR_LAMPORTS: u64 = 42; // fun fact: rustc is very close to make this const fn. pub fn bootstrap_validator_stake_lamports() -> u64 { - Rent::default().minimum_balance(StakeState::size_of()) + Rent::default().minimum_balance(StakeStateWithFlags::size_of()) } // Number of lamports automatically used for genesis accounts diff --git a/runtime/src/non_circulating_supply.rs b/runtime/src/non_circulating_supply.rs index 7cde838c4d..566160ad28 100644 --- a/runtime/src/non_circulating_supply.rs +++ b/runtime/src/non_circulating_supply.rs @@ -7,7 +7,7 @@ use { solana_sdk::{ account::ReadableAccount, pubkey::Pubkey, - stake::{self, state::StakeState}, + stake::{self, state::StakeStateWithFlags}, }, solana_stake_program::stake_state, std::{collections::HashSet, sync::Arc}, @@ -53,14 +53,14 @@ pub fn calculate_non_circulating_supply(bank: &Arc) -> ScanResult { + StakeStateWithFlags::Initialized(meta) => { if meta.lockup.is_in_force(&clock, None) || withdraw_authority_list.contains(&meta.authorized.withdrawer) { non_circulating_accounts_set.insert(*pubkey); } } - StakeState::Stake(meta, _stake, _stake_flags) => { + StakeStateWithFlags::Stake(meta, _stake, _stake_flags) => { if meta.lockup.is_in_force(&clock, None) || withdraw_authority_list.contains(&meta.authorized.withdrawer) { @@ -264,8 +264,8 @@ mod tests { }; let stake_account = Account::new_data_with_space( balance, - &StakeState::Initialized(meta), - StakeState::size_of(), + &StakeStateWithFlags::Initialized(meta), + StakeStateWithFlags::size_of(), &stake::program::id(), ) .unwrap(); diff --git a/runtime/src/stake_account.rs b/runtime/src/stake_account.rs index 589da714e2..ab76acce9b 100644 --- a/runtime/src/stake_account.rs +++ b/runtime/src/stake_account.rs @@ -6,7 +6,7 @@ use { account_utils::StateMut, instruction::InstructionError, pubkey::Pubkey, - stake::state::{Delegation, StakeState}, + stake::state::{Delegation, StakeStateWithFlags}, }, std::marker::PhantomData, thiserror::Error, @@ -19,7 +19,7 @@ use { #[derive(Clone, Debug, Default)] pub struct StakeAccount { account: AccountSharedData, - stake_state: StakeState, + stake_state: StakeStateWithFlags, _phantom: PhantomData, } @@ -29,7 +29,7 @@ pub enum Error { #[error(transparent)] InstructionError(#[from] InstructionError), #[error("Invalid delegation: {0:?}")] - InvalidDelegation(Box), + InvalidDelegation(Box), #[error("Invalid stake account owner: {0}")] InvalidOwner(/*owner:*/ Pubkey), } @@ -41,7 +41,7 @@ impl StakeAccount { } #[inline] - pub(crate) fn stake_state(&self) -> &StakeState { + pub(crate) fn stake_state(&self) -> &StakeStateWithFlags { &self.stake_state } } @@ -61,7 +61,7 @@ impl TryFrom for StakeAccount { if account.owner() != &solana_stake_program::id() { return Err(Error::InvalidOwner(*account.owner())); } - let stake_state: StakeState = account.state()?; + let stake_state: StakeStateWithFlags = account.state()?; if stake_state.delegation().is_none() { return Err(Error::InvalidDelegation(Box::new(stake_state))); } @@ -73,7 +73,7 @@ impl TryFrom for StakeAccount { } } -impl From> for (AccountSharedData, StakeState) { +impl From> for (AccountSharedData, StakeStateWithFlags) { #[inline] fn from(stake_account: StakeAccount) -> Self { (stake_account.account, stake_account.stake_state) @@ -102,7 +102,7 @@ impl AbiExample for StakeAccount { }, }; let stake_state = - StakeState::Stake(Meta::example(), Stake::example(), StakeFlags::example()); + StakeStateWithFlags::Stake(Meta::example(), Stake::example(), StakeFlags::example()); let mut account = Account::example(); account.data.resize(200, 0u8); account.owner = solana_stake_program::id(); diff --git a/runtime/src/stakes.rs b/runtime/src/stakes.rs index c83da33d13..91b308d762 100644 --- a/runtime/src/stakes.rs +++ b/runtime/src/stakes.rs @@ -179,7 +179,7 @@ impl StakesCache { /// [`Stakes`] is equivalent to the old code and is used for backward /// compatibility in [`crate::bank::BankFieldsToDeserialize`]. /// But banks cache [`Stakes`] which includes the entire stake -/// account and StakeState deserialized from the account. Doing so, will remove +/// account and StakeStateWithFlags deserialized from the account. Doing so, will remove /// the need to load the stake account from accounts-db when working with /// stake-delegations. #[derive(Default, Clone, PartialEq, Debug, Deserialize, Serialize, AbiExample)] diff --git a/runtime/tests/stake.rs b/runtime/tests/stake.rs index b99fed712f..4141fa4d9f 100755 --- a/runtime/tests/stake.rs +++ b/runtime/tests/stake.rs @@ -19,7 +19,7 @@ use { signature::{Keypair, Signer}, stake::{ self, instruction as stake_instruction, - state::{Authorized, Lockup, StakeState}, + state::{Authorized, Lockup, StakeStateWithFlags}, }, sysvar::{self, stake_history::StakeHistory}, }, @@ -145,7 +145,7 @@ fn test_stake_create_and_split_single_signature() { let lamports = { let rent = &bank.rent_collector().rent; - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let minimum_delegation = solana_stake_program::get_minimum_delegation(&bank.feature_set); 2 * (rent_exempt_reserve + minimum_delegation) }; @@ -221,7 +221,7 @@ fn test_stake_create_and_split_to_existing_system_account() { let lamports = { let rent = &bank.rent_collector().rent; - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let minimum_delegation = solana_stake_program::get_minimum_delegation(&bank.feature_set); 2 * (rent_exempt_reserve + minimum_delegation) }; @@ -314,7 +314,7 @@ fn test_stake_account_lifetime() { let rent = &bank.rent_collector().rent; ( rent.minimum_balance(VoteState::size_of()), - rent.minimum_balance(StakeState::size_of()), + rent.minimum_balance(StakeStateWithFlags::size_of()), solana_stake_program::get_minimum_delegation(&bank.feature_set), ) }; @@ -367,7 +367,7 @@ fn test_stake_account_lifetime() { // Test that correct lamports are staked let account = bank.get_account(&stake_pubkey).expect("account not found"); let stake_state = account.state().expect("couldn't unpack account data"); - if let StakeState::Stake(_meta, stake, _stake_flags) = stake_state { + if let StakeStateWithFlags::Stake(_meta, stake, _stake_flags) = stake_state { assert_eq!(stake.delegation.stake, stake_starting_delegation,); } else { panic!("wrong account type found") @@ -391,7 +391,7 @@ fn test_stake_account_lifetime() { // Test that lamports are still staked let account = bank.get_account(&stake_pubkey).expect("account not found"); let stake_state = account.state().expect("couldn't unpack account data"); - if let StakeState::Stake(_meta, stake, _stake_flags) = stake_state { + if let StakeStateWithFlags::Stake(_meta, stake, _stake_flags) = stake_state { assert_eq!(stake.delegation.stake, stake_starting_delegation,); } else { panic!("wrong account type found") @@ -615,7 +615,7 @@ fn test_create_stake_account_from_seed() { let authorized = Authorized::auto(&mint_pubkey); let (balance, delegation) = { let rent = &bank.rent_collector().rent; - let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); + let rent_exempt_reserve = rent.minimum_balance(StakeStateWithFlags::size_of()); let minimum_delegation = solana_stake_program::get_minimum_delegation(&bank.feature_set); (rent_exempt_reserve + minimum_delegation, minimum_delegation) }; @@ -641,7 +641,7 @@ fn test_create_stake_account_from_seed() { // Test that correct lamports are staked let account = bank.get_account(&stake_pubkey).expect("account not found"); let stake_state = account.state().expect("couldn't unpack account data"); - if let StakeState::Stake(_meta, stake, _) = stake_state { + if let StakeStateWithFlags::Stake(_meta, stake, _) = stake_state { assert_eq!(stake.delegation.stake, delegation); } else { panic!("wrong account type found") diff --git a/sdk/program/src/stake/instruction.rs b/sdk/program/src/stake/instruction.rs index 14a3df011a..48c60a43cd 100644 --- a/sdk/program/src/stake/instruction.rs +++ b/sdk/program/src/stake/instruction.rs @@ -8,7 +8,7 @@ use { pubkey::Pubkey, stake::{ program::id, - state::{Authorized, Lockup, StakeAuthorize, StakeState}, + state::{Authorized, Lockup, StakeAuthorize, StakeStateWithFlags}, }, system_instruction, sysvar, }, @@ -364,7 +364,7 @@ pub fn create_account_with_seed( base, seed, lamports, - StakeState::size_of() as u64, + StakeStateWithFlags::size_of() as u64, &id(), ), initialize(stake_pubkey, authorized, lockup), @@ -383,7 +383,7 @@ pub fn create_account( from_pubkey, stake_pubkey, lamports, - StakeState::size_of() as u64, + StakeStateWithFlags::size_of() as u64, &id(), ), initialize(stake_pubkey, authorized, lockup), @@ -405,7 +405,7 @@ pub fn create_account_with_seed_checked( base, seed, lamports, - StakeState::size_of() as u64, + StakeStateWithFlags::size_of() as u64, &id(), ), initialize_checked(stake_pubkey, authorized), @@ -423,7 +423,7 @@ pub fn create_account_checked( from_pubkey, stake_pubkey, lamports, - StakeState::size_of() as u64, + StakeStateWithFlags::size_of() as u64, &id(), ), initialize_checked(stake_pubkey, authorized), @@ -452,7 +452,7 @@ pub fn split( split_stake_pubkey: &Pubkey, ) -> Vec { vec![ - system_instruction::allocate(split_stake_pubkey, StakeState::size_of() as u64), + system_instruction::allocate(split_stake_pubkey, StakeStateWithFlags::size_of() as u64), system_instruction::assign(split_stake_pubkey, &id()), _split( stake_pubkey, @@ -476,7 +476,7 @@ pub fn split_with_seed( split_stake_pubkey, base, seed, - StakeState::size_of() as u64, + StakeStateWithFlags::size_of() as u64, &id(), ), _split( @@ -796,7 +796,10 @@ pub fn redelegate( uninitialized_stake_pubkey: &Pubkey, ) -> Vec { vec![ - system_instruction::allocate(uninitialized_stake_pubkey, StakeState::size_of() as u64), + system_instruction::allocate( + uninitialized_stake_pubkey, + StakeStateWithFlags::size_of() as u64, + ), system_instruction::assign(uninitialized_stake_pubkey, &id()), _redelegate( stake_pubkey, @@ -820,7 +823,7 @@ pub fn redelegate_with_seed( uninitialized_stake_pubkey, base, seed, - StakeState::size_of() as u64, + StakeStateWithFlags::size_of() as u64, &id(), ), _redelegate( diff --git a/sdk/program/src/stake/state.rs b/sdk/program/src/stake/state.rs index 3a9d5cd276..f3b331be41 100644 --- a/sdk/program/src/stake/state.rs +++ b/sdk/program/src/stake/state.rs @@ -1,4 +1,7 @@ #![allow(clippy::integer_arithmetic)] +// Remove the following `allow` when `StakeState` is removed, required to avoid +// warnings from uses of deprecated types during trait derivations. +#![allow(deprecated)] use { crate::{ @@ -33,14 +36,17 @@ pub fn warmup_cooldown_rate(current_epoch: Epoch, new_rate_activation_epoch: Opt #[derive(Debug, Default, Serialize, Deserialize, PartialEq, Clone, Copy, AbiExample)] #[allow(clippy::large_enum_variant)] +#[deprecated( + since = "1.17.0", + note = "Please use `StakeStateWithFlags` instead, and match the third `StakeFlags` field when matching `StakeStateWithFlags::Stake` to resolve any breakage. For example, `if let StakeState::Stake(meta, stake)` becomes `if let StakeStateWithFlags::Stake(meta, stake, _stake_flags)`." +)] pub enum StakeState { #[default] Uninitialized, Initialized(Meta), - Stake(Meta, Stake, StakeFlags), + Stake(Meta, Stake), RewardsPool, } - impl BorshDeserialize for StakeState { fn deserialize_reader(reader: &mut R) -> io::Result { let enum_value = u32::deserialize_reader(reader)?; @@ -53,8 +59,7 @@ impl BorshDeserialize for StakeState { 2 => { let meta: Meta = BorshDeserialize::deserialize_reader(reader)?; let stake: Stake = BorshDeserialize::deserialize_reader(reader)?; - let stake_flags: StakeFlags = BorshDeserialize::deserialize_reader(reader)?; - Ok(StakeState::Stake(meta, stake, stake_flags)) + Ok(StakeState::Stake(meta, stake)) } 3 => Ok(StakeState::RewardsPool), _ => Err(io::Error::new( @@ -64,7 +69,6 @@ impl BorshDeserialize for StakeState { } } } - impl BorshSerialize for StakeState { fn serialize(&self, writer: &mut W) -> io::Result<()> { match self { @@ -73,17 +77,15 @@ impl BorshSerialize for StakeState { writer.write_all(&1u32.to_le_bytes())?; meta.serialize(writer) } - StakeState::Stake(meta, stake, stake_flags) => { + StakeState::Stake(meta, stake) => { writer.write_all(&2u32.to_le_bytes())?; meta.serialize(writer)?; - stake.serialize(writer)?; - stake_flags.serialize(writer) + stake.serialize(writer) } StakeState::RewardsPool => writer.write_all(&3u32.to_le_bytes()), } } } - impl StakeState { /// The fixed number of bytes used to serialize each stake account pub const fn size_of() -> usize { @@ -92,21 +94,21 @@ impl StakeState { pub fn stake(&self) -> Option { match self { - StakeState::Stake(_meta, stake, _stake_flags) => Some(*stake), + StakeState::Stake(_meta, stake) => Some(*stake), _ => None, } } pub fn delegation(&self) -> Option { match self { - StakeState::Stake(_meta, stake, _stake_flags) => Some(stake.delegation), + StakeState::Stake(_meta, stake) => Some(stake.delegation), _ => None, } } pub fn authorized(&self) -> Option { match self { - StakeState::Stake(meta, _stake, _stake_flags) => Some(meta.authorized), + StakeState::Stake(meta, _stake) => Some(meta.authorized), StakeState::Initialized(meta) => Some(meta.authorized), _ => None, } @@ -118,13 +120,107 @@ impl StakeState { pub fn meta(&self) -> Option { match self { - StakeState::Stake(meta, _stake, _stake_flags) => Some(*meta), + StakeState::Stake(meta, _stake) => Some(*meta), StakeState::Initialized(meta) => Some(*meta), _ => None, } } } +#[derive(Debug, Default, Serialize, Deserialize, PartialEq, Clone, Copy, AbiExample)] +#[allow(clippy::large_enum_variant)] +pub enum StakeStateWithFlags { + #[default] + Uninitialized, + Initialized(Meta), + Stake(Meta, Stake, StakeFlags), + RewardsPool, +} + +impl BorshDeserialize for StakeStateWithFlags { + fn deserialize_reader(reader: &mut R) -> io::Result { + let enum_value = u32::deserialize_reader(reader)?; + match enum_value { + 0 => Ok(StakeStateWithFlags::Uninitialized), + 1 => { + let meta = Meta::deserialize_reader(reader)?; + Ok(StakeStateWithFlags::Initialized(meta)) + } + 2 => { + let meta: Meta = BorshDeserialize::deserialize_reader(reader)?; + let stake: Stake = BorshDeserialize::deserialize_reader(reader)?; + let stake_flags: StakeFlags = BorshDeserialize::deserialize_reader(reader)?; + Ok(StakeStateWithFlags::Stake(meta, stake, stake_flags)) + } + 3 => Ok(StakeStateWithFlags::RewardsPool), + _ => Err(io::Error::new( + io::ErrorKind::InvalidData, + "Invalid enum value", + )), + } + } +} + +impl BorshSerialize for StakeStateWithFlags { + fn serialize(&self, writer: &mut W) -> io::Result<()> { + match self { + StakeStateWithFlags::Uninitialized => writer.write_all(&0u32.to_le_bytes()), + StakeStateWithFlags::Initialized(meta) => { + writer.write_all(&1u32.to_le_bytes())?; + meta.serialize(writer) + } + StakeStateWithFlags::Stake(meta, stake, stake_flags) => { + writer.write_all(&2u32.to_le_bytes())?; + meta.serialize(writer)?; + stake.serialize(writer)?; + stake_flags.serialize(writer) + } + StakeStateWithFlags::RewardsPool => writer.write_all(&3u32.to_le_bytes()), + } + } +} + +impl StakeStateWithFlags { + /// The fixed number of bytes used to serialize each stake account + pub const fn size_of() -> usize { + 200 // see test_size_of + } + + pub fn stake(&self) -> Option { + match self { + StakeStateWithFlags::Stake(_meta, stake, _stake_flags) => Some(*stake), + _ => None, + } + } + + pub fn delegation(&self) -> Option { + match self { + StakeStateWithFlags::Stake(_meta, stake, _stake_flags) => Some(stake.delegation), + _ => None, + } + } + + pub fn authorized(&self) -> Option { + match self { + StakeStateWithFlags::Stake(meta, _stake, _stake_flags) => Some(meta.authorized), + StakeStateWithFlags::Initialized(meta) => Some(meta.authorized), + _ => None, + } + } + + pub fn lockup(&self) -> Option { + self.meta().map(|meta| meta.lockup) + } + + pub fn meta(&self) -> Option { + match self { + StakeStateWithFlags::Stake(meta, _stake, _stake_flags) => Some(*meta), + StakeStateWithFlags::Initialized(meta) => Some(*meta), + _ => None, + } + } +} + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone, Copy, AbiExample)] pub enum StakeAuthorize { Staker, @@ -615,28 +711,31 @@ mod test { bincode::serialize, }; - fn check_borsh_deserialization(stake: StakeState) { + fn check_borsh_deserialization(stake: StakeStateWithFlags) { let serialized = serialize(&stake).unwrap(); - let deserialized = StakeState::try_from_slice(&serialized).unwrap(); + let deserialized = StakeStateWithFlags::try_from_slice(&serialized).unwrap(); assert_eq!(stake, deserialized); } - fn check_borsh_serialization(stake: StakeState) { + fn check_borsh_serialization(stake: StakeStateWithFlags) { let bincode_serialized = serialize(&stake).unwrap(); - let borsh_serialized = StakeState::try_to_vec(&stake).unwrap(); + let borsh_serialized = StakeStateWithFlags::try_to_vec(&stake).unwrap(); assert_eq!(bincode_serialized, borsh_serialized); } #[test] fn test_size_of() { - assert_eq!(StakeState::size_of(), std::mem::size_of::()); + assert_eq!( + StakeStateWithFlags::size_of(), + std::mem::size_of::() + ); } #[test] fn bincode_vs_borsh_deserialization() { - check_borsh_deserialization(StakeState::Uninitialized); - check_borsh_deserialization(StakeState::RewardsPool); - check_borsh_deserialization(StakeState::Initialized(Meta { + check_borsh_deserialization(StakeStateWithFlags::Uninitialized); + check_borsh_deserialization(StakeStateWithFlags::RewardsPool); + check_borsh_deserialization(StakeStateWithFlags::Initialized(Meta { rent_exempt_reserve: u64::MAX, authorized: Authorized { staker: Pubkey::new_unique(), @@ -644,7 +743,7 @@ mod test { }, lockup: Lockup::default(), })); - check_borsh_deserialization(StakeState::Stake( + check_borsh_deserialization(StakeStateWithFlags::Stake( Meta { rent_exempt_reserve: 1, authorized: Authorized { @@ -669,9 +768,9 @@ mod test { #[test] fn bincode_vs_borsh_serialization() { - check_borsh_serialization(StakeState::Uninitialized); - check_borsh_serialization(StakeState::RewardsPool); - check_borsh_serialization(StakeState::Initialized(Meta { + check_borsh_serialization(StakeStateWithFlags::Uninitialized); + check_borsh_serialization(StakeStateWithFlags::RewardsPool); + check_borsh_serialization(StakeStateWithFlags::Initialized(Meta { rent_exempt_reserve: u64::MAX, authorized: Authorized { staker: Pubkey::new_unique(), @@ -679,7 +778,7 @@ mod test { }, lockup: Lockup::default(), })); - check_borsh_serialization(StakeState::Stake( + check_borsh_serialization(StakeStateWithFlags::Stake( Meta { rent_exempt_reserve: 1, authorized: Authorized { @@ -717,13 +816,126 @@ mod test { ]; // As long as we get the 4-byte enum and the first field right, then // we're sure the rest works out - let deserialized = try_from_slice_unchecked::(&data).unwrap(); + let deserialized = try_from_slice_unchecked::(&data).unwrap(); assert_matches!( deserialized, - StakeState::Initialized(Meta { + StakeStateWithFlags::Initialized(Meta { rent_exempt_reserve: 2282880, .. }) ); } + + mod deprecated { + use super::*; + fn check_borsh_deserialization(stake: StakeState) { + let serialized = serialize(&stake).unwrap(); + let deserialized = StakeState::try_from_slice(&serialized).unwrap(); + assert_eq!(stake, deserialized); + } + + fn check_borsh_serialization(stake: StakeState) { + let bincode_serialized = serialize(&stake).unwrap(); + let borsh_serialized = StakeState::try_to_vec(&stake).unwrap(); + assert_eq!(bincode_serialized, borsh_serialized); + } + + #[test] + fn test_size_of() { + assert_eq!(StakeState::size_of(), std::mem::size_of::()); + } + + #[test] + fn bincode_vs_borsh_deserialization() { + check_borsh_deserialization(StakeState::Uninitialized); + check_borsh_deserialization(StakeState::RewardsPool); + check_borsh_deserialization(StakeState::Initialized(Meta { + rent_exempt_reserve: u64::MAX, + authorized: Authorized { + staker: Pubkey::new_unique(), + withdrawer: Pubkey::new_unique(), + }, + lockup: Lockup::default(), + })); + check_borsh_deserialization(StakeState::Stake( + Meta { + rent_exempt_reserve: 1, + authorized: Authorized { + staker: Pubkey::new_unique(), + withdrawer: Pubkey::new_unique(), + }, + lockup: Lockup::default(), + }, + Stake { + delegation: Delegation { + voter_pubkey: Pubkey::new_unique(), + stake: u64::MAX, + activation_epoch: Epoch::MAX, + deactivation_epoch: Epoch::MAX, + warmup_cooldown_rate: f64::MAX, + }, + credits_observed: 1, + }, + )); + } + + #[test] + fn bincode_vs_borsh_serialization() { + check_borsh_serialization(StakeState::Uninitialized); + check_borsh_serialization(StakeState::RewardsPool); + check_borsh_serialization(StakeState::Initialized(Meta { + rent_exempt_reserve: u64::MAX, + authorized: Authorized { + staker: Pubkey::new_unique(), + withdrawer: Pubkey::new_unique(), + }, + lockup: Lockup::default(), + })); + check_borsh_serialization(StakeState::Stake( + Meta { + rent_exempt_reserve: 1, + authorized: Authorized { + staker: Pubkey::new_unique(), + withdrawer: Pubkey::new_unique(), + }, + lockup: Lockup::default(), + }, + Stake { + delegation: Delegation { + voter_pubkey: Pubkey::new_unique(), + stake: u64::MAX, + activation_epoch: Epoch::MAX, + deactivation_epoch: Epoch::MAX, + warmup_cooldown_rate: f64::MAX, + }, + credits_observed: 1, + }, + )); + } + + #[test] + fn borsh_deserialization_live_data() { + let data = [ + 1, 0, 0, 0, 128, 213, 34, 0, 0, 0, 0, 0, 133, 0, 79, 231, 141, 29, 73, 61, 232, 35, + 119, 124, 168, 12, 120, 216, 195, 29, 12, 166, 139, 28, 36, 182, 186, 154, 246, + 149, 224, 109, 52, 100, 133, 0, 79, 231, 141, 29, 73, 61, 232, 35, 119, 124, 168, + 12, 120, 216, 195, 29, 12, 166, 139, 28, 36, 182, 186, 154, 246, 149, 224, 109, 52, + 100, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + ]; + // As long as we get the 4-byte enum and the first field right, then + // we're sure the rest works out + let deserialized = try_from_slice_unchecked::(&data).unwrap(); + assert_matches!( + deserialized, + StakeState::Initialized(Meta { + rent_exempt_reserve: 2282880, + .. + }) + ); + } + } } diff --git a/stake-accounts/src/stake_accounts.rs b/stake-accounts/src/stake_accounts.rs index 62c8f01c37..cc2d6802b2 100644 --- a/stake-accounts/src/stake_accounts.rs +++ b/stake-accounts/src/stake_accounts.rs @@ -289,7 +289,7 @@ mod tests { client::SyncClient, genesis_config::create_genesis_config, signature::{Keypair, Signer}, - stake::state::StakeState, + stake::state::StakeStateWithFlags, }, solana_stake_program::stake_state, }; @@ -297,7 +297,8 @@ mod tests { fn create_bank(lamports: u64) -> (Bank, Keypair, u64, u64) { let (genesis_config, mint_keypair) = create_genesis_config(lamports); let bank = Bank::new_for_tests(&genesis_config); - let stake_rent = bank.get_minimum_balance_for_rent_exemption(StakeState::size_of()); + let stake_rent = + bank.get_minimum_balance_for_rent_exemption(StakeStateWithFlags::size_of()); let system_rent = bank.get_minimum_balance_for_rent_exemption(0); (bank, mint_keypair, stake_rent, system_rent) }