LCOV - code coverage report
Current view: top level - flamenco/leaders - fd_leaders_base.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 18 31 58.1 %
Date: 2026-09-17 04:28:31 Functions: 10 918 1.1 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_leaders_fd_leaders_base_h
       2             : #define HEADER_fd_src_flamenco_leaders_fd_leaders_base_h
       3             : 
       4             : #include "../stakes/fd_stake_weight.h"
       5             : #include "../runtime/sysvar/fd_sysvar_base.h"
       6             : #include "../features/fd_features.h"
       7             : 
       8      592023 : #define MAX_SHRED_DESTS     40200UL /* 200 * 201 - 1 (exclude self) */
       9          30 : #define MAX_SLOTS_PER_EPOCH 432000UL
      10          30 : #define MAX_STAKE_WEIGHTS   2000UL  /* validator_admission_ticket limit */
      11             : 
      12             : /* Follows message structure in fd_stake_ci_stake_msg_init.
      13             :    Frankendancer only */
      14             : struct fd_stake_weight_msg_t {
      15             :   ulong             epoch;             /* Epoch for which the stake weights are valid */
      16             :   ulong             staked_vote_cnt;   /* Number of staked nodes */
      17             :   ulong             staked_id_cnt;     /* Number of staked nodes */
      18             :   ulong             start_slot;        /* Start slot of the epoch */
      19             :   ulong             slot_cnt;          /* Number of slots in the epoch */
      20             :   ulong             ns_per_slot;       /* Slot time duration */
      21             : };
      22             : typedef struct fd_stake_weight_msg_t fd_stake_weight_msg_t;
      23             : 
      24         603 : #define FD_STAKE_CI_STAKE_MSG_HEADER_SZ (sizeof(fd_stake_weight_msg_t))
      25         267 : #define FD_STAKE_CI_STAKE_MSG_RECORD_SZ (sizeof(fd_vote_stake_weight_t))
      26           0 : #define FD_STAKE_CI_ID_WEIGHT_RECORD_SZ (sizeof(fd_stake_weight_t))
      27           0 : #define FD_STAKE_CI_STAKE_MSG_SZ (FD_STAKE_CI_STAKE_MSG_HEADER_SZ + MAX_STAKE_WEIGHTS * (FD_STAKE_CI_STAKE_MSG_RECORD_SZ + FD_STAKE_CI_ID_WEIGHT_RECORD_SZ))
      28             : 
      29           0 : #define FD_STAKE_OUT_MTU FD_STAKE_CI_STAKE_MSG_SZ
      30             : 
      31             : static inline ulong fd_stake_weight_msg_sz( ulong staked_vote_cnt,
      32           0 :                                             ulong staked_id_cnt ) {
      33           0 :   return FD_STAKE_CI_STAKE_MSG_HEADER_SZ + staked_vote_cnt * FD_STAKE_CI_STAKE_MSG_RECORD_SZ + staked_id_cnt * FD_STAKE_CI_ID_WEIGHT_RECORD_SZ;
      34           0 : }
      35             : 
      36             : static inline fd_vote_stake_weight_t *
      37         336 : fd_stake_weight_msg_stake_weights( fd_stake_weight_msg_t const * stake_weight_msg ) {
      38         336 :   return (fd_vote_stake_weight_t *)fd_type_pun( (uchar *)stake_weight_msg + FD_STAKE_CI_STAKE_MSG_HEADER_SZ );
      39         336 : }
      40             : 
      41             : static inline fd_stake_weight_t *
      42         267 : fd_stake_weight_msg_id_weights( fd_stake_weight_msg_t const * stake_weight_msg ) {
      43         267 :   return (fd_stake_weight_t *)fd_type_pun( (uchar *)stake_weight_msg + FD_STAKE_CI_STAKE_MSG_HEADER_SZ + stake_weight_msg->staked_vote_cnt * FD_STAKE_CI_STAKE_MSG_RECORD_SZ );
      44         267 : }
      45             : 
      46             : /* Firedancer only */
      47             : struct fd_epoch_info_msg_t {
      48             :   ulong               epoch;             /* Epoch for which the info is valid */
      49             :   ulong               staked_vote_cnt;   /* Number of staked nodes */
      50             :   ulong               staked_id_cnt;     /* Number of staked nodes */
      51             :   ulong               start_slot;        /* Start slot of the epoch */
      52             :   ulong               slot_cnt;          /* Number of slots in the epoch */
      53             :   ulong               ns_per_slot;       /* Slot time duration */
      54             :   fd_epoch_schedule_t epoch_schedule;    /* Epoch schedule */
      55             :   fd_features_t       features;          /* Feature activation slots */
      56             : };
      57             : typedef struct fd_epoch_info_msg_t fd_epoch_info_msg_t;
      58             : 
      59         348 : #define FD_EPOCH_INFO_MSG_HEADER_SZ (sizeof(fd_epoch_info_msg_t))
      60           0 : #define FD_EPOCH_INFO_MAX_MSG_SZ    (FD_EPOCH_INFO_MSG_HEADER_SZ + MAX_STAKE_WEIGHTS * (sizeof(fd_vote_stake_weight_t) + sizeof(fd_stake_weight_t)))
      61           0 : #define FD_EPOCH_OUT_MTU            FD_EPOCH_INFO_MAX_MSG_SZ
      62             : 
      63             : static inline ulong fd_epoch_info_msg_sz( ulong vote_cnt,
      64           0 :                                           ulong id_weight_cnt ) {
      65           0 :   return FD_EPOCH_INFO_MSG_HEADER_SZ +
      66           0 :          (vote_cnt * sizeof(fd_vote_stake_weight_t)) +
      67           0 :          (id_weight_cnt * sizeof(fd_stake_weight_t));
      68           0 : }
      69             : 
      70             : static inline fd_vote_stake_weight_t *
      71         174 : fd_epoch_info_msg_stake_weights( fd_epoch_info_msg_t const * epoch_info_msg ) {
      72         174 :   return (fd_vote_stake_weight_t *)fd_type_pun( (uchar *)epoch_info_msg + FD_EPOCH_INFO_MSG_HEADER_SZ );
      73         174 : }
      74             : 
      75             : static inline fd_stake_weight_t *
      76         174 : fd_epoch_info_msg_id_weights( fd_epoch_info_msg_t const * epoch_info_msg ) {
      77         174 :   return (fd_stake_weight_t *)fd_type_pun( (uchar *)epoch_info_msg + FD_EPOCH_INFO_MSG_HEADER_SZ + epoch_info_msg->staked_vote_cnt * sizeof(fd_vote_stake_weight_t) );
      78         174 : }
      79             : 
      80             : /* compute_id_weights_from_vote_weights() translates vote-based
      81             :    stake weights into (older) identity-based stake weights.
      82             : 
      83             :    Before SIMD-0180, the leader schedule was generated starting from
      84             :    a list [(id, stake)] where `id` is the validator identity and
      85             :    `stake` its aggregated stake, and the same list was used to build
      86             :    the Turbine tree.
      87             : 
      88             :    After SIMD-0180, the leader schedule is generated by vote
      89             :    accounts, i.e. starting from a list [(vote, id, stake)] instead.
      90             :    This makes it easier to send rewards to the expected vote account.
      91             :    Notably, turbine tree doesn't change with SIMD-0180, so the old
      92             :    list [(id, stake)] is still necessary.
      93             : 
      94             :    Realistically, there should be a 1:1 relationship between id and
      95             :    vote, but unfortunately the on chain state allows for a 1:N
      96             :    relationship (1 id could be associated to N vote accounts).
      97             :    At the time of writing, testnet has one such example.
      98             :    id: DtSguGSHVrXdqZU1mKWKocsAjrXMhaC7YJic5xxN1Uom
      99             :    votes:
     100             :    - https://solscan.io/account/BbtyLT1ntMFbbXtsJRCZnYjpe7d7TUtyZeGKzod3eNsN?cluster=testnet
     101             :    - https://solscan.io/account/FFr8Gyjy3Wjeqv6oD4RjbwqD1mVfKycAFxQdASYAfR75?cluster=testnet
     102             : 
     103             :    Even when there is a 1:1 relationship, the order of the 2 lists
     104             :    can be different because validators with the same stake could
     105             :    be ordered differently by vote vs id.
     106             : 
     107             :    Last consideration, this operation is done only once per epoch, twice
     108             :    at startup.
     109             : 
     110             :    The current implementation uses sort in place to avoid extra memory
     111             :    for a map or tree. */
     112             :    ulong
     113             :    compute_id_weights_from_vote_weights( fd_stake_weight_t *            stake_weight,
     114             :                                          fd_vote_stake_weight_t const * vote_stake_weight,
     115             :                                          ulong                          staked_cnt );
     116             : 
     117             : #endif /* HEADER_fd_src_flamenco_leaders_fd_leaders_base_h */

Generated by: LCOV version 1.14