LCOV - code coverage report
Current view: top level - flamenco/rewards - fd_stake_rewards.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 1 1 100.0 %
Date: 2026-05-16 06:43:53 Functions: 0 0 -

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_rewards_fd_stake_rewards_h
       2             : #define HEADER_fd_src_flamenco_rewards_fd_stake_rewards_h
       3             : 
       4             : #include "../fd_flamenco_base.h"
       5             : 
       6             : /* fd_stake_rewards is a fork aware structure that stores and keeps
       7             :    track of pending stake rewards for the purposes of partitioned epoch
       8             :    rewards that occurs after the epoch boundary.
       9             : 
      10             :    The access pattern is as follows:
      11             :    1. Insertion/Hashing: This occurs at the epoch boundary after stake
      12             :       rewards are computed before rewards are distributed.  The stake
      13             :       account along with corresponding lamports and credits observed are
      14             :       hashed into a rewards partition.  These rewards will be paid out
      15             :       later.
      16             :    2. Iteration: A partition is paid out per slot.  All of the accounts
      17             :       in the partition are iterated over and the rewards are distributed
      18             :       to the stake accounts involved.
      19             : 
      20             :   The protocol level guarantees is just that there can be up to 43200
      21             :   rewards slots.  There is no gap on the number of stake rewards paid
      22             :   out per slot.
      23             : 
      24             :   A naive approach with a worst case number of stake accounts (assume
      25             :   ~200M) and a reasonable amount of forks across the epoch boundary
      26             :   (assume 32) would require an element of size 48 (pubkey, lamports, and
      27             :   credits observed).  So we would need a structure of size: 48 bytes *
      28             :   200M accounts * 32 forks = 307GB of memory.  This also doesn't involve
      29             :   any data to keep track of pool/map overhead.
      30             : 
      31             :   Instead we use the property that across forks almost every single
      32             :   stake account will have the same rewards.  So we can use a shared
      33             :   index of (pubkey, stake, credit) entries to store the rewards for all
      34             :   forks.
      35             : 
      36             :   For each fork, we will need to keep track of what elements are in
      37             :   each partition.  But each partition can be of unequal size so we use
      38             :   a singly linked list to store the elements in each partition.  Each
      39             :   partition member will just contain a linked-list pointer and an index
      40             :   into the aforementioned index pool.  When stake rewards are being paid
      41             :   out, the iterator will iterate through the linked list and dereference
      42             :   the index pool to get the pubkey and associated rewards.
      43             : 
      44             :   As a note, the structure is also only partially fork-aware.  It safely
      45             :   assumes that the epoch boundary of a second epoch will not happen
      46             :   while the stake rewards are still being paid out of a first epoch.
      47             :   The protocol guarantees this because stake rewards must be paid out
      48             :   within the first 10% of an epoch.
      49             : 
      50             :   It is assumed that there will not be concurrent users of the stake
      51             :   rewards structure.  The caller is expected to manage synchronization
      52             :   between threads. */
      53             : 
      54       15450 : #define FD_STAKE_REWARDS_ALIGN (128UL)
      55             : 
      56             : struct fd_stake_rewards;
      57             : typedef struct fd_stake_rewards fd_stake_rewards_t;
      58             : 
      59             : FD_PROTOTYPES_BEGIN
      60             : 
      61             : /* fd_stake_rewards_align is used to get the alignment for the stake
      62             :    rewards structure. */
      63             : 
      64             : ulong
      65             : fd_stake_rewards_align( void );
      66             : 
      67             : /* fd_stake_rewards_footprint is used to get the footprint for the stake
      68             :    rewards structure given the max number of stake accounts, the max
      69             :    number of forks, and the expected number of stake accounts.  The
      70             :    expected number of stake accounts is used to internally size out the
      71             :    map chain for the index. */
      72             : 
      73             : ulong
      74             : fd_stake_rewards_footprint( ulong max_stake_accounts,
      75             :                             ulong expected_stake_accs,
      76             :                             ulong max_fork_width );
      77             : 
      78             : /* fd_stake_rewards_new creates a new stake rewards structure. */
      79             : 
      80             : void *
      81             : fd_stake_rewards_new( void * shmem,
      82             :                       ulong  max_stake_accounts,
      83             :                       ulong  expected_stake_accs,
      84             :                       ulong  max_fork_width,
      85             :                       ulong  seed );
      86             : 
      87             : /* fd_stake_rewards_join joins the caller to the stake rewards
      88             :    structure. */
      89             : 
      90             : fd_stake_rewards_t *
      91             : fd_stake_rewards_join( void * shmem );
      92             : 
      93             : /* fd_stake_rewards_clear resets the stake rewards structure to a
      94             :    post-new state. */
      95             : 
      96             : void
      97             : fd_stake_rewards_clear( fd_stake_rewards_t * stake_rewards );
      98             : 
      99             : /* fd_stake_rewards_init initializes the stake rewards structure for a
     100             :    given fork.  It should be used at the start of epoch reward
     101             :    calculation or recalculation.  It returns a fork index. */
     102             : 
     103             : uchar
     104             : fd_stake_rewards_init( fd_stake_rewards_t * stake_rewards,
     105             :                        ulong                epoch,
     106             :                        fd_hash_t const *    parent_blockhash,
     107             :                        ulong                starting_block_height,
     108             :                        uint                 partitions_cnt );
     109             : 
     110             : /* fd_stake_rewards_insert inserts a new stake reward for a given
     111             :    fork.  It adds it to the index and hashes it into the approporiate
     112             :    partition. */
     113             : 
     114             : void
     115             : fd_stake_rewards_insert( fd_stake_rewards_t * stake_rewards,
     116             :                          uchar                fork_idx,
     117             :                          fd_pubkey_t const *  pubkey,
     118             :                          ulong                lamports,
     119             :                          ulong                credits_observed );
     120             : 
     121             : /* Iterator for iterating over the stake rewards for a given fork and
     122             :    partition.  The caller should not interleave any other iteration or
     123             :    modification of the stake rewards structure while iterating.
     124             : 
     125             :    Example use:
     126             :    for( fd_stake_rewards_iter_init( stake_rewards, fork_idx, partition_idx );
     127             :         !fd_stake_rewards_iter_done( stake_rewards, fork_idx );
     128             :         fd_stake_rewards_iter_next( stake_rewards, fork_idx ) ) {
     129             :      fd_pubkey_t pubkey;
     130             :      ulong       lamports;
     131             :      ulong       credits_observed;
     132             :      fd_stake_rewards_iter_ele( iter, &pubkey, &lamports, &credits_observed );
     133             :    }
     134             :    */
     135             : 
     136             : void
     137             : fd_stake_rewards_iter_init( fd_stake_rewards_t * stake_rewards,
     138             :                             uchar                fork_idx,
     139             :                             uint                 partition_idx );
     140             : 
     141             : void
     142             : fd_stake_rewards_iter_next( fd_stake_rewards_t * stake_rewards,
     143             :                             uchar                fork_idx );
     144             : 
     145             : int
     146             : fd_stake_rewards_iter_done( fd_stake_rewards_t * stake_rewards );
     147             : 
     148             : void
     149             : fd_stake_rewards_iter_ele( fd_stake_rewards_t * stake_rewards,
     150             :                            uchar                fork_idx,
     151             :                            fd_pubkey_t *        pubkey_out,
     152             :                            ulong *              lamports_out,
     153             :                            ulong *              credits_observed_out );
     154             : 
     155             : /* Simple accessors for stake rewards information. */
     156             : 
     157             : ulong
     158             : fd_stake_rewards_total_rewards( fd_stake_rewards_t const * stake_rewards,
     159             :                                 uchar                      fork_idx );
     160             : 
     161             : uint
     162             : fd_stake_rewards_num_partitions( fd_stake_rewards_t const * stake_rewards,
     163             :                                  uchar                      fork_idx );
     164             : 
     165             : ulong
     166             : fd_stake_rewards_starting_block_height( fd_stake_rewards_t const * stake_rewards,
     167             :                                         uchar                      fork_idx );
     168             : 
     169             : ulong
     170             : fd_stake_rewards_exclusive_ending_block_height( fd_stake_rewards_t const * stake_rewards,
     171             :                                                 uchar                      fork_idx );
     172             : 
     173             : FD_PROTOTYPES_END
     174             : 
     175             : #endif /* HEADER_fd_src_flamenco_rewards_fd_stake_rewards_h */

Generated by: LCOV version 1.14