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: 2025-07-01 05:00:49 Functions: 1 32 3.1 %

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

Generated by: LCOV version 1.14