LCOV - code coverage report
Current view: top level - choreo/voter - fd_voter.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 24 0.0 %
Date: 2025-08-05 05:04:49 Functions: 0 39 0.0 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_choreo_voter_fd_voter_h
       2             : #define HEADER_fd_src_choreo_voter_fd_voter_h
       3             : 
       4             : #include "../fd_choreo_base.h"
       5             : #include "../../funk/fd_funk_rec.h"
       6             : 
       7             : /* FD_VOTER_USE_HANDHOLDING:  Define this to non-zero at compile time
       8             :    to turn on additional runtime checks and logging. */
       9             : 
      10             : #ifndef FD_VOTER_USE_HANDHOLDING
      11             : #define FD_VOTER_USE_HANDHOLDING 1
      12             : #endif
      13             : 
      14             : #define FD_VOTER_STATE_V0_23_5  (0)
      15             : #define FD_VOTER_STATE_V1_14_11 (1)
      16             : #define FD_VOTER_STATE_CURRENT  (2)
      17             : FD_STATIC_ASSERT(FD_VOTER_STATE_V0_23_5 ==fd_vote_state_versioned_enum_v0_23_5,  FD_VOTER_STATE_V0_23_5 );
      18             : FD_STATIC_ASSERT(FD_VOTER_STATE_V1_14_11==fd_vote_state_versioned_enum_v1_14_11, FD_VOTER_STATE_V1_14_11);
      19             : FD_STATIC_ASSERT(FD_VOTER_STATE_CURRENT ==fd_vote_state_versioned_enum_current,  FD_VOTER_STATE_CURRENT );
      20             : 
      21             : /* Useful to keep both the block_id and slot in the vote record,
      22             :    for handling equivocation cases. Potentially re-evaluate removing the
      23             :    slot altogether.*/
      24             : struct fd_vote_record {
      25             :   ulong     slot;
      26             :   fd_hash_t hash;
      27             : };
      28             : typedef struct fd_vote_record fd_vote_record_t;
      29             : 
      30             : /* A fd_voter_t describes a voter.  The voter is generic to the context
      31             :    in which it is used, eg. it might be a voter in a slot-level context
      32             :    in which its stake value may be different from the same voter in an
      33             :    epoch-level context which in turn is different from the same voter in
      34             :    the prior epoch's context.
      35             : 
      36             :    The voter is used by various choreo APIs including fd_epoch which
      37             :    tracks all the voters in a given epoch, fd_forks which performs
      38             :    choreo-related fork updates after replaying a slot, and ghost and
      39             :    tower which both require bookkeeping the epoch voters. */
      40             : 
      41             : struct fd_voter {
      42             :   union {
      43             :     fd_pubkey_t       key; /* vote account address */
      44             :     fd_funk_rec_key_t rec; /* funk record key to query above */
      45             :   };
      46             :   uint hash; /* reserved for fd_map_dynamic.c */
      47             : 
      48             :   /* IMPORTANT! The values below should only be modified by fd_epoch and
      49             :      fd_ghost. */
      50             : 
      51             :   ulong stake;       /* voter's stake */
      52             :   fd_vote_record_t replay_vote; /* cached read of last tower vote via replay */
      53             :   fd_vote_record_t gossip_vote; /* cached read of last tower vote via gossip */
      54             :   fd_vote_record_t rooted_vote; /* cached read of last tower root via replay */
      55             : };
      56             : typedef struct fd_voter fd_voter_t;
      57             : 
      58             : /* fd_voter_{vote_old, vote, meta, meta_old, state} are struct
      59             :    representations of the bincode-serialized layout of a voter's state
      60             :    stored in a vote account. These structs are used to support zero-copy
      61             :    reads of the vote account.
      62             : 
      63             :    The voter's state is versioned, and the serialized formats differ
      64             :    depending on this.  Currently, the only version that differs from the
      65             :    others that is relevant here is v0.23.5.  Thus v0.23.5 has its own
      66             :    dedicated struct definition with a different set of fields that
      67             :    precede the votes than the other versions.  Furthermore, v0.23.5
      68             :    contains votes of type `fd_vote_lockout_t` vs. the other versions
      69             :    which are of type `fd_landed_vote_t`.  The only difference between
      70             :    `fd_vote_lockout_t` and `fd_landed_vote_t` is there is an additional
      71             :    uchar field `latency`, so that is we include an offset of 0 or 1
      72             :    depending on which vote state type it is.
      73             : 
      74             :    The layout begins with a set of fields providing important metadata
      75             :    about the voter.  Immediately following these fields is the tower
      76             :    itself. The tower layout begins with the number of votes currently in
      77             :    the tower ie. `cnt`.  Then the votes themselves follow. The format of
      78             :    the votes varies depending on the version.  Finally the layout
      79             :    concludes with the tower's root slot.
      80             : 
      81             :    --------
      82             :    metadata <- sizeof(fd_voter_meta_t) or sizeof(fd_voter_meta_old_t)
      83             :    --------
      84             :    votes    <- {sizeof(vote) or sizeof(vote_old)} * cnt
      85             :    --------
      86             :    root     <- 5 or 1 byte(s). bincode-serialized Option<u64>
      87             :    --------
      88             : */
      89             : 
      90             : struct __attribute__((packed)) fd_voter_vote_old {
      91             :   ulong slot;
      92             :   uint  conf;
      93             : };
      94             : typedef struct fd_voter_vote_old fd_voter_vote_old_t;
      95             : 
      96             : struct __attribute__((packed)) fd_voter_vote {
      97             :   uchar latency;
      98             :   ulong slot;
      99             :   uint  conf;
     100             : };
     101             : typedef struct fd_voter_vote fd_voter_vote_t;
     102             : 
     103             : struct __attribute__((packed)) fd_voter_meta_old {
     104             :   fd_pubkey_t node_pubkey;
     105             :   fd_pubkey_t authorized_voter;
     106             :   ulong       authorized_voter_epoch;
     107             :   uchar       prior_voters[ (32*56+sizeof(ulong)) /* serialized bincode sz */ ];
     108             :   fd_pubkey_t authorized_withdrawer;
     109             :   uchar       commission;
     110             :   ulong       cnt;
     111             : };
     112             : typedef struct fd_voter_meta_old fd_voter_meta_old_t;
     113             : 
     114             : struct __attribute__((packed)) fd_voter_meta {
     115             :   fd_pubkey_t node_pubkey;
     116             :   fd_pubkey_t authorized_withdrawer;
     117             :   uchar       commission;
     118             :   ulong       cnt;
     119             : };
     120             : typedef struct fd_voter_meta fd_voter_meta_t;
     121             : 
     122             : struct __attribute__((packed)) fd_voter_state {
     123             :   uint discriminant;
     124             :   union {
     125             :     struct __attribute__((packed)) {
     126             :       fd_voter_meta_old_t meta;
     127             :       fd_voter_vote_old_t votes[31];
     128             :     } v0_23_5;
     129             : 
     130             :     struct __attribute__((packed)) {
     131             :       fd_voter_meta_t     meta;
     132             :       fd_voter_vote_old_t votes[31];
     133             :     } v1_14_11;
     134             : 
     135             :     struct __attribute__((packed)) {
     136             :       fd_voter_meta_t meta;
     137             :       fd_voter_vote_t votes[31];
     138             :     };
     139             : 
     140             :     /* The voter's root (a bincode-serialized Option<u64>) follows
     141             :        votes. Because the preceding votes are variable-length in
     142             :        serialized form, we cannot encode the root directly inside the
     143             :        struct. */
     144             :   };
     145             : };
     146             : typedef struct fd_voter_state fd_voter_state_t;
     147             : 
     148             : 
     149             : /* fd_voter_state queries funk for the record in the provided `txn` and
     150             :    `key`.  Returns a pointer to the start of the voter's state.  Assumes
     151             :    `key` is a vote account address and the record is a voter's state
     152             :    (fd_voter_state_t).  U.B. if `key` does not point to a valid vote
     153             :    account.
     154             : 
     155             :    It will update the given Funk query with the version at the point of
     156             :    querying. fd_funk_rec_query_test must be called after usage to check
     157             :    that the record has not been modified. */
     158             : 
     159             : fd_voter_state_t const *
     160             : fd_voter_state( fd_funk_t * funk, fd_funk_rec_t const * rec );
     161             : 
     162             : /* fd_voter_state_cnt returns the number of votes in the voter's tower.
     163             :    Assumes `state` is a valid fd_voter_state_t. */
     164             : 
     165             : FD_FN_PURE static inline ulong
     166           0 : fd_voter_state_cnt( fd_voter_state_t const * state ) {
     167           0 :   if( FD_UNLIKELY( state->discriminant == FD_VOTER_STATE_V0_23_5 ) )  return state->v0_23_5.meta.cnt;
     168           0 :   if( FD_UNLIKELY( state->discriminant == FD_VOTER_STATE_V1_14_11 ) ) return state->v1_14_11.meta.cnt;
     169           0 :   return state->meta.cnt;
     170           0 : }
     171             : 
     172             : /* fd_voter_state_vote returns the voter's most recent vote (ie. the
     173             :    last vote of the tower in the voter's state).  Assumes `state` is a
     174             :    valid fd_voter_state_t. */
     175             : 
     176             : FD_FN_PURE static inline ulong
     177           0 : fd_voter_state_vote( fd_voter_state_t const * state ) {
     178           0 :   ulong cnt = fd_voter_state_cnt( state );
     179           0 :   if( FD_UNLIKELY( !cnt ) ) return FD_SLOT_NULL;
     180             : 
     181           0 :   if( FD_UNLIKELY( state->discriminant == FD_VOTER_STATE_V0_23_5 ) )  return state->v0_23_5.votes[cnt - 1].slot;
     182           0 :   if( FD_UNLIKELY( state->discriminant == FD_VOTER_STATE_V1_14_11 ) ) return state->v1_14_11.votes[cnt - 1].slot;
     183           0 :   return state->votes[cnt - 1].slot;
     184           0 : }
     185             : 
     186             : /* fd_voter_state_root returns the voter's tower root.  Assumes `state`
     187             :    is a valid fd_voter_state_t. */
     188             : 
     189             : static inline ulong
     190           0 : fd_voter_state_root( fd_voter_state_t const * state ) {
     191           0 :   ulong cnt = fd_voter_state_cnt( state );
     192           0 :   if( FD_UNLIKELY( !cnt ) ) return FD_SLOT_NULL;
     193             : 
     194           0 :   uchar * root = NULL;
     195           0 :   if( FD_UNLIKELY( state->discriminant == FD_VOTER_STATE_V0_23_5 ) )       root = (uchar *)&state->v0_23_5.votes[cnt];
     196           0 :   else if( FD_UNLIKELY( state->discriminant == FD_VOTER_STATE_V1_14_11 ) ) root = (uchar *)&state->v1_14_11.votes[cnt];
     197           0 :   else                                                                     root = (uchar *)&state->votes[cnt];
     198             : 
     199           0 :   #if FD_VOTER_USE_HANDHOLDING
     200           0 :   FD_TEST( root );
     201           0 :   #endif
     202             : 
     203           0 :   return *(uchar *)root ? *(ulong *)(root+sizeof(uchar)) /* Some(root) */ : FD_SLOT_NULL /* None */;
     204           0 : }
     205             : 
     206             : #endif /* HEADER_fd_src_choreo_voter_fd_voter_h */

Generated by: LCOV version 1.14