diff --git a/Cargo.lock b/Cargo.lock index c6c7f3845c48d6..82cd98f60e1f33 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10681,9 +10681,9 @@ dependencies = [ [[package]] name = "solana-stake-interface" -version = "2.0.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f912ae679b683365348dea482dbd9468d22ff258b554fd36e3d3683c2122e3" +checksum = "9fd582fe900e43db96651a5b43956b8ebfab1944d091b391d89140635900ef46" dependencies = [ "borsh", "num-traits", diff --git a/Cargo.toml b/Cargo.toml index 46338860fbd12f..76bd4f197f9f4a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -515,7 +515,7 @@ solana-signer = "3.0.0" solana-slot-hashes = "3.0.0" solana-slot-history = "3.0.0" solana-stable-layout = "3.0.0" -solana-stake-interface = { version = "2.0.1" } +solana-stake-interface = { version = "2.0.0" } solana-stake-program = { path = "programs/stake", version = "=3.1.0" } solana-storage-bigtable = { path = "storage-bigtable", version = "=3.1.0" } solana-storage-proto = { path = "storage-proto", version = "=3.1.0" } diff --git a/cli/Cargo.toml b/cli/Cargo.toml index a049322c38df04..fd957781138897 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -81,7 +81,7 @@ solana-sdk-ids = "=3.0.0" solana-signature = { version = "=3.1.0", default-features = false } solana-signer = "=3.0.0" solana-slot-history = "=3.0.0" -solana-stake-interface = "=2.0.1" +solana-stake-interface = "=2.0.0" solana-streamer = { workspace = true } solana-system-interface = { version = "=2.0", features = ["bincode"] } solana-sysvar = "=3.0.0" diff --git a/genesis/Cargo.toml b/genesis/Cargo.toml index 91a95e87e7a628..38503b573bbb66 100644 --- a/genesis/Cargo.toml +++ b/genesis/Cargo.toml @@ -54,7 +54,7 @@ solana-rpc-client-api = { workspace = true } solana-runtime = { workspace = true } solana-sdk-ids = "=3.0.0" solana-signer = "=3.0.0" -solana-stake-interface = { version = "=2.0.1", features = ["borsh"] } +solana-stake-interface = { version = "=2.0.0", features = ["borsh"] } solana-stake-program = { workspace = true } solana-time-utils = "3.0.0" solana-version = { workspace = true } diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index 55dea45e83d364..d8ae9ed3ab5857 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -9126,9 +9126,9 @@ dependencies = [ [[package]] name = "solana-stake-interface" -version = "2.0.1" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f912ae679b683365348dea482dbd9468d22ff258b554fd36e3d3683c2122e3" +checksum = "9fd582fe900e43db96651a5b43956b8ebfab1944d091b391d89140635900ef46" dependencies = [ "num-traits", "serde", diff --git a/programs/sbf/Cargo.toml b/programs/sbf/Cargo.toml index b5d031f87d67df..a9ab1b0eade470 100644 --- a/programs/sbf/Cargo.toml +++ b/programs/sbf/Cargo.toml @@ -157,7 +157,7 @@ solana-sbpf = "=0.12.2" solana-sdk-ids = "=3.0.0" solana-secp256k1-recover = "=3.0.0" solana-sha256-hasher = { version = "=3.0.0", features = ["sha2"] } -solana-stake-interface = { version = "=2.0.1", features = ["bincode"] } +solana-stake-interface = { version = "=2.0.0", features = ["bincode"] } solana-svm = { path = "../../svm", version = "=3.1.0" } solana-svm-callback = { path = "../../svm-callback", version = "=3.1.0" } solana-svm-feature-set = { path = "../../svm-feature-set", version = "=3.1.0" } diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 8321b52b619e28..5ba54f1cbad495 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -63,7 +63,7 @@ use { agave_syscalls::{ create_program_runtime_environment_v1, create_program_runtime_environment_v2, }, - ahash::AHashSet, + ahash::{AHashSet, RandomState}, dashmap::DashMap, log::*, partitioned_epoch_rewards::PartitionedRewardsCalculation, @@ -113,7 +113,7 @@ use { solana_program_runtime::{ invoke_context::BuiltinFunctionWithContext, loaded_programs::ProgramCacheEntry, }, - solana_pubkey::{Pubkey, PubkeyHasherBuilder}, + solana_pubkey::Pubkey, solana_reward_info::RewardInfo, solana_runtime_transaction::{ runtime_transaction::RuntimeTransaction, transaction_with_meta::TransactionWithMeta, @@ -916,7 +916,7 @@ struct VoteReward { vote_rewards: u64, } -type VoteRewards = HashMap; +type VoteRewards = DashMap; #[derive(Debug, Default)] pub struct NewBankOptions { diff --git a/runtime/src/bank/partitioned_epoch_rewards/calculation.rs b/runtime/src/bank/partitioned_epoch_rewards/calculation.rs index 28216740c66bdb..ec7e7536864b5e 100644 --- a/runtime/src/bank/partitioned_epoch_rewards/calculation.rs +++ b/runtime/src/bank/partitioned_epoch_rewards/calculation.rs @@ -3,8 +3,8 @@ use { epoch_rewards_hasher::hash_rewards_into_partitions, Bank, CalculateRewardsAndDistributeVoteRewardsResult, CalculateValidatorRewardsResult, EpochRewardCalculateParamInfo, PartitionedRewardsCalculation, PartitionedStakeReward, - PartitionedStakeRewards, StakeRewardCalculation, VoteRewardsAccounts, - VoteRewardsAccountsStorable, REWARD_CALCULATION_NUM_BLOCKS, + StakeRewardCalculation, VoteRewardsAccounts, VoteRewardsAccountsStorable, + REWARD_CALCULATION_NUM_BLOCKS, }, crate::{ bank::{ @@ -18,22 +18,24 @@ use { stake_account::StakeAccount, stakes::Stakes, }, + ahash::random_state::RandomState as AHashRandomState, + dashmap::DashMap, log::{debug, info}, rayon::{ - iter::{IndexedParallelIterator, IntoParallelRefIterator, ParallelIterator}, + iter::{IntoParallelRefIterator, ParallelIterator}, ThreadPool, }, solana_account::ReadableAccount, solana_clock::{Epoch, Slot}, - solana_measure::{measure::Measure, measure_us}, - solana_pubkey::{Pubkey, PubkeyHasherBuilder}, + solana_measure::measure_us, + solana_pubkey::Pubkey, solana_stake_interface::state::Delegation, solana_sysvar::epoch_rewards::EpochRewards, solana_vote::vote_account::VoteAccount, solana_vote_program::vote_state::VoteStateVersions, - std::{ - collections::HashMap, - sync::{atomic::Ordering::Relaxed, Arc}, + std::sync::{ + atomic::{AtomicU64, Ordering::Relaxed}, + Arc, }, }; @@ -341,171 +343,103 @@ impl Bank { } = reward_calculate_params; let new_warmup_cooldown_rate_epoch = self.new_warmup_cooldown_rate_epoch(); + let estimated_num_vote_accounts = cached_vote_accounts.len(); + let vote_account_rewards: VoteRewards = DashMap::with_capacity_and_hasher_and_shard_amount( + estimated_num_vote_accounts, + AHashRandomState::default(), + 1024, // shard amount + ); + let total_stake_rewards = AtomicU64::default(); const ASSERT_STAKE_CACHE: bool = false; // Turn this on to assert that all vote accounts are in the cache - 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. - // - // Producing the stake reward with rayon triggers a lot of - // (re)allocations. To avoid that, we allocate it at the start and - // pass `stake_rewards.spare_capacity_mut()` as one of iterators. - let mut stake_rewards = Vec::with_capacity(stake_delegations.len()); - let (vote_account_rewards, total_stake_rewards_lamports): (VoteRewards, u64) = thread_pool - .install(|| { - stake_delegations - .par_iter() - .zip_eq(stake_rewards.spare_capacity_mut()) - .with_min_len(500) - .filter_map(|((stake_pubkey, stake_account), stake_reward_ref)| { - // 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_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 vote_pubkey = stake_account.delegation().voter_pubkey; - let vote_account_from_cache = cached_vote_accounts.get(&vote_pubkey); - if ASSERT_STAKE_CACHE && vote_account_from_cache.is_none() { - let account_from_db = self.get_account_with_fixed_root(&vote_pubkey); - if let Some(account_from_db) = account_from_db { - if VoteStateVersions::is_correct_size_and_initialized( - account_from_db.data(), - ) && VoteAccount::try_from(account_from_db.clone()).is_ok() - { - panic!( - "Vote account {} not found in cache, but found in db: {:?}", - vote_pubkey, account_from_db - ); - } + let stake_pubkey = **stake_pubkey; + let vote_pubkey = stake_account.delegation().voter_pubkey; + let vote_account_from_cache = cached_vote_accounts.get(&vote_pubkey); + if ASSERT_STAKE_CACHE && vote_account_from_cache.is_none() { + let account_from_db = self.get_account_with_fixed_root(&vote_pubkey); + if let Some(account_from_db) = account_from_db { + if VoteStateVersions::is_correct_size_and_initialized( + account_from_db.data(), + ) && VoteAccount::try_from(account_from_db.clone()).is_ok() + { + panic!( + "Vote account {vote_pubkey} not found in cache, but found in \ + db: {account_from_db:?}" + ); } } - let (stake_reward, res) = if let Some(vote_account) = - vote_account_from_cache - { - let vote_state_view = vote_account.vote_state_view(); - let mut stake_state = *stake_account.stake_state(); - - let redeemed = redeem_rewards( - rewarded_epoch, - &mut stake_state, - vote_state_view, - &point_value, - stake_history, - reward_calc_tracer.as_ref(), - new_warmup_cooldown_rate_epoch, - ); - - if let Ok((stakers_reward, voters_reward)) = redeemed { - let commission = vote_state_view.commission(); - - // Safe to unwrap because all stake_delegations are type - // StakeAccount, which will always only wrap - // a `StakeStateV2::Stake` variant. - let stake = stake_state.stake().unwrap(); - - ( - Some(PartitionedStakeReward { - stake_pubkey, - stake_reward: stakers_reward, - stake, - commission, - }), - Some(( - vote_pubkey, - VoteReward { - commission, - vote_account: vote_account.into(), - vote_rewards: voters_reward, - }, - stakers_reward, - )), - ) - } else { - debug!("redeem_rewards() failed for {stake_pubkey}: {redeemed:?}"); - (None, None) - } - } else { - debug!("could not find vote account {vote_pubkey} in cache"); - (None, None) - }; - stake_reward_ref.write(stake_reward); - res - }) - .fold( - || { - ( - HashMap::with_hasher(PubkeyHasherBuilder::default()), - u64::default(), - ) - }, - |(mut vote_rewards, total_stake_rewards), - (vote_pubkey, vote_reward, stakers_reward)| { - 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) - }) - .or_insert(vote_reward); - ( - vote_rewards, - total_stake_rewards.saturating_add(stakers_reward), - ) - }, - ) - .reduce( - || { - ( - HashMap::with_hasher(PubkeyHasherBuilder::default()), - u64::default(), - ) - }, - |(vote_rewards_a, total_stake_rewards_a), - (vote_rewards_b, total_stake_rewards_b)| { - let (mut dst_vote_rewards, src_vote_rewards) = - if vote_rewards_a.len() >= vote_rewards_b.len() { - (vote_rewards_a, vote_rewards_b) - } else { - (vote_rewards_b, vote_rewards_a) - }; - 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) - }) - .or_insert(vote_reward); - } - ( - dst_vote_rewards, - total_stake_rewards_a.saturating_add(total_stake_rewards_b), - ) - }, - ) - }); - // SAFETY: We initialized all the `stake_rewards` elements up to the capacity. - unsafe { - stake_rewards.set_len(stake_rewards.capacity()); - } - let vote_rewards = Self::calc_vote_accounts_to_store(vote_account_rewards); - measure_redeem_rewards.stop(); - metrics.redeem_rewards_us = measure_redeem_rewards.as_us(); + } + let vote_account = vote_account_from_cache?; + let vote_state_view = vote_account.vote_state_view(); + let mut stake_state = *stake_account.stake_state(); + + let redeemed = redeem_rewards( + rewarded_epoch, + &mut stake_state, + vote_state_view, + &point_value, + stake_history, + reward_calc_tracer.as_ref(), + new_warmup_cooldown_rate_epoch, + ); + + if let Ok((stakers_reward, voters_reward)) = redeemed { + let commission = vote_state_view.commission(); + + // track voter rewards + let mut voters_reward_entry = vote_account_rewards + .entry(vote_pubkey) + .or_insert(VoteReward { + commission, + vote_account: vote_account.into(), + vote_rewards: 0, + }); + + voters_reward_entry.vote_rewards = voters_reward_entry + .vote_rewards + .saturating_add(voters_reward); + + total_stake_rewards.fetch_add(stakers_reward, Relaxed); + + // Safe to unwrap because all stake_delegations are type + // StakeAccount, which will always only wrap + // a `StakeStateV2::Stake` variant. + let stake = stake_state.stake().unwrap(); + return Some(PartitionedStakeReward { + stake_pubkey, + stake_reward: stakers_reward, + stake, + commission, + }); + } else { + debug!("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: Arc::new(stake_rewards), - total_stake_rewards_lamports, + total_stake_rewards_lamports: total_stake_rewards.load(Relaxed), }, ) } @@ -587,7 +521,7 @@ impl Bank { epoch_rewards_sysvar: &EpochRewards, reward_calc_tracer: Option, thread_pool: &ThreadPool, - ) -> (Arc, Vec>) { + ) -> (Arc>, Vec>) { assert!(epoch_rewards_sysvar.active); // If rewards are active, the rewarded epoch is always the immediately // preceding epoch. @@ -906,10 +840,7 @@ mod tests { commission, } }; - assert_eq!( - stake_reward_calculation.stake_rewards[0].as_ref().unwrap(), - &expected_reward - ); + assert_eq!(stake_reward_calculation.stake_rewards[0], expected_reward); } fn compare_stake_rewards( diff --git a/runtime/src/bank/partitioned_epoch_rewards/distribution.rs b/runtime/src/bank/partitioned_epoch_rewards/distribution.rs index 8ec40df5c24a5f..4a363aee7e7a5f 100644 --- a/runtime/src/bank/partitioned_epoch_rewards/distribution.rs +++ b/runtime/src/bank/partitioned_epoch_rewards/distribution.rs @@ -271,10 +271,6 @@ impl Bank { "partition reward out of bound: {index} >= {}", partition_rewards.all_stake_rewards.len() ) - }) - .as_ref() - .unwrap_or_else(|| { - panic!("partition reward {index} is empty"); }); let stake_pubkey = partitioned_stake_reward.stake_pubkey; let reward_amount = partitioned_stake_reward.stake_reward; @@ -343,7 +339,7 @@ mod tests { let expected_num = 100; let stake_rewards = (0..expected_num) - .map(|_| Some(PartitionedStakeReward::new_random())) + .map(|_| PartitionedStakeReward::new_random()) .collect::>(); let partition_indices = @@ -367,7 +363,7 @@ mod tests { let expected_num = 1; let stake_rewards = (0..expected_num) - .map(|_| Some(PartitionedStakeReward::new_random())) + .map(|_| PartitionedStakeReward::new_random()) .collect::>(); let partition_indices = hash_rewards_into_partitions( @@ -753,11 +749,7 @@ mod tests { let expected_total = converted_rewards .iter() - .filter_map(|stake_reward| { - stake_reward - .as_ref() - .map(|stake_reward| stake_reward.stake_reward) - }) + .map(|stake_reward| stake_reward.stake_reward) .sum::(); let partitioned_rewards = StartBlockHeightAndPartitionedRewards { diff --git a/runtime/src/bank/partitioned_epoch_rewards/epoch_rewards_hasher.rs b/runtime/src/bank/partitioned_epoch_rewards/epoch_rewards_hasher.rs index 52259611a0b0da..df81921afe9a88 100644 --- a/runtime/src/bank/partitioned_epoch_rewards/epoch_rewards_hasher.rs +++ b/runtime/src/bank/partitioned_epoch_rewards/epoch_rewards_hasher.rs @@ -1,10 +1,10 @@ use { - crate::bank::partitioned_epoch_rewards::PartitionedStakeRewards, itertools::enumerate, + crate::bank::partitioned_epoch_rewards::PartitionedStakeReward, itertools::enumerate, solana_epoch_rewards_hasher::EpochRewardsHasher, solana_hash::Hash, }; pub(in crate::bank::partitioned_epoch_rewards) fn hash_rewards_into_partitions( - stake_rewards: &PartitionedStakeRewards, + stake_rewards: &[PartitionedStakeReward], parent_blockhash: &Hash, num_partitions: usize, ) -> Vec> { @@ -12,15 +12,13 @@ pub(in crate::bank::partitioned_epoch_rewards) fn hash_rewards_into_partitions( let mut indices = vec![vec![]; num_partitions]; for (i, reward) in enumerate(stake_rewards) { - if let Some(ref reward) = reward { - // clone here so the hasher's state is re-used on each call to `hash_address_to_partition`. - // This prevents us from re-hashing the seed each time. - // The clone is explicit (as opposed to an implicit copy) so it is clear this is intended. - let partition_index = hasher - .clone() - .hash_address_to_partition(&reward.stake_pubkey); - indices[partition_index].push(i); - } + // clone here so the hasher's state is re-used on each call to `hash_address_to_partition`. + // This prevents us from re-hashing the seed each time. + // The clone is explicit (as opposed to an implicit copy) so it is clear this is intended. + let partition_index = hasher + .clone() + .hash_address_to_partition(&reward.stake_pubkey); + indices[partition_index].push(i); } indices } @@ -45,7 +43,7 @@ mod tests { let expected_num = 12345; let stake_rewards = (0..expected_num) - .map(|_| Some(PartitionedStakeReward::new_random())) + .map(|_| PartitionedStakeReward::new_random()) .collect::>(); let partition_indices = hash_rewards_into_partitions(&stake_rewards, &Hash::default(), 5); @@ -81,7 +79,7 @@ mod tests { // simulate 40K - 1 rewards, the expected num of credit blocks should be 10. let expected_num = 40959; let stake_rewards = (0..expected_num) - .map(|_| Some(PartitionedStakeReward::new_random())) + .map(|_| PartitionedStakeReward::new_random()) .collect::>(); let partition_indices = diff --git a/runtime/src/bank/partitioned_epoch_rewards/mod.rs b/runtime/src/bank/partitioned_epoch_rewards/mod.rs index f33fac10aa4b0a..6fecfa899be06d 100644 --- a/runtime/src/bank/partitioned_epoch_rewards/mod.rs +++ b/runtime/src/bank/partitioned_epoch_rewards/mod.rs @@ -39,14 +39,14 @@ pub(crate) struct PartitionedStakeReward { pub commission: u8, } -type PartitionedStakeRewards = Vec>; +type PartitionedStakeRewards = Vec; #[derive(Debug, Clone, PartialEq)] pub(crate) struct StartBlockHeightAndRewards { /// the block height of the slot at which rewards distribution began pub(crate) distribution_starting_block_height: u64, /// calculated epoch rewards before partitioning - pub(crate) all_stake_rewards: Arc, + pub(crate) all_stake_rewards: Arc>, } #[derive(Debug, Clone, PartialEq)] @@ -55,7 +55,7 @@ pub(crate) struct StartBlockHeightAndPartitionedRewards { pub(crate) distribution_starting_block_height: u64, /// calculated epoch rewards pending distribution - pub(crate) all_stake_rewards: Arc, + pub(crate) all_stake_rewards: Arc>, /// indices of calculated epoch rewards per partition, outer Vec is by /// partition (one partition per block), inner Vec is the indices for one @@ -196,7 +196,7 @@ pub(super) struct CalculateRewardsAndDistributeVoteRewardsResult { /// vote accounts pub(super) point_value: PointValue, /// stake rewards that still need to be distributed - pub(super) stake_rewards: Arc, + pub(super) stake_rewards: Arc>, } pub(crate) type StakeRewards = Vec; @@ -234,7 +234,7 @@ impl Bank { pub(crate) fn set_epoch_reward_status_calculation( &mut self, distribution_starting_block_height: u64, - stake_rewards: Arc, + stake_rewards: Arc>, ) { self.epoch_reward_status = EpochRewardStatus::Active(EpochRewardPhase::Calculation(StartBlockHeightAndRewards { @@ -246,7 +246,7 @@ impl Bank { pub(crate) fn set_epoch_reward_status_distribution( &mut self, distribution_starting_block_height: u64, - all_stake_rewards: Arc, + all_stake_rewards: Arc>, partition_indices: Vec>, ) { self.epoch_reward_status = EpochRewardStatus::Active(EpochRewardPhase::Distribution( @@ -351,9 +351,9 @@ mod tests { } pub fn build_partitioned_stake_rewards( - stake_rewards: &[Option], + stake_rewards: &[PartitionedStakeReward], partition_indices: &[Vec], - ) -> Vec>> { + ) -> Vec> { partition_indices .iter() .map(|partition_index| { @@ -372,7 +372,7 @@ mod tests { ) -> PartitionedStakeRewards { stake_rewards .into_iter() - .map(|stake_reward| Some(PartitionedStakeReward::maybe_from(&stake_reward).unwrap())) + .map(|stake_reward| PartitionedStakeReward::maybe_from(&stake_reward).unwrap()) .collect() } @@ -546,7 +546,7 @@ mod tests { let expected_num = 100; let stake_rewards = (0..expected_num) - .map(|_| Some(PartitionedStakeReward::new_random())) + .map(|_| PartitionedStakeReward::new_random()) .collect::>(); let partition_indices = vec![(0..expected_num).collect()]; @@ -598,7 +598,7 @@ mod tests { |num_stakes: u64, expected_num_reward_distribution_blocks: u64| { // Given the short epoch, i.e. 32 slots, we should cap the number of reward distribution blocks to 32/10 = 3. let stake_rewards = (0..num_stakes) - .map(|_| Some(PartitionedStakeReward::new_random())) + .map(|_| PartitionedStakeReward::new_random()) .collect::>(); assert_eq!( @@ -636,7 +636,7 @@ mod tests { // Given 8k rewards, it will take 2 blocks to credit all the rewards let expected_num = 8192; let stake_rewards = (0..expected_num) - .map(|_| Some(PartitionedStakeReward::new_random())) + .map(|_| PartitionedStakeReward::new_random()) .collect::>(); assert_eq!(bank.get_reward_distribution_num_blocks(&stake_rewards), 2); diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index 181cbd03a72c76..ba13e21b54110e 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -11362,7 +11362,7 @@ fn test_system_instruction_unsigned_transaction() { #[test] fn test_calc_vote_accounts_to_store_empty() { - let vote_account_rewards = HashMap::default(); + let vote_account_rewards = DashMap::default(); let result = Bank::calc_vote_accounts_to_store(vote_account_rewards); assert_eq!( result.accounts_with_rewards.len(), @@ -11373,7 +11373,7 @@ fn test_calc_vote_accounts_to_store_empty() { #[test] fn test_calc_vote_accounts_to_store_overflow() { - let mut vote_account_rewards = HashMap::default(); + let vote_account_rewards = DashMap::default(); let pubkey = solana_pubkey::new_rand(); let mut vote_account = AccountSharedData::default(); vote_account.set_lamports(u64::MAX); @@ -11398,7 +11398,7 @@ fn test_calc_vote_accounts_to_store_normal() { let pubkey = solana_pubkey::new_rand(); for commission in 0..2 { for vote_rewards in 0..2 { - let mut vote_account_rewards = HashMap::default(); + let vote_account_rewards = DashMap::default(); let mut vote_account = AccountSharedData::default(); vote_account.set_lamports(1); vote_account_rewards.insert(