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 15 33.3 %
Date: 2026-11-12 04:25:03 Functions: 1 52 1.9 %

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

Generated by: LCOV version 1.14