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}