Move Bank::calculate_stake_vote_rewards to sub-submodule (#827)

This commit is contained in:
Tyera 2024-04-15 17:41:32 -06:00 committed by GitHub
parent f2aa4f0741
commit 7a15ec99cd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 150 additions and 145 deletions

View File

@ -874,15 +874,6 @@ pub struct CommitTransactionCounts {
pub signature_count: u64,
}
#[derive(Debug, Default)]
/// result of calculating the stake rewards at end of epoch
struct StakeRewardCalculation {
/// each individual stake account to reward
stake_rewards: StakeRewards,
/// total lamports across all `stake_rewards`
total_stake_rewards_lamports: u64,
}
impl Bank {
fn default_with_accounts(accounts: Accounts) -> Self {
let mut bank = Self {
@ -2553,137 +2544,6 @@ impl Bank {
(points > 0).then_some(PointValue { rewards, points })
}
/// Calculates epoch rewards for stake/vote accounts
/// Returns vote rewards, stake rewards, and the sum of all stake rewards in lamports
fn calculate_stake_vote_rewards(
&self,
reward_calculate_params: &EpochRewardCalculateParamInfo,
rewarded_epoch: Epoch,
point_value: PointValue,
thread_pool: &ThreadPool,
reward_calc_tracer: Option<impl RewardCalcTracer>,
metrics: &mut RewardsMetrics,
) -> (VoteRewardsAccounts, StakeRewardCalculation) {
let EpochRewardCalculateParamInfo {
stake_history,
stake_delegations,
cached_vote_accounts,
} = reward_calculate_params;
let solana_vote_program: Pubkey = solana_vote_program::id();
let get_vote_account = |vote_pubkey: &Pubkey| -> Option<VoteAccount> {
if let Some(vote_account) = cached_vote_accounts.get(vote_pubkey) {
return Some(vote_account.clone());
}
// If accounts-db contains a valid vote account, then it should
// already have been cached in cached_vote_accounts; so the code
// below is only for sanity checking, and can be removed once
// the cache is deemed to be reliable.
let account = self.get_account_with_fixed_root(vote_pubkey)?;
VoteAccount::try_from(account).ok()
};
let new_warmup_cooldown_rate_epoch = self.new_warmup_cooldown_rate_epoch();
let vote_account_rewards: VoteRewards = DashMap::new();
let total_stake_rewards = AtomicU64::default();
let (stake_rewards, measure_stake_rewards_us) = measure_us!(thread_pool.install(|| {
stake_delegations
.par_iter()
.filter_map(|(stake_pubkey, stake_account)| {
// curry closure to add the contextual stake_pubkey
let reward_calc_tracer = reward_calc_tracer.as_ref().map(|outer| {
// inner
move |inner_event: &_| {
outer(&RewardCalculationEvent::Staking(stake_pubkey, inner_event))
}
});
let stake_pubkey = **stake_pubkey;
let stake_account = (*stake_account).to_owned();
let delegation = stake_account.delegation();
let (mut stake_account, stake_state) =
<(AccountSharedData, StakeStateV2)>::from(stake_account);
let vote_pubkey = delegation.voter_pubkey;
let vote_account = get_vote_account(&vote_pubkey)?;
if vote_account.owner() != &solana_vote_program {
return None;
}
let vote_state = vote_account.vote_state().cloned().ok()?;
let pre_lamport = stake_account.lamports();
let redeemed = solana_stake_program::rewards::redeem_rewards(
rewarded_epoch,
stake_state,
&mut stake_account,
&vote_state,
&point_value,
stake_history,
reward_calc_tracer.as_ref(),
new_warmup_cooldown_rate_epoch,
);
let post_lamport = stake_account.lamports();
if let Ok((stakers_reward, voters_reward)) = redeemed {
debug!(
"calculated reward: {} {} {} {}",
stake_pubkey, pre_lamport, post_lamport, stakers_reward
);
// track voter rewards
let mut voters_reward_entry = vote_account_rewards
.entry(vote_pubkey)
.or_insert(VoteReward {
vote_account: vote_account.into(),
commission: vote_state.commission,
vote_rewards: 0,
vote_needs_store: false,
});
voters_reward_entry.vote_needs_store = true;
voters_reward_entry.vote_rewards = voters_reward_entry
.vote_rewards
.saturating_add(voters_reward);
let post_balance = stake_account.lamports();
total_stake_rewards.fetch_add(stakers_reward, Relaxed);
return Some(StakeReward {
stake_pubkey,
stake_reward_info: RewardInfo {
reward_type: RewardType::Staking,
lamports: i64::try_from(stakers_reward).unwrap(),
post_balance,
commission: Some(vote_state.commission),
},
stake_account,
});
} else {
debug!(
"solana_stake_program::rewards::redeem_rewards() failed for {}: {:?}",
stake_pubkey, redeemed
);
}
None
})
.collect()
}));
let (vote_rewards, measure_vote_rewards_us) =
measure_us!(Self::calc_vote_accounts_to_store(vote_account_rewards));
metrics.redeem_rewards_us += measure_stake_rewards_us + measure_vote_rewards_us;
(
vote_rewards,
StakeRewardCalculation {
stake_rewards,
total_stake_rewards_lamports: total_stake_rewards.load(Relaxed),
},
)
}
fn redeem_rewards(
&self,
vote_with_stake_delegations_map: DashMap<Pubkey, VoteWithStakeDelegations>,

View File

@ -2,26 +2,31 @@ use {
super::{
epoch_rewards_hasher::hash_rewards_into_partitions, Bank,
CalculateRewardsAndDistributeVoteRewardsResult, CalculateValidatorRewardsResult,
EpochRewardCalculateParamInfo, PartitionedRewardsCalculation,
EpochRewardCalculateParamInfo, PartitionedRewardsCalculation, StakeRewardCalculation,
StakeRewardCalculationPartitioned, VoteRewardsAccounts,
},
crate::bank::{
PrevEpochInflationRewards, RewardCalcTracer, RewardCalculationEvent, RewardsMetrics,
VoteAccount,
VoteAccount, VoteReward, VoteRewards,
},
log::info,
dashmap::DashMap,
log::{debug, info},
rayon::{
iter::{IntoParallelRefIterator, ParallelIterator},
ThreadPool,
},
solana_accounts_db::stake_rewards::StakeReward,
solana_measure::measure_us,
solana_sdk::{
account::{AccountSharedData, ReadableAccount},
clock::{Epoch, Slot},
pubkey::Pubkey,
reward_info::RewardInfo,
reward_type::RewardType,
stake::state::StakeStateV2,
},
solana_stake_program::points::PointValue,
std::sync::atomic::Ordering::Relaxed,
std::sync::atomic::{AtomicU64, Ordering::Relaxed},
};
impl Bank {
@ -288,6 +293,137 @@ impl Bank {
})
}
/// Calculates epoch rewards for stake/vote accounts
/// Returns vote rewards, stake rewards, and the sum of all stake rewards in lamports
fn calculate_stake_vote_rewards(
&self,
reward_calculate_params: &EpochRewardCalculateParamInfo,
rewarded_epoch: Epoch,
point_value: PointValue,
thread_pool: &ThreadPool,
reward_calc_tracer: Option<impl RewardCalcTracer>,
metrics: &mut RewardsMetrics,
) -> (VoteRewardsAccounts, StakeRewardCalculation) {
let EpochRewardCalculateParamInfo {
stake_history,
stake_delegations,
cached_vote_accounts,
} = reward_calculate_params;
let solana_vote_program: Pubkey = solana_vote_program::id();
let get_vote_account = |vote_pubkey: &Pubkey| -> Option<VoteAccount> {
if let Some(vote_account) = cached_vote_accounts.get(vote_pubkey) {
return Some(vote_account.clone());
}
// If accounts-db contains a valid vote account, then it should
// already have been cached in cached_vote_accounts; so the code
// below is only for sanity checking, and can be removed once
// the cache is deemed to be reliable.
let account = self.get_account_with_fixed_root(vote_pubkey)?;
VoteAccount::try_from(account).ok()
};
let new_warmup_cooldown_rate_epoch = self.new_warmup_cooldown_rate_epoch();
let vote_account_rewards: VoteRewards = DashMap::new();
let total_stake_rewards = AtomicU64::default();
let (stake_rewards, measure_stake_rewards_us) = measure_us!(thread_pool.install(|| {
stake_delegations
.par_iter()
.filter_map(|(stake_pubkey, stake_account)| {
// curry closure to add the contextual stake_pubkey
let reward_calc_tracer = reward_calc_tracer.as_ref().map(|outer| {
// inner
move |inner_event: &_| {
outer(&RewardCalculationEvent::Staking(stake_pubkey, inner_event))
}
});
let stake_pubkey = **stake_pubkey;
let stake_account = (*stake_account).to_owned();
let delegation = stake_account.delegation();
let (mut stake_account, stake_state) =
<(AccountSharedData, StakeStateV2)>::from(stake_account);
let vote_pubkey = delegation.voter_pubkey;
let vote_account = get_vote_account(&vote_pubkey)?;
if vote_account.owner() != &solana_vote_program {
return None;
}
let vote_state = vote_account.vote_state().cloned().ok()?;
let pre_lamport = stake_account.lamports();
let redeemed = solana_stake_program::rewards::redeem_rewards(
rewarded_epoch,
stake_state,
&mut stake_account,
&vote_state,
&point_value,
stake_history,
reward_calc_tracer.as_ref(),
new_warmup_cooldown_rate_epoch,
);
let post_lamport = stake_account.lamports();
if let Ok((stakers_reward, voters_reward)) = redeemed {
debug!(
"calculated reward: {} {} {} {}",
stake_pubkey, pre_lamport, post_lamport, stakers_reward
);
// track voter rewards
let mut voters_reward_entry = vote_account_rewards
.entry(vote_pubkey)
.or_insert(VoteReward {
vote_account: vote_account.into(),
commission: vote_state.commission,
vote_rewards: 0,
vote_needs_store: false,
});
voters_reward_entry.vote_needs_store = true;
voters_reward_entry.vote_rewards = voters_reward_entry
.vote_rewards
.saturating_add(voters_reward);
let post_balance = stake_account.lamports();
total_stake_rewards.fetch_add(stakers_reward, Relaxed);
return Some(StakeReward {
stake_pubkey,
stake_reward_info: RewardInfo {
reward_type: RewardType::Staking,
lamports: i64::try_from(stakers_reward).unwrap(),
post_balance,
commission: Some(vote_state.commission),
},
stake_account,
});
} else {
debug!(
"solana_stake_program::rewards::redeem_rewards() failed for {}: {:?}",
stake_pubkey, redeemed
);
}
None
})
.collect()
}));
let (vote_rewards, measure_vote_rewards_us) =
measure_us!(Self::calc_vote_accounts_to_store(vote_account_rewards));
metrics.redeem_rewards_us += measure_stake_rewards_us + measure_vote_rewards_us;
(
vote_rewards,
StakeRewardCalculation {
stake_rewards,
total_stake_rewards_lamports: total_stake_rewards.load(Relaxed),
},
)
}
/// Calculates epoch reward points from stake/vote accounts.
/// Returns reward lamports and points for the epoch or none if points == 0.
fn calculate_reward_points_partitioned(

View File

@ -5,7 +5,7 @@ mod epoch_rewards_hasher;
mod sysvar;
use {
super::{Bank, StakeRewardCalculation},
super::Bank,
crate::{stake_account::StakeAccount, stake_history::StakeHistory},
solana_accounts_db::{
partitioned_rewards::PartitionedEpochRewardsConfig, stake_rewards::StakeReward,
@ -50,6 +50,15 @@ pub(super) struct VoteRewardsAccounts {
pub(super) accounts_to_store: Vec<Option<AccountSharedData>>,
}
#[derive(Debug, Default)]
/// result of calculating the stake rewards at end of epoch
struct StakeRewardCalculation {
/// each individual stake account to reward
stake_rewards: StakeRewards,
/// total lamports across all `stake_rewards`
total_stake_rewards_lamports: u64,
}
#[derive(Debug, Default)]
struct CalculateValidatorRewardsResult {
vote_rewards_accounts: VoteRewardsAccounts,