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

Generated by: LCOV version 1.14