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

Generated by: LCOV version 1.14