diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index c82b12ac14e..6dae87ff62c 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -39,7 +39,7 @@ use { bank::{ metrics::*, partitioned_epoch_rewards::{ - CachedVoteAccounts, EpochRewardStatus, VoteRewardsAccounts, + CachedVoteAccounts, EpochRewardStatus, RewardCommissionAccounts, }, }, bank_forks::BankForks, @@ -941,13 +941,13 @@ pub struct Bank { } #[derive(Debug)] -struct VoteReward { - vote_account: AccountSharedData, +struct RewardCommission { + commission_account: AccountSharedData, commission_bps: u16, - vote_rewards: u64, + commission_lamports: u64, } -type VoteRewards = HashMap; +type RewardCommissions = HashMap; #[derive(Debug, Default)] pub struct NewBankOptions { @@ -2474,55 +2474,57 @@ impl Bank { } } - /// Convert computed VoteRewards to VoteRewardsAccounts for storing. + /// Convert computed RewardCommissions to RewardCommissionAccounts for storing. /// - /// This function processes vote rewards and consolidates them into a single - /// structure containing the pubkey, reward info, and updated account data - /// for each vote account. The resulting structure is optimized for storage - /// by combining previously separate rewards and accounts vectors into a - /// single accounts_with_rewards vector. - fn calc_vote_accounts_to_store(vote_account_rewards: VoteRewards) -> VoteRewardsAccounts { - let mut result = VoteRewardsAccounts { - accounts_with_rewards: Vec::with_capacity(vote_account_rewards.len()), - total_vote_rewards_lamports: 0, + /// This function processes reward commissions and consolidates them into a + /// single structure containing the pubkey, reward info, and updated account + /// data for each commission account. The resulting structure is optimized + /// for storage by combining previously separate rewards and accounts + /// vectors into a single accounts_with_rewards vector. + fn calculate_commission_accounts( + reward_commissions: RewardCommissions, + ) -> RewardCommissionAccounts { + let mut result = RewardCommissionAccounts { + accounts_with_rewards: Vec::with_capacity(reward_commissions.len()), + total_reward_commission_lamports: 0, }; for ( - vote_pubkey, - VoteReward { - mut vote_account, + commission_pubkey, + RewardCommission { + mut commission_account, commission_bps, - vote_rewards, + commission_lamports, }, - ) in vote_account_rewards + ) in reward_commissions { - if let Err(err) = vote_account.checked_add_lamports(vote_rewards) { - debug!("reward redemption failed for {vote_pubkey}: {err:?}"); + if let Err(err) = commission_account.checked_add_lamports(commission_lamports) { + debug!("reward redemption failed for {commission_pubkey}: {err:?}"); continue; } result.accounts_with_rewards.push(( - vote_pubkey, + commission_pubkey, RewardInfo { reward_type: RewardType::Voting, - lamports: vote_rewards as i64, - post_balance: vote_account.lamports(), + lamports: commission_lamports as i64, + post_balance: commission_account.lamports(), commission_bps: Some(commission_bps), }, - vote_account, + commission_account, )); - result.total_vote_rewards_lamports += vote_rewards; + result.total_reward_commission_lamports += commission_lamports; } result } - fn update_vote_rewards(&self, vote_rewards: &VoteRewardsAccounts) { + fn update_reward_commissions(&self, reward_commission_accounts: &RewardCommissionAccounts) { let mut rewards = self.rewards.write().unwrap(); - rewards.reserve(vote_rewards.accounts_with_rewards.len()); - vote_rewards + rewards.reserve(reward_commission_accounts.accounts_with_rewards.len()); + reward_commission_accounts .accounts_with_rewards .iter() - .for_each(|(vote_pubkey, vote_reward, _)| { - rewards.push((*vote_pubkey, *vote_reward)); + .for_each(|(commission_pubkey, reward_commission, _)| { + rewards.push((*commission_pubkey, *reward_commission)); }); } diff --git a/runtime/src/bank/metrics.rs b/runtime/src/bank/metrics.rs index 9609a641a28..1204960b660 100644 --- a/runtime/src/bank/metrics.rs +++ b/runtime/src/bank/metrics.rs @@ -21,7 +21,7 @@ pub(crate) struct RewardsMetrics { pub(crate) calculate_points_us: AtomicU64, pub(crate) redeem_rewards_us: u64, pub(crate) store_stake_accounts_us: AtomicU64, - pub(crate) store_vote_accounts_us: AtomicU64, + pub(crate) store_commission_accounts_us: AtomicU64, } pub(crate) struct NewBankTimings { @@ -90,8 +90,8 @@ pub(crate) fn report_new_epoch_metrics( i64 ), ( - "store_vote_accounts_us", - metrics.store_vote_accounts_us.load(Relaxed), + "store_commission_accounts_us", + metrics.store_commission_accounts_us.load(Relaxed), i64 ), ); diff --git a/runtime/src/bank/partitioned_epoch_rewards/calculation.rs b/runtime/src/bank/partitioned_epoch_rewards/calculation.rs index 3d38e19e530..79d9da67ee7 100644 --- a/runtime/src/bank/partitioned_epoch_rewards/calculation.rs +++ b/runtime/src/bank/partitioned_epoch_rewards/calculation.rs @@ -3,13 +3,13 @@ use { epoch_rewards_hasher::hash_rewards_into_partitions, Bank, CachedVoteAccounts, CalculateValidatorRewardsResult, EpochRewardCalculateParamInfo, FilteredStakeDelegations, PartitionedRewardsCalculation, PartitionedStakeReward, PartitionedStakeRewards, - StakeRewardCalculation, VoteRewardsAccounts, VoteRewardsAccountsStorable, + RewardCommissionAccounts, RewardCommissionAccountsStorable, StakeRewardCalculation, REWARD_CALCULATION_NUM_BLOCKS, }, crate::{ bank::{ null_tracer, EpochInflationRewards, RewardCalcTracer, RewardCalculationEvent, - RewardsMetrics, VoteReward, VoteRewards, + RewardCommission, RewardCommissions, RewardsMetrics, }, inflation_rewards::{ points::{calculate_points, DelegatedVoteState, PointValue}, @@ -37,55 +37,60 @@ use { #[derive(Debug)] struct DelegationRewards { stake_reward: PartitionedStakeReward, - vote_pubkey: Pubkey, - vote_reward: VoteReward, + commission_pubkey: Pubkey, + reward_commission: RewardCommission, } #[derive(Default)] struct RewardsAccumulator { - vote_rewards: VoteRewards, + reward_commissions: RewardCommissions, num_stake_rewards: usize, total_stake_rewards_lamports: u64, } impl RewardsAccumulator { - fn add_reward(&mut self, vote_pubkey: Pubkey, vote_reward: VoteReward, stakers_reward: u64) { - self.vote_rewards - .entry(vote_pubkey) - .and_modify(|dst_vote_reward| { - dst_vote_reward.vote_rewards = dst_vote_reward - .vote_rewards - .saturating_add(vote_reward.vote_rewards) + fn add_reward( + &mut self, + commission_pubkey: Pubkey, + reward_commission: RewardCommission, + stakers_reward: u64, + ) { + self.reward_commissions + .entry(commission_pubkey) + .and_modify(|dst_reward_commission| { + dst_reward_commission.commission_lamports = dst_reward_commission + .commission_lamports + .saturating_add(reward_commission.commission_lamports) }) - .or_insert(vote_reward); + .or_insert(reward_commission); self.num_stake_rewards = self.num_stake_rewards.saturating_add(1); self.total_stake_rewards_lamports = self .total_stake_rewards_lamports .saturating_add(stakers_reward); } - /// Merges two instances by combining their vote rewards and stake rewards. + /// Merges two instances by combining their reward commissions and stake rewards. /// - /// To minimize reallocations, the instance with more vote rewards is used + /// To minimize reallocations, the instance with more reward commissions is used /// as the base and the smaller instance is merged into it. fn accumulate_into_larger(self, rhs: Self) -> Self { - // Check which instance has more vote rewards. Treat the bigger one + // Check which instance has more reward commissions. Treat the bigger one // as a destination, which is going to be extended. This way we make // the reallocation as small as possible. - let (mut dst, src) = if self.vote_rewards.len() >= rhs.vote_rewards.len() { + let (mut dst, src) = if self.reward_commissions.len() >= rhs.reward_commissions.len() { (self, rhs) } else { (rhs, self) }; - for (vote_pubkey, vote_reward) in src.vote_rewards { - dst.vote_rewards - .entry(vote_pubkey) - .and_modify(|dst_vote_reward: &mut VoteReward| { - dst_vote_reward.vote_rewards = dst_vote_reward - .vote_rewards - .saturating_add(vote_reward.vote_rewards) + for (commission_pubkey, reward_commission) in src.reward_commissions { + dst.reward_commissions + .entry(commission_pubkey) + .and_modify(|dst_reward_commission: &mut RewardCommission| { + dst_reward_commission.commission_lamports = dst_reward_commission + .commission_lamports + .saturating_add(reward_commission.commission_lamports) }) - .or_insert(vote_reward); + .or_insert(reward_commission); } dst.num_stake_rewards = dst.num_stake_rewards.saturating_add(src.num_stake_rewards); dst.total_stake_rewards_lamports = dst @@ -107,20 +112,20 @@ impl Bank { rewards_calculation: &PartitionedRewardsCalculation, rewards_metrics: &RewardsMetrics, ) { - self.distribute_vote_rewards(parent_epoch, rewards_calculation, rewards_metrics); + self.distribute_reward_commissions(parent_epoch, rewards_calculation, rewards_metrics); let slot = self.slot(); let distribution_starting_block_height = self.block_height() + REWARD_CALCULATION_NUM_BLOCKS; let PartitionedRewardsCalculation { - vote_account_rewards, + reward_commission_accounts, stake_rewards, point_value, .. } = rewards_calculation; - let distributed_rewards = vote_account_rewards.total_vote_rewards_lamports; + let distributed_rewards = reward_commission_accounts.total_reward_commission_lamports; let stake_rewards = Arc::clone(&stake_rewards.stake_rewards); let num_partitions = self.get_reward_distribution_num_blocks(&stake_rewards); @@ -144,7 +149,7 @@ impl Bank { ); } - // Calculate rewards from previous epoch and distribute vote rewards + // Calculate rewards from previous epoch and distribute reward commissions pub(in crate::bank) fn calculate_rewards( &self, stake_history: &StakeHistory, @@ -196,14 +201,14 @@ impl Bank { rewards_calculation } - pub(in crate::bank) fn distribute_vote_rewards( + pub(in crate::bank) fn distribute_reward_commissions( &mut self, prev_epoch: Epoch, rewards_calculation: &PartitionedRewardsCalculation, rewards_metrics: &RewardsMetrics, ) { let PartitionedRewardsCalculation { - vote_account_rewards, + reward_commission_accounts, stake_rewards, validator_rate, foundation_rate, @@ -212,9 +217,9 @@ impl Bank { .. } = rewards_calculation; - let total_vote_rewards = vote_account_rewards.total_vote_rewards_lamports; - self.store_vote_accounts_partitioned(vote_account_rewards, rewards_metrics); - self.update_vote_rewards(vote_account_rewards); + let total_reward_commissions = reward_commission_accounts.total_reward_commission_lamports; + self.store_commission_accounts_partitioned(reward_commission_accounts, rewards_metrics); + self.update_reward_commissions(reward_commission_accounts); let StakeRewardCalculation { total_stake_rewards_lamports, @@ -222,10 +227,10 @@ impl Bank { } = stake_rewards; // verify that we didn't pay any more than we expected to - assert!(point_value.rewards >= total_vote_rewards + total_stake_rewards_lamports); + assert!(point_value.rewards >= total_reward_commissions + total_stake_rewards_lamports); info!( - "distributed vote rewards: {} out of {}, remaining {}", - total_vote_rewards, point_value.rewards, total_stake_rewards_lamports + "distributed reward commissions: {} out of {}, remaining {}", + total_reward_commissions, point_value.rewards, total_stake_rewards_lamports ); let (num_stake_accounts, num_vote_accounts) = { @@ -235,7 +240,8 @@ impl Bank { stakes.vote_accounts().len(), ) }; - self.capitalization.fetch_add(total_vote_rewards, Relaxed); + self.capitalization + .fetch_add(total_reward_commissions, Relaxed); let active_stake = if let Some(stake_history_entry) = self.stakes_cache.stakes().history().get(prev_epoch) @@ -251,7 +257,7 @@ impl Bank { ("epoch", prev_epoch, i64), ("validator_rate", *validator_rate, f64), ("foundation_rate", *foundation_rate, f64), - ("validator_rewards", total_vote_rewards, i64), + ("validator_rewards", total_reward_commissions, i64), ("active_stake", active_stake, i64), ("pre_capitalization", *capitalization, i64), ("post_capitalization", self.capitalization(), i64), @@ -260,21 +266,21 @@ impl Bank { ); } - fn store_vote_accounts_partitioned( + fn store_commission_accounts_partitioned( &self, - vote_account_rewards: &VoteRewardsAccounts, + reward_commission_accounts: &RewardCommissionAccounts, metrics: &RewardsMetrics, ) { let (_, measure_us) = measure_us!({ - let storable = VoteRewardsAccountsStorable { + let storable = RewardCommissionAccountsStorable { slot: self.slot(), - vote_rewards_accounts: vote_account_rewards, + reward_commission_accounts, }; self.store_accounts(storable); }); metrics - .store_vote_accounts_us + .store_commission_accounts_us .fetch_add(measure_us, Relaxed); } @@ -297,7 +303,7 @@ impl Bank { } = self.calculate_epoch_inflation_rewards(capitalization, rewarded_epoch); let CalculateValidatorRewardsResult { - vote_rewards_accounts: vote_account_rewards, + reward_commission_accounts, stake_reward_calculation: stake_rewards, point_value, } = self @@ -319,7 +325,7 @@ impl Bank { ); PartitionedRewardsCalculation { - vote_account_rewards, + reward_commission_accounts, stake_rewards, validator_rate, foundation_rate, @@ -328,7 +334,7 @@ impl Bank { } } - /// Calculate epoch reward and return vote and stake rewards. + /// Calculate epoch reward and return stake rewards and commissions. fn calculate_validator_rewards<'a>( &self, stake_history: &StakeHistory, @@ -349,8 +355,8 @@ impl Bank { metrics, ) .map(|point_value| { - let (vote_rewards_accounts, stake_reward_calculation) = self - .calculate_stake_vote_rewards( + let (reward_commission_accounts, stake_reward_calculation) = self + .calculate_stake_rewards_and_commissions( stake_history, stake_delegations, cached_vote_accounts, @@ -361,7 +367,7 @@ impl Bank { metrics, ); CalculateValidatorRewardsResult { - vote_rewards_accounts, + reward_commission_accounts, stake_reward_calculation, point_value, } @@ -492,7 +498,7 @@ impl Bank { new_rate_activation_epoch, commission_rate_in_basis_points, ) { - Ok((stake_reward, vote_rewards, stake)) => { + Ok((stake_reward, commission_lamports, stake)) => { let stake_reward = PartitionedStakeReward { stake_pubkey, stake, @@ -500,15 +506,15 @@ impl Bank { commission_bps, }; let vote_account = vote_account.into(); - let vote_reward = VoteReward { + let reward_commission = RewardCommission { commission_bps, - vote_account, - vote_rewards, + commission_account: vote_account, + commission_lamports, }; Some(DelegationRewards { stake_reward, - vote_pubkey, - vote_reward, + commission_pubkey: vote_pubkey, + reward_commission, }) } Err(e) => { @@ -518,9 +524,9 @@ 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<'a>( + /// Calculates epoch rewards for stake/commission accounts + /// Returns commission accounts, stake rewards, and the sum of all stake rewards in lamports + fn calculate_stake_rewards_and_commissions<'a>( &self, stake_history: &StakeHistory, stake_delegations: &'a FilteredStakeDelegations<'a>, @@ -530,7 +536,7 @@ impl Bank { thread_pool: &ThreadPool, reward_calc_tracer: Option, metrics: &mut RewardsMetrics, - ) -> (VoteRewardsAccounts, StakeRewardCalculation) { + ) -> (RewardCommissionAccounts, StakeRewardCalculation) { let new_warmup_cooldown_rate_epoch = self.new_warmup_cooldown_rate_epoch(); let delay_commission_updates = self .feature_set @@ -542,9 +548,9 @@ impl Bank { let mut measure_redeem_rewards = Measure::start("redeem-rewards"); // For N stake delegations, where N is >1,000,000, we produce: // * N stake rewards, - // * M vote rewards, where M is a number of stake nodes. Currently, way - // smaller number than 1,000,000. And we can expect it to always be - // significantly smaller than number of delegations. + // * M reward commission accounts, where M is a number of stake nodes. + // Currently, way smaller number than 1,000,000. And we can expect it + // to always be significantly smaller than number of delegations. // // Producing the stake reward with rayon triggers a lot of // (re)allocations. To avoid that, we allocate it at the start and @@ -575,13 +581,13 @@ impl Bank { Some(res) => { let DelegationRewards { stake_reward, - vote_pubkey, - vote_reward, + commission_pubkey, + reward_commission, } = res; let stakers_reward = stake_reward.stake_reward; ( Some(stake_reward), - Some((stakers_reward, vote_pubkey, vote_reward)), + Some((stakers_reward, commission_pubkey, reward_commission)), ) } None => (None, None), @@ -597,8 +603,13 @@ impl Bank { }) .fold( RewardsAccumulator::default, - |mut rewards_accumulator, (stake_reward, vote_pubkey, vote_reward)| { - rewards_accumulator.add_reward(vote_pubkey, vote_reward, stake_reward); + |mut rewards_accumulator, + (stakers_reward, commission_pubkey, reward_commission)| { + rewards_accumulator.add_reward( + commission_pubkey, + reward_commission, + stakers_reward, + ); rewards_accumulator }, ) @@ -610,7 +621,7 @@ impl Bank { ) }); let RewardsAccumulator { - vote_rewards, + reward_commissions, num_stake_rewards, total_stake_rewards_lamports, } = rewards_accumulator; @@ -618,12 +629,12 @@ impl Bank { unsafe { stake_rewards.assume_init(num_stake_rewards); } - let vote_rewards = Self::calc_vote_accounts_to_store(vote_rewards); + let reward_commission_accounts = Self::calculate_commission_accounts(reward_commissions); measure_redeem_rewards.stop(); metrics.redeem_rewards_us = measure_redeem_rewards.as_us(); ( - vote_rewards, + reward_commission_accounts, StakeRewardCalculation { stake_rewards: Arc::new(stake_rewards), total_stake_rewards_lamports, @@ -680,9 +691,9 @@ impl Bank { } /// If rewards are still active, recalculates partitioned stake rewards and - /// updates Bank::epoch_reward_status. This method assumes that vote rewards - /// have already been calculated and delivered, and *only* recalculates - /// stake rewards + /// updates Bank::epoch_reward_status. This method assumes that reward + /// commissions have already been calculated and delivered, and *only* + /// recalculates stake rewards pub(in crate::bank) fn recalculate_partitioned_rewards_if_active( &mut self, thread_pool_builder: F, @@ -711,7 +722,7 @@ impl Bank { epoch_rewards_sysvar: &EpochRewards, thread_pool: &ThreadPool, ) -> ( - VoteRewardsAccounts, + RewardCommissionAccounts, Arc, Vec>, ) { @@ -733,12 +744,12 @@ impl Bank { } = self.get_epoch_params_for_recalculation(rewarded_epoch, &stakes); // On recalculation, only the `StakeRewardCalculation::stake_rewards` - // field is relevant. It is assumed that vote-account rewards have + // field is relevant. It is assumed that reward commission accounts have // already been calculated and delivered, while // `StakeRewardCalculation::total_rewards` only reflects rewards that // have not yet been distributed. - let (vote_rewards_accounts, StakeRewardCalculation { stake_rewards, .. }) = self - .calculate_stake_vote_rewards( + let (reward_commission_accounts, StakeRewardCalculation { stake_rewards, .. }) = self + .calculate_stake_rewards_and_commissions( &stake_history, &stake_delegations, cached_vote_accounts, @@ -754,7 +765,7 @@ impl Bank { &epoch_rewards_sysvar.parent_blockhash, epoch_rewards_sysvar.num_partitions as usize, ); - (vote_rewards_accounts, stake_rewards, partition_indices) + (reward_commission_accounts, stake_rewards, partition_indices) } } @@ -775,7 +786,7 @@ mod tests { StartBlockHeightAndPartitionedRewards, }, tests::create_genesis_config, - RewardInfo, SlotLeader, VoteReward, + RewardCommission, RewardInfo, SlotLeader, }, genesis_utils::{self, deactivate_features, GenesisConfigInfo}, stake_account::StakeAccount, @@ -808,77 +819,80 @@ mod tests { }; #[test] - fn test_store_vote_accounts_partitioned() { + fn test_store_commission_accounts_partitioned() { let (genesis_config, _mint_keypair) = create_genesis_config(1_000_000 * LAMPORTS_PER_SOL); let bank = Bank::new_for_tests(&genesis_config); - let expected_vote_rewards_num = 100; - - let vote_rewards = (0..expected_vote_rewards_num) - .map(|_| (Pubkey::new_unique(), VoteReward::new_random())) + let num_reward_commissions = 100; + let reward_commissions = (0..num_reward_commissions) + .map(|_| (Pubkey::new_unique(), RewardCommission::new_random())) .collect::>(); - let mut vote_rewards_account = VoteRewardsAccounts::default(); - vote_rewards + let mut reward_commission_accounts = RewardCommissionAccounts::default(); + reward_commissions .iter() - .for_each(|(vote_key, vote_reward_info)| { + .for_each(|(commission_pubkey, reward_commission)| { let info = RewardInfo { reward_type: RewardType::Voting, - lamports: vote_reward_info.vote_rewards as i64, - post_balance: vote_reward_info.vote_rewards, - commission_bps: Some(vote_reward_info.commission_bps), + lamports: reward_commission.commission_lamports as i64, + post_balance: reward_commission.commission_lamports, + commission_bps: Some(reward_commission.commission_bps), }; - vote_rewards_account.accounts_with_rewards.push(( - *vote_key, + reward_commission_accounts.accounts_with_rewards.push(( + *commission_pubkey, info, - vote_reward_info.vote_account.clone(), + reward_commission.commission_account.clone(), )); - vote_rewards_account.total_vote_rewards_lamports += vote_reward_info.vote_rewards; + reward_commission_accounts.total_reward_commission_lamports += + reward_commission.commission_lamports; }); let metrics = RewardsMetrics::default(); - let total_vote_rewards = vote_rewards_account.total_vote_rewards_lamports; - bank.store_vote_accounts_partitioned(&vote_rewards_account, &metrics); + let total_reward_commissions = reward_commission_accounts.total_reward_commission_lamports; + bank.store_commission_accounts_partitioned(&reward_commission_accounts, &metrics); assert_eq!( - expected_vote_rewards_num, - vote_rewards_account.accounts_with_rewards.len() + num_reward_commissions, + reward_commission_accounts.accounts_with_rewards.len() ); assert_eq!( - vote_rewards + reward_commissions .iter() - .map(|(_, vote_reward_info)| vote_reward_info.vote_rewards) + .map(|(_, reward_commission)| reward_commission.commission_lamports) .sum::(), - total_vote_rewards + total_reward_commissions ); // load accounts to make sure they were stored correctly - vote_rewards + reward_commissions .iter() - .for_each(|(vote_key, vote_reward_info)| { + .for_each(|(commission_pubkey, reward_commission)| { let loaded_account = bank - .load_slow_with_fixed_root(&bank.ancestors, vote_key) + .load_slow_with_fixed_root(&bank.ancestors, commission_pubkey) .unwrap(); assert!(accounts_equal( &loaded_account.0, - &vote_reward_info.vote_account + &reward_commission.commission_account )); }); } #[test] - fn test_store_vote_accounts_partitioned_empty() { + fn test_store_commission_accounts_partitioned_empty() { let (genesis_config, _mint_keypair) = create_genesis_config(1_000_000 * LAMPORTS_PER_SOL); let bank = Bank::new_for_tests(&genesis_config); let expected = 0; - let vote_rewards = VoteRewardsAccounts::default(); + let reward_commission_accounts = RewardCommissionAccounts::default(); let metrics = RewardsMetrics::default(); - let total_vote_rewards = vote_rewards.total_vote_rewards_lamports; + let total_reward_commissions = reward_commission_accounts.total_reward_commission_lamports; - bank.store_vote_accounts_partitioned(&vote_rewards, &metrics); - assert_eq!(expected, vote_rewards.accounts_with_rewards.len()); - assert_eq!(0, total_vote_rewards); + bank.store_commission_accounts_partitioned(&reward_commission_accounts, &metrics); + assert_eq!( + expected, + reward_commission_accounts.accounts_with_rewards.len() + ); + assert_eq!(0, total_reward_commissions); } #[test] @@ -925,21 +939,24 @@ mod tests { &mut rewards_metrics, ); - let vote_rewards = &calculated_rewards.as_ref().unwrap().vote_rewards_accounts; + let reward_commission_accounts = &calculated_rewards + .as_ref() + .unwrap() + .reward_commission_accounts; let stake_rewards = &calculated_rewards .as_ref() .unwrap() .stake_reward_calculation; - let total_vote_rewards: u64 = vote_rewards + let total_reward_commissions: u64 = reward_commission_accounts .accounts_with_rewards .iter() .map(|(_, reward_info, _)| reward_info.lamports) .sum::() as u64; - // assert that total rewards matches the sum of vote rewards and stake rewards + // assert that total rewards matches the sum of reward commissions and stake rewards assert_eq!( - stake_rewards.total_stake_rewards_lamports + total_vote_rewards, + stake_rewards.total_stake_rewards_lamports + total_reward_commissions, expected_rewards ); @@ -1030,18 +1047,18 @@ mod tests { earned_credits: Option, } - fn recalculate_vote_rewards_for_tests( + fn recalculate_reward_commission_for_tests( bank: &Bank, - vote_address: &Pubkey, + commission_pubkey: &Pubkey, ) -> Option { let epoch_rewards_sysvar = bank.get_epoch_rewards_sysvar(); let thread_pool = ThreadPoolBuilder::new().num_threads(1).build().unwrap(); - let (vote_rewards_accounts, ..) = + let (reward_commissions, ..) = bank.recalculate_stake_rewards(&epoch_rewards_sysvar, &thread_pool); - vote_rewards_accounts + reward_commissions .accounts_with_rewards .iter() - .find(|(reward_address, ..)| reward_address == vote_address) + .find(|(reward_address, ..)| reward_address == commission_pubkey) .map(|(_, reward, _)| *reward) } @@ -1139,7 +1156,8 @@ mod tests { for (vote_address, vote_op) in &op.vote_operations { let expected_commission = vote_op.expected_reward_commission; - let recalculated_vote_reward = recalculate_vote_rewards_for_tests(&bank, vote_address); + let recalculated_vote_reward = + recalculate_reward_commission_for_tests(&bank, vote_address); let vote_reward = bank .rewards .read() @@ -1493,16 +1511,17 @@ mod tests { stake_delegations, cached_vote_accounts, } = bank.get_epoch_params_for_recalculation(rewarded_epoch, &stakes); - let (vote_rewards_accounts, stake_reward_calculation) = bank.calculate_stake_vote_rewards( - &stake_history, - &stake_delegations, - cached_vote_accounts, - rewarded_epoch, - point_value, - &thread_pool, - reward_calc_tracer, - &mut rewards_metrics, - ); + let (vote_rewards_accounts, stake_reward_calculation) = bank + .calculate_stake_rewards_and_commissions( + &stake_history, + &stake_delegations, + cached_vote_accounts, + rewarded_epoch, + point_value, + &thread_pool, + reward_calc_tracer, + &mut rewards_metrics, + ); drop(stakes); let vote_account = bank @@ -1927,113 +1946,107 @@ mod tests { let mut accumulator1 = RewardsAccumulator::default(); let mut accumulator2 = RewardsAccumulator::default(); - let vote_pubkey_a = Pubkey::new_unique(); - let node_pubkey_a = Pubkey::new_unique(); - let vote_account_a = vote_state::create_v4_account_with_authorized( - &node_pubkey_a, - &vote_pubkey_a, - [0u8; BLS_PUBLIC_KEY_COMPRESSED_SIZE], - &vote_pubkey_a, - 2000, - &vote_pubkey_a, - 0, - &vote_pubkey_a, - 100, - ); - let vote_pubkey_b = Pubkey::new_unique(); - let node_pubkey_b = Pubkey::new_unique(); - let vote_account_b = vote_state::create_v4_account_with_authorized( - &node_pubkey_b, - &vote_pubkey_b, - [0u8; BLS_PUBLIC_KEY_COMPRESSED_SIZE], - &vote_pubkey_b, - 2000, - &vote_pubkey_b, - 0, - &vote_pubkey_b, - 100, - ); - let vote_pubkey_c = Pubkey::new_unique(); - let node_pubkey_c = Pubkey::new_unique(); - let vote_account_c = vote_state::create_v4_account_with_authorized( - &node_pubkey_c, - &vote_pubkey_c, - [0u8; BLS_PUBLIC_KEY_COMPRESSED_SIZE], - &vote_pubkey_c, - 2000, - &vote_pubkey_c, - 0, - &vote_pubkey_c, - 100, - ); + let commission_pubkey_a = Pubkey::new_unique(); + let commission_account_a = AccountSharedData::default(); + + let commission_pubkey_b = Pubkey::new_unique(); + let commission_account_b = AccountSharedData::default(); + + let commission_pubkey_c = Pubkey::new_unique(); + let commission_account_c = AccountSharedData::default(); accumulator1.add_reward( - vote_pubkey_a, - VoteReward { - vote_account: vote_account_a.clone(), + commission_pubkey_a, + RewardCommission { + commission_account: commission_account_a.clone(), commission_bps: 1_000, - vote_rewards: 50, + commission_lamports: 50, }, 50, ); accumulator1.add_reward( - vote_pubkey_b, - VoteReward { - vote_account: vote_account_b.clone(), + commission_pubkey_b, + RewardCommission { + commission_account: commission_account_b.clone(), commission_bps: 1_000, - vote_rewards: 50, + commission_lamports: 50, }, 50, ); accumulator2.add_reward( - vote_pubkey_b, - VoteReward { - vote_account: vote_account_b, + commission_pubkey_b, + RewardCommission { + commission_account: commission_account_b, commission_bps: 1_000, - vote_rewards: 30, + commission_lamports: 30, }, 30, ); accumulator2.add_reward( - vote_pubkey_c, - VoteReward { - vote_account: vote_account_c, + commission_pubkey_c, + RewardCommission { + commission_account: commission_account_c, commission_bps: 1_000, - vote_rewards: 50, + commission_lamports: 50, }, 50, ); assert_eq!(accumulator1.num_stake_rewards, 2); assert_eq!(accumulator1.total_stake_rewards_lamports, 100); - let vote_reward_a_1 = accumulator1.vote_rewards.get(&vote_pubkey_a).unwrap(); - assert_eq!(vote_reward_a_1.commission_bps, 1_000); - assert_eq!(vote_reward_a_1.vote_rewards, 50); - let vote_reward_b_1 = accumulator1.vote_rewards.get(&vote_pubkey_b).unwrap(); - assert_eq!(vote_reward_b_1.commission_bps, 1_000); - assert_eq!(vote_reward_b_1.vote_rewards, 50); - - let vote_reward_b_2 = accumulator2.vote_rewards.get(&vote_pubkey_b).unwrap(); - assert_eq!(vote_reward_b_2.commission_bps, 1_000); - assert_eq!(vote_reward_b_2.vote_rewards, 30); - let vote_reward_c_2 = accumulator2.vote_rewards.get(&vote_pubkey_c).unwrap(); - assert_eq!(vote_reward_c_2.commission_bps, 1_000); - assert_eq!(vote_reward_c_2.vote_rewards, 50); + let reward_commission_a_1 = accumulator1 + .reward_commissions + .get(&commission_pubkey_a) + .unwrap(); + assert_eq!(reward_commission_a_1.commission_bps, 1_000); + assert_eq!(reward_commission_a_1.commission_lamports, 50); + + let reward_commission_b_1 = accumulator1 + .reward_commissions + .get(&commission_pubkey_b) + .unwrap(); + assert_eq!(reward_commission_b_1.commission_bps, 1_000); + assert_eq!(reward_commission_b_1.commission_lamports, 50); + + let reward_commission_b_2 = accumulator2 + .reward_commissions + .get(&commission_pubkey_b) + .unwrap(); + assert_eq!(reward_commission_b_2.commission_bps, 1_000); + assert_eq!(reward_commission_b_2.commission_lamports, 30); + + let reward_commission_c_2 = accumulator2 + .reward_commissions + .get(&commission_pubkey_c) + .unwrap(); + assert_eq!(reward_commission_c_2.commission_bps, 1_000); + assert_eq!(reward_commission_c_2.commission_lamports, 50); let accumulator = accumulator1.accumulate_into_larger(accumulator2); assert_eq!(accumulator.num_stake_rewards, 4); assert_eq!(accumulator.total_stake_rewards_lamports, 180); - let vote_reward_a = accumulator.vote_rewards.get(&vote_pubkey_a).unwrap(); - assert_eq!(vote_reward_a.commission_bps, 1_000); - assert_eq!(vote_reward_a.vote_rewards, 50); - let vote_reward_b = accumulator.vote_rewards.get(&vote_pubkey_b).unwrap(); - assert_eq!(vote_reward_b.commission_bps, 1_000); - // sum of the vote rewards from both accumulators - assert_eq!(vote_reward_b.vote_rewards, 80); - let vote_reward_c = accumulator.vote_rewards.get(&vote_pubkey_c).unwrap(); - assert_eq!(vote_reward_c.commission_bps, 1_000); - assert_eq!(vote_reward_c.vote_rewards, 50); + let reward_commission_a = accumulator + .reward_commissions + .get(&commission_pubkey_a) + .unwrap(); + assert_eq!(reward_commission_a.commission_bps, 1_000); + assert_eq!(reward_commission_a.commission_lamports, 50); + + let reward_commission_b = accumulator + .reward_commissions + .get(&commission_pubkey_b) + .unwrap(); + assert_eq!(reward_commission_b.commission_bps, 1_000); + // sum of the reward commissions from both accumulators + assert_eq!(reward_commission_b.commission_lamports, 80); + + let reward_commission_c = accumulator + .reward_commissions + .get(&commission_pubkey_c) + .unwrap(); + assert_eq!(reward_commission_c.commission_bps, 1_000); + assert_eq!(reward_commission_c.commission_lamports, 50); } #[test] @@ -2141,7 +2154,7 @@ mod tests { expected_cache_len: usize, expected_voters: &HashSet, expected_stakers: &HashSet, - expected_vote_rewards: u64, + expected_reward_commissions: u64, expected_stake_rewards: u64, expected_rewards: u64, expected_points: u128, @@ -2150,11 +2163,11 @@ mod tests { let cache = bank.epoch_rewards_calculation_cache.lock().unwrap(); assert_eq!(cache.len(), expected_cache_len); let partitioned = cache.get(&bank.parent_hash()).unwrap().as_ref(); - let VoteRewardsAccounts { + let RewardCommissionAccounts { accounts_with_rewards, - total_vote_rewards_lamports, + total_reward_commission_lamports, .. - } = &partitioned.vote_account_rewards; + } = &partitioned.reward_commission_accounts; let StakeRewardCalculation { stake_rewards, total_stake_rewards_lamports, @@ -2173,12 +2186,18 @@ mod tests { .collect(); assert_eq!(expected_voters, &voters); assert_eq!(expected_stakers, &stakers); - assert_eq!(*total_vote_rewards_lamports, expected_vote_rewards); + assert_eq!( + *total_reward_commission_lamports, + expected_reward_commissions + ); assert_eq!(*total_stake_rewards_lamports, expected_stake_rewards); assert_eq!(point_value.rewards, expected_rewards); assert_eq!(point_value.points, expected_points); if let Some(parent_cap) = parent_capitalization { - assert_eq!(bank.capitalization(), parent_cap + expected_vote_rewards); + assert_eq!( + bank.capitalization(), + parent_cap + expected_reward_commissions + ); } } @@ -2214,7 +2233,7 @@ mod tests { 1, // expected_cache_len &voters, // expected_voters &stakers, // expected_stakers - 0, // expected_vote_rewards + 0, // expected_reward_commissions 12300, // expected_stake_rewards 12395, // expected_rewards 8_400_000_000_000u128, // expected_points @@ -2235,7 +2254,7 @@ mod tests { 2, // expected_cache_len &voters, // expected_voters &stakers, // expected_stakers - 145, // expected_vote_rewards + 145, // expected_reward_commissions 13010, // expected_stake_rewards 13165, // expected_rewards 9_450_000_000_000u128, // expected_points @@ -2256,7 +2275,7 @@ mod tests { 3, // expected_cache_len &voters, // expected_voters &stakers, // expected_stakers - 525, // expected_vote_rewards + 525, // expected_reward_commissions 15030, // expected_stake_rewards 15631, // expected_rewards 12_810_000_000_000u128, // expected_points diff --git a/runtime/src/bank/partitioned_epoch_rewards/mod.rs b/runtime/src/bank/partitioned_epoch_rewards/mod.rs index efdc2b8aa05..d46024b32fc 100644 --- a/runtime/src/bank/partitioned_epoch_rewards/mod.rs +++ b/runtime/src/bank/partitioned_epoch_rewards/mod.rs @@ -35,7 +35,7 @@ pub(crate) struct PartitionedStakeReward { pub stake: Stake, /// Stake reward for recording in the Bank on distribution pub stake_reward: u64, - /// Vote commission in basis points (0-10,000 representing 0-100%) for + /// Reward commission in basis points (0-10,000 representing 0-100%) for /// recording reward info. pub commission_bps: u16, } @@ -151,45 +151,45 @@ pub(crate) enum EpochRewardPhase { } #[derive(Debug, Default)] -pub(super) struct VoteRewardsAccounts { +pub(super) struct RewardCommissionAccounts { /// accounts with rewards to be stored pub(super) accounts_with_rewards: Vec<(Pubkey, RewardInfo, AccountSharedData)>, - /// total lamports across all `vote_rewards` - pub(super) total_vote_rewards_lamports: u64, + /// total lamports across all `accounts_with_rewards` + pub(super) total_reward_commission_lamports: u64, } -/// Wrapper struct to implement StorableAccounts for VoteRewardsAccounts -pub(super) struct VoteRewardsAccountsStorable<'a> { +/// Wrapper struct to implement StorableAccounts for RewardCommissionAccounts +pub(super) struct RewardCommissionAccountsStorable<'a> { pub slot: Slot, - pub vote_rewards_accounts: &'a VoteRewardsAccounts, + pub reward_commission_accounts: &'a RewardCommissionAccounts, } -impl<'a> StorableAccounts<'a> for VoteRewardsAccountsStorable<'a> { +impl<'a> StorableAccounts<'a> for RewardCommissionAccountsStorable<'a> { fn account( &self, index: usize, mut callback: impl for<'local> FnMut(AccountForStorage<'local>) -> Ret, ) -> Ret { - let (pubkey, _, account) = &self.vote_rewards_accounts.accounts_with_rewards[index]; + let (pubkey, _, account) = &self.reward_commission_accounts.accounts_with_rewards[index]; callback((pubkey, account).into()) } fn is_zero_lamport(&self, index: usize) -> bool { - self.vote_rewards_accounts.accounts_with_rewards[index] + self.reward_commission_accounts.accounts_with_rewards[index] .2 .lamports() == 0 } fn data_len(&self, index: usize) -> usize { - self.vote_rewards_accounts.accounts_with_rewards[index] + self.reward_commission_accounts.accounts_with_rewards[index] .2 .data() .len() } fn pubkey(&self, index: usize) -> &Pubkey { - &self.vote_rewards_accounts.accounts_with_rewards[index].0 + &self.reward_commission_accounts.accounts_with_rewards[index].0 } fn slot(&self, _index: usize) -> Slot { @@ -201,7 +201,7 @@ impl<'a> StorableAccounts<'a> for VoteRewardsAccountsStorable<'a> { } fn len(&self) -> usize { - self.vote_rewards_accounts.accounts_with_rewards.len() + self.reward_commission_accounts.accounts_with_rewards.len() } } @@ -216,7 +216,7 @@ pub(super) struct StakeRewardCalculation { #[derive(Debug)] struct CalculateValidatorRewardsResult { - vote_rewards_accounts: VoteRewardsAccounts, + reward_commission_accounts: RewardCommissionAccounts, stake_reward_calculation: StakeRewardCalculation, point_value: PointValue, } @@ -224,7 +224,7 @@ struct CalculateValidatorRewardsResult { impl Default for CalculateValidatorRewardsResult { fn default() -> Self { Self { - vote_rewards_accounts: VoteRewardsAccounts::default(), + reward_commission_accounts: RewardCommissionAccounts::default(), stake_reward_calculation: StakeRewardCalculation::default(), point_value: PointValue { points: 0, @@ -300,7 +300,7 @@ pub(super) struct EpochRewardCalculateParamInfo<'a> { /// side effects. #[derive(Debug)] pub(super) struct PartitionedRewardsCalculation { - pub(super) vote_account_rewards: VoteRewardsAccounts, + pub(super) reward_commission_accounts: RewardCommissionAccounts, pub(super) stake_rewards: StakeRewardCalculation, pub(super) validator_rate: f64, pub(super) foundation_rate: f64, diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index 31c2bdf9577..f9308aed48e 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -142,31 +142,20 @@ use { test_case::test_case, }; -impl VoteReward { +impl RewardCommission { pub fn new_random() -> Self { let mut rng = rand::rng(); - let validator_pubkey = solana_pubkey::new_rand(); - let validator_stake_lamports = rng.random_range(1..200); - let validator_voting_keypair = Keypair::new(); + let commission_balance = rng.random_range(1..200); let commission_bps: u16 = rng.random_range(100..2_000); - let validator_vote_account = vote_state::create_v4_account_with_authorized( - &validator_pubkey, - &validator_voting_keypair.pubkey(), - [0u8; BLS_PUBLIC_KEY_COMPRESSED_SIZE], - &validator_voting_keypair.pubkey(), - commission_bps, - &validator_voting_keypair.pubkey(), - 0, - &validator_voting_keypair.pubkey(), - validator_stake_lamports, - ); + let mut commission_account = AccountSharedData::default(); + commission_account.set_lamports(commission_balance); Self { - vote_account: validator_vote_account, + commission_account, commission_bps, - vote_rewards: rng.random_range(1..200), + commission_lamports: rng.random_range(1..200), } } } @@ -11425,56 +11414,56 @@ fn test_system_instruction_unsigned_transaction() { } #[test] -fn test_calc_vote_accounts_to_store_empty() { - let vote_account_rewards = HashMap::default(); - let result = Bank::calc_vote_accounts_to_store(vote_account_rewards); +fn test_calculate_commission_accounts_empty() { + let reward_commissions = HashMap::default(); + let result = Bank::calculate_commission_accounts(reward_commissions); assert!(result.accounts_with_rewards.is_empty()); } #[test] -fn test_calc_vote_accounts_to_store_overflow() { - let mut vote_account_rewards = HashMap::default(); +fn test_calculate_commission_accounts_overflow() { + let mut reward_commissions = HashMap::default(); let pubkey = solana_pubkey::new_rand(); - let mut vote_account = AccountSharedData::default(); - vote_account.set_lamports(u64::MAX); - vote_account_rewards.insert( + let mut commission_account = AccountSharedData::default(); + commission_account.set_lamports(u64::MAX); + reward_commissions.insert( pubkey, - VoteReward { - vote_account, + RewardCommission { + commission_account, commission_bps: 0, - vote_rewards: 1, // enough to overflow + commission_lamports: 1, // enough to overflow }, ); - let result = Bank::calc_vote_accounts_to_store(vote_account_rewards); + let result = Bank::calculate_commission_accounts(reward_commissions); assert!(result.accounts_with_rewards.is_empty()); } #[test] -fn test_calc_vote_accounts_to_store_normal() { +fn test_calculate_commission_accounts_normal() { let pubkey = solana_pubkey::new_rand(); for commission_bps in [0, 100] { - for vote_rewards in 0..2 { - let mut vote_account_rewards = HashMap::default(); - let mut vote_account = AccountSharedData::default(); - vote_account.set_lamports(1); - vote_account_rewards.insert( + for commission_lamports in 0..2 { + let mut reward_commissions = HashMap::default(); + let mut commission_account = AccountSharedData::default(); + commission_account.set_lamports(1); + reward_commissions.insert( pubkey, - VoteReward { - vote_account: vote_account.clone(), + RewardCommission { + commission_account: commission_account.clone(), commission_bps, - vote_rewards, + commission_lamports, }, ); - let result = Bank::calc_vote_accounts_to_store(vote_account_rewards); + let result = Bank::calculate_commission_accounts(reward_commissions); assert_eq!(result.accounts_with_rewards.len(), 1); let (pubkey_result, rewards, account) = &result.accounts_with_rewards[0]; - _ = vote_account.checked_add_lamports(vote_rewards); - assert!(accounts_equal(account, &vote_account)); + _ = commission_account.checked_add_lamports(commission_lamports); + assert!(accounts_equal(account, &commission_account)); let expected_reward_info = RewardInfo { reward_type: RewardType::Voting, - lamports: vote_rewards as i64, - post_balance: vote_account.lamports(), + lamports: commission_lamports as i64, + post_balance: commission_account.lamports(), commission_bps: Some(commission_bps), }; assert_eq!(*rewards, expected_reward_info);