Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 22 additions & 14 deletions programs/stake/src/stake_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,37 +407,45 @@ impl Stake {
/// for credits_observed were the points paid
pub fn calculate_points_and_credits(
&self,
vote_state: &VoteState,
new_vote_state: &VoteState,
stake_history: Option<&StakeHistory>,
) -> (u128, u64) {
if self.credits_observed >= vote_state.credits() {
// if there is no newer credits since observed, return no point
if new_vote_state.credits() <= self.credits_observed {
return (0, 0);
}

let mut credits_observed = self.credits_observed;
let mut points = 0u128;
for (epoch, credits, prev_credits) in vote_state.epoch_credits() {
let mut points = 0;
let mut new_credits_observed = self.credits_observed;

for (epoch, final_epoch_credits, initial_epoch_credits) in
new_vote_state.epoch_credits().iter().copied()
{
let stake = u128::from(self.delegation.stake(epoch, stake_history));

// figure out how much this stake has seen that
// for which the vote account has a record
let epoch_credits = if self.credits_observed < *prev_credits {
let earned_credits = if self.credits_observed < initial_epoch_credits {
// the staker observed the entire epoch
credits - prev_credits
} else if self.credits_observed < *credits {
final_epoch_credits - initial_epoch_credits
} else if self.credits_observed < final_epoch_credits {
// the staker registered sometime during the epoch, partial credit
credits - credits_observed
final_epoch_credits - new_credits_observed
} else {
// the staker has already observed or been redeemed this epoch
// or was activated after this epoch
0
};

points += u128::from(self.delegation.stake(*epoch, stake_history))
* u128::from(epoch_credits);
let earned_credits = u128::from(earned_credits);

// don't want to assume anything about order of the iterator...
credits_observed = credits_observed.max(*credits);
new_credits_observed = new_credits_observed.max(final_epoch_credits);

// finally calculate points for this epoch
points += stake * earned_credits;
}
(points, credits_observed)

(points, new_credits_observed)
}

/// for a given stake and vote_state, calculate what distributions and what updates should be made
Expand Down
6 changes: 2 additions & 4 deletions programs/vote/src/vote_state/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,7 @@ pub const MAX_LOCKOUT_HISTORY: usize = 31;
pub const INITIAL_LOCKOUT: usize = 2;

// Maximum number of credits history to keep around
// smaller numbers makes
pub const MAX_EPOCH_CREDITS_HISTORY: usize = 64;
const MAX_EPOCH_CREDITS_HISTORY: usize = 64;

#[frozen_abi(digest = "Ch2vVEwos2EjAVqSHCyJjnN2MNX1yrpapZTGhMSCjWUH")]
#[derive(Serialize, Default, Deserialize, Debug, PartialEq, Eq, Clone, AbiExample)]
Expand Down Expand Up @@ -392,8 +391,7 @@ impl VoteState {
self.epoch_credits.last_mut().unwrap().0 = epoch;
}

// if stakers do not claim before the epoch goes away they lose the
// credits...
// Remove too old epoch_credits
if self.epoch_credits.len() > MAX_EPOCH_CREDITS_HISTORY {
self.epoch_credits.remove(0);
}
Expand Down
8 changes: 4 additions & 4 deletions runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1280,7 +1280,7 @@ impl Bank {
let validator_rewards =
(validator_rate * capitalization as f64 * epoch_duration_in_years) as u64;

let vote_balance_and_staked = self.stakes.read().unwrap().vote_balance_and_staked();
let old_vote_balance_and_staked = self.stakes.read().unwrap().vote_balance_and_staked();

let validator_point_value = self.pay_validator_rewards(validator_rewards);

Expand All @@ -1297,8 +1297,8 @@ impl Bank {
});
}

let validator_rewards_paid =
self.stakes.read().unwrap().vote_balance_and_staked() - vote_balance_and_staked;
let new_vote_balance_and_staked = self.stakes.read().unwrap().vote_balance_and_staked();
let validator_rewards_paid = new_vote_balance_and_staked - old_vote_balance_and_staked;
assert_eq!(
validator_rewards_paid,
u64::try_from(
Expand Down Expand Up @@ -6068,7 +6068,7 @@ mod tests {
// The same reward should be distributed given same credits
let expected_capitalization = do_test_bank_update_rewards_determinism();
// Repeat somewhat large number of iterations to expose possible different behavior
// depending on the randamly-seeded HashMap ordering
// depending on the randomly-seeded HashMap ordering
for _ in 0..30 {
let actual_capitalization = do_test_bank_update_rewards_determinism();
assert_eq!(actual_capitalization, expected_capitalization);
Expand Down