Move Bank::calculate_stake_vote_rewards to sub-submodule (#827)
This commit is contained in:
parent
f2aa4f0741
commit
7a15ec99cd
|
@ -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>,
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue