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-09-17 04:28:31 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 tracks pending partitioned epoch rewards across
       7             :    forks.
       8             : 
       9             :    The access pattern is as follows:
      10             :    1. Insertion/Hashing: This occurs at the epoch boundary after stake
      11             :       rewards are computed before rewards are distributed.  The stake
      12             :       account along with corresponding lamports and credits observed are
      13             :       hashed into a rewards partition.  These rewards will be paid out
      14             :       later.
      15             :    2. Iteration: A partition is paid out per slot.  All of the accounts
      16             :       in the partition are iterated over and the rewards are distributed
      17             :       to the stake accounts involved.
      18             : 
      19             :   The protocol level guarantees is just that there can be up to 43200
      20             :   rewards slots.  There is no limit on the number of stake rewards paid
      21             :   out per slot.
      22             : 
      23             :   Reward entries use cache_cnt+1 equivalent buffers: up to cache_cnt
      24             :   completed windows and one window under construction.  Entries are
      25             :   built directly in the buffer that becomes resident, so finishing a
      26             :   window does not move them.  Per-bank metadata is dynamically sized
      27             :   and does not multiply reward-entry storage.  Finishing a fork when
      28             :   the completed-window cache is full evicts the least recently finished
      29             :   window, but keeps that fork's metadata.  If an evicted window is
      30             :   needed, the caller recalculates it.
      31             : 
      32             :   As a note, the structure is also only partially fork-aware.  It safely
      33             :   assumes that the epoch boundary of a second epoch will not happen
      34             :   while the stake rewards are still being paid out of a first epoch.
      35             :   The protocol guarantees this because stake rewards must be paid out
      36             :   within the first 10% of an epoch.
      37             : 
      38             :   It is assumed that there will not be concurrent users of the stake
      39             :   rewards structure.  The caller is expected to manage synchronization
      40             :   between threads. */
      41             : 
      42        3606 : #define FD_STAKE_REWARDS_ALIGN (128UL)
      43             : 
      44             : struct fd_stake_rewards;
      45             : typedef struct fd_stake_rewards fd_stake_rewards_t;
      46             : 
      47             : FD_PROTOTYPES_BEGIN
      48             : 
      49             : /* fd_stake_rewards_align is used to get the alignment for the stake
      50             :    rewards structure. */
      51             : 
      52             : ulong
      53             : fd_stake_rewards_align( void );
      54             : 
      55             : /* fd_stake_rewards_footprint returns the footprint given the maximum
      56             :    number of stake accounts and banks.  max_stake_accounts is the
      57             :    capacity of each in-memory window, not a bound on the rewards in an
      58             :    epoch.  max_bank_cnt sizes metadata, not reward-entry buffers.
      59             :    cache_cnt is the number of completed windows retained in memory and
      60             :    must be in [1,max_bank_cnt+1].  Storage includes one additional
      61             :    construction buffer.  An ancestor bank can retain an older evicted
      62             :    generation, so there is one metadata slot per bank.  An additional
      63             :    slot allows a cached window to be replaced before its old shared
      64             :    handle is released. */
      65             : 
      66             : ulong
      67             : fd_stake_rewards_footprint( ulong max_stake_accounts,
      68             :                             ulong max_bank_cnt,
      69             :                             ulong cache_cnt );
      70             : 
      71             : /* fd_stake_rewards_new creates a new stake rewards structure. */
      72             : 
      73             : void *
      74             : fd_stake_rewards_new( void * shmem,
      75             :                       ulong  max_stake_accounts,
      76             :                       ulong  max_bank_cnt,
      77             :                       ulong  cache_cnt );
      78             : 
      79             : /* fd_stake_rewards_join joins the caller to the stake rewards
      80             :    structure. */
      81             : 
      82             : fd_stake_rewards_t *
      83             : fd_stake_rewards_join( void * shmem );
      84             : 
      85             : /* fd_stake_rewards_clear resets the stake rewards structure to a
      86             :    post-new state. */
      87             : 
      88             : void
      89             : fd_stake_rewards_clear( fd_stake_rewards_t * stake_rewards );
      90             : 
      91             : /* Each stake rewards fork idx must be refcnt'd since they are shared
      92             :    across banks.  fd_stake_rewards_acquire increments the reference
      93             :    count and fd_stake_rewards_release decrements it.  Once the count
      94             :    reaches zero, the fork is purged. */
      95             : 
      96             : void
      97             : fd_stake_rewards_acquire( fd_stake_rewards_t * stake_rewards,
      98             :                           ushort               fork_idx );
      99             : 
     100             : void
     101             : fd_stake_rewards_release( fd_stake_rewards_t * stake_rewards,
     102             :                           ushort               fork_idx );
     103             : 
     104             : ulong
     105             : fd_stake_rewards_refcnt( fd_stake_rewards_t const * stake_rewards,
     106             :                          ushort                     fork_idx );
     107             : 
     108             : /* fd_stake_rewards_free_cnt returns how many forks can still be
     109             :    acquired, including the replacement slot.  A bank needs one whenever
     110             :    it computes rewards it does not already hold: at an epoch boundary,
     111             :    or when the partition it has to distribute falls outside its
     112             :    window. */
     113             : 
     114             : ulong
     115             : fd_stake_rewards_free_cnt( fd_stake_rewards_t const * stake_rewards );
     116             : 
     117             : /* fd_stake_rewards_init starts reward calculation for a new fork and
     118             :    returns its index.  win_lo is the first partition to retain.  The
     119             :    fork claims the free construction buffer.  No other fork may be
     120             :    staged. */
     121             : 
     122             : ushort
     123             : fd_stake_rewards_init( fd_stake_rewards_t * stake_rewards,
     124             :                        fd_hash_t const *    parent_blockhash,
     125             :                        ulong                starting_block_height,
     126             :                        uint                 partitions_cnt,
     127             :                        uint                 win_lo,
     128             :                        ulong                max_rewards_cnt );
     129             : 
     130             : /* fd_stake_rewards_window_{lo,hi} return the inclusive range of
     131             :    partitions that a fork currently holds.  A staged fork reports its
     132             :    range but is not iterable until fd_stake_rewards_fini.  Both return
     133             :    UINT_MAX for an evicted fork.  The caller must recalculate a missing
     134             :    window. */
     135             : 
     136             : uint
     137             : fd_stake_rewards_window_lo( fd_stake_rewards_t const * stake_rewards,
     138             :                             ushort                     fork_idx );
     139             : 
     140             : uint
     141             : fd_stake_rewards_window_hi( fd_stake_rewards_t const * stake_rewards,
     142             :                             ushort                     fork_idx );
     143             : 
     144             : /* fd_stake_rewards_insert inserts a new stake reward for a given fork.
     145             :    It hashes the reward into the appropriate partition.  The reward is
     146             :    only stored if its partition falls inside the fork's window, but it
     147             :    always counts towards fd_stake_rewards_total_rewards. */
     148             : 
     149             : void
     150             : fd_stake_rewards_insert( fd_stake_rewards_t * stake_rewards,
     151             :                          ushort               fork_idx,
     152             :                          fd_pubkey_t const *  pubkey,
     153             :                          ulong                lamports,
     154             :                          ulong                credits_observed );
     155             : 
     156             : /* fd_stake_rewards_fini makes the construction buffer resident without
     157             :    moving its entries.  An empty window releases its buffer.  The oldest
     158             :    resident window is evicted when the completed-window cache is full. */
     159             : 
     160             : void
     161             : fd_stake_rewards_fini( fd_stake_rewards_t * stake_rewards,
     162             :                        ushort               fork_idx );
     163             : 
     164             : /* Iterator for the rewards in one resident fork partition.
     165             :    partition_idx must lie inside the fork's window.  The caller should
     166             :    not interleave any other iteration or modification of the stake
     167             :    rewards structure while iterating.
     168             : 
     169             :    Example use:
     170             :    for( fd_stake_rewards_iter_init( stake_rewards, fork_idx,
     171             :                                     partition_idx );
     172             :         !fd_stake_rewards_iter_done( stake_rewards );
     173             :         fd_stake_rewards_iter_next( stake_rewards, fork_idx ) ) {
     174             :      fd_pubkey_t pubkey;
     175             :      ulong       lamports;
     176             :      ulong       credits_observed;
     177             :      fd_stake_rewards_iter_ele( stake_rewards, fork_idx, &pubkey,
     178             :                                 &lamports, &credits_observed );
     179             :    }
     180             : */
     181             : 
     182             : void
     183             : fd_stake_rewards_iter_init( fd_stake_rewards_t * stake_rewards,
     184             :                             ushort               fork_idx,
     185             :                             uint                 partition_idx );
     186             : 
     187             : void
     188             : fd_stake_rewards_iter_next( fd_stake_rewards_t * stake_rewards,
     189             :                             ushort               fork_idx );
     190             : 
     191             : int
     192             : fd_stake_rewards_iter_done( fd_stake_rewards_t * stake_rewards );
     193             : 
     194             : void
     195             : fd_stake_rewards_iter_ele( fd_stake_rewards_t * stake_rewards,
     196             :                            ushort               fork_idx,
     197             :                            fd_pubkey_t *        pubkey_out,
     198             :                            ulong *              lamports_out,
     199             :                            ulong *              credits_observed_out );
     200             : 
     201             : /* Simple accessors for stake rewards information. */
     202             : 
     203             : ulong
     204             : fd_stake_rewards_total_rewards( fd_stake_rewards_t const * stake_rewards,
     205             :                                 ushort                     fork_idx );
     206             : 
     207             : uint
     208             : fd_stake_rewards_num_partitions( fd_stake_rewards_t const * stake_rewards,
     209             :                                  ushort                     fork_idx );
     210             : 
     211             : ulong
     212             : fd_stake_rewards_starting_block_height( fd_stake_rewards_t const * stake_rewards,
     213             :                                         ushort                     fork_idx );
     214             : 
     215             : ulong
     216             : fd_stake_rewards_exclusive_ending_block_height( fd_stake_rewards_t const * stake_rewards,
     217             :                                                 ushort                     fork_idx );
     218             : 
     219             : FD_PROTOTYPES_END
     220             : 
     221             : #endif /* HEADER_fd_src_flamenco_rewards_fd_stake_rewards_h */

Generated by: LCOV version 1.14