LCOV - code coverage report
Current view: top level - flamenco/leaders - fd_multi_epoch_leaders.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 5 14 35.7 %
Date: 2026-03-29 06:20:31 Functions: 1 40 2.5 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_leaders_fd_multi_epoch_leaders_h
       2             : #define HEADER_fd_src_flamenco_leaders_fd_multi_epoch_leaders_h
       3             : 
       4             : #include "fd_leaders.h"
       5             : 
       6             : /* fd_multi_epoch_leaders is a wrapper around multiple fd_epoch_leaders
       7             :    objects.  It simplifies tracking leader schedules for multiple epochs,
       8             :    and querying to find the leader for a given slot.  While maintaining
       9             :    the leader schedule for the current epoch i, you can also prepare the
      10             :    schedule for epoch i+1 and send to the next epoch's leader as you
      11             :    approach the boundary. */
      12             : 
      13             : typedef uchar __attribute__((aligned(FD_EPOCH_LEADERS_ALIGN)))
      14             :     _lsched_t[FD_EPOCH_LEADERS_FOOTPRINT(MAX_COMPRESSED_STAKE_WEIGHTS, MAX_SLOTS_PER_EPOCH)];
      15             : 
      16         192 : #define MULTI_EPOCH_LEADERS_EPOCH_CNT (2UL)
      17             : FD_STATIC_ASSERT(MULTI_EPOCH_LEADERS_EPOCH_CNT == 2UL, "This implementation depends on epoch_cnt==2");
      18             : 
      19             : struct fd_multi_epoch_leaders_priv {
      20             :   fd_epoch_leaders_t * lsched       [ MULTI_EPOCH_LEADERS_EPOCH_CNT ];
      21             :   fd_vote_stake_weight_t vote_stake_weight [ MAX_COMPRESSED_STAKE_WEIGHTS ];
      22             : 
      23             :   /* has that epoch's mem experienced a stake_msg_fini? */
      24             :   int                  init_done    [ MULTI_EPOCH_LEADERS_EPOCH_CNT ];
      25             :   struct {
      26             :     ulong epoch;
      27             :     ulong start_slot;
      28             :     ulong slot_cnt;
      29             :     ulong staked_cnt;
      30             :   } scratch[1];
      31             : 
      32             :   _lsched_t _lsched[MULTI_EPOCH_LEADERS_EPOCH_CNT];
      33             : };
      34             : typedef struct fd_multi_epoch_leaders_priv fd_multi_epoch_leaders_priv_t;
      35             : 
      36             : typedef fd_multi_epoch_leaders_priv_t fd_multi_epoch_leaders_t;
      37             : 
      38             : 
      39             : FD_PROTOTYPES_BEGIN
      40             : 
      41             : /* ********    OBJECT LIFECYCLE FUNCTIONS    ******** */
      42             : 
      43             : /* fd_epoch_leaders_{align,footprint} describe the required footprint
      44             :    and alignment of the leader schedule object. They have compile friendly
      45             :    versions for static allocation of underlying mem */
      46             : 
      47             : #define FD_MULTI_EPOCH_LEADERS_ALIGN \
      48          24 :   FD_ULONG_MAX( FD_EPOCH_LEADERS_ALIGN, alignof(fd_multi_epoch_leaders_t) )
      49             : 
      50             : #define FD_MULTI_EPOCH_LEADERS_FOOTPRINT \
      51             :   sizeof(fd_multi_epoch_leaders_t)
      52             : 
      53             : FD_FN_CONST static inline ulong
      54          24 : fd_multi_epoch_leaders_align( void ) {
      55          24 :   return FD_MULTI_EPOCH_LEADERS_ALIGN;
      56          24 : }
      57             : 
      58             : FD_FN_CONST static inline ulong
      59           0 : fd_multi_epoch_leaders_footprint( void ) {
      60           0 :   return FD_MULTI_EPOCH_LEADERS_FOOTPRINT;
      61           0 : }
      62             : 
      63             : /* fd_multi_epoch_leaders_new formats a memory region for use as a multi-epoch
      64             :    leader schedule object.  shmem points to the first byte of a memory
      65             :    region with matching alignment and footprint requirements. Returns NULL
      66             :    if shmem is NULL or misaligned. Else returns pointer to formatted memory.
      67             :    Does not join. */
      68             : 
      69             : void *
      70             : fd_multi_epoch_leaders_new( void  * shmem );
      71             : 
      72             : /* fd_multi_epoch_leaders_join joins the caller to the leader schedule object.
      73             :    fd_multi_epoch_leaders_leave undoes an existing join. */
      74             : 
      75             : fd_multi_epoch_leaders_t *
      76             : fd_multi_epoch_leaders_join( void * shleaders );
      77             : 
      78             : void *
      79             : fd_multi_epoch_leaders_leave( fd_multi_epoch_leaders_t * mleaders );
      80             : 
      81             : /* fd_multi_epoch_leaders_delete unformats a memory region and returns owner-
      82             :    ship back to the caller. */
      83             : 
      84             : void *
      85             : fd_multi_epoch_leaders_delete( void * shleaders );
      86             : 
      87             : /* ********    LEADER INFO GETTER FUNCTIONS    ******** */
      88             : 
      89             : /* fd_multi_epoch_leaders_get_stake_{weights,cnt} returns a pointer to
      90             :    the stake weights and count for the latest epoch. Returns null if never
      91             :    initialized. The pointer lifetime is until the next leave on mleaders.
      92             :    However, cnt is the valid length for stake_weights only until the next
      93             :    call to stake_msg_init. */
      94             : FD_FN_PURE static inline fd_vote_stake_weight_t const *
      95           0 : fd_multi_epoch_leaders_get_stake_weights( fd_multi_epoch_leaders_t const * mleaders ) {
      96           0 :    return fd_ptr_if( mleaders->init_done[0] | mleaders->init_done[1], (fd_vote_stake_weight_t const *)mleaders->vote_stake_weight, NULL );
      97           0 : }
      98             : FD_FN_PURE static inline ulong
      99           0 : fd_multi_epoch_leaders_get_stake_cnt( fd_multi_epoch_leaders_t const * mleaders ) {
     100           0 :    return mleaders->scratch->staked_cnt;
     101           0 : }
     102             : 
     103             : /* fd_multi_epoch_leaders_get_leader_for_slot returns a pointer to the selected
     104             :    public key given a slot.  Returns NULL if slot is not in epochs tracked
     105             :    by multi-epoch leader object. If the leader for slot is part of the
     106             :    excluded_stake for that epoch, instead of returning the correct value
     107             :    (which is not known), returns a pointer to a pubkey with value
     108             :    FD_INDETERMINATE_LEADER. */
     109             : 
     110             : FD_FN_PURE fd_pubkey_t const *
     111             : fd_multi_epoch_leaders_get_leader_for_slot( fd_multi_epoch_leaders_t const * mleaders,
     112             :                                             ulong                            slot );
     113             : 
     114             : /* fd_multi_epoch_leaders_get_lsched_for_{epoch,slot} return the leader
     115             :    schedule for epoch or epoch containing slot, respectively.  Returns
     116             :    NULL if not tracked by mleaders. */
     117             : 
     118             : FD_FN_PURE fd_epoch_leaders_t const *
     119             : fd_multi_epoch_leaders_get_lsched_for_epoch( fd_multi_epoch_leaders_t const * mleaders,
     120             :                                              ulong                            epoch );
     121             : FD_FN_PURE fd_epoch_leaders_t const *
     122             : fd_multi_epoch_leaders_get_lsched_for_slot( fd_multi_epoch_leaders_t const * mleaders,
     123             :                                              ulong                           slot   );
     124             : 
     125             : /* fd_multi_epoch_leaders_get_sorted_lscheds returns up to two lscheds,
     126             :    sorted in increasing epoch order. If we only have data for one epoch,
     127             :    the first element will be the corresponding lsched. If no lsched data,
     128             :    both will be null. Lifetime of returned pointers is until next call to
     129             :    fd_multi_epoch_leaders_stake_msg_fini. */
     130             : typedef struct {
     131             :   fd_epoch_leaders_t const * lscheds[2];
     132             : } fd_multi_epoch_leaders_lsched_sorted_t;
     133             : 
     134             : FD_FN_PURE fd_multi_epoch_leaders_lsched_sorted_t
     135             : fd_multi_epoch_leaders_get_sorted_lscheds( fd_multi_epoch_leaders_t const * mleaders );
     136             : 
     137             : 
     138             : /* fd_multi_epoch_leaders_get_next_slot returns the first slot on or after
     139             :    start_slot that 'leader' will be leader. If it can't find one, returns ULONG_MAX.
     140             : 
     141             :    Failures cases include:
     142             :       - mleaders does not track the epoch containing start_slot
     143             :         - It was either never initialized with that epoch information, or
     144             :         - It was overwritten by another epoch with the same parity
     145             :       - leader_q does not have a leader slot in the epochs tracked
     146             :       - leader_q was part of the excluded_stake for that epoch, and the lsched
     147             :         returns FD_INDETERMINATE_LEADER as the leader for leader_q's slots.
     148             : */
     149             : 
     150             : FD_FN_PURE ulong
     151             : fd_multi_epoch_leaders_get_next_slot( fd_multi_epoch_leaders_t const * mleaders,
     152             :                                       ulong                            start_slot,
     153             :                                       fd_pubkey_t const *              leader_q );
     154             : 
     155             : /* ********    STAKE INFO UPDATE METHODS    ******** */
     156             : 
     157             : /* fd_stake_ci_stake_msg_{init, fini} are used to handle messages
     158             :    containing stake weight updates from the Rust side of the splice,.
     159             :    Since these messages arrive on a dcache and can get overrun, both
     160             :    expose a init/fini model. Calling init multiple times without calling
     161             :    fini will not leak any resources.
     162             : 
     163             :    msg should be a pointer to the first byte of the dcache entry
     164             :    containing the stakes update.  msg will be accessed
     165             :    msg->weights[i] for i in [0, msg->staked_cnt).  msg->weights
     166             :    must contain at least one staked pubkey, and the pubkeys must be
     167             :    sorted in the usual way (by stake descending, ties broken by pubkey
     168             :    ascending). multi_epoch_leaders will only use the staked node.
     169             : 
     170             :    init does not maintain a read interest in msg after returning. */
     171             : 
     172             : void
     173             : fd_multi_epoch_leaders_stake_msg_init( fd_multi_epoch_leaders_t    * mleaders,
     174             :                                        fd_stake_weight_msg_t const * msg );
     175             : 
     176             : void
     177             : fd_multi_epoch_leaders_stake_msg_fini( fd_multi_epoch_leaders_t * mleaders );
     178             : 
     179             : 
     180             : /* fd_multi_epoch_leaders_epoch_msg_{init, fini} are the Firedancer
     181             :    equivalents to the Frankendancer fd_multi_epoch_leaders_stake_msg_{init, fini}.
     182             :    They take a different input message structure (fd_epoch_info_msg_t
     183             :    vs fd_stake_weight_msg_t). */
     184             : 
     185             : void
     186             : fd_multi_epoch_leaders_epoch_msg_init( fd_multi_epoch_leaders_t   * mleaders,
     187             :                                        fd_epoch_info_msg_t const  * msg );
     188             : 
     189             : void
     190             : fd_multi_epoch_leaders_epoch_msg_fini( fd_multi_epoch_leaders_t * mleaders );
     191             : 
     192             : FD_PROTOTYPES_END
     193             : 
     194             : #endif /* HEADER_fd_src_flamenco_leaders_fd_multi_epoch_leaders_h */

Generated by: LCOV version 1.14