stake: Remove `stake_allow_zero_undelegated_amount` usage (#32210)

This commit is contained in:
Jon Cinque 2023-06-23 22:57:18 +02:00 committed by GitHub
parent 9a620b4862
commit 383063eeb2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 12 additions and 73 deletions

View File

@ -77,13 +77,7 @@ declare_process_instruction!(
let mut me = get_stake_account()?; let mut me = get_stake_account()?;
let rent = let rent =
get_sysvar_with_account_check::rent(invoke_context, instruction_context, 1)?; get_sysvar_with_account_check::rent(invoke_context, instruction_context, 1)?;
initialize( initialize(&mut me, &authorized, &lockup, &rent)
&mut me,
&authorized,
&lockup,
&rent,
&invoke_context.feature_set,
)
} }
Ok(StakeInstruction::Authorize(authorized_pubkey, stake_authorize)) => { Ok(StakeInstruction::Authorize(authorized_pubkey, stake_authorize)) => {
let mut me = get_stake_account()?; let mut me = get_stake_account()?;
@ -261,7 +255,6 @@ declare_process_instruction!(
} else { } else {
None None
}, },
&invoke_context.feature_set,
) )
} }
Ok(StakeInstruction::Deactivate) => { Ok(StakeInstruction::Deactivate) => {
@ -302,13 +295,7 @@ declare_process_instruction!(
instruction_context, instruction_context,
1, 1,
)?; )?;
initialize( initialize(&mut me, &authorized, &Lockup::default(), &rent)
&mut me,
&authorized,
&Lockup::default(),
&rent,
&invoke_context.feature_set,
)
} else { } else {
Err(InstructionError::InvalidInstructionData) Err(InstructionError::InvalidInstructionData)
} }
@ -525,16 +512,6 @@ mod tests {
feature_set feature_set
} }
/// The "old old" behavior is both before the stake minimum delegation was raised *and* before
/// undelegated stake accounts could have zero lamports beyond rent
fn feature_set_old_old_behavior() -> Arc<FeatureSet> {
let mut feature_set = feature_set_old_behavior();
Arc::get_mut(&mut feature_set)
.unwrap()
.deactivate(&feature_set::stake_allow_zero_undelegated_amount::id());
feature_set
}
fn create_default_account() -> AccountSharedData { fn create_default_account() -> AccountSharedData {
AccountSharedData::new(0, 0, &Pubkey::new_unique()) AccountSharedData::new(0, 0, &Pubkey::new_unique())
} }
@ -4470,17 +4447,9 @@ mod tests {
/// 3. Deactives the delegation /// 3. Deactives the delegation
/// 4. Withdraws from the account such that the ending balance is *below* rent + minimum delegation /// 4. Withdraws from the account such that the ending balance is *below* rent + minimum delegation
/// 5. Re-delegates, now with less than the minimum delegation, but it still succeeds /// 5. Re-delegates, now with less than the minimum delegation, but it still succeeds
// #[test]
// The "old old" behavior relies on `validate_delegated_amount()` *not* checking if the fn test_behavior_withdrawal_then_redelegate_with_less_than_minimum_stake_delegation() {
// stake amount meets the minimum delegation. Once the let feature_set = feature_set_new_behavior();
// `stake_allow_zero_undelegated_amount` feature is activated, `the expected_result`
// parameter can be removed and consolidated.
#[test_case(feature_set_old_old_behavior(), Ok(()); "old_old_behavior")]
#[test_case(feature_set_new_behavior(), Err(StakeError::InsufficientDelegation.into()); "new_behavior")]
fn test_behavior_withdrawal_then_redelegate_with_less_than_minimum_stake_delegation(
feature_set: Arc<FeatureSet>,
expected_result: Result<(), InstructionError>,
) {
let minimum_delegation = crate::get_minimum_delegation(&feature_set); let minimum_delegation = crate::get_minimum_delegation(&feature_set);
let rent = Rent::default(); let rent = Rent::default();
let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of()); let rent_exempt_reserve = rent.minimum_balance(StakeState::size_of());
@ -4641,7 +4610,7 @@ mod tests {
&serialize(&StakeInstruction::DelegateStake).unwrap(), &serialize(&StakeInstruction::DelegateStake).unwrap(),
transaction_accounts, transaction_accounts,
instruction_accounts, instruction_accounts,
expected_result, Err(StakeError::InsufficientDelegation.into()),
); );
} }

View File

@ -15,8 +15,8 @@ use {
account_utils::StateMut, account_utils::StateMut,
clock::{Clock, Epoch}, clock::{Clock, Epoch},
feature_set::{ feature_set::{
self, clean_up_delegation_errors, stake_allow_zero_undelegated_amount, self, clean_up_delegation_errors, stake_merge_with_unmatched_credits_observed,
stake_merge_with_unmatched_credits_observed, stake_split_uses_rent_sysvar, FeatureSet, stake_split_uses_rent_sysvar, FeatureSet,
}, },
instruction::{checked_add, InstructionError}, instruction::{checked_add, InstructionError},
pubkey::Pubkey, pubkey::Pubkey,
@ -464,22 +464,13 @@ pub fn initialize(
authorized: &Authorized, authorized: &Authorized,
lockup: &Lockup, lockup: &Lockup,
rent: &Rent, rent: &Rent,
feature_set: &FeatureSet,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
if stake_account.get_data().len() != StakeState::size_of() { if stake_account.get_data().len() != StakeState::size_of() {
return Err(InstructionError::InvalidAccountData); return Err(InstructionError::InvalidAccountData);
} }
if let StakeState::Uninitialized = stake_account.get_state()? { if let StakeState::Uninitialized = stake_account.get_state()? {
let rent_exempt_reserve = rent.minimum_balance(stake_account.get_data().len()); let rent_exempt_reserve = rent.minimum_balance(stake_account.get_data().len());
// when removing this feature, remove `minimum_balance` and just use `rent_exempt_reserve` if stake_account.get_lamports() >= rent_exempt_reserve {
let minimum_balance = if feature_set.is_active(&stake_allow_zero_undelegated_amount::id()) {
rent_exempt_reserve
} else {
let minimum_delegation = crate::get_minimum_delegation(feature_set);
rent_exempt_reserve + minimum_delegation
};
if stake_account.get_lamports() >= minimum_balance {
stake_account.set_state(&StakeState::Initialized(Meta { stake_account.set_state(&StakeState::Initialized(Meta {
rent_exempt_reserve, rent_exempt_reserve,
authorized: *authorized, authorized: *authorized,
@ -774,14 +765,6 @@ pub fn split(
} }
StakeState::Initialized(meta) => { StakeState::Initialized(meta) => {
meta.authorized.check(signers, StakeAuthorize::Staker)?; meta.authorized.check(signers, StakeAuthorize::Staker)?;
let additional_required_lamports = if invoke_context
.feature_set
.is_active(&stake_allow_zero_undelegated_amount::id())
{
0
} else {
crate::get_minimum_delegation(&invoke_context.feature_set)
};
let validated_split_info = validate_split_amount( let validated_split_info = validate_split_amount(
invoke_context, invoke_context,
transaction_context, transaction_context,
@ -791,7 +774,7 @@ pub fn split(
lamports, lamports,
&meta, &meta,
None, None,
additional_required_lamports, 0, // additional_required_lamports
)?; )?;
let mut split_meta = meta; let mut split_meta = meta;
split_meta.rent_exempt_reserve = validated_split_info.destination_rent_exempt_reserve; split_meta.rent_exempt_reserve = validated_split_info.destination_rent_exempt_reserve;
@ -1026,7 +1009,6 @@ pub fn withdraw(
stake_history: &StakeHistory, stake_history: &StakeHistory,
withdraw_authority_index: IndexOfAccount, withdraw_authority_index: IndexOfAccount,
custodian_index: Option<IndexOfAccount>, custodian_index: Option<IndexOfAccount>,
feature_set: &FeatureSet,
) -> Result<(), InstructionError> { ) -> Result<(), InstructionError> {
let withdraw_authority_pubkey = transaction_context.get_key_of_account_at_index( let withdraw_authority_pubkey = transaction_context.get_key_of_account_at_index(
instruction_context instruction_context
@ -1061,16 +1043,7 @@ pub fn withdraw(
meta.authorized meta.authorized
.check(&signers, StakeAuthorize::Withdrawer)?; .check(&signers, StakeAuthorize::Withdrawer)?;
// stake accounts must have a balance >= rent_exempt_reserve // stake accounts must have a balance >= rent_exempt_reserve
let reserve = if feature_set.is_active(&stake_allow_zero_undelegated_amount::id()) { (meta.lockup, meta.rent_exempt_reserve, false)
meta.rent_exempt_reserve
} else {
checked_add(
meta.rent_exempt_reserve,
crate::get_minimum_delegation(feature_set),
)?
};
(meta.lockup, reserve, false)
} }
StakeState::Uninitialized => { StakeState::Uninitialized => {
if !signers.contains(stake_account.get_key()) { if !signers.contains(stake_account.get_key()) {
@ -1200,10 +1173,7 @@ fn validate_delegated_amount(
// Stake accounts may be initialized with a stake amount below the minimum delegation so check // Stake accounts may be initialized with a stake amount below the minimum delegation so check
// that the minimum is met before delegation. // that the minimum is met before delegation.
if (feature_set.is_active(&stake_allow_zero_undelegated_amount::id()) if stake_amount < crate::get_minimum_delegation(feature_set) {
|| feature_set.is_active(&feature_set::stake_raise_minimum_delegation_to_1_sol::id()))
&& stake_amount < crate::get_minimum_delegation(feature_set)
{
return Err(StakeError::InsufficientDelegation.into()); return Err(StakeError::InsufficientDelegation.into());
} }
Ok(ValidatedDelegatedInfo { stake_amount }) Ok(ValidatedDelegatedInfo { stake_amount })