Skip to content

Commit ff89b6b

Browse files
authored
Misc delegate flow refactor (#198)
1 parent 16ad96b commit ff89b6b

File tree

2 files changed

+29
-48
lines changed

2 files changed

+29
-48
lines changed

program/src/helpers/delegate.rs

Lines changed: 0 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
use {
2-
crate::PERPETUAL_NEW_WARMUP_COOLDOWN_RATE_EPOCH,
32
solana_account_info::AccountInfo,
43
solana_clock::Epoch,
54
solana_program_error::ProgramError,
65
solana_pubkey::Pubkey,
76
solana_stake_interface::{
87
error::StakeError,
98
state::{Delegation, Meta, Stake},
10-
sysvar::stake_history::StakeHistorySysvar,
119
},
1210
};
1311

@@ -29,46 +27,6 @@ pub(crate) fn new_stake(
2927
}
3028
}
3129

32-
pub(crate) fn redelegate_stake(
33-
stake: &mut Stake,
34-
stake_lamports: u64,
35-
voter_pubkey: &Pubkey,
36-
credits_observed: u64,
37-
epoch: Epoch,
38-
stake_history: &StakeHistorySysvar,
39-
) -> Result<(), ProgramError> {
40-
// If stake is currently active:
41-
if stake.stake(
42-
epoch,
43-
stake_history,
44-
PERPETUAL_NEW_WARMUP_COOLDOWN_RATE_EPOCH,
45-
) != 0
46-
{
47-
// If pubkey of new voter is the same as current,
48-
// and we are scheduled to start deactivating this epoch,
49-
// we rescind deactivation
50-
if stake.delegation.voter_pubkey == *voter_pubkey
51-
&& epoch == stake.delegation.deactivation_epoch
52-
{
53-
stake.delegation.deactivation_epoch = u64::MAX;
54-
return Ok(());
55-
} else {
56-
// can't redelegate to another pubkey if stake is active.
57-
return Err(StakeError::TooSoonToRedelegate.into());
58-
}
59-
}
60-
// Either the stake is freshly activated, is active but has been
61-
// deactivated this epoch, or has fully de-activated.
62-
// Redelegation implies either re-activation or un-deactivation
63-
64-
stake.delegation.stake = stake_lamports;
65-
stake.delegation.activation_epoch = epoch;
66-
stake.delegation.deactivation_epoch = u64::MAX;
67-
stake.delegation.voter_pubkey = *voter_pubkey;
68-
stake.credits_observed = credits_observed;
69-
Ok(())
70-
}
71-
7230
/// Ensure the stake delegation amount is valid. This checks that the account
7331
/// meets the minimum balance requirements of delegated stake. If not, return
7432
/// an error.

program/src/processor.rs

Lines changed: 29 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -404,22 +404,45 @@ impl Processor {
404404
)
405405
}
406406
StakeStateV2::Stake(meta, mut stake, flags) => {
407+
// Only the staker may (re)delegate
407408
meta.authorized
408409
.check(&signers, StakeAuthorize::Staker)
409410
.map_err(to_program_error)?;
410411

412+
// Compute the maximum stake allowed to (re)delegate
411413
let ValidatedDelegatedInfo { stake_amount } =
412414
validate_delegated_amount(stake_account_info, &meta)?;
413415

414-
redelegate_stake(
415-
&mut stake,
416-
stake_amount,
417-
vote_account_info.key,
418-
vote_state.credits(),
416+
// Get current activation status at this epoch
417+
let effective_stake = stake.delegation.stake(
419418
clock.epoch,
420419
stake_history,
421-
)?;
420+
PERPETUAL_NEW_WARMUP_COOLDOWN_RATE_EPOCH,
421+
);
422+
423+
if effective_stake == 0 {
424+
// The stake has no effective voting power this epoch. This means it is either:
425+
// 1. Inactive (fully cooled down after a previous deactivation)
426+
// 2. Still activating (was delegated for the first time this epoch)
427+
stake = new_stake(
428+
stake_amount,
429+
vote_account_info.key,
430+
vote_state.credits(),
431+
clock.epoch,
432+
);
433+
} else if clock.epoch == stake.delegation.deactivation_epoch
434+
&& stake.delegation.voter_pubkey == *vote_account_info.key
435+
{
436+
if stake_amount < stake.delegation.stake {
437+
return Err(StakeError::InsufficientDelegation.into());
438+
}
439+
stake.delegation.deactivation_epoch = u64::MAX;
440+
} else {
441+
// Not a valid state for redelegation
442+
return Err(StakeError::TooSoonToRedelegate.into());
443+
}
422444

445+
// Persist the updated stake state back to the account.
423446
set_stake_state(stake_account_info, &StakeStateV2::Stake(meta, stake, flags))
424447
}
425448
_ => Err(ProgramError::InvalidAccountData),

0 commit comments

Comments
 (0)