LCOV - code coverage report
Current view: top level - flamenco/stakes - fd_vote_stakes.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 442 484 91.3 %
Date: 2026-08-13 04:56:22 Functions: 40 40 100.0 %

          Line data    Source code
       1             : #include "fd_vote_stakes.h"
       2             : #include "../accdb/fd_accdb.h"
       3             : #include "../fd_flamenco_base.h"
       4             : #include "../runtime/fd_runtime_const.h"
       5             : #include "../runtime/program/vote/fd_vote_state_versioned.h"
       6             : #include "../runtime/program/vote/fd_vote_codec.h"
       7             : #include "../../util/bits/fd_bits.h"
       8             : #include "../../util/log/fd_log.h"
       9             : 
      10         117 : #define FD_VOTE_STAKES_MAGIC          (0xF17EDA2CE7601E70UL) /* FIREDANCER VOTE STAKES V0 */
      11             : #define FD_VOTE_STAKES_MAX_FORK_WIDTH (128UL)
      12             : 
      13             : struct vacc {
      14             :   fd_pubkey_t pubkey;
      15             :   fd_pubkey_t node_account;
      16             :   ulong       stake;
      17             :   ushort      commission;
      18             :   uint        left;
      19             :   uint        right;
      20             :   uint        next;
      21             : };
      22             : typedef struct vacc vacc_t;
      23             : 
      24             : #define HEAP_NAME       vacc_heap
      25        6333 : #define HEAP_IDX_T      uint
      26             : #define HEAP_T          vacc_t
      27       54906 : #define HEAP_LT(e0,e1) ( ((e0)->stake < (e1)->stake) | \
      28       54906 :                          (((e0)->stake==(e1)->stake) & \
      29       54906 :                           (memcmp( &(e0)->pubkey, &(e1)->pubkey, sizeof(fd_pubkey_t) )<0 ) ) )
      30             : #include "../../util/tmpl/fd_heap.c"
      31             : 
      32             : #define POOL_NAME  vacc_pool
      33        2334 : #define POOL_T     vacc_t
      34             : #define POOL_IDX_T uint
      35             : #define POOL_LAZY  1
      36             : #include "../../util/tmpl/fd_pool.c"
      37             : 
      38             : #define MAP_NAME               vacc_map
      39             : #define MAP_KEY_T              fd_pubkey_t
      40             : #define MAP_ELE_T              vacc_t
      41       14565 : #define MAP_KEY                pubkey
      42        4869 : #define MAP_KEY_EQ(k0,k1)      (!memcmp( k0, k1, sizeof(fd_pubkey_t) ))
      43       19473 : #define MAP_KEY_HASH(key,seed) (fd_hash( seed, key, sizeof(fd_pubkey_t) ))
      44       89376 : #define MAP_IDX_T              uint
      45             : #include "../../util/tmpl/fd_map_chain.c"
      46             : 
      47             : struct vacc_fork {
      48             :   uint ref_cnt;
      49             :   uint next;
      50             : };
      51             : typedef struct vacc_fork vacc_fork_t;
      52             : 
      53             : #define POOL_NAME  vacc_fork_pool
      54         234 : #define POOL_T     vacc_fork_t
      55             : #define POOL_IDX_T uint
      56             : #define POOL_LAZY  1
      57             : #include "../../util/tmpl/fd_pool.c"
      58             : 
      59             : struct vacc_states {
      60             :   struct {
      61             :     ulong last_vote_slot;
      62             :     long  last_vote_ts;
      63             :     uchar is_valid;
      64             :   } states[ FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS ];
      65             :   uint next;
      66             : };
      67             : typedef struct vacc_states vacc_states_t;
      68             : 
      69             : #define POOL_NAME  vacc_state_pool
      70         234 : #define POOL_T     vacc_states_t
      71             : #define POOL_IDX_T uint
      72             : #define POOL_LAZY  1
      73             : #include "../../util/tmpl/fd_pool.c"
      74             : 
      75             : struct fd_vote_stakes {
      76             :   ulong magic;
      77             :   ulong max_fork_width;
      78             :   ulong max_live_slots;
      79             :   ulong min_stake_wmark;
      80             : 
      81             :   /* (pubkey, stake) pairs for the t-2 epoch.  These are shared across
      82             :      forks/banks. */
      83             :   ulong t_2_epoch[ 2UL ];
      84             :   uint  t_2_vacc_pool_off[ 2UL ];
      85             :   uint  t_2_vacc_map_off [ 2UL ];
      86             : 
      87             :   /* (pubkey, stake) pairs for the t-1 epoch.  These can be different
      88             :      for every fork across the epoch boundary.  These must be sized to
      89             :      the max fork width of the running system.  These are keyed by fork
      90             :      idx. */
      91             :   uint vacc_fork_pool_off;
      92             :   uint t_1_vacc_pools_off;
      93             :   uint t_1_vacc_maps_off;
      94             :   uint vacc_heap_off;
      95             : 
      96             :   /* Per-bank state about the t-2 vote state.  Each per-bank state will
      97             :      be an array sized to length max_live_slots which is a system-wide
      98             :      bound.  Keyed by bank idx. */
      99             :   uint vacc_states_pool_off;
     100             : };
     101             : typedef struct fd_vote_stakes fd_vote_stakes_t;
     102             : 
     103             : FD_FN_UNUSED static inline vacc_t *
     104             : t_2_vacc_pool( fd_vote_stakes_t const * vote_stakes,
     105       52104 :                ulong                    idx ) {
     106       52104 :   return fd_type_pun( (uchar *)vote_stakes + vote_stakes->t_2_vacc_pool_off[ idx ] );
     107       52104 : }
     108             : 
     109             : FD_FN_UNUSED static inline vacc_map_t *
     110             : t_2_vacc_map( fd_vote_stakes_t const * vote_stakes,
     111       52095 :               ulong                    idx ) {
     112       52095 :   return fd_type_pun( (uchar *)vote_stakes + vote_stakes->t_2_vacc_map_off[ idx ] );
     113       52095 : }
     114             : 
     115             : FD_FN_UNUSED static inline vacc_fork_t *
     116       17850 : vacc_fork_pool( fd_vote_stakes_t const * vote_stakes ) {
     117       17850 :   return fd_type_pun( (uchar *)vote_stakes + vote_stakes->vacc_fork_pool_off );
     118       17850 : }
     119             : 
     120             : FD_FN_UNUSED static inline vacc_t *
     121             : t_1_vacc_pool( fd_vote_stakes_t const * vote_stakes,
     122       53676 :                ulong                    width_idx ) {
     123       53676 :   ulong off = vote_stakes->t_1_vacc_pools_off + width_idx*vacc_pool_footprint( FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS );
     124       53676 :   return fd_type_pun( (uchar *)vote_stakes + off );
     125       53676 : }
     126             : 
     127             : FD_FN_UNUSED static inline vacc_map_t *
     128             : t_1_vacc_map( fd_vote_stakes_t const * vote_stakes,
     129       53652 :               ulong                    width_idx ) {
     130       53652 :   ulong chain_cnt = vacc_map_chain_cnt_est( FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS );
     131       53652 :   ulong off       = vote_stakes->t_1_vacc_maps_off + width_idx*vacc_map_footprint( chain_cnt );
     132       53652 :   return fd_type_pun( (uchar *)vote_stakes + off );
     133       53652 : }
     134             : 
     135             : FD_FN_UNUSED static inline vacc_heap_t *
     136       14598 : vacc_heap( fd_vote_stakes_t const * vote_stakes ) {
     137       14598 :   return fd_type_pun( (uchar *)vote_stakes + vote_stakes->vacc_heap_off );
     138       14598 : }
     139             : 
     140             : FD_FN_UNUSED static inline vacc_states_t *
     141       28176 : vacc_states_pool( fd_vote_stakes_t const * vote_stakes ) {
     142       28176 :   return fd_type_pun( (uchar *)vote_stakes + vote_stakes->vacc_states_pool_off );
     143       28176 : }
     144             : 
     145             : /* The fork id is a compound of the epoch, width idx, and bank idx. */
     146             : 
     147             : FD_FN_UNUSED static inline ushort
     148       16335 : fork_id_bank_id( ulong fork_id ) {
     149       16335 :   return (ushort)(fork_id & (ulong)USHORT_MAX);
     150       16335 : }
     151             : 
     152             : FD_FN_UNUSED static inline ushort
     153       23274 : fork_id_width_id( ulong fork_id ) {
     154       23274 :   return (ushort)((fork_id>>16UL) & (ulong)USHORT_MAX);
     155       23274 : }
     156             : 
     157             : FD_FN_UNUSED static inline ushort
     158       45588 : fork_id_epoch( ulong fork_id ) {
     159       45588 :   return (ushort)((fork_id>>32UL) & (ulong)USHORT_MAX);
     160       45588 : }
     161             : 
     162             : FD_FN_UNUSED static inline void
     163             : fork_id_set_bank_id( ulong * fork_id,
     164        8985 :                      ushort  bank_id ) {
     165        8985 :   *fork_id = (*fork_id & ~(ulong)USHORT_MAX) | (ulong)bank_id;
     166        8985 : }
     167             : 
     168             : FD_FN_UNUSED static inline void
     169             : fork_id_set_width_id( ulong * fork_id,
     170        8985 :                       ushort  width_id ) {
     171        8985 :   *fork_id = (*fork_id & ~((ulong)USHORT_MAX<<16UL)) | ((ulong)width_id<<16UL);
     172        8985 : }
     173             : 
     174             : FD_FN_UNUSED static inline void
     175             : fork_id_set_epoch( ulong * fork_id,
     176        8985 :                    ushort  epoch ) {
     177        8985 :   *fork_id = (*fork_id & ~((ulong)USHORT_MAX<<32UL)) | ((ulong)epoch<<32UL);
     178        8985 : }
     179             : 
     180             : ulong
     181        3657 : fd_vote_stakes_align( void ) {
     182        3657 :   return FD_VOTE_STAKES_ALIGN;
     183        3657 : }
     184             : 
     185             : ulong
     186             : fd_vote_stakes_footprint( ulong max_live_slots,
     187         609 :                           ulong max_fork_width ) {
     188         609 :   if( FD_UNLIKELY( !max_live_slots || max_live_slots>USHORT_MAX ) ) return 0UL;
     189         609 :   if( FD_UNLIKELY( !max_fork_width || max_fork_width>FD_VOTE_STAKES_MAX_FORK_WIDTH ) ) return 0UL;
     190             : 
     191         609 :   ulong map_chain_cnt  = vacc_map_chain_cnt_est( FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS );
     192         609 :   ulong pool_footprint = vacc_pool_footprint( FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS );
     193         609 :   ulong map_footprint  = vacc_map_footprint( map_chain_cnt );
     194         609 :   ulong width_cnt      = max_fork_width + 1UL;
     195             : 
     196         609 :   ulong l = FD_LAYOUT_INIT;
     197         609 :   l = FD_LAYOUT_APPEND( l, fd_vote_stakes_align(), sizeof(fd_vote_stakes_t) );
     198        1827 :   for( ulong i=0UL; i<2UL; i++ ) {
     199        1218 :     l = FD_LAYOUT_APPEND( l, vacc_pool_align(), pool_footprint );
     200        1218 :     l = FD_LAYOUT_APPEND( l, vacc_map_align(),  map_footprint );
     201        1218 :   }
     202         609 :   l = FD_LAYOUT_APPEND( l, vacc_fork_pool_align(),  vacc_fork_pool_footprint( width_cnt ) );
     203         609 :   l = FD_LAYOUT_APPEND( l, vacc_pool_align(),       width_cnt*pool_footprint );
     204         609 :   l = FD_LAYOUT_APPEND( l, vacc_map_align(),        width_cnt*map_footprint );
     205         609 :   l = FD_LAYOUT_APPEND( l, vacc_heap_align(),       vacc_heap_footprint( FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS ) );
     206         609 :   l = FD_LAYOUT_APPEND( l, vacc_state_pool_align(), vacc_state_pool_footprint( max_live_slots ) );
     207         609 :   return FD_LAYOUT_FINI( l, fd_vote_stakes_align() );
     208         609 : }
     209             : 
     210             : void *
     211             : fd_vote_stakes_new( void * mem,
     212             :                     ulong  max_live_slots,
     213             :                     ulong  max_fork_width,
     214         117 :                     ulong  seed ) {
     215         117 :   if( FD_UNLIKELY( !mem ) ) {
     216           0 :     FD_LOG_WARNING(( "NULL mem" ));
     217           0 :     return NULL;
     218           0 :   }
     219             : 
     220         117 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, fd_vote_stakes_align() ) ) ) {
     221           0 :     FD_LOG_WARNING(( "misaligned mem" ));
     222           0 :     return NULL;
     223           0 :   }
     224             : 
     225         117 :   if( FD_UNLIKELY( !max_live_slots || max_live_slots>USHORT_MAX ) ) {
     226           0 :     FD_LOG_WARNING(( "invalid max_live_slots" ));
     227           0 :     return NULL;
     228           0 :   }
     229             : 
     230         117 :   if( FD_UNLIKELY( !max_fork_width || max_fork_width>FD_VOTE_STAKES_MAX_FORK_WIDTH ) ) {
     231           0 :     FD_LOG_WARNING(( "invalid max_fork_width" ));
     232           0 :     return NULL;
     233           0 :   }
     234             : 
     235         117 :   ulong map_chain_cnt  = vacc_map_chain_cnt_est( FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS );
     236         117 :   ulong pool_footprint = vacc_pool_footprint( FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS );
     237         117 :   ulong map_footprint  = vacc_map_footprint( map_chain_cnt );
     238         117 :   ulong width_cnt      = max_fork_width + 1UL;
     239             : 
     240         117 :   FD_SCRATCH_ALLOC_INIT( l, mem );
     241         117 :   fd_vote_stakes_t * vote_stakes = FD_SCRATCH_ALLOC_APPEND( l, fd_vote_stakes_align(), sizeof(fd_vote_stakes_t) );
     242         117 :   void * t_2_pool_mem[ 2UL ];
     243         117 :   void * t_2_map_mem [ 2UL ];
     244         351 :   for( ulong i=0UL; i<2UL; i++ ) {
     245         234 :     t_2_pool_mem[ i ] = FD_SCRATCH_ALLOC_APPEND( l, vacc_pool_align(), pool_footprint );
     246         234 :     t_2_map_mem [ i ] = FD_SCRATCH_ALLOC_APPEND( l, vacc_map_align(),  map_footprint );
     247         234 :   }
     248         117 :   void * vacc_fork_pool_mem   = FD_SCRATCH_ALLOC_APPEND( l, vacc_fork_pool_align(), vacc_fork_pool_footprint( width_cnt ) );
     249         117 :   void * t_1_vacc_pools_mem   = FD_SCRATCH_ALLOC_APPEND( l, vacc_pool_align(),      width_cnt*pool_footprint );
     250         117 :   void * t_1_vacc_maps_mem    = FD_SCRATCH_ALLOC_APPEND( l, vacc_map_align(),       width_cnt*map_footprint );
     251         117 :   void * vacc_heap_mem        = FD_SCRATCH_ALLOC_APPEND( l, vacc_heap_align(),       vacc_heap_footprint( FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS ) );
     252         117 :   void * vacc_states_pool_mem = FD_SCRATCH_ALLOC_APPEND( l, vacc_state_pool_align(), vacc_state_pool_footprint( max_live_slots ) );
     253             : 
     254         117 :   if( FD_UNLIKELY( FD_SCRATCH_ALLOC_FINI( l, fd_vote_stakes_align() )!=(ulong)mem+fd_vote_stakes_footprint( max_live_slots, max_fork_width ) ) ) {
     255           0 :     FD_LOG_WARNING(( "fd_vote_stakes_new: bad layout" ));
     256           0 :     return NULL;
     257           0 :   }
     258             : 
     259         351 :   for( ulong i=0UL; i<2UL; i++ ) {
     260         234 :     vacc_t * t_2_pool = vacc_pool_join( vacc_pool_new( t_2_pool_mem[ i ], FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS ) );
     261         234 :     if( FD_UNLIKELY( !t_2_pool ) ) {
     262           0 :       FD_LOG_WARNING(( "Failed to create t-2 vote account pool" ));
     263           0 :       return NULL;
     264           0 :     }
     265             : 
     266         234 :     vacc_map_t * t_2_map = vacc_map_join( vacc_map_new( t_2_map_mem[ i ], map_chain_cnt, seed ) );
     267         234 :     if( FD_UNLIKELY( !t_2_map ) ) {
     268           0 :       FD_LOG_WARNING(( "Failed to create t-2 vote account map" ));
     269           0 :       return NULL;
     270           0 :     }
     271             : 
     272         234 :     vote_stakes->t_2_vacc_pool_off[ i ] = (uint)((ulong)t_2_pool - (ulong)mem);
     273         234 :     vote_stakes->t_2_vacc_map_off [ i ] = (uint)((ulong)t_2_map  - (ulong)mem);
     274         234 :   }
     275             : 
     276         117 :   vacc_fork_t * fork_pool = vacc_fork_pool_join( vacc_fork_pool_new( vacc_fork_pool_mem, width_cnt ) );
     277         117 :   if( FD_UNLIKELY( !fork_pool ) ) {
     278           0 :     FD_LOG_WARNING(( "Failed to create vote account fork pool" ));
     279           0 :     return NULL;
     280           0 :   }
     281         117 :   vote_stakes->vacc_fork_pool_off = (uint)((ulong)fork_pool - (ulong)mem);
     282             : 
     283        1050 :   for( ulong i=0UL; i<width_cnt; i++ ) {
     284         933 :     void *   pool_mem = (uchar *)t_1_vacc_pools_mem + i*pool_footprint;
     285         933 :     vacc_t * pool     = vacc_pool_join( vacc_pool_new( pool_mem, FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS ) );
     286         933 :     if( FD_UNLIKELY( !pool ) ) {
     287           0 :       FD_LOG_WARNING(( "Failed to create t-1 vote account pool" ));
     288           0 :       return NULL;
     289           0 :     }
     290         933 :     if( FD_UNLIKELY( !i ) ) vote_stakes->t_1_vacc_pools_off = (uint)((ulong)pool - (ulong)mem);
     291             : 
     292         933 :     void *       map_mem = (uchar *)t_1_vacc_maps_mem + i*map_footprint;
     293         933 :     vacc_map_t * map = vacc_map_join( vacc_map_new( map_mem, map_chain_cnt, seed ) );
     294         933 :     if( FD_UNLIKELY( !map ) ) {
     295           0 :       FD_LOG_WARNING(( "Failed to create t-1 vote account map" ));
     296           0 :       return NULL;
     297           0 :     }
     298         933 :   }
     299         117 :   vote_stakes->t_1_vacc_maps_off = (uint)((ulong)t_1_vacc_maps_mem - (ulong)mem);
     300             : 
     301         117 :   vacc_heap_t * heap = vacc_heap_join( vacc_heap_new( vacc_heap_mem, FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS ) );
     302         117 :   if( FD_UNLIKELY( !heap ) ) {
     303           0 :     FD_LOG_WARNING(( "Failed to create vote account heap" ));
     304           0 :     return NULL;
     305           0 :   }
     306             : 
     307         117 :   vacc_states_t * vacc_states_pool = vacc_state_pool_join( vacc_state_pool_new( vacc_states_pool_mem, max_live_slots ) );
     308         117 :   if( FD_UNLIKELY( !vacc_states_pool ) ) {
     309           0 :     FD_LOG_WARNING(( "Failed to create vote account state pool" ));
     310           0 :     return NULL;
     311           0 :   }
     312             : 
     313         117 :   vote_stakes->max_live_slots       = max_live_slots;
     314         117 :   vote_stakes->max_fork_width       = max_fork_width;
     315         117 :   vote_stakes->min_stake_wmark      = 0UL;
     316         117 :   vote_stakes->vacc_heap_off        = (uint)((ulong)heap - (ulong)mem);
     317         117 :   vote_stakes->vacc_states_pool_off = (uint)((ulong)vacc_states_pool - (ulong)mem);
     318         117 :   vote_stakes->t_2_epoch[ 0 ]       = ULONG_MAX;
     319         117 :   vote_stakes->t_2_epoch[ 1 ]       = ULONG_MAX;
     320             : 
     321         117 :   FD_COMPILER_MFENCE();
     322         117 :   FD_VOLATILE( vote_stakes->magic ) = FD_VOTE_STAKES_MAGIC;
     323         117 :   FD_COMPILER_MFENCE();
     324             : 
     325         117 :   return vote_stakes;
     326         117 : }
     327             : 
     328             : fd_vote_stakes_t *
     329         231 : fd_vote_stakes_join( void * mem ) {
     330         231 :   fd_vote_stakes_t * vote_stakes = (fd_vote_stakes_t *)mem;
     331             : 
     332         231 :   if( FD_UNLIKELY( !vote_stakes ) ) {
     333           0 :     FD_LOG_WARNING(( "NULL vote stakes" ));
     334           0 :     return NULL;
     335           0 :   }
     336             : 
     337         231 :   if( FD_UNLIKELY( vote_stakes->magic!=FD_VOTE_STAKES_MAGIC ) ) {
     338           0 :     FD_LOG_WARNING(( "Invalid vote stakes magic" ));
     339           0 :     return NULL;
     340           0 :   }
     341             : 
     342         231 :   return vote_stakes;
     343         231 : }
     344             : 
     345             : ulong
     346        4458 : fd_vote_stakes_fork_epoch( ulong fork_id ) {
     347        4458 :   return (ulong)fork_id_epoch( fork_id );
     348        4458 : }
     349             : 
     350             : ulong
     351             : fd_vote_stakes_init( fd_vote_stakes_t * vote_stakes,
     352        3969 :                      ulong              epoch ) {
     353             :   /* Acquire t-1 key set width idx */
     354        3969 :   vacc_fork_t * fork_pool = vacc_fork_pool( vote_stakes );
     355        3969 :   FD_CHECK_CRIT( vacc_fork_pool_free( fork_pool ), "vote stakes width pool exhausted" );
     356        3969 :   ushort        width_idx = (ushort)vacc_fork_pool_idx_acquire( fork_pool );
     357        3969 :   vacc_fork_pool_ele( fork_pool, width_idx )->ref_cnt = 1U;
     358             : 
     359             :   /* Acquire t-2 state bank idx */
     360        3969 :   vacc_states_t * states_pool = vacc_states_pool( vote_stakes );
     361        3969 :   FD_CHECK_CRIT( vacc_state_pool_free( states_pool ), "vote stakes state pool exhausted" );
     362        3969 :   ushort          bank_idx    = (ushort)vacc_state_pool_idx_acquire( states_pool );
     363        3969 :   vacc_states_t * states = vacc_state_pool_ele( states_pool, bank_idx );
     364        3969 :   memset( states->states, 0, sizeof(states->states) );
     365        3969 :   vote_stakes->t_2_epoch[ epoch & 1UL ] = epoch;
     366             : 
     367             :   /* Construct the fork id */
     368        3969 :   ulong fork_id = 0UL;
     369        3969 :   fork_id_set_bank_id( &fork_id, bank_idx );
     370        3969 :   fork_id_set_width_id( &fork_id, width_idx );
     371        3969 :   fork_id_set_epoch( &fork_id, (ushort)epoch );
     372        3969 :   return fork_id;
     373        3969 : }
     374             : 
     375             : void
     376        7872 : fd_vote_stakes_reset( fd_vote_stakes_t * vote_stakes ) {
     377       23616 :   for( ulong i=0UL; i<2UL; i++ ) {
     378       15744 :     vacc_map_reset( t_2_vacc_map( vote_stakes, i ) );
     379       15744 :     vacc_pool_reset( t_2_vacc_pool( vote_stakes, i ) );
     380       15744 :     vote_stakes->t_2_epoch[ i ] = ULONG_MAX;
     381       15744 :   }
     382             : 
     383        7872 :   ulong width_cnt = vote_stakes->max_fork_width + 1UL;
     384       47211 :   for( ulong i=0UL; i<width_cnt; i++ ) {
     385       39339 :     vacc_map_reset( t_1_vacc_map( vote_stakes, i ) );
     386       39339 :     vacc_pool_reset( t_1_vacc_pool( vote_stakes, i ) );
     387       39339 :   }
     388             : 
     389        7872 :   vacc_fork_pool_reset( vacc_fork_pool( vote_stakes ) );
     390        7872 :   vacc_state_pool_reset( vacc_states_pool( vote_stakes ) );
     391        7872 :   FD_TEST( vacc_heap_new( vacc_heap( vote_stakes ), FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS ) );
     392        7872 :   vote_stakes->min_stake_wmark = 0UL;
     393        7872 : }
     394             : 
     395             : void
     396             : fd_vote_stakes_snap_insert_t_1( fd_vote_stakes_t *  vote_stakes,
     397             :                                 ulong               fork_id,
     398             :                                 fd_pubkey_t const * pubkey,
     399             :                                 fd_pubkey_t const * node_account,
     400             :                                 ulong               stake,
     401        3918 :                                 ushort              commission ) {
     402        3918 :   if( FD_UNLIKELY( !stake ) ) return;
     403             : 
     404        3918 :   vacc_t *     pool = t_1_vacc_pool( vote_stakes, fork_id_width_id( fork_id ) );
     405        3918 :   vacc_map_t * map  = t_1_vacc_map ( vote_stakes, fork_id_width_id( fork_id ) );
     406             : 
     407        3918 :   vacc_t * vacc      = vacc_pool_ele_acquire( pool );
     408        3918 :   vacc->pubkey       = *pubkey;
     409        3918 :   vacc->node_account = *node_account;
     410        3918 :   vacc->stake        = stake;
     411        3918 :   vacc->commission   = commission;
     412        3918 :   FD_TEST( vacc_map_ele_insert( map, vacc, pool ) );
     413        3918 : }
     414             : 
     415             : void
     416             : fd_vote_stakes_snap_insert_t_2( fd_vote_stakes_t *  vote_stakes,
     417             :                                 ulong               fork_id,
     418             :                                 fd_pubkey_t const * pubkey,
     419             :                                 fd_pubkey_t const * node_account,
     420             :                                 ulong               stake,
     421        3912 :                                 ushort              commission ) {
     422        3912 :   if( FD_UNLIKELY( !stake ) ) return;
     423             : 
     424        3912 :   ulong        epoch_idx = (ulong)fork_id_epoch( fork_id ) & 1UL;
     425        3912 :   vacc_t *     pool      = t_2_vacc_pool( vote_stakes, epoch_idx );
     426        3912 :   vacc_map_t * map       = t_2_vacc_map ( vote_stakes, epoch_idx );
     427             : 
     428        3912 :   vacc_t * vacc      = vacc_pool_ele_acquire( pool );
     429        3912 :   vacc->pubkey       = *pubkey;
     430        3912 :   vacc->node_account = *node_account;
     431        3912 :   vacc->stake        = stake;
     432        3912 :   vacc->commission   = commission;
     433        3912 :   FD_TEST( vacc_map_ele_insert( map, vacc, pool ) );
     434        3912 : }
     435             : 
     436             : void
     437             : fd_vote_stakes_insert( fd_vote_stakes_t *  vote_stakes,
     438             :                        ulong               fork_id,
     439             :                        fd_pubkey_t const * pubkey,
     440             :                        fd_pubkey_t const * node_account,
     441             :                        ulong               stake,
     442        6330 :                        ushort              commission ) {
     443        6330 :   ulong         width_idx = (ulong)fork_id_width_id( fork_id );
     444        6330 :   vacc_t *      pool      = t_1_vacc_pool( vote_stakes, width_idx );
     445        6330 :   vacc_map_t *  map       = t_1_vacc_map ( vote_stakes, width_idx );
     446        6330 :   vacc_heap_t * heap      = vacc_heap( vote_stakes );
     447             : 
     448        6330 :   if( FD_UNLIKELY( stake==0UL || stake<=vote_stakes->min_stake_wmark ) ) return;
     449             : 
     450        6330 :   if( FD_UNLIKELY( vacc_heap_ele_cnt( heap )==vacc_heap_ele_max( heap ) ) ) {
     451           3 :     vacc_t * ele       = vacc_heap_ele_peek_min( heap, pool );
     452           3 :     ulong    min_stake = ele->stake;
     453           3 :     if( stake<min_stake ) return;
     454             : 
     455           3 :     vote_stakes->min_stake_wmark = min_stake;
     456           9 :     while( (ele=vacc_heap_ele_peek_min( heap, pool )) && min_stake==ele->stake ) {
     457           6 :       vacc_heap_ele_remove_min( heap, pool );
     458           6 :       vacc_map_ele_remove( map, &ele->pubkey, NULL, pool );
     459           6 :       vacc_pool_ele_release( pool, ele );
     460           6 :     }
     461           3 :     if( FD_UNLIKELY( stake==min_stake ) ) return;
     462           3 :   }
     463             : 
     464        6327 :   vacc_t * vacc      = vacc_pool_ele_acquire( pool );
     465        6327 :   vacc->pubkey       = *pubkey;
     466        6327 :   vacc->node_account = *node_account;
     467        6327 :   vacc->stake        = stake;
     468        6327 :   vacc->commission   = commission;
     469        6327 :   vacc_heap_ele_insert( heap, vacc, pool );
     470        6327 :   FD_TEST( vacc_map_ele_insert( map, vacc, pool ) );
     471        6327 : }
     472             : 
     473             : void
     474             : fd_vote_stakes_purge_fork( fd_vote_stakes_t * vote_stakes,
     475         993 :                            ulong              fork_id ) {
     476         993 :   ushort bank_id  = fork_id_bank_id( fork_id );
     477         993 :   ushort width_id = fork_id_width_id( fork_id );
     478             : 
     479         993 :   vacc_state_pool_idx_release( vacc_states_pool( vote_stakes ), bank_id );
     480             : 
     481         993 :   vacc_fork_t * fork_pool = vacc_fork_pool( vote_stakes );
     482         993 :   vacc_fork_t * fork      = vacc_fork_pool_ele( fork_pool, width_id );
     483         993 :   FD_TEST( fork->ref_cnt );
     484         993 :   if( !--fork->ref_cnt ) {
     485         198 :     vacc_map_reset( t_1_vacc_map( vote_stakes, width_id ) );
     486         198 :     vacc_pool_reset( t_1_vacc_pool( vote_stakes, width_id ) );
     487         198 :     vacc_fork_pool_idx_release( fork_pool, width_id );
     488         198 :   }
     489         993 : }
     490             : 
     491             : ulong
     492             : fd_vote_stakes_new_fork( fd_vote_stakes_t * vote_stakes,
     493             :                          ulong              parent_fork_id,
     494        5016 :                          ulong              epoch ) {
     495        5016 :   FD_TEST( epoch<=USHORT_MAX );
     496             : 
     497        5016 :   vacc_states_t * states_pool    = vacc_states_pool( vote_stakes );
     498        5016 :   FD_CHECK_CRIT( vacc_state_pool_free( states_pool ), "vote stakes state pool exhausted" );
     499        5016 :   ushort          parent_bank_id = fork_id_bank_id( parent_fork_id );
     500        5016 :   ushort          bank_id        = (ushort)vacc_state_pool_idx_acquire( states_pool );
     501        5016 :   ushort          parent_epoch   = fork_id_epoch( parent_fork_id );
     502        5016 :   ushort          width_id;
     503             : 
     504        5016 :   vacc_states_t * child_state = vacc_state_pool_ele( states_pool, bank_id );
     505        5016 :   if( FD_LIKELY( epoch==(ulong)parent_epoch ) ) {
     506             :     /* Standard case: just inherit the parent's t-1 set (and increment
     507             :        the ref count) and copy over the t-2 state. */
     508        4620 :     width_id = fork_id_width_id( parent_fork_id );
     509        4620 :     vacc_fork_pool_ele( vacc_fork_pool( vote_stakes ), width_id )->ref_cnt++;
     510             : 
     511        4620 :     vacc_states_t const * parent_state = vacc_state_pool_ele_const( states_pool, parent_bank_id );
     512        4620 :     memcpy( child_state->states, parent_state->states, sizeof(child_state->states) );
     513        4620 :   } else {
     514             :     /* Epoch boundary: copy the parent's t-1 set into the t-2 set and
     515             :        acquire new t-1 and t-2 state. */
     516             : 
     517             :     /* Copy the t-1 set iff it's the first time crossing into a new
     518             :        epoch boundary. */
     519         396 :     ulong t_2_idx = epoch & 1UL;
     520         396 :     if( vote_stakes->t_2_epoch[ t_2_idx ]!=epoch ) {
     521         351 :       ulong        parent_width_id = (ulong)fork_id_width_id( parent_fork_id );
     522         351 :       vacc_t *     t_1_pool        = t_1_vacc_pool( vote_stakes, parent_width_id );
     523         351 :       vacc_map_t * t_1_map         = t_1_vacc_map ( vote_stakes, parent_width_id );
     524         351 :       vacc_t *     t_2_pool        = t_2_vacc_pool( vote_stakes, t_2_idx );
     525         351 :       vacc_map_t * t_2_map         = t_2_vacc_map ( vote_stakes, t_2_idx );
     526             : 
     527         351 :       vacc_map_reset( t_2_map );
     528         351 :       vacc_pool_reset( t_2_pool );
     529         351 :       for( vacc_map_iter_t iter = vacc_map_iter_init( t_1_map, t_1_pool );
     530         759 :            !vacc_map_iter_done( iter, t_1_map, t_1_pool );
     531         408 :            iter = vacc_map_iter_next( iter, t_1_map, t_1_pool ) ) {
     532         408 :         vacc_t const * src = vacc_map_iter_ele_const( iter, t_1_map, t_1_pool );
     533         408 :         vacc_t *       dst = vacc_pool_ele_acquire( t_2_pool );
     534         408 :         dst->pubkey       = src->pubkey;
     535         408 :         dst->node_account = src->node_account;
     536         408 :         dst->stake        = src->stake;
     537         408 :         dst->commission   = src->commission;
     538         408 :         FD_TEST( vacc_map_ele_insert( t_2_map, dst, t_2_pool ) );
     539         408 :       }
     540         351 :       vote_stakes->t_2_epoch[ t_2_idx ] = epoch;
     541         351 :     }
     542             : 
     543             :     /* Reset the t-2 states for the new fork and prepare the heap for
     544             :        insertion into the new t-1 set. */
     545         396 :     vacc_fork_t * fork_pool = vacc_fork_pool( vote_stakes );
     546         396 :     FD_CHECK_CRIT( vacc_fork_pool_free( fork_pool ), "vote stakes width pool exhausted" );
     547         396 :     width_id = (ushort)vacc_fork_pool_idx_acquire( fork_pool );
     548         396 :     vacc_fork_pool_ele( fork_pool, width_id )->ref_cnt = 1U;
     549         396 :     vacc_map_reset( t_1_vacc_map( vote_stakes, width_id ) );
     550         396 :     vacc_pool_reset( t_1_vacc_pool( vote_stakes, width_id ) );
     551         396 :     memset( child_state->states, 0, sizeof(child_state->states) );
     552             : 
     553         396 :     FD_TEST( vacc_heap_new( vacc_heap( vote_stakes ), FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS ) );
     554         396 :     vote_stakes->min_stake_wmark = 0UL;
     555         396 :   }
     556             : 
     557        5016 :   ulong fork_id = 0UL;
     558        5016 :   fork_id_set_bank_id( &fork_id, bank_id );
     559        5016 :   fork_id_set_width_id( &fork_id, width_id );
     560        5016 :   fork_id_set_epoch( &fork_id, (ushort)epoch );
     561        5016 :   return fork_id;
     562        5016 : }
     563             : 
     564             : void
     565             : fd_vote_stakes_update_state( fd_vote_stakes_t *  vote_stakes,
     566             :                              ulong               fork_id,
     567             :                              fd_pubkey_t const * pubkey,
     568             :                              ulong               last_vote_slot,
     569             :                              long                last_vote_ts,
     570        4302 :                              uchar               is_valid ) {
     571        4302 :   ulong        epoch_idx = (ulong)fork_id_epoch( fork_id ) & 1UL;
     572        4302 :   vacc_t *     pool      = t_2_vacc_pool( vote_stakes, epoch_idx );
     573        4302 :   vacc_map_t * map       = t_2_vacc_map ( vote_stakes, epoch_idx );
     574             : 
     575        4302 :   vacc_t const * vacc = vacc_map_ele_query_const( map, pubkey, NULL, pool );
     576        4302 :   if( FD_UNLIKELY( !vacc ) ) return;
     577             : 
     578        4242 :   ulong           vacc_idx = vacc_pool_idx( pool, vacc );
     579        4242 :   vacc_states_t * states   = vacc_state_pool_ele( vacc_states_pool( vote_stakes ), fork_id_bank_id( fork_id ) );
     580        4242 :   states->states[ vacc_idx ].is_valid = (uchar)!!is_valid;
     581        4242 :   if( is_valid ) {
     582        4236 :     states->states[ vacc_idx ].last_vote_slot = last_vote_slot;
     583        4236 :     states->states[ vacc_idx ].last_vote_ts   = last_vote_ts;
     584        4236 :   }
     585        4242 : }
     586             : 
     587             : void
     588             : fd_vote_stakes_refresh( fd_vote_stakes_t * vote_stakes,
     589             :                         ulong              fork_id,
     590             :                         fd_accdb_t *        accdb,
     591         264 :                         fd_accdb_fork_id_t  accdb_fork_id ) {
     592         264 :   uchar __attribute__((aligned(FD_VOTE_STAKES_T_2_ITER_ALIGN))) iter_mem[ FD_VOTE_STAKES_T_2_ITER_FOOTPRINT ];
     593             : 
     594         264 :   for( fd_vote_stakes_t_2_iter_t * iter = fd_vote_stakes_t_2_iter_init( vote_stakes, fork_id, iter_mem );
     595         588 :        !fd_vote_stakes_t_2_iter_done( vote_stakes, fork_id, iter );
     596         324 :        fd_vote_stakes_t_2_iter_next( vote_stakes, fork_id, iter ) ) {
     597         324 :     fd_pubkey_t pubkey;
     598         324 :     fd_vote_stakes_t_2_iter_ele( vote_stakes, fork_id, iter, &pubkey, NULL, NULL, NULL, NULL, NULL, NULL );
     599             : 
     600         324 :     fd_acc_t acc = fd_accdb_read_one( accdb, accdb_fork_id, pubkey.uc );
     601         324 :     if( FD_UNLIKELY( !acc.lamports || !fd_vsv_is_correct_size_owner_and_init( acc.owner, acc.data, acc.data_len ) ) ) {
     602           3 :       fd_accdb_unread_one( accdb, &acc );
     603           3 :       fd_vote_stakes_update_state( vote_stakes, fork_id, &pubkey, 0UL, 0L, 0 );
     604           3 :       continue;
     605           3 :     }
     606             : 
     607         321 :     fd_vote_block_timestamp_t last_vote;
     608         321 :     FD_TEST( !fd_vote_account_last_timestamp( acc.data, acc.data_len, &last_vote ) );
     609         321 :     fd_vote_stakes_update_state( vote_stakes, fork_id, &pubkey, last_vote.slot, last_vote.timestamp, 1 );
     610         321 :     fd_accdb_unread_one( accdb, &acc );
     611         321 :   }
     612         264 : }
     613             : 
     614             : int
     615             : fd_vote_stakes_query_t_1( fd_vote_stakes_t const * vote_stakes,
     616             :                           ulong                    fork_id,
     617             :                           fd_pubkey_t const *      pubkey,
     618             :                           fd_pubkey_t *            node_account_out_opt,
     619             :                           ulong *                  stake_out_opt,
     620          45 :                           ushort *                 commission_out_opt ) {
     621          45 :   ulong        width_idx = (ulong)fork_id_width_id( fork_id );
     622          45 :   vacc_t *     pool      = t_1_vacc_pool( vote_stakes, width_idx );
     623          45 :   vacc_map_t * map       = t_1_vacc_map ( vote_stakes, width_idx );
     624             : 
     625          45 :   vacc_t const * vacc = vacc_map_ele_query_const( map, pubkey, NULL, pool );
     626          45 :   if( FD_UNLIKELY( !vacc ) ) return 0;
     627             : 
     628          30 :   if( node_account_out_opt ) *node_account_out_opt = vacc->node_account;
     629          30 :   if( stake_out_opt )        *stake_out_opt        = vacc->stake;
     630          30 :   if( commission_out_opt )   *commission_out_opt   = vacc->commission;
     631          30 :   return 1;
     632          45 : }
     633             : 
     634             : int
     635             : fd_vote_stakes_query_t_2( fd_vote_stakes_t const * vote_stakes,
     636             :                           ulong                    fork_id,
     637             :                           fd_pubkey_t const *      pubkey,
     638             :                           fd_pubkey_t *            node_account_out_opt,
     639             :                           ulong *                  stake_out_opt,
     640             :                           ulong *                  last_vote_slot_out_opt,
     641             :                           long *                   last_vote_ts_out_opt,
     642             :                           ushort *                 commission_out_opt,
     643         336 :                           uchar *                  is_valid_out_opt ) {
     644         336 :   ulong        epoch_idx = (ulong)fork_id_epoch( fork_id ) & 1UL;
     645         336 :   vacc_t *     pool      = t_2_vacc_pool( vote_stakes, epoch_idx );
     646         336 :   vacc_map_t * map       = t_2_vacc_map ( vote_stakes, epoch_idx );
     647             : 
     648         336 :   vacc_t const * vacc = vacc_map_ele_query_const( map, pubkey, NULL, pool );
     649         336 :   if( FD_UNLIKELY( !vacc ) ) return 0;
     650             : 
     651         333 :   ulong                 vacc_idx = vacc_pool_idx( pool, vacc );
     652         333 :   vacc_states_t const * states   = vacc_state_pool_ele_const( vacc_states_pool( vote_stakes ), fork_id_bank_id( fork_id ) );
     653             : 
     654         333 :   if( node_account_out_opt )   *node_account_out_opt   = vacc->node_account;
     655         333 :   if( stake_out_opt )          *stake_out_opt          = vacc->stake;
     656         333 :   if( last_vote_slot_out_opt ) *last_vote_slot_out_opt = states->states[ vacc_idx ].last_vote_slot;
     657         333 :   if( last_vote_ts_out_opt )   *last_vote_ts_out_opt   = states->states[ vacc_idx ].last_vote_ts;
     658         333 :   if( commission_out_opt )     *commission_out_opt     = vacc->commission;
     659         333 :   if( is_valid_out_opt )       *is_valid_out_opt       = states->states[ vacc_idx ].is_valid;
     660         333 :   return 1;
     661         336 : }
     662             : 
     663             : int
     664             : fd_vote_stakes_query_t_3( fd_vote_stakes_t const * vote_stakes,
     665             :                           ulong                    fork_id,
     666             :                           fd_pubkey_t const *      pubkey,
     667             :                           fd_pubkey_t *            node_account_out_opt,
     668             :                           ulong *                  stake_out_opt,
     669         324 :                           ushort *                 commission_out_opt ) {
     670         324 :   ulong epoch = (ulong)fork_id_epoch( fork_id );
     671         324 :   if( FD_UNLIKELY( !epoch ) ) return 0;
     672             : 
     673         324 :   ulong t_3_epoch = epoch - 1UL;
     674         324 :   ulong t_3_idx   = t_3_epoch & 1UL;
     675         324 :   if( FD_UNLIKELY( vote_stakes->t_2_epoch[ t_3_idx ]!=t_3_epoch ) ) return 0;
     676             : 
     677         219 :   vacc_t *       pool = t_2_vacc_pool( vote_stakes, t_3_idx );
     678         219 :   vacc_map_t *   map  = t_2_vacc_map ( vote_stakes, t_3_idx );
     679         219 :   vacc_t const * vacc = vacc_map_ele_query_const( map, pubkey, NULL, pool );
     680         219 :   if( FD_UNLIKELY( !vacc ) ) return 0;
     681             : 
     682         216 :   if( node_account_out_opt ) *node_account_out_opt = vacc->node_account;
     683         216 :   if( stake_out_opt )        *stake_out_opt        = vacc->stake;
     684         216 :   if( commission_out_opt )   *commission_out_opt   = vacc->commission;
     685         216 :   return 1;
     686         219 : }
     687             : 
     688             : ulong
     689             : fd_vote_stakes_cnt_t_1( fd_vote_stakes_t const * vote_stakes,
     690          24 :                         ulong                    fork_id ) {
     691          24 :   return vacc_pool_used( t_1_vacc_pool( vote_stakes, fork_id_width_id( fork_id ) ) );
     692          24 : }
     693             : 
     694             : ulong
     695             : fd_vote_stakes_cnt_t_2( fd_vote_stakes_t const * vote_stakes,
     696           9 :                         ulong                    fork_id ) {
     697           9 :   return vacc_pool_used( t_2_vacc_pool( vote_stakes, (ulong)fork_id_epoch( fork_id ) & 1UL ) );
     698           9 : }
     699             : 
     700             : FD_STATIC_ASSERT( FD_VOTE_STAKES_T_1_ITER_FOOTPRINT == sizeof(vacc_map_iter_t), t_1_iter_footprint );
     701             : FD_STATIC_ASSERT( FD_VOTE_STAKES_T_1_ITER_ALIGN == alignof(vacc_map_iter_t), t_1_iter_align );
     702             : FD_STATIC_ASSERT( FD_VOTE_STAKES_T_2_ITER_FOOTPRINT == sizeof(vacc_map_iter_t), t_2_iter_footprint );
     703             : FD_STATIC_ASSERT( FD_VOTE_STAKES_T_2_ITER_ALIGN == alignof(vacc_map_iter_t), t_2_iter_align );
     704             : 
     705             : fd_vote_stakes_t_1_iter_t *
     706             : fd_vote_stakes_t_1_iter_init( fd_vote_stakes_t const * vote_stakes,
     707             :                               ulong                    fork_id,
     708         540 :                               uchar                    iter_mem[ static FD_VOTE_STAKES_T_1_ITER_FOOTPRINT ] ) {
     709         540 :   ulong        width_idx = (ulong)fork_id_width_id( fork_id );
     710         540 :   vacc_t *     pool      = t_1_vacc_pool( vote_stakes, width_idx );
     711         540 :   vacc_map_t * map       = t_1_vacc_map ( vote_stakes, width_idx );
     712         540 :   vacc_map_iter_t iter = vacc_map_iter_init( map, pool );
     713         540 :   memcpy( iter_mem, &iter, sizeof(iter) );
     714         540 :   return (fd_vote_stakes_t_1_iter_t *)iter_mem;
     715         540 : }
     716             : 
     717             : int
     718             : fd_vote_stakes_t_1_iter_done( fd_vote_stakes_t const *    vote_stakes,
     719             :                               ulong                       fork_id,
     720        1200 :                               fd_vote_stakes_t_1_iter_t * iter ) {
     721        1200 :   ulong        width_idx = (ulong)fork_id_width_id( fork_id );
     722        1200 :   vacc_t *     pool      = t_1_vacc_pool( vote_stakes, width_idx );
     723        1200 :   vacc_map_t * map       = t_1_vacc_map ( vote_stakes, width_idx );
     724        1200 :   return vacc_map_iter_done( *(vacc_map_iter_t *)iter, map, pool );
     725        1200 : }
     726             : 
     727             : void
     728             : fd_vote_stakes_t_1_iter_next( fd_vote_stakes_t const *    vote_stakes,
     729             :                               ulong                       fork_id,
     730         666 :                               fd_vote_stakes_t_1_iter_t * iter ) {
     731         666 :   ulong            width_idx = (ulong)fork_id_width_id( fork_id );
     732         666 :   vacc_t *         pool      = t_1_vacc_pool( vote_stakes, width_idx );
     733         666 :   vacc_map_t *     map       = t_1_vacc_map ( vote_stakes, width_idx );
     734         666 :   vacc_map_iter_t * map_iter = (vacc_map_iter_t *)iter;
     735         666 :   *map_iter = vacc_map_iter_next( *map_iter, map, pool );
     736         666 : }
     737             : 
     738             : void
     739             : fd_vote_stakes_t_1_iter_ele( fd_vote_stakes_t const *    vote_stakes,
     740             :                              ulong                       fork_id,
     741             :                              fd_vote_stakes_t_1_iter_t * iter,
     742             :                              fd_pubkey_t *               pubkey_out,
     743             :                              fd_pubkey_t *               node_account_out_opt,
     744             :                              ulong *                     stake_out_opt,
     745         669 :                              ushort *                    commission_out_opt ) {
     746         669 :   ulong          width_idx = (ulong)fork_id_width_id( fork_id );
     747         669 :   vacc_t *       pool      = t_1_vacc_pool( vote_stakes, width_idx );
     748         669 :   vacc_map_t *   map       = t_1_vacc_map ( vote_stakes, width_idx );
     749         669 :   vacc_t const * vacc      = vacc_map_iter_ele_const( *(vacc_map_iter_t *)iter, map, pool );
     750             : 
     751         669 :   *pubkey_out = vacc->pubkey;
     752         669 :   if( node_account_out_opt ) *node_account_out_opt = vacc->node_account;
     753         669 :   if( stake_out_opt )        *stake_out_opt        = vacc->stake;
     754         669 :   if( commission_out_opt )   *commission_out_opt   = vacc->commission;
     755         669 : }
     756             : 
     757             : fd_vote_stakes_t_2_iter_t *
     758             : fd_vote_stakes_t_2_iter_init( fd_vote_stakes_t const * vote_stakes,
     759             :                               ulong                    fork_id,
     760        4992 :                               uchar                    iter_mem[ static FD_VOTE_STAKES_T_2_ITER_FOOTPRINT ] ) {
     761        4992 :   ulong        epoch_idx = (ulong)fork_id_epoch( fork_id ) & 1UL;
     762        4992 :   vacc_t *     pool      = t_2_vacc_pool( vote_stakes, epoch_idx );
     763        4992 :   vacc_map_t * map       = t_2_vacc_map ( vote_stakes, epoch_idx );
     764        4992 :   vacc_map_iter_t iter = vacc_map_iter_init( map, pool );
     765        4992 :   memcpy( iter_mem, &iter, sizeof(iter) );
     766        4992 :   return (fd_vote_stakes_t_2_iter_t *)iter_mem;
     767        4992 : }
     768             : 
     769             : int
     770             : fd_vote_stakes_t_2_iter_done( fd_vote_stakes_t const *    vote_stakes,
     771             :                               ulong                       fork_id,
     772       10737 :                               fd_vote_stakes_t_2_iter_t * iter ) {
     773       10737 :   ulong        epoch_idx = (ulong)fork_id_epoch( fork_id ) & 1UL;
     774       10737 :   vacc_t *     pool      = t_2_vacc_pool( vote_stakes, epoch_idx );
     775       10737 :   vacc_map_t * map       = t_2_vacc_map ( vote_stakes, epoch_idx );
     776       10737 :   return vacc_map_iter_done( *(vacc_map_iter_t *)iter, map, pool );
     777       10737 : }
     778             : 
     779             : void
     780             : fd_vote_stakes_t_2_iter_next( fd_vote_stakes_t const *    vote_stakes,
     781             :                               ulong                       fork_id,
     782        5751 :                               fd_vote_stakes_t_2_iter_t * iter ) {
     783        5751 :   ulong            epoch_idx = (ulong)fork_id_epoch( fork_id ) & 1UL;
     784        5751 :   vacc_t *         pool      = t_2_vacc_pool( vote_stakes, epoch_idx );
     785        5751 :   vacc_map_t *     map       = t_2_vacc_map ( vote_stakes, epoch_idx );
     786        5751 :   vacc_map_iter_t * map_iter = (vacc_map_iter_t *)iter;
     787        5751 :   *map_iter = vacc_map_iter_next( *map_iter, map, pool );
     788        5751 : }
     789             : 
     790             : void
     791             : fd_vote_stakes_t_2_iter_ele( fd_vote_stakes_t const *    vote_stakes,
     792             :                              ulong                       fork_id,
     793             :                              fd_vote_stakes_t_2_iter_t * iter,
     794             :                              fd_pubkey_t *               pubkey_out,
     795             :                              fd_pubkey_t *               node_account_out_opt,
     796             :                              ulong *                     stake_out_opt,
     797             :                              ulong *                     last_vote_slot_out_opt,
     798             :                              long *                      last_vote_ts_out_opt,
     799             :                              ushort *                    commission_out_opt,
     800        5751 :                              uchar *                     is_valid_out_opt ) {
     801        5751 :   ulong                 epoch_idx = (ulong)fork_id_epoch( fork_id ) & 1UL;
     802        5751 :   vacc_t *              pool      = t_2_vacc_pool( vote_stakes, epoch_idx );
     803        5751 :   vacc_map_t *          map       = t_2_vacc_map ( vote_stakes, epoch_idx );
     804        5751 :   vacc_t const *        vacc      = vacc_map_iter_ele_const( *(vacc_map_iter_t *)iter, map, pool );
     805        5751 :   ulong                 vacc_idx  = vacc_pool_idx( pool, vacc );
     806        5751 :   vacc_states_t const * states    = vacc_state_pool_ele_const( vacc_states_pool( vote_stakes ), fork_id_bank_id( fork_id ) );
     807             : 
     808        5751 :   *pubkey_out = vacc->pubkey;
     809        5751 :   if( node_account_out_opt )   *node_account_out_opt   = vacc->node_account;
     810        5751 :   if( stake_out_opt )          *stake_out_opt          = vacc->stake;
     811        5751 :   if( last_vote_slot_out_opt ) *last_vote_slot_out_opt = states->states[ vacc_idx ].last_vote_slot;
     812        5751 :   if( last_vote_ts_out_opt )   *last_vote_ts_out_opt   = states->states[ vacc_idx ].last_vote_ts;
     813        5751 :   if( commission_out_opt )     *commission_out_opt     = vacc->commission;
     814        5751 :   if( is_valid_out_opt )       *is_valid_out_opt       = states->states[ vacc_idx ].is_valid;
     815        5751 : }

Generated by: LCOV version 1.14