stake: Remove v2 program references (#19308)

* stake: Remove v2 program references

* Remove stake v2 feature, along with stake rewrite
This commit is contained in:
Jon Cinque
2021-08-20 01:08:44 -04:00
committed by GitHub
parent 2a877ae06e
commit 73aa004c59
11 changed files with 100 additions and 618 deletions

View File

@ -99,7 +99,7 @@ fn redelegate(
can_reverse_deactivation: bool,
) -> Result<(), StakeError> {
// If stake is currently active:
if stake.stake(clock.epoch, Some(stake_history), true) != 0 {
if stake.stake(clock.epoch, Some(stake_history)) != 0 {
// If pubkey of new voter is the same as current,
// and we are scheduled to start deactivating this epoch,
// we rescind deactivation
@ -161,7 +161,6 @@ fn redeem_stake_rewards(
vote_state: &VoteState,
stake_history: Option<&StakeHistory>,
inflation_point_calc_tracer: &mut Option<impl FnMut(&InflationPointCalculationEvent)>,
fix_stake_deactivate: bool,
) -> Option<(u64, u64)> {
if let Some(inflation_point_calc_tracer) = inflation_point_calc_tracer {
inflation_point_calc_tracer(&InflationPointCalculationEvent::CreditsObserved(
@ -175,7 +174,6 @@ fn redeem_stake_rewards(
vote_state,
stake_history,
inflation_point_calc_tracer,
fix_stake_deactivate,
)
.map(|(stakers_reward, voters_reward, credits_observed)| {
if let Some(inflation_point_calc_tracer) = inflation_point_calc_tracer {
@ -195,14 +193,12 @@ fn calculate_stake_points(
vote_state: &VoteState,
stake_history: Option<&StakeHistory>,
inflation_point_calc_tracer: &mut Option<impl FnMut(&InflationPointCalculationEvent)>,
fix_stake_deactivate: bool,
) -> u128 {
calculate_stake_points_and_credits(
stake,
vote_state,
stake_history,
inflation_point_calc_tracer,
fix_stake_deactivate,
)
.0
}
@ -215,21 +211,13 @@ fn calculate_stake_points_and_credits(
new_vote_state: &VoteState,
stake_history: Option<&StakeHistory>,
inflation_point_calc_tracer: &mut Option<impl FnMut(&InflationPointCalculationEvent)>,
fix_stake_deactivate: bool,
) -> (u128, u64) {
// if there is no newer credits since observed, return no point
if new_vote_state.credits() <= stake.credits_observed {
if fix_stake_deactivate {
if let Some(inflation_point_calc_tracer) = inflation_point_calc_tracer {
inflation_point_calc_tracer(&SkippedReason::ZeroCreditsAndReturnCurrent.into());
}
return (0, stake.credits_observed);
} else {
if let Some(inflation_point_calc_tracer) = inflation_point_calc_tracer {
inflation_point_calc_tracer(&SkippedReason::ZeroCreditsAndReturnZero.into());
}
return (0, 0);
if let Some(inflation_point_calc_tracer) = inflation_point_calc_tracer {
inflation_point_calc_tracer(&SkippedReason::ZeroCreditsAndReturnCurrent.into());
}
return (0, stake.credits_observed);
}
let mut points = 0;
@ -238,11 +226,7 @@ fn calculate_stake_points_and_credits(
for (epoch, final_epoch_credits, initial_epoch_credits) in
new_vote_state.epoch_credits().iter().copied()
{
let stake_amount = u128::from(stake.delegation.stake(
epoch,
stake_history,
fix_stake_deactivate,
));
let stake_amount = u128::from(stake.delegation.stake(epoch, stake_history));
// figure out how much this stake has seen that
// for which the vote account has a record
@ -285,24 +269,22 @@ fn calculate_stake_points_and_credits(
/// * voter_rewards to be distributed
/// * new value for credits_observed in the stake
/// returns None if there's no payout or if any deserved payout is < 1 lamport
pub fn calculate_stake_rewards(
fn calculate_stake_rewards(
stake: &Stake,
point_value: &PointValue,
vote_state: &VoteState,
stake_history: Option<&StakeHistory>,
inflation_point_calc_tracer: &mut Option<impl FnMut(&InflationPointCalculationEvent)>,
fix_stake_deactivate: bool,
) -> Option<(u64, u64, u64)> {
let (points, credits_observed) = calculate_stake_points_and_credits(
stake,
vote_state,
stake_history,
inflation_point_calc_tracer,
fix_stake_deactivate,
);
// Drive credits_observed forward unconditionally when rewards are disabled
if point_value.rewards == 0 && fix_stake_deactivate {
if point_value.rewards == 0 {
return Some((0, 0, credits_observed));
}
@ -786,9 +768,7 @@ impl<'a> StakeAccount for KeyedAccount<'a> {
.check(&signers, StakeAuthorize::Withdrawer)?;
// if we have a deactivation epoch and we're in cooldown
let staked = if clock.epoch >= stake.delegation.deactivation_epoch {
stake
.delegation
.stake(clock.epoch, Some(stake_history), true)
stake.delegation.stake(clock.epoch, Some(stake_history))
} else {
// Assume full stake if the stake account hasn't been
// de-activated, because in the future the exposed stake
@ -886,11 +866,10 @@ impl MergeKind {
StakeState::Stake(meta, stake) => {
// stake must not be in a transient state. Transient here meaning
// activating or deactivating with non-zero effective stake.
match stake.delegation.stake_activating_and_deactivating(
clock.epoch,
Some(stake_history),
true,
) {
match stake
.delegation
.stake_activating_and_deactivating(clock.epoch, Some(stake_history))
{
/*
(e, a, d): e - effective, a - activating, d - deactivating */
(0, 0, 0) => Ok(Self::Inactive(meta, stake_keyed_account.lamports()?)),
@ -1119,16 +1098,13 @@ pub fn redeem_rewards(
point_value: &PointValue,
stake_history: Option<&StakeHistory>,
inflation_point_calc_tracer: &mut Option<impl FnMut(&InflationPointCalculationEvent)>,
fix_stake_deactivate: bool,
) -> Result<(u64, u64), InstructionError> {
if let StakeState::Stake(meta, mut stake) = stake_account.state()? {
if let Some(inflation_point_calc_tracer) = inflation_point_calc_tracer {
inflation_point_calc_tracer(
&InflationPointCalculationEvent::EffectiveStakeAtRewardedEpoch(stake.stake(
rewarded_epoch,
stake_history,
fix_stake_deactivate,
)),
&InflationPointCalculationEvent::EffectiveStakeAtRewardedEpoch(
stake.stake(rewarded_epoch, stake_history),
),
);
inflation_point_calc_tracer(&InflationPointCalculationEvent::RentExemptReserve(
meta.rent_exempt_reserve,
@ -1144,7 +1120,6 @@ pub fn redeem_rewards(
vote_state,
stake_history,
inflation_point_calc_tracer,
fix_stake_deactivate,
) {
stake_account.checked_add_lamports(stakers_reward)?;
vote_account.checked_add_lamports(voters_reward)?;
@ -1165,7 +1140,6 @@ pub fn calculate_points(
stake_account: &AccountSharedData,
vote_account: &AccountSharedData,
stake_history: Option<&StakeHistory>,
fix_stake_deactivate: bool,
) -> Result<u128, InstructionError> {
if let StakeState::Stake(_meta, stake) = stake_account.state()? {
let vote_state: VoteState =
@ -1176,7 +1150,6 @@ pub fn calculate_points(
&vote_state,
stake_history,
&mut null_tracer(),
fix_stake_deactivate,
))
} else {
Err(InstructionError::InvalidAccountData)
@ -1198,48 +1171,11 @@ fn calculate_split_rent_exempt_reserve(
pub type RewriteStakeStatus = (&'static str, (u64, u64), (u64, u64));
pub fn rewrite_stakes(
stake_account: &mut AccountSharedData,
rent: &Rent,
) -> Result<RewriteStakeStatus, InstructionError> {
match stake_account.state()? {
StakeState::Initialized(mut meta) => {
let meta_status = meta.rewrite_rent_exempt_reserve(rent, stake_account.data().len());
if meta_status.is_none() {
return Err(InstructionError::InvalidAccountData);
}
stake_account.set_state(&StakeState::Initialized(meta))?;
Ok(("initialized", meta_status.unwrap_or_default(), (0, 0)))
}
StakeState::Stake(mut meta, mut stake) => {
let meta_status = meta.rewrite_rent_exempt_reserve(rent, stake_account.data().len());
let stake_status = stake
.delegation
.rewrite_stake(stake_account.lamports(), meta.rent_exempt_reserve);
if meta_status.is_none() && stake_status.is_none() {
return Err(InstructionError::InvalidAccountData);
}
stake_account.set_state(&StakeState::Stake(meta, stake))?;
Ok((
"stake",
meta_status.unwrap_or_default(),
stake_status.unwrap_or_default(),
))
}
_ => Err(InstructionError::InvalidAccountData),
}
}
// utility function, used by runtime::Stakes, tests
pub fn new_stake_history_entry<'a, I>(
epoch: Epoch,
stakes: I,
history: Option<&StakeHistory>,
fix_stake_deactivate: bool,
) -> StakeHistoryEntry
where
I: Iterator<Item = &'a Delegation>,
@ -1250,10 +1186,7 @@ where
(a.0 + b.0, a.1 + b.1, a.2 + b.2)
}
let (effective, activating, deactivating) = stakes.fold((0, 0, 0), |sum, stake| {
add(
sum,
stake.stake_activating_and_deactivating(epoch, history, fix_stake_deactivate),
)
add(sum, stake.stake_activating_and_deactivating(epoch, history))
});
StakeHistoryEntry {
@ -1801,7 +1734,6 @@ mod tests {
epoch,
delegations.iter().chain(bootstrap_delegation.iter()),
Some(&stake_history),
true,
);
stake_history.add(epoch, entry);
}
@ -1824,26 +1756,19 @@ mod tests {
let mut stake_history = StakeHistory::default();
// assert that this stake follows step function if there's no history
assert_eq!(
stake.stake_activating_and_deactivating(
stake.activation_epoch,
Some(&stake_history),
true
),
stake.stake_activating_and_deactivating(stake.activation_epoch, Some(&stake_history),),
(0, stake.stake, 0)
);
for epoch in stake.activation_epoch + 1..stake.deactivation_epoch {
assert_eq!(
stake.stake_activating_and_deactivating(epoch, Some(&stake_history), true),
stake.stake_activating_and_deactivating(epoch, Some(&stake_history)),
(stake.stake, 0, 0)
);
}
// assert that this stake is full deactivating
assert_eq!(
stake.stake_activating_and_deactivating(
stake.deactivation_epoch,
Some(&stake_history),
true
),
stake
.stake_activating_and_deactivating(stake.deactivation_epoch, Some(&stake_history),),
(stake.stake, 0, stake.stake)
);
// assert that this stake is fully deactivated if there's no history
@ -1851,7 +1776,6 @@ mod tests {
stake.stake_activating_and_deactivating(
stake.deactivation_epoch + 1,
Some(&stake_history),
true,
),
(0, 0, 0)
);
@ -1866,7 +1790,7 @@ mod tests {
);
// assert that this stake is broken, because above setup is broken
assert_eq!(
stake.stake_activating_and_deactivating(1, Some(&stake_history), true),
stake.stake_activating_and_deactivating(1, Some(&stake_history)),
(0, stake.stake, 0)
);
@ -1881,7 +1805,7 @@ mod tests {
);
// assert that this stake is broken, because above setup is broken
assert_eq!(
stake.stake_activating_and_deactivating(2, Some(&stake_history), true),
stake.stake_activating_and_deactivating(2, Some(&stake_history)),
(increment, stake.stake - increment, 0)
);
@ -1901,7 +1825,6 @@ mod tests {
stake.stake_activating_and_deactivating(
stake.deactivation_epoch + 1,
Some(&stake_history),
true,
),
(stake.stake, 0, stake.stake) // says "I'm still waiting for deactivation"
);
@ -1920,7 +1843,6 @@ mod tests {
stake.stake_activating_and_deactivating(
stake.deactivation_epoch + 2,
Some(&stake_history),
true,
),
(stake.stake - increment, 0, stake.stake - increment) // hung, should be lower
);
@ -1934,11 +1856,7 @@ mod tests {
Slow,
}
fn do_test(
old_behavior: OldDeactivationBehavior,
fix_stake_deactivate: bool,
expected_stakes: &[(u64, u64, u64)],
) {
fn do_test(old_behavior: OldDeactivationBehavior, expected_stakes: &[(u64, u64, u64)]) {
let cluster_stake = 1_000;
let activating_stake = 10_000;
let some_stake = 700;
@ -1987,49 +1905,12 @@ mod tests {
assert_eq!(
expected_stakes,
(0..expected_stakes.len())
.map(|epoch| stake.stake_activating_and_deactivating(
epoch as u64,
Some(&stake_history),
fix_stake_deactivate
))
.map(|epoch| stake
.stake_activating_and_deactivating(epoch as u64, Some(&stake_history),))
.collect::<Vec<_>>()
);
}
#[test]
fn test_old_behavior_slow() {
do_test(
OldDeactivationBehavior::Slow,
false,
&[
(0, 0, 0),
(13, 0, 13),
(10, 0, 10),
(8, 0, 8),
(0, 0, 0),
(0, 0, 0),
(0, 0, 0),
],
);
}
#[test]
fn test_old_behavior_stuck() {
do_test(
OldDeactivationBehavior::Stuck,
false,
&[
(0, 0, 0),
(17, 0, 17),
(17, 0, 17),
(17, 0, 17),
(17, 0, 17),
(17, 0, 17),
(17, 0, 17),
],
);
}
#[test]
fn test_new_behavior_previously_slow() {
// any stake accounts activated and deactivated at the same epoch
@ -2037,7 +1918,6 @@ mod tests {
do_test(
OldDeactivationBehavior::Slow,
true,
&[
(0, 0, 0),
(0, 0, 0),
@ -2057,7 +1937,6 @@ mod tests {
do_test(
OldDeactivationBehavior::Stuck,
true,
&[
(0, 0, 0),
(0, 0, 0),
@ -2154,11 +2033,7 @@ mod tests {
let calculate_each_staking_status = |stake: &Delegation, epoch_count: usize| -> Vec<_> {
(0..epoch_count)
.map(|epoch| {
stake.stake_activating_and_deactivating(
epoch as u64,
Some(&stake_history),
true,
)
stake.stake_activating_and_deactivating(epoch as u64, Some(&stake_history))
})
.collect::<Vec<_>>()
};
@ -2282,7 +2157,7 @@ mod tests {
(0, history.deactivating)
};
assert_eq!(
stake.stake_activating_and_deactivating(epoch, Some(&stake_history), true),
stake.stake_activating_and_deactivating(epoch, Some(&stake_history)),
(expected_stake, expected_activating, expected_deactivating)
);
}
@ -2309,7 +2184,7 @@ mod tests {
for epoch in 0..epochs {
let stake = delegations
.iter()
.map(|delegation| delegation.stake(epoch, Some(&stake_history), true))
.map(|delegation| delegation.stake(epoch, Some(&stake_history)))
.sum::<u64>();
max_stake = max_stake.max(stake);
min_stake = min_stake.min(stake);
@ -2368,7 +2243,7 @@ mod tests {
let mut prev_total_effective_stake = delegations
.iter()
.map(|delegation| delegation.stake(0, Some(&stake_history), true))
.map(|delegation| delegation.stake(0, Some(&stake_history)))
.sum::<u64>();
// uncomment and add ! for fun with graphing
@ -2376,7 +2251,7 @@ mod tests {
for epoch in 1..epochs {
let total_effective_stake = delegations
.iter()
.map(|delegation| delegation.stake(epoch, Some(&stake_history), true))
.map(|delegation| delegation.stake(epoch, Some(&stake_history)))
.sum::<u64>();
let delta = if total_effective_stake > prev_total_effective_stake {
@ -3512,7 +3387,6 @@ mod tests {
&vote_state,
None,
&mut null_tracer(),
true,
)
);
@ -3532,7 +3406,6 @@ mod tests {
&vote_state,
None,
&mut null_tracer(),
true,
)
);
@ -3569,7 +3442,6 @@ mod tests {
&vote_state,
None,
&mut null_tracer(),
true,
)
);
@ -3583,7 +3455,7 @@ mod tests {
// no overflow on points
assert_eq!(
u128::from(stake.delegation.stake) * epoch_slots,
calculate_stake_points(&stake, &vote_state, None, &mut null_tracer(), true)
calculate_stake_points(&stake, &vote_state, None, &mut null_tracer())
);
}
@ -3612,7 +3484,6 @@ mod tests {
&vote_state,
None,
&mut null_tracer(),
true,
)
);
@ -3632,7 +3503,6 @@ mod tests {
&vote_state,
None,
&mut null_tracer(),
true,
)
);
@ -3649,7 +3519,6 @@ mod tests {
&vote_state,
None,
&mut null_tracer(),
true,
)
);
@ -3669,7 +3538,6 @@ mod tests {
&vote_state,
None,
&mut null_tracer(),
true,
)
);
@ -3687,7 +3555,6 @@ mod tests {
&vote_state,
None,
&mut null_tracer(),
true,
)
);
@ -3711,7 +3578,6 @@ mod tests {
&vote_state,
None,
&mut null_tracer(),
true,
)
);
@ -3729,7 +3595,6 @@ mod tests {
&vote_state,
None,
&mut null_tracer(),
true,
)
);
vote_state.commission = 99;
@ -3744,7 +3609,6 @@ mod tests {
&vote_state,
None,
&mut null_tracer(),
true,
)
);
@ -3762,7 +3626,6 @@ mod tests {
&vote_state,
None,
&mut null_tracer(),
true,
)
);
@ -3780,24 +3643,13 @@ mod tests {
&vote_state,
None,
&mut null_tracer(),
true,
)
);
// assert the previous behavior is preserved where fix_stake_deactivate=false
assert_eq!(
(0, 0),
calculate_stake_points_and_credits(
&stake,
&vote_state,
None,
&mut null_tracer(),
false
)
);
assert_eq!(
(0, 4),
calculate_stake_points_and_credits(&stake, &vote_state, None, &mut null_tracer(), true)
calculate_stake_points_and_credits(&stake, &vote_state, None, &mut null_tracer())
);
}
@ -5520,8 +5372,8 @@ mod tests {
deactivating,
},
);
if stake_amount == stake.stake(clock.epoch, Some(&stake_history), true)
&& source_amount == source_stake.stake(clock.epoch, Some(&stake_history), true)
if stake_amount == stake.stake(clock.epoch, Some(&stake_history))
&& source_amount == source_stake.stake(clock.epoch, Some(&stake_history))
{
break;
}
@ -5606,8 +5458,8 @@ mod tests {
deactivating,
},
);
if 0 == stake.stake(clock.epoch, Some(&stake_history), true)
&& 0 == source_stake.stake(clock.epoch, Some(&stake_history), true)
if 0 == stake.stake(clock.epoch, Some(&stake_history))
&& 0 == source_stake.stake(clock.epoch, Some(&stake_history))
{
break;
}
@ -5968,98 +5820,6 @@ mod tests {
}
}
#[test]
fn test_stake_rewrite_stake() {
let right_data_len = std::mem::size_of::<StakeState>() as u64;
let rent = Rent::default();
let rent_exempt_reserve = rent.minimum_balance(right_data_len as usize);
let expected_stake = 1000;
let account_balance = rent_exempt_reserve + expected_stake;
let test_cases = [
(9999, Some((9999, expected_stake))), // large stake
(1000, None), // correct
(42, Some((42, expected_stake))), // small stake
];
for (staked_amount, expected_rewrite) in &test_cases {
let mut delegation = Delegation {
stake: *staked_amount,
..Delegation::default()
};
let actual_rewrite = delegation.rewrite_stake(account_balance, rent_exempt_reserve);
assert_eq!(actual_rewrite, *expected_rewrite);
assert_eq!(delegation.stake, expected_stake);
}
}
enum ExpectedRewriteResult {
NotRewritten,
Rewritten,
}
#[test]
fn test_rewrite_stakes_initialized() {
let right_data_len = std::mem::size_of::<StakeState>();
let rent = Rent::default();
let rent_exempt_reserve = rent.minimum_balance(right_data_len as usize);
let expected_stake = 1000;
let account_balance = rent_exempt_reserve + expected_stake;
let test_cases = [
(1, ExpectedRewriteResult::Rewritten),
(0, ExpectedRewriteResult::NotRewritten),
];
for (offset, expected_rewrite) in &test_cases {
let meta = Meta {
rent_exempt_reserve: rent_exempt_reserve + offset,
..Meta::default()
};
let mut account = AccountSharedData::new(account_balance, right_data_len, &id());
account.set_state(&StakeState::Initialized(meta)).unwrap();
let result = rewrite_stakes(&mut account, &rent);
match expected_rewrite {
ExpectedRewriteResult::NotRewritten => assert!(result.is_err()),
ExpectedRewriteResult::Rewritten => assert!(result.is_ok()),
}
}
}
#[test]
fn test_rewrite_stakes_stake() {
let right_data_len = std::mem::size_of::<StakeState>();
let rent = Rent::default();
let rent_exempt_reserve = rent.minimum_balance(right_data_len as usize);
let expected_stake = 1000;
let account_balance = rent_exempt_reserve + expected_stake;
let test_cases = [
(1, 9999, ExpectedRewriteResult::Rewritten), // bad meta, bad stake
(1, 1000, ExpectedRewriteResult::Rewritten), // bad meta, good stake
(0, 9999, ExpectedRewriteResult::Rewritten), // good meta, bad stake
(0, 1000, ExpectedRewriteResult::NotRewritten), // good meta, good stake
];
for (offset, staked_amount, expected_rewrite) in &test_cases {
let meta = Meta {
rent_exempt_reserve: rent_exempt_reserve + offset,
..Meta::default()
};
let stake = Stake {
delegation: (Delegation {
stake: *staked_amount,
..Delegation::default()
}),
..Stake::default()
};
let mut account = AccountSharedData::new(account_balance, right_data_len, &id());
account.set_state(&StakeState::Stake(meta, stake)).unwrap();
let result = rewrite_stakes(&mut account, &rent);
match expected_rewrite {
ExpectedRewriteResult::NotRewritten => assert!(result.is_err()),
ExpectedRewriteResult::Rewritten => assert!(result.is_ok()),
}
}
}
#[test]
fn test_calculate_lamports_per_byte_year() {
let rent = Rent::default();