Skip to content

Commit 82c1514

Browse files
authored
Optimize VoteRewardsAccounts (#7236)
* refactor VoteRewardsAccounts * impl<'a> StorableAccounts<'a> for VoteRewardsAccountsStorable<'a>
1 parent 9869ae5 commit 82c1514

File tree

4 files changed

+107
-44
lines changed

4 files changed

+107
-44
lines changed

runtime/src/bank.rs

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2354,8 +2354,7 @@ impl Bank {
23542354
fn calc_vote_accounts_to_store(vote_account_rewards: VoteRewards) -> VoteRewardsAccounts {
23552355
let len = vote_account_rewards.len();
23562356
let mut result = VoteRewardsAccounts {
2357-
rewards: Vec::with_capacity(len),
2358-
accounts_to_store: Vec::with_capacity(len),
2357+
accounts_with_rewards: Vec::with_capacity(len),
23592358
total_vote_rewards_lamports: 0,
23602359
};
23612360
vote_account_rewards.into_iter().for_each(
@@ -2372,16 +2371,16 @@ impl Bank {
23722371
return;
23732372
}
23742373

2375-
result.rewards.push((
2374+
result.accounts_with_rewards.push((
23762375
vote_pubkey,
23772376
RewardInfo {
23782377
reward_type: RewardType::Voting,
23792378
lamports: vote_rewards as i64,
23802379
post_balance: vote_account.lamports(),
23812380
commission: Some(commission),
23822381
},
2382+
vote_account,
23832383
));
2384-
result.accounts_to_store.push((vote_pubkey, vote_account));
23852384
result.total_vote_rewards_lamports += vote_rewards;
23862385
},
23872386
);
@@ -2391,14 +2390,17 @@ impl Bank {
23912390
fn update_reward_history(
23922391
&self,
23932392
stake_rewards: StakeRewards,
2394-
vote_rewards: &[(Pubkey, RewardInfo)],
2393+
vote_rewards: &VoteRewardsAccounts,
23952394
) {
2396-
let additional_reserve = stake_rewards.len() + vote_rewards.len();
2395+
let additional_reserve = stake_rewards.len() + vote_rewards.accounts_with_rewards.len();
23972396
let mut rewards = self.rewards.write().unwrap();
23982397
rewards.reserve(additional_reserve);
2399-
vote_rewards.iter().for_each(|(vote_pubkey, vote_reward)| {
2400-
rewards.push((*vote_pubkey, *vote_reward));
2401-
});
2398+
vote_rewards
2399+
.accounts_with_rewards
2400+
.iter()
2401+
.for_each(|(vote_pubkey, vote_reward, _)| {
2402+
rewards.push((*vote_pubkey, *vote_reward));
2403+
});
24022404
stake_rewards
24032405
.into_iter()
24042406
.filter(|x| x.get_stake_reward() > 0)

runtime/src/bank/partitioned_epoch_rewards/calculation.rs

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use {
33
epoch_rewards_hasher::hash_rewards_into_partitions, Bank,
44
CalculateRewardsAndDistributeVoteRewardsResult, CalculateValidatorRewardsResult,
55
EpochRewardCalculateParamInfo, PartitionedRewardsCalculation, PartitionedStakeReward,
6-
StakeRewardCalculation, VoteRewardsAccounts, REWARD_CALCULATION_NUM_BLOCKS,
6+
StakeRewardCalculation, VoteRewardsAccounts, VoteRewardsAccountsStorable,
7+
REWARD_CALCULATION_NUM_BLOCKS,
78
},
89
crate::{
910
bank::{
@@ -147,7 +148,7 @@ impl Bank {
147148
self.store_vote_accounts_partitioned(vote_account_rewards, metrics);
148149

149150
// update reward history of JUST vote_rewards, stake_rewards is vec![] here
150-
self.update_reward_history(vec![], &vote_account_rewards.rewards[..]);
151+
self.update_reward_history(vec![], vote_account_rewards);
151152

152153
let StakeRewardCalculation {
153154
stake_rewards,
@@ -210,7 +211,11 @@ impl Bank {
210211
metrics: &RewardsMetrics,
211212
) {
212213
let (_, measure_us) = measure_us!({
213-
self.store_accounts((self.slot(), &vote_account_rewards.accounts_to_store[..]));
214+
let storable = VoteRewardsAccountsStorable {
215+
slot: self.slot(),
216+
vote_rewards_accounts: vote_account_rewards,
217+
};
218+
self.store_accounts(storable);
214219
});
215220

216221
metrics
@@ -606,10 +611,11 @@ mod tests {
606611
post_balance: vote_reward_info.vote_rewards,
607612
commission: Some(vote_reward_info.commission),
608613
};
609-
vote_rewards_account.rewards.push((*vote_key, info));
610-
vote_rewards_account
611-
.accounts_to_store
612-
.push((*vote_key, vote_reward_info.vote_account.clone()));
614+
vote_rewards_account.accounts_with_rewards.push((
615+
*vote_key,
616+
info,
617+
vote_reward_info.vote_account.clone(),
618+
));
613619
vote_rewards_account.total_vote_rewards_lamports += vote_reward_info.vote_rewards;
614620
});
615621

@@ -619,7 +625,7 @@ mod tests {
619625
bank.store_vote_accounts_partitioned(&vote_rewards_account, &metrics);
620626
assert_eq!(
621627
expected_vote_rewards_num,
622-
vote_rewards_account.accounts_to_store.len()
628+
vote_rewards_account.accounts_with_rewards.len()
623629
);
624630
assert_eq!(
625631
vote_rewards
@@ -654,7 +660,7 @@ mod tests {
654660
let total_vote_rewards = vote_rewards.total_vote_rewards_lamports;
655661

656662
bank.store_vote_accounts_partitioned(&vote_rewards, &metrics);
657-
assert_eq!(expected, vote_rewards.accounts_to_store.len());
663+
assert_eq!(expected, vote_rewards.accounts_with_rewards.len());
658664
assert_eq!(0, total_vote_rewards);
659665
}
660666

@@ -688,9 +694,9 @@ mod tests {
688694
.stake_reward_calculation;
689695

690696
let total_vote_rewards: u64 = vote_rewards
691-
.rewards
697+
.accounts_with_rewards
692698
.iter()
693-
.map(|reward| reward.1.lamports)
699+
.map(|(_, reward_info, _)| reward_info.lamports)
694700
.sum::<i64>() as u64;
695701

696702
// assert that total rewards matches the sum of vote rewards and stake rewards
@@ -800,26 +806,26 @@ mod tests {
800806
let vote_state = VoteState::deserialize(vote_account.data()).unwrap();
801807

802808
assert_eq!(
803-
vote_rewards_accounts.rewards.len(),
804-
vote_rewards_accounts.accounts_to_store.len()
809+
vote_rewards_accounts.accounts_with_rewards.len(),
810+
vote_rewards_accounts.accounts_with_rewards.len()
805811
);
806-
assert_eq!(vote_rewards_accounts.rewards.len(), 1);
807-
let rewards = &vote_rewards_accounts.rewards[0];
808-
let account = &vote_rewards_accounts.accounts_to_store[0].1;
812+
assert_eq!(vote_rewards_accounts.accounts_with_rewards.len(), 1);
813+
let (vote_pubkey_from_result, rewards, account) =
814+
&vote_rewards_accounts.accounts_with_rewards[0];
809815
let vote_rewards = 0;
810816
let commission = vote_state.commission;
811817
assert_eq!(account.lamports(), vote_account.lamports());
812818
assert!(accounts_equal(account, &vote_account));
813819
assert_eq!(
814-
rewards.1,
820+
*rewards,
815821
RewardInfo {
816822
reward_type: RewardType::Voting,
817823
lamports: vote_rewards as i64,
818824
post_balance: vote_account.lamports(),
819825
commission: Some(commission),
820826
}
821827
);
822-
assert_eq!(&rewards.0, vote_pubkey);
828+
assert_eq!(vote_pubkey_from_result, vote_pubkey);
823829

824830
assert_eq!(stake_reward_calculation.stake_rewards.len(), 1);
825831
let expected_reward = {

runtime/src/bank/partitioned_epoch_rewards/mod.rs

Lines changed: 54 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,13 @@ use {
99
inflation_rewards::points::PointValue, stake_account::StakeAccount,
1010
stake_history::StakeHistory,
1111
},
12-
solana_account::AccountSharedData,
12+
solana_account::{AccountSharedData, ReadableAccount},
1313
solana_accounts_db::{
14-
partitioned_rewards::PartitionedEpochRewardsConfig, stake_rewards::StakeReward,
14+
partitioned_rewards::PartitionedEpochRewardsConfig,
15+
stake_rewards::StakeReward,
16+
storable_accounts::{AccountForStorage, StorableAccounts},
1517
},
18+
solana_clock::Slot,
1619
solana_pubkey::Pubkey,
1720
solana_reward_info::RewardInfo,
1821
solana_stake_interface::state::{Delegation, Stake},
@@ -81,15 +84,59 @@ pub(crate) enum EpochRewardPhase {
8184

8285
#[derive(Debug, Default)]
8386
pub(super) struct VoteRewardsAccounts {
84-
/// reward info for each vote account pubkey.
85-
/// This type is used by `update_reward_history()`
86-
pub(super) rewards: Vec<(Pubkey, RewardInfo)>,
87-
/// account to be stored, corresponds to pubkey in `rewards`
88-
pub(super) accounts_to_store: Vec<(Pubkey, AccountSharedData)>,
87+
/// accounts with rewards to be stored
88+
pub(super) accounts_with_rewards: Vec<(Pubkey, RewardInfo, AccountSharedData)>,
8989
/// total lamports across all `vote_rewards`
9090
pub(super) total_vote_rewards_lamports: u64,
9191
}
9292

93+
/// Wrapper struct to implement StorableAccounts for VoteRewardsAccounts
94+
pub(super) struct VoteRewardsAccountsStorable<'a> {
95+
pub slot: Slot,
96+
pub vote_rewards_accounts: &'a VoteRewardsAccounts,
97+
}
98+
99+
impl<'a> StorableAccounts<'a> for VoteRewardsAccountsStorable<'a> {
100+
fn account<Ret>(
101+
&self,
102+
index: usize,
103+
mut callback: impl for<'local> FnMut(AccountForStorage<'local>) -> Ret,
104+
) -> Ret {
105+
let (pubkey, _, account) = &self.vote_rewards_accounts.accounts_with_rewards[index];
106+
callback((pubkey, account).into())
107+
}
108+
109+
fn is_zero_lamport(&self, index: usize) -> bool {
110+
self.vote_rewards_accounts.accounts_with_rewards[index]
111+
.2
112+
.lamports()
113+
== 0
114+
}
115+
116+
fn data_len(&self, index: usize) -> usize {
117+
self.vote_rewards_accounts.accounts_with_rewards[index]
118+
.2
119+
.data()
120+
.len()
121+
}
122+
123+
fn pubkey(&self, index: usize) -> &Pubkey {
124+
&self.vote_rewards_accounts.accounts_with_rewards[index].0
125+
}
126+
127+
fn slot(&self, _index: usize) -> Slot {
128+
self.target_slot()
129+
}
130+
131+
fn target_slot(&self) -> Slot {
132+
self.slot
133+
}
134+
135+
fn len(&self) -> usize {
136+
self.vote_rewards_accounts.accounts_with_rewards.len()
137+
}
138+
}
139+
93140
#[derive(Debug, Default)]
94141
/// result of calculating the stake rewards at end of epoch
95142
pub(super) struct StakeRewardCalculation {

runtime/src/bank/tests.rs

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11205,8 +11205,11 @@ fn test_system_instruction_unsigned_transaction() {
1120511205
fn test_calc_vote_accounts_to_store_empty() {
1120611206
let vote_account_rewards = DashMap::default();
1120711207
let result = Bank::calc_vote_accounts_to_store(vote_account_rewards);
11208-
assert_eq!(result.rewards.len(), result.accounts_to_store.len());
11209-
assert!(result.rewards.is_empty());
11208+
assert_eq!(
11209+
result.accounts_with_rewards.len(),
11210+
result.accounts_with_rewards.len()
11211+
);
11212+
assert!(result.accounts_with_rewards.is_empty());
1121011213
}
1121111214

1121211215
#[test]
@@ -11224,8 +11227,11 @@ fn test_calc_vote_accounts_to_store_overflow() {
1122411227
},
1122511228
);
1122611229
let result = Bank::calc_vote_accounts_to_store(vote_account_rewards);
11227-
assert_eq!(result.rewards.len(), result.accounts_to_store.len());
11228-
assert!(result.rewards.is_empty());
11230+
assert_eq!(
11231+
result.accounts_with_rewards.len(),
11232+
result.accounts_with_rewards.len()
11233+
);
11234+
assert!(result.accounts_with_rewards.is_empty());
1122911235
}
1123011236

1123111237
#[test]
@@ -11245,22 +11251,24 @@ fn test_calc_vote_accounts_to_store_normal() {
1124511251
},
1124611252
);
1124711253
let result = Bank::calc_vote_accounts_to_store(vote_account_rewards);
11248-
assert_eq!(result.rewards.len(), result.accounts_to_store.len());
11249-
assert_eq!(result.rewards.len(), 1);
11250-
let rewards = &result.rewards[0];
11251-
let account = &result.accounts_to_store[0].1;
11254+
assert_eq!(
11255+
result.accounts_with_rewards.len(),
11256+
result.accounts_with_rewards.len()
11257+
);
11258+
assert_eq!(result.accounts_with_rewards.len(), 1);
11259+
let (pubkey_result, rewards, account) = &result.accounts_with_rewards[0];
1125211260
_ = vote_account.checked_add_lamports(vote_rewards);
1125311261
assert!(accounts_equal(account, &vote_account));
1125411262
assert_eq!(
11255-
rewards.1,
11263+
*rewards,
1125611264
RewardInfo {
1125711265
reward_type: RewardType::Voting,
1125811266
lamports: vote_rewards as i64,
1125911267
post_balance: vote_account.lamports(),
1126011268
commission: Some(commission),
1126111269
}
1126211270
);
11263-
assert_eq!(rewards.0, pubkey);
11271+
assert_eq!(*pubkey_result, pubkey);
1126411272
}
1126511273
}
1126611274
}

0 commit comments

Comments
 (0)