solana_accounts_db/partitioned_rewards.rs
1//! Code related to partitioned rewards distribution
2
3#[derive(Debug)]
4/// Configuration options for partitioned epoch rewards.
5/// This struct allows various forms of testing, especially prior to feature activation.
6pub struct PartitionedEpochRewardsConfig {
7 /// number of stake accounts to store in one block during partitioned reward interval
8 /// normally, this is a number tuned for reasonable performance, such as 4096 accounts/block
9 /// if force_one_slot_partitioned_rewards, this will usually be u64::MAX so that all stake accounts are written in the first block
10 pub stake_account_stores_per_block: u64,
11 /// if true, end of epoch bank rewards will force using partitioned rewards distribution.
12 /// see `set_test_enable_partitioned_rewards`
13 pub test_enable_partitioned_rewards: bool,
14 /// if true, end of epoch non-partitioned bank rewards will test the partitioned rewards distribution vote and stake accounts
15 /// This has a significant performance impact on the first slot in each new epoch.
16 pub test_compare_partitioned_epoch_rewards: bool,
17}
18
19impl Default for PartitionedEpochRewardsConfig {
20 fn default() -> Self {
21 Self {
22 // # stake accounts to store in one block during partitioned reward interval
23 // Target to store 64 rewards per entry/tick in a block. A block has a minimum of 64
24 // entries/tick. This gives 4096 total rewards to store in one block.
25 // This constant affects consensus.
26 stake_account_stores_per_block: 4096,
27 test_enable_partitioned_rewards: false,
28 test_compare_partitioned_epoch_rewards: false,
29 }
30 }
31}
32
33#[derive(Debug, Default, Clone, Copy)]
34pub enum TestPartitionedEpochRewards {
35 #[default]
36 None,
37 CompareResults,
38 ForcePartitionedEpochRewardsInOneBlock,
39 PartitionedEpochRewardsConfigRewardBlocks {
40 stake_account_stores_per_block: u64,
41 },
42}
43
44impl PartitionedEpochRewardsConfig {
45 pub fn new(test: TestPartitionedEpochRewards) -> Self {
46 match test {
47 TestPartitionedEpochRewards::None => Self::default(),
48 TestPartitionedEpochRewards::CompareResults => {
49 Self::set_test_compare_partitioned_epoch_rewards()
50 }
51 TestPartitionedEpochRewards::ForcePartitionedEpochRewardsInOneBlock => {
52 Self::set_test_enable_partitioned_rewards()
53 }
54 TestPartitionedEpochRewards::PartitionedEpochRewardsConfigRewardBlocks {
55 stake_account_stores_per_block,
56 } => {
57 Self::set_test_enable_partitioned_rewards_with_custom_number_of_stake_accounts_per_block(
58 stake_account_stores_per_block
59 )
60 }
61 }
62 }
63
64 /// All rewards will be distributed in the first block in the epoch, matching
65 /// consensus for the non-partitioned rewards, but running all the partitioned rewards
66 /// code.
67 fn set_test_enable_partitioned_rewards() -> Self {
68 Self {
69 stake_account_stores_per_block: u64::MAX,
70 test_enable_partitioned_rewards: true,
71 // irrelevant if we are not running old code path
72 test_compare_partitioned_epoch_rewards: false,
73 }
74 }
75
76 /// All rewards will be distributed in the first block in the epoch as normal.
77 /// Then, the partitioned rewards code will calculate expected results and compare to
78 /// the old code path's results.
79 fn set_test_compare_partitioned_epoch_rewards() -> Self {
80 Self {
81 test_compare_partitioned_epoch_rewards: true,
82 ..PartitionedEpochRewardsConfig::default()
83 }
84 }
85
86 /// A method that configures how many reward reward calculation blocks and how many stake
87 /// accounts to store per reward block.
88 fn set_test_enable_partitioned_rewards_with_custom_number_of_stake_accounts_per_block(
89 stake_account_stores_per_block: u64,
90 ) -> Self {
91 Self {
92 stake_account_stores_per_block,
93 test_enable_partitioned_rewards: true,
94 // irrelevant if we are not running old code path
95 test_compare_partitioned_epoch_rewards: false,
96 }
97 }
98}