LCOV - code coverage report
Current view: top level - flamenco/stakes - fd_vote_stakes.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 8 8 100.0 %
Date: 2026-11-12 04:25:03 Functions: 0 0 -

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_stakes_fd_vote_stakes_h
       2             : #define HEADER_fd_src_flamenco_stakes_fd_vote_stakes_h
       3             : 
       4             : #include "../../util/fd_util_base.h"
       5             : #include "../fd_flamenco_base.h"
       6             : #include "../accdb/fd_accdb_base.h"
       7             : #include "../runtime/program/vote/fd_vote_codec.h"
       8             : 
       9         426 : #define FD_VOTE_STAKES_FD                   (123454)
      10        6036 : #define FD_VOTE_STAKES_ALIGN                (128UL)
      11       61071 : #define FD_VOTE_STAKES_ALPENGLOW_RANK_NULL  USHORT_MAX
      12             : 
      13             : /* fd_vote_stakes is the Firedancer equivalent of the Agave epoch stakes
      14             :    data structure.  It is a fork aware data structure that maintains the
      15             :    vote account state that is used for VM syscall calculations during
      16             :    execution.
      17             : 
      18             :    The underlying data structure is a tiered set of caches:
      19             :    - t-2..t-5: these are caches used for the vote account states at
      20             :      the end of the t-2 through t-5 epochs assuming you are currently
      21             :      in the t epoch.  These caches are shared across all forks.
      22             :    - t-1: computed at the most recent epoch boundary.  These sets are
      23             :      ref-counted and fork specific, up to max_live_slots of them;
      24             :      cache_cnt are kept in memory and the rest spill to disk.
      25             :    - state: each bank has its own view of which t-2 vote accounts are
      26             :      still valid, stored as a bitset.
      27             : 
      28             :    fd_vote_stakes also handles the creation of new vote stakes caches.
      29             :    The creation of new vote stakes caches happens at the epoch boundary
      30             :    and follows the rules defined in the validator_admission_ticket
      31             :    feature where every vote account must be in the top 2000 by stake.
      32             :    Under the hood, this is managed by a stake-sorted heap that is shared
      33             :    across all forks.
      34             : 
      35             :    NOTE:
      36             :    This system assumes that multiple forks can cross an epoch boundary
      37             :    but only one epoch boundary can be crossed at a time.  This means
      38             :    that there can be multiple t-1 forks after an epoch boundary, but
      39             :    only one will be active when the first fork crosses into an epoch
      40             :    boundary.  Similarly, this means that live forks address 5 epoch
      41             :    sets during an epoch boundary crossing and 4 most of the time:
      42             :    crossing into t+1 evicts the t-6 set, which no live fork addresses. */
      43             : 
      44             : struct fd_vote_stakes;
      45             : typedef struct fd_vote_stakes fd_vote_stakes_t;
      46             : 
      47             : /* fd_vote_stakes_ele_t is a copy of one vote account in a vote stakes
      48             :    set. */
      49             : 
      50             : struct fd_vote_stakes_ele {
      51             :   fd_pubkey_t             pubkey;
      52             :   fd_pubkey_t             node_account;
      53             :   ulong                   stake;
      54             :   ushort                  commission;                   /* inflation rewards, basis points */
      55             :   ushort                  block_revenue_commission_bps; /* SIMD-0123 */
      56             :   ulong                   pending_delegator_rewards;    /* SIMD-0123 */
      57             :   fd_pubkey_t             inflation_collector;          /* SIMD-0232 */
      58             :   fd_pubkey_t             block_collector;              /* SIMD-0232 */
      59             :   ushort                  rank;
      60             :   uchar                   bls_key[ FD_BLS_PUBKEY_COMPRESSED_SZ ];
      61             :   uchar                   bls_key_uncompressed[ FD_BLS_PUBKEY_UNCOMPRESSED_SZ ];
      62             :   fd_validator_location_t location;
      63             : 
      64             :   /* The fork's validity, only set for t-2 (zero otherwise). */
      65             :   uchar                   is_valid;
      66             : };
      67             : typedef struct fd_vote_stakes_ele fd_vote_stakes_ele_t;
      68             : 
      69             : FD_PROTOTYPES_BEGIN
      70             : 
      71             : ulong
      72             : fd_vote_stakes_align( void );
      73             : 
      74             : ulong
      75             : fd_vote_stakes_footprint( ulong max_live_slots,
      76             :                           ulong cache_cnt );
      77             : 
      78             : void *
      79             : fd_vote_stakes_new( void * mem,
      80             :                     int    disk_fd,
      81             :                     ulong  max_live_slots,
      82             :                     ulong  cache_cnt,
      83             :                     ulong  seed );
      84             : 
      85             : fd_vote_stakes_t *
      86             : fd_vote_stakes_join( void * mem,
      87             :                      int    disk_fd );
      88             : 
      89             : /* fd_vote_stakes_fork_epoch returns the epoch of the fork. */
      90             : 
      91             : ulong
      92             : fd_vote_stakes_fork_epoch( fd_vote_stakes_t const * vote_stakes,
      93             :                            ushort                   fork_id );
      94             : 
      95             : /* fd_vote_stakes_init initializes the vote stakes data structure for a
      96             :    given epoch and returns the root fork's id, in [0,max_live_slots). */
      97             : 
      98             : ushort
      99             : fd_vote_stakes_init( fd_vote_stakes_t * vote_stakes,
     100             :                      ulong              epoch );
     101             : 
     102             : /* fd_vote_stakes_reset resets the vote stakes data structure. */
     103             : 
     104             : void
     105             : fd_vote_stakes_reset( fd_vote_stakes_t * vote_stakes );
     106             : 
     107             : /* fd_vote_stakes_snap_insert_t_1 inserts a new vote account into the
     108             :    t-1 set.  This skips over any vote account validation and should
     109             :    only be used when loading in vote accounts from a snapshot. */
     110             : 
     111             : void
     112             : fd_vote_stakes_snap_insert_t_1( fd_vote_stakes_t *              vote_stakes,
     113             :                                 ushort                          fork_id,
     114             :                                 fd_pubkey_t const *             pubkey,
     115             :                                 fd_pubkey_t const *             node_account,
     116             :                                 ulong                           stake,
     117             :                                 ushort                          commission,
     118             :                                 uchar const                     bls_key[ static FD_BLS_PUBKEY_COMPRESSED_SZ ],
     119             :                                 ushort                          block_revenue_commission_bps,
     120             :                                 ulong                           pending_delegator_rewards,
     121             :                                 fd_pubkey_t const *             inflation_collector_opt,
     122             :                                 fd_pubkey_t const *             block_collector_opt,
     123             :                                 fd_validator_location_t const * location );
     124             : 
     125             : /* fd_vote_stakes_snap_insert_t_2 inserts a new vote account into the
     126             :    t-2 set.  This skips over any vote account validation and should
     127             :    only be used when loading in vote accounts from a snapshot. */
     128             : 
     129             : void
     130             : fd_vote_stakes_snap_insert_t_2( fd_vote_stakes_t *              vote_stakes,
     131             :                                 ushort                          fork_id,
     132             :                                 fd_pubkey_t const *             pubkey,
     133             :                                 fd_pubkey_t const *             node_account,
     134             :                                 ulong                           stake,
     135             :                                 ushort                          commission,
     136             :                                 uchar const                     bls_key[ static FD_BLS_PUBKEY_COMPRESSED_SZ ],
     137             :                                 ushort                          block_revenue_commission_bps,
     138             :                                 ulong                           pending_delegator_rewards,
     139             :                                 fd_pubkey_t const *             inflation_collector_opt,
     140             :                                 fd_pubkey_t const *             block_collector_opt,
     141             :                                 fd_validator_location_t const * location );
     142             : 
     143             : /* fd_vote_stakes_snap_insert_t_n inserts a new vote account into the
     144             :    t-n set, n in 3..5, and marks that set resident.  This skips over
     145             :    any vote account validation and should only be used when loading in
     146             :    vote accounts from a snapshot. */
     147             : 
     148             : void
     149             : fd_vote_stakes_snap_insert_t_n( fd_vote_stakes_t *              vote_stakes,
     150             :                                 ushort                          fork_id,
     151             :                                 ulong                           n,
     152             :                                 fd_pubkey_t const *             pubkey,
     153             :                                 fd_pubkey_t const *             node_account,
     154             :                                 ulong                           stake,
     155             :                                 ushort                          commission,
     156             :                                 uchar const                     bls_key[ static FD_BLS_PUBKEY_COMPRESSED_SZ ],
     157             :                                 ushort                          block_revenue_commission_bps,
     158             :                                 ulong                           pending_delegator_rewards,
     159             :                                 fd_pubkey_t const *             inflation_collector_opt,
     160             :                                 fd_pubkey_t const *             block_collector_opt,
     161             :                                 fd_validator_location_t const * location );
     162             : 
     163             : /* fd_vote_stakes_insert inserts a new vote account into the t-1 set.
     164             :    This can be called repeatedly after a boundary-crossing
     165             :    fd_vote_stakes_new_fork.  An account will only be inserted if it
     166             :    matches the semantics of the validator_admission_ticket feature.
     167             :    The top 2000 vote accounts by stake are inserted into the t-1 set. */
     168             : 
     169             : void
     170             : fd_vote_stakes_insert( fd_vote_stakes_t *              vote_stakes,
     171             :                        ushort                          fork_id,
     172             :                        fd_pubkey_t const *             pubkey,
     173             :                        fd_pubkey_t const *             node_account,
     174             :                        ulong                           stake,
     175             :                        ushort                          commission,
     176             :                        uchar const                     bls_key[ static FD_BLS_PUBKEY_COMPRESSED_SZ ],
     177             :                        ushort                          block_revenue_commission_bps,
     178             :                        ulong                           pending_delegator_rewards,
     179             :                        fd_pubkey_t const *             inflation_collector_opt,
     180             :                        fd_pubkey_t const *             block_collector_opt,
     181             :                        fd_validator_location_t const * location );
     182             : 
     183             : /* fd_vote_stakes_finalize assigns Alpenglow ranks to the set that
     184             :    iter_kind addresses for fork_id.  Accounts with invalid or infinity
     185             :    BLS keys or duplicate BLS/identity keys retain
     186             :    FD_VOTE_STAKES_ALPENGLOW_RANK_NULL but remain in the set.  This is a
     187             :    no-op if the set is not resident. */
     188             : 
     189             : void
     190             : fd_vote_stakes_finalize( fd_vote_stakes_t * vote_stakes,
     191             :                          ushort             fork_id,
     192             :                          int                iter_kind );
     193             : 
     194             : /* fd_vote_stakes_purge_fork removes a t-1 set.  This should be called
     195             :    when the banks are evicting a bank or during root advancement. */
     196             : 
     197             : void
     198             : fd_vote_stakes_purge_fork( fd_vote_stakes_t * vote_stakes,
     199             :                            ushort             fork_id );
     200             : 
     201             : /* fd_vote_stakes_new_fork creates a child of the given parent fork.
     202             :    Within an epoch, the child shares the parent's t-1 set and receives a
     203             :    copy of its t-2 validity.  At an epoch boundary, it rotates t-1 into
     204             :    t-2 and acquires a fresh t-1 set and t-2 validity. */
     205             : 
     206             : ushort
     207             : fd_vote_stakes_new_fork( fd_vote_stakes_t * vote_stakes,
     208             :                          ushort             parent_fork_id,
     209             :                          ulong              epoch );
     210             : 
     211             : /* fd_vote_stakes_update_state sets whether a t-2 vote account is valid
     212             :    for a given fork id.  It is a no-op if the pubkey corresponds to an
     213             :    account not in the t-2 set. */
     214             : 
     215             : void
     216             : fd_vote_stakes_update_state( fd_vote_stakes_t *  vote_stakes,
     217             :                              ushort              fork_id,
     218             :                              fd_pubkey_t const * pubkey,
     219             :                              int                 is_valid );
     220             : 
     221             : void
     222             : fd_vote_stakes_refresh( fd_vote_stakes_t * vote_stakes,
     223             :                         ushort             fork_id,
     224             :                         fd_accdb_t *        accdb,
     225             :                         fd_accdb_fork_id_t  accdb_fork_id );
     226             : 
     227             : /* fd_vote_stakes_query_t_{1,2,3} look up pubkey in the fork's t-1,
     228             :    t-2 or t-3 set and, if ele_out_opt is non-NULL, copy the entry to
     229             :    it.  Only query_t_2 sets the vote state fields.  Returns 1 if the
     230             :    account is in the set, 0 otherwise. */
     231             : 
     232             : int
     233             : fd_vote_stakes_query_t_1( fd_vote_stakes_t *     vote_stakes,
     234             :                           ushort                 fork_id,
     235             :                           fd_pubkey_t const *    pubkey,
     236             :                           fd_vote_stakes_ele_t * ele_out_opt );
     237             : 
     238             : int
     239             : fd_vote_stakes_query_t_2( fd_vote_stakes_t const * vote_stakes,
     240             :                           ushort                   fork_id,
     241             :                           fd_pubkey_t const *      pubkey,
     242             :                           fd_vote_stakes_ele_t *   ele_out_opt );
     243             : 
     244             : int
     245             : fd_vote_stakes_query_t_3( fd_vote_stakes_t const * vote_stakes,
     246             :                           ushort                   fork_id,
     247             :                           fd_pubkey_t const *      pubkey,
     248             :                           fd_vote_stakes_ele_t *   ele_out_opt );
     249             : 
     250             : /* fd_vote_stakes_cnt_t_{1,2} returns the number of vote accounts in the
     251             :    t-1 and t-2 sets respectively. */
     252             : 
     253             : ulong
     254             : fd_vote_stakes_cnt_t_1( fd_vote_stakes_t * vote_stakes,
     255             :                         ushort             fork_id );
     256             : 
     257             : ulong
     258             : fd_vote_stakes_cnt_t_2( fd_vote_stakes_t const * vote_stakes,
     259             :                         ushort                   fork_id );
     260             : 
     261             : /* fd_vote_stakes_total_stake returns the total stake of the epoch
     262             :    stakes set for epoch.
     263             :    epoch must be one of the t-2 through t-5 sets; returns 0 if that
     264             :    epoch's set is not resident. */
     265             : 
     266             : ulong
     267             : fd_vote_stakes_total_stake( fd_vote_stakes_t const * vote_stakes,
     268             :                             ulong                    epoch );
     269             : 
     270             : /* The iterator will NOT skip over invalid vote accounts
     271             :    intentionally.  The reason being is that invalid vote accounts are
     272             :    still considered for stake and leader calculations: the caller is
     273             :    expected to handle the state of each account correctly. */
     274             : 
     275             : #define FD_VOTE_STAKES_ITER_FOOTPRINT     (16UL)
     276             : #define FD_VOTE_STAKES_ITER_ALIGN         (8UL)
     277       18837 : #define FD_VOTE_STAKES_ITER_T_1           (1)
     278      309027 : #define FD_VOTE_STAKES_ITER_T_2           (2)
     279        3090 : #define FD_VOTE_STAKES_ITER_T_3           (3)
     280           9 : #define FD_VOTE_STAKES_ITER_T_4           (4)
     281          21 : #define FD_VOTE_STAKES_ITER_T_5           (5)
     282             : 
     283             : struct vacc_map_iter;
     284             : typedef struct vacc_map_iter fd_vote_stakes_iter_t;
     285             : 
     286             : /* The iterator walks the fork's set selected by iter_kind.  The vote
     287             :    state fields of the element are only set for T_2. */
     288             : 
     289             : fd_vote_stakes_iter_t *
     290             : fd_vote_stakes_iter_init( fd_vote_stakes_t * vote_stakes,
     291             :                           ushort             fork_id,
     292             :                           int                iter_kind,
     293             :                           uchar              iter_mem[ static FD_VOTE_STAKES_ITER_FOOTPRINT ] );
     294             : 
     295             : int
     296             : fd_vote_stakes_iter_done( fd_vote_stakes_t *      vote_stakes,
     297             :                           ushort                  fork_id,
     298             :                           int                     iter_kind,
     299             :                           fd_vote_stakes_iter_t * iter );
     300             : 
     301             : void
     302             : fd_vote_stakes_iter_next( fd_vote_stakes_t *      vote_stakes,
     303             :                           ushort                  fork_id,
     304             :                           int                     iter_kind,
     305             :                           fd_vote_stakes_iter_t * iter );
     306             : 
     307             : void
     308             : fd_vote_stakes_iter_ele( fd_vote_stakes_t *      vote_stakes,
     309             :                          ushort                  fork_id,
     310             :                          int                     iter_kind,
     311             :                          fd_vote_stakes_iter_t * iter,
     312             :                          fd_vote_stakes_ele_t *  ele_out );
     313             : 
     314             : FD_PROTOTYPES_END
     315             : 
     316             : #endif /* HEADER_fd_src_flamenco_stakes_fd_vote_stakes_h */

Generated by: LCOV version 1.14