LCOV - code coverage report
Current view: top level - flamenco/runtime/program - fd_vote_program.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 1350 1709 79.0 %
Date: 2024-11-13 11:58:15 Functions: 56 65 86.2 %

          Line data    Source code
       1             : #define FD_SCRATCH_USE_HANDHOLDING 1
       2             : #include "fd_vote_program.h"
       3             : #include "../../types/fd_types_yaml.h"
       4             : #include "../fd_account.h"
       5             : #include "../fd_executor.h"
       6             : #include "../fd_pubkey_utils.h"
       7             : #include "../sysvar/fd_sysvar_epoch_schedule.h"
       8             : #include "../sysvar/fd_sysvar_rent.h"
       9             : 
      10             : #include <limits.h>
      11             : #include <math.h>
      12             : #include <stdio.h>
      13             : #include <string.h>
      14             : 
      15             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L35
      16        4689 : #define MAX_LOCKOUT_HISTORY 31UL
      17             : 
      18             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L36
      19         759 : #define INITIAL_LOCKOUT 2UL
      20             : 
      21             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L36
      22             : #define MAX_EPOCH_CREDITS_HISTORY 64UL
      23             : 
      24             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L42
      25           0 : #define DEFAULT_PRIOR_VOTERS_OFFSET 114
      26             : 
      27             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L45
      28           0 : #define VOTE_CREDITS_GRACE_SLOTS 2
      29             : 
      30             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L48
      31           0 : #define VOTE_CREDITS_MAXIMUM_PER_SLOT 16
      32             : 
      33             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L51
      34          66 : #define VOTE_CREDITS_MAXIMUM_PER_SLOT_OLD 8
      35             : 
      36             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/clock.rs#L147
      37             : #define SLOT_DEFAULT 0UL
      38             : 
      39             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/clock.rs#L147
      40             : #define SLOT_MAX ULONG_MAX
      41             : 
      42             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L886
      43           0 : #define VERSION_OFFSET (4UL)
      44             : 
      45             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L887
      46             : #define DEFAULT_PRIOR_VOTERS_END (118)
      47             : 
      48             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/vote_state_1_14_11.rs#L6
      49           0 : #define DEFAULT_PRIOR_VOTERS_OFFSET_1_14_11 (82UL)
      50             : 
      51             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/vote_state_1_14_11.rs#L60
      52             : #define DEFAULT_PRIOR_VOTERS_END_1_14_11 (86UL)
      53             : 
      54             : #define ACCOUNTS_MAX 4 /* Vote instructions take in at most 4 accounts */
      55             : 
      56             : #define DEFAULT_COMPUTE_UNITS 2100UL
      57             : extern fd_flamenco_yaml_t * fd_get_types_yaml(void);
      58             : /**********************************************************************/
      59             : /* size_of                                                            */
      60             : /**********************************************************************/
      61             : 
      62             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/vote_state_versions.rs#L82
      63             : static inline ulong
      64        1383 : size_of_versioned( int is_current ) {
      65        1383 :   return fd_ulong_if( is_current, FD_VOTE_STATE_V3_SZ, FD_VOTE_STATE_V2_SZ );
      66        1383 : }
      67             : 
      68             : /**********************************************************************/
      69             : /* impl Lockout                                                       */
      70             : /**********************************************************************/
      71             : 
      72             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L104
      73             : static inline ulong
      74         729 : lockout( fd_vote_lockout_t * self ) {
      75         729 :   return (ulong)pow( INITIAL_LOCKOUT, self->confirmation_count );
      76         729 : }
      77             : 
      78             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L110
      79             : static inline ulong
      80         729 : last_locked_out_slot( fd_vote_lockout_t * self ) {
      81         729 :   return fd_ulong_sat_add( self->slot, lockout( self ) );
      82         729 : }
      83             : 
      84             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L114
      85             : static inline ulong
      86           6 : is_locked_out_at_slot( fd_vote_lockout_t * self, ulong slot ) {
      87           6 :   return last_locked_out_slot( self ) >= slot;
      88           6 : }
      89             : 
      90             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L122
      91             : static void
      92          18 : increase_confirmation_count( fd_vote_lockout_t * self, uint by ) {
      93          18 :   self->confirmation_count = fd_uint_sat_add( self->confirmation_count, by );
      94          18 : }
      95             : 
      96             : /**********************************************************************/
      97             : /* impl From<VoteState> for VoteState1_14_11                          */
      98             : /**********************************************************************/
      99             : 
     100             : /* from_vote_state_1_14_11 converts a "current" vote state object into
     101             :    the older "v1.14.11" version.  This destroys the "current" object in
     102             :    the process.  valloc is the heap allocator to be used, which must be
     103             :    the same as the one used for v1.14.11.
     104             : */
     105             : 
     106             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/vote_state_1_14_11.rs#L67
     107             : static void
     108             : from_vote_state_1_14_11( fd_vote_state_t *         vote_state,
     109             :                          fd_vote_state_1_14_11_t * vote_state_1_14_11, /* out */
     110         351 :                          fd_valloc_t               valloc ) {
     111         351 :   vote_state_1_14_11->node_pubkey           = vote_state->node_pubkey;            /* copy */
     112         351 :   vote_state_1_14_11->authorized_withdrawer = vote_state->authorized_withdrawer;  /* copy */
     113         351 :   vote_state_1_14_11->commission            = vote_state->commission;             /* copy */
     114             : 
     115             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/vote_state_1_14_11.rs#L72
     116         351 :   if( vote_state->votes ) {
     117         330 :     vote_state_1_14_11->votes = deq_fd_vote_lockout_t_alloc( valloc, deq_fd_landed_vote_t_cnt( vote_state->votes ) );
     118         330 :     for( deq_fd_landed_vote_t_iter_t iter = deq_fd_landed_vote_t_iter_init( vote_state->votes );
     119        4566 :          !deq_fd_landed_vote_t_iter_done( vote_state->votes, iter );
     120        4236 :          iter = deq_fd_landed_vote_t_iter_next( vote_state->votes, iter ) ) {
     121        4236 :       fd_landed_vote_t const * landed_vote = deq_fd_landed_vote_t_iter_ele_const( vote_state->votes, iter );
     122        4236 :       deq_fd_vote_lockout_t_push_tail( vote_state_1_14_11->votes, landed_vote->lockout );
     123        4236 :     }
     124         330 :   }
     125             : 
     126         351 :   vote_state_1_14_11->has_root_slot     = vote_state->has_root_slot;      /* copy */
     127         351 :   vote_state_1_14_11->root_slot         = vote_state->root_slot;          /* copy */
     128         351 :   vote_state_1_14_11->authorized_voters = vote_state->authorized_voters;  /* move */
     129         351 :   vote_state_1_14_11->prior_voters      = vote_state->prior_voters;       /* deep copy */
     130         351 :   vote_state_1_14_11->epoch_credits     = vote_state->epoch_credits;      /* move */
     131         351 :   vote_state_1_14_11->last_timestamp    = vote_state->last_timestamp;     /* deep copy */
     132             : 
     133             :   /* Clear moved objects */
     134         351 :   vote_state->authorized_voters.treap = NULL;
     135         351 :   vote_state->authorized_voters.pool  = NULL;
     136         351 :   vote_state->epoch_credits           = NULL;
     137             : 
     138         351 :   fd_bincode_destroy_ctx_t destroy = { .valloc = valloc };
     139         351 :   fd_vote_state_destroy( vote_state, &destroy );
     140         351 : }
     141             : 
     142             : /**********************************************************************/
     143             : /* impl VoteAccount                                                   */
     144             : /**********************************************************************/
     145             : 
     146             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1074
     147             : static int
     148             : get_state( fd_borrowed_account_t const * self,
     149             :            fd_valloc_t                   valloc,
     150       12012 :            fd_vote_state_versioned_t *   versioned /* out */ ) {
     151       12012 :   int rc;
     152             : 
     153       12012 :   fd_bincode_decode_ctx_t decode_ctx;
     154       12012 :   decode_ctx.data    = self->const_data;
     155       12012 :   decode_ctx.dataend = &self->const_data[self->const_meta->dlen];
     156       12012 :   decode_ctx.valloc  = valloc;
     157             : 
     158       12012 :   rc = fd_vote_state_versioned_decode( versioned, &decode_ctx );
     159       12012 :   if( FD_UNLIKELY( rc != FD_BINCODE_SUCCESS ) )
     160        3930 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
     161             : 
     162        8082 :   return FD_EXECUTOR_INSTR_SUCCESS;
     163       12012 : }
     164             : 
     165             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/src/transaction_context.rs#L976
     166             : static int
     167             : set_state( ulong                       self_acct_idx,
     168             :            fd_borrowed_account_t *     self,
     169             :            fd_vote_state_versioned_t * state,
     170        1158 :            fd_exec_instr_ctx_t const * ctx ) {
     171             : 
     172             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/src/transaction_context.rs#L977
     173        1158 :   do {
     174        1158 :     int err = 0;
     175        1158 :     if( FD_UNLIKELY( !fd_account_can_data_be_changed( ctx->instr, self_acct_idx, &err ) ) )
     176         306 :       return err;
     177        1158 :   } while(0);
     178             : 
     179         852 :   do {
     180         852 :     int err = fd_instr_borrowed_account_modify_idx( ctx, self_acct_idx, 0UL, &self );
     181         852 :     if( FD_UNLIKELY( err ) ) FD_LOG_ERR(( "fd_instr_borrowed_account_modify_idx failed (%d)", err ));
     182         852 :   } while(0);
     183             : 
     184             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/src/transaction_context.rs#L978
     185         852 :   ulong serialized_size = fd_vote_state_versioned_size( state );
     186         852 :   if( FD_UNLIKELY( serialized_size > self->const_meta->dlen ) )
     187          21 :     return FD_EXECUTOR_INSTR_ERR_ACC_DATA_TOO_SMALL;
     188             : 
     189             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/src/transaction_context.rs#L983
     190         831 :   fd_bincode_encode_ctx_t encode =
     191         831 :     { .data    = self->data,
     192         831 :       .dataend = self->data + self->meta->dlen };
     193         831 :   do {
     194         831 :     int err = fd_vote_state_versioned_encode( state, &encode );
     195         831 :     if( FD_UNLIKELY( err ) ) FD_LOG_ERR(( "fd_vote_state_versioned_encode failed (%d)", err ));
     196         831 :   } while(0);
     197             : 
     198         831 :   return FD_EXECUTOR_INSTR_SUCCESS;
     199         831 : }
     200             : 
     201             : /**********************************************************************/
     202             : /* impl AuthorizedVoters                                              */
     203             : /**********************************************************************/
     204             : 
     205             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L17
     206             : static void
     207             : authorized_voters_new( ulong                         epoch,
     208             :                        fd_pubkey_t const *           pubkey,
     209             :                        fd_valloc_t                   valloc,
     210        1935 :                        fd_vote_authorized_voters_t * authorized_voters /* out */ ) {
     211        1935 :   authorized_voters->pool  = fd_vote_authorized_voters_pool_alloc ( valloc, FD_VOTE_AUTHORIZED_VOTERS_MIN );
     212        1935 :   authorized_voters->treap = fd_vote_authorized_voters_treap_alloc( valloc, FD_VOTE_AUTHORIZED_VOTERS_MIN );
     213        1935 :   if( 0 == fd_vote_authorized_voters_pool_free( authorized_voters->pool) ) {
     214           0 :     FD_LOG_ERR(( "Authorized_voter pool is empty" ));
     215           0 :   }
     216        1935 :   fd_vote_authorized_voter_t * ele =
     217        1935 :       fd_vote_authorized_voters_pool_ele_acquire( authorized_voters->pool );
     218        1935 :   ele->epoch = epoch;
     219        1935 :   memcpy( &ele->pubkey, pubkey, sizeof( fd_pubkey_t ) );
     220        1935 :   ele->prio = (ulong)&ele->pubkey;
     221        1935 :   fd_vote_authorized_voters_treap_ele_insert(
     222        1935 :       authorized_voters->treap, ele, authorized_voters->pool );
     223        1935 : }
     224             : 
     225             : static inline int
     226        4737 : authorized_voters_is_empty( fd_vote_authorized_voters_t * self ) {
     227        4737 :   return fd_vote_authorized_voters_treap_ele_cnt( self->treap ) == 0;
     228        4737 : }
     229             : 
     230             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L80
     231             : static inline int
     232         402 : authorized_voters_contains( fd_vote_authorized_voters_t * self, ulong epoch ) {
     233         402 :   return !!fd_vote_authorized_voters_treap_ele_query( self->treap, epoch, self->pool );
     234         402 : }
     235             : 
     236             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L72
     237             : static inline fd_vote_authorized_voter_t *
     238         396 : authorized_voters_last( fd_vote_authorized_voters_t * self ) {
     239         396 :   fd_vote_authorized_voters_treap_rev_iter_t iter =
     240         396 :       fd_vote_authorized_voters_treap_rev_iter_init( self->treap, self->pool );
     241         396 :   return fd_vote_authorized_voters_treap_rev_iter_ele( iter, self->pool );
     242         396 : }
     243             : 
     244             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L43
     245             : static void
     246             : authorized_voters_purge_authorized_voters( fd_vote_authorized_voters_t * self,
     247        3027 :                                            ulong                         current_epoch ) {
     248             : 
     249        3027 :   FD_SCRATCH_SCOPE_BEGIN {
     250             : 
     251             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L46
     252        3027 :   ulong *expired_keys = fd_scratch_alloc( alignof(ulong), fd_vote_authorized_voters_treap_ele_cnt(self->treap) * sizeof(ulong) );
     253        3027 :   ulong key_cnt                                     = 0;
     254        3027 :   for( fd_vote_authorized_voters_treap_fwd_iter_t iter =
     255        3027 :            fd_vote_authorized_voters_treap_fwd_iter_init( self->treap, self->pool );
     256       57372 :        !fd_vote_authorized_voters_treap_fwd_iter_done( iter );
     257       54345 :        iter = fd_vote_authorized_voters_treap_fwd_iter_next( iter, self->pool ) ) {
     258       54345 :     fd_vote_authorized_voter_t * ele =
     259       54345 :         fd_vote_authorized_voters_treap_fwd_iter_ele( iter, self->pool );
     260       54345 :     if( ele->epoch < current_epoch ) expired_keys[key_cnt++] = ele->epoch;
     261       54345 :   }
     262             : 
     263             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L52
     264       50046 :   for( ulong i = 0; i < key_cnt; i++ ) {
     265       47019 :     fd_vote_authorized_voter_t * ele =
     266       47019 :         fd_vote_authorized_voters_treap_ele_query( self->treap, expired_keys[i], self->pool );
     267       47019 :     fd_vote_authorized_voters_treap_ele_remove( self->treap, ele, self->pool );
     268       47019 :     fd_vote_authorized_voters_pool_ele_release( self->pool, ele );
     269             :     // fd_vote_authorized_voter_destroy( &self->pool[i], &ctx3 );
     270       47019 :   }
     271             : 
     272             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L60
     273        3027 :   FD_TEST( !authorized_voters_is_empty( self ) );
     274             : 
     275        3027 :   }
     276        3027 :   FD_SCRATCH_SCOPE_END;
     277             : 
     278        3027 : }
     279             : 
     280             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L91
     281             : static fd_vote_authorized_voter_t *
     282             : authorized_voters_get_or_calculate_authorized_voter_for_epoch( fd_vote_authorized_voters_t * self,
     283             :                                                                ulong                         epoch,
     284        3372 :                                                                int * existed ) {
     285        3372 :   *existed                                  = 0;
     286        3372 :   ulong                        latest_epoch = 0;
     287        3372 :   fd_vote_authorized_voter_t * res =
     288        3372 :       fd_vote_authorized_voters_treap_ele_query( self->treap, epoch, self->pool );
     289             :   // "predecessor" would be more big-O optimal here, but mirroring labs logic
     290             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L93
     291        3372 :   if( FD_UNLIKELY( !res ) ) {
     292        3213 :     for( fd_vote_authorized_voters_treap_fwd_iter_t iter =
     293        3213 :              fd_vote_authorized_voters_treap_fwd_iter_init( self->treap, self->pool );
     294       54480 :          !fd_vote_authorized_voters_treap_fwd_iter_done( iter );
     295       51267 :          iter = fd_vote_authorized_voters_treap_fwd_iter_next( iter, self->pool ) ) {
     296       51267 :       fd_vote_authorized_voter_t * ele =
     297       51267 :           fd_vote_authorized_voters_treap_fwd_iter_ele( iter, self->pool );
     298       51267 :       if( ele->epoch < epoch && ( latest_epoch == 0 || ele->epoch > latest_epoch ) ) {
     299       46989 :         latest_epoch = ele->epoch;
     300       46989 :         res          = ele;
     301       46989 :       }
     302       51267 :     }
     303        3213 :     *existed = 0;
     304        3213 :     return res;
     305        3213 :   } else {
     306         159 :     *existed = 1;
     307         159 :     return res;
     308         159 :   }
     309           0 :   return res;
     310        3372 : }
     311             : 
     312             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L28
     313             : static fd_vote_authorized_voter_t *
     314             : authorized_voters_get_and_cache_authorized_voter_for_epoch( fd_vote_authorized_voters_t * self,
     315        3372 :                                                             ulong                         epoch ) {
     316        3372 :   int                          existed = 0;
     317             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L29
     318        3372 :   fd_vote_authorized_voter_t * res =
     319        3372 :       authorized_voters_get_or_calculate_authorized_voter_for_epoch( self, epoch, &existed );
     320        3372 :   if( !res ) return NULL;
     321             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L32
     322        3027 :   if( !existed ) {
     323             :     /* insert cannot fail because !existed */
     324        2868 :     if( 0 == fd_vote_authorized_voters_pool_free( self->pool) ) {
     325           0 :       FD_LOG_ERR(( "Authorized_voter pool is empty" ));
     326           0 :     }
     327        2868 :     fd_vote_authorized_voter_t * ele = fd_vote_authorized_voters_pool_ele_acquire( self->pool );
     328        2868 :     ele->epoch                       = epoch;
     329        2868 :     memcpy( &ele->pubkey, &res->pubkey, sizeof( fd_pubkey_t ) );
     330        2868 :     ele->prio = (ulong)&res->pubkey;
     331             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L33
     332        2868 :     fd_vote_authorized_voters_treap_ele_insert( self->treap, ele, self->pool );
     333        2868 :   }
     334        3027 :   return res;
     335        3027 : }
     336             : 
     337             : /**********************************************************************/
     338             : /* impl VoteStateVersions                                             */
     339             : /**********************************************************************/
     340             : 
     341             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/vote_state_versions.rs#L66
     342             : static fd_landed_vote_t *
     343             : landed_votes_from_lockouts( fd_vote_lockout_t * lockouts,
     344        4287 :                             fd_valloc_t         valloc ) {
     345        4287 :   if( !lockouts ) return NULL;
     346             : 
     347             :   /* Allocate MAX_LOCKOUT_HISTORY (sane case) by default.  In case the
     348             :      vote account is corrupt, allocate as many entries are needed. */
     349             : 
     350        4287 :   ulong cnt = deq_fd_vote_lockout_t_cnt( lockouts );
     351        4287 :         cnt = fd_ulong_max( cnt, MAX_LOCKOUT_HISTORY );
     352        4287 :   fd_landed_vote_t * landed_votes = deq_fd_landed_vote_t_alloc( valloc, cnt );
     353             : 
     354        4287 :   for( deq_fd_vote_lockout_t_iter_t iter = deq_fd_vote_lockout_t_iter_init( lockouts );
     355      110928 :        !deq_fd_vote_lockout_t_iter_done( lockouts, iter );
     356      106641 :        iter = deq_fd_vote_lockout_t_iter_next( lockouts, iter ) ) {
     357      106641 :     fd_vote_lockout_t const * ele = deq_fd_vote_lockout_t_iter_ele_const( lockouts, iter );
     358             : 
     359      106641 :     fd_landed_vote_t * elem = deq_fd_landed_vote_t_push_tail_nocopy( landed_votes );
     360      106641 :     fd_landed_vote_new( elem );
     361             : 
     362      106641 :     elem->latency                    = 0;
     363      106641 :     elem->lockout.slot               = ele->slot;
     364      106641 :     elem->lockout.confirmation_count = ele->confirmation_count;
     365      106641 :   }
     366             : 
     367        4287 :   return landed_votes;
     368        4287 : }
     369             : 
     370             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/vote_state_versions.rs#L70
     371             : static inline int
     372        2601 : is_uninitialized( fd_vote_state_versioned_t * self ) {
     373        2601 :   switch( self->discriminant ) {
     374         891 :   case fd_vote_state_versioned_enum_v0_23_5:;
     375             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/vote_state_versions.rs#L73
     376         891 :     fd_pubkey_t pubkey_default = { 0 };
     377         891 :     return 0 ==
     378         891 :            memcmp( &self->inner.v0_23_5.authorized_voter, &pubkey_default, sizeof( fd_pubkey_t ) );
     379         804 :   case fd_vote_state_versioned_enum_v1_14_11:;
     380         804 :     return authorized_voters_is_empty( &self->inner.v1_14_11.authorized_voters );
     381         906 :   case fd_vote_state_versioned_enum_current:
     382         906 :     return authorized_voters_is_empty( &self->inner.current.authorized_voters );
     383           0 :   default:
     384           0 :     FD_LOG_ERR(( "missing handler or invalid vote state version: %u", self->discriminant ));
     385        2601 :   }
     386        2601 : }
     387             : 
     388             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/vote_state_versions.rs#L73
     389             : static void
     390             : convert_to_current( fd_vote_state_versioned_t * self,
     391        7533 :                     fd_valloc_t                 valloc ) {
     392        7533 :   switch( self->discriminant ) {
     393             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/vote_state_versions.rs#L19
     394        1926 :   case fd_vote_state_versioned_enum_v0_23_5: {
     395        1926 :     fd_vote_state_0_23_5_t * state = &self->inner.v0_23_5;
     396        1926 :     fd_vote_authorized_voters_t authorized_voters;
     397             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/vote_state_versions.rs#L21
     398        1926 :     authorized_voters_new(
     399        1926 :         state->authorized_voter_epoch, &state->authorized_voter, valloc, &authorized_voters );
     400             : 
     401             :     /* Temporary to hold current */
     402             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/vote_state_versions.rs#L23
     403        1926 :     fd_vote_state_t current = {
     404        1926 :       .node_pubkey           = state->node_pubkey,            /* copy */
     405        1926 :       .authorized_withdrawer = state->authorized_withdrawer,  /* copy */
     406        1926 :       .commission            = state->commission,             /* copy */
     407        1926 :       .votes                 = landed_votes_from_lockouts( state->votes, valloc ),
     408        1926 :       .has_root_slot         = state->has_root_slot,  /* copy */
     409        1926 :       .root_slot             = state->root_slot,      /* copy */
     410        1926 :       .authorized_voters     = authorized_voters,
     411        1926 :       .prior_voters = (fd_vote_prior_voters_t) {
     412        1926 :         .idx      = 31UL,
     413        1926 :         .is_empty = 1,
     414        1926 :       },
     415        1926 :       .epoch_credits  = state->epoch_credits,   /* move */
     416        1926 :       .last_timestamp = state->last_timestamp,  /* deep copy */
     417        1926 :     };
     418             : 
     419             :     /* Move objects */
     420        1926 :     state->epoch_credits = NULL;
     421             : 
     422             :     /* Deallocate objects owned by old vote state */
     423        1926 :     fd_bincode_destroy_ctx_t destroy = { .valloc = valloc };
     424        1926 :     fd_vote_state_0_23_5_destroy( state, &destroy );
     425             : 
     426             :     /* Emplace new vote state into target */
     427        1926 :     self->discriminant = fd_vote_state_versioned_enum_current;
     428        1926 :     memcpy( &self->inner.current, &current, sizeof(fd_vote_state_t) );
     429             : 
     430        1926 :     break;
     431           0 :   }
     432             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/vote_state_versions.rs#L44
     433        2358 :   case fd_vote_state_versioned_enum_v1_14_11: {
     434        2358 :     fd_vote_state_1_14_11_t * state = &self->inner.v1_14_11;
     435             : 
     436             :     /* Temporary to hold current */
     437        2358 :     fd_vote_state_t current = {
     438        2358 :       .node_pubkey            = state->node_pubkey,            /* copy */
     439        2358 :       .authorized_withdrawer  = state->authorized_withdrawer,  /* copy */
     440        2358 :       .commission             = state->commission,             /* copy */
     441        2358 :       .votes                  = landed_votes_from_lockouts( state->votes, valloc ),
     442        2358 :       .has_root_slot          = state->has_root_slot,          /* copy */
     443        2358 :       .root_slot              = state->root_slot,              /* copy */
     444        2358 :       .authorized_voters      = state->authorized_voters,      /* move */
     445        2358 :       .prior_voters           = state->prior_voters,           /* deep copy */
     446        2358 :       .epoch_credits          = state->epoch_credits,          /* move */
     447        2358 :       .last_timestamp         = state->last_timestamp          /* deep copy */
     448        2358 :     };
     449             : 
     450             :     /* Move objects */
     451        2358 :     state->authorized_voters.treap = NULL;
     452        2358 :     state->authorized_voters.pool  = NULL;
     453        2358 :     state->epoch_credits           = NULL;
     454             : 
     455             :     /* Deallocate objects owned by old vote state */
     456        2358 :     fd_bincode_destroy_ctx_t destroy = { .valloc = valloc };
     457        2358 :     fd_vote_state_1_14_11_destroy( state, &destroy );
     458             : 
     459             :     /* Emplace new vote state into target */
     460        2358 :     self->discriminant = fd_vote_state_versioned_enum_current;
     461        2358 :     memcpy( &self->inner.current, &current, sizeof( fd_vote_state_t ) );
     462             : 
     463        2358 :     break;
     464           0 :   }
     465        3249 :   case fd_vote_state_versioned_enum_current:
     466        3249 :     break;
     467           0 :   default:
     468           0 :     FD_LOG_ERR( ( "unsupported vote state version: %u", self->discriminant ) );
     469        7533 :   }
     470        7533 : }
     471             : 
     472             : /**********************************************************************/
     473             : /* impl VoteState                                                     */
     474             : /**********************************************************************/
     475             : 
     476             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L428
     477             : static void
     478             : vote_state_new( fd_vote_init_t *              vote_init,
     479             :                 fd_sol_sysvar_clock_t const * clock,
     480             :                 fd_valloc_t                   valloc,
     481           9 :                 fd_vote_state_t *             vote_state /* out */ ) {
     482           9 :   vote_state->node_pubkey = vote_init->node_pubkey;
     483           9 :   authorized_voters_new(
     484           9 :       clock->epoch, &vote_init->authorized_voter, valloc, &vote_state->authorized_voters );
     485             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L431
     486           9 :   vote_state->authorized_withdrawer = vote_init->authorized_withdrawer;
     487           9 :   vote_state->commission            = vote_init->commission;
     488             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L434
     489           9 :   vote_state->prior_voters.idx      = 31;
     490           9 :   vote_state->prior_voters.is_empty = 1;
     491           9 : }
     492             : 
     493             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L985
     494             : static inline int
     495             : verify_authorized_signer( fd_pubkey_t const * authorized,
     496        6267 :                           fd_pubkey_t const * signers[static FD_TXN_SIG_MAX] ) {
     497             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L989
     498        6267 :   return fd_instr_signers_contains( signers, authorized ) ?
     499        2718 :     FD_EXECUTOR_INSTR_SUCCESS :
     500        6267 :     FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
     501        6267 : }
     502             : 
     503             : // lambda function: https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L873
     504             : static inline int
     505             : verify( fd_pubkey_t *       epoch_authorized_voter,
     506             :         int                 authorized_withdrawer_signer,
     507         807 :         fd_pubkey_t const * signers[static FD_TXN_SIG_MAX] ) {
     508         807 :   if( authorized_withdrawer_signer )
     509         324 :     return 0;
     510         483 :   else
     511         483 :     return verify_authorized_signer( epoch_authorized_voter, signers );
     512         807 : }
     513             : 
     514             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L845
     515             : static void
     516           9 : pop_expired_votes( fd_vote_state_t * self, ulong next_vote_slot ) {
     517          12 :   while( !deq_fd_landed_vote_t_empty( self->votes ) ) {
     518           6 :     fd_landed_vote_t * vote = deq_fd_landed_vote_t_peek_tail( self->votes );
     519           6 :     if( !( is_locked_out_at_slot( &vote->lockout, next_vote_slot ) ) ) {
     520           3 :       deq_fd_landed_vote_t_pop_tail( self->votes );
     521           3 :     } else {
     522           3 :       break;
     523           3 :     }
     524           6 :   }
     525           9 : }
     526             : 
     527             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L855
     528             : static void
     529           9 : double_lockouts( fd_vote_state_t * self ) {
     530             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L856
     531           9 :   ulong stack_depth = deq_fd_landed_vote_t_cnt( self->votes );
     532           9 :   ulong i           = 0;
     533             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L857
     534           9 :   for( deq_fd_landed_vote_t_iter_t iter = deq_fd_landed_vote_t_iter_init( self->votes );
     535          66 :        !deq_fd_landed_vote_t_iter_done( self->votes, iter );
     536          57 :        iter = deq_fd_landed_vote_t_iter_next( self->votes, iter ) ) {
     537          57 :     fd_landed_vote_t * v = deq_fd_landed_vote_t_iter_ele( self->votes, iter );
     538             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L860
     539          57 :     if( stack_depth >
     540          57 :         fd_ulong_checked_add_expect(
     541          57 :             i,
     542          57 :             (ulong)v->lockout.confirmation_count,
     543          57 :             "`confirmation_count` and tower_size should be bounded by `MAX_LOCKOUT_HISTORY`" ) )
     544          18 :       {
     545             :         // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L864
     546          18 :         increase_confirmation_count( &v->lockout, 1 );
     547          18 :       }
     548          57 :     i++;
     549          57 :   }
     550           9 : }
     551             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L668
     552             : static inline uchar
     553           6 : compute_vote_latency( ulong voted_for_slot, ulong current_slot ) {
     554           6 :   return (uchar)fd_ulong_min( fd_ulong_sat_sub( current_slot, voted_for_slot ), UCHAR_MAX );
     555           6 : }
     556             : 
     557             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L673
     558             : static ulong
     559          33 : credits_for_vote_at_index( fd_vote_state_t * self, ulong index, int timely_vote_credits, int deprecate_unused_legacy_vote_plumbing ) {
     560             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L679
     561          33 :   fd_landed_vote_t * landed_vote = deq_fd_landed_vote_t_peek_index( self->votes, index );
     562          33 :   ulong              latency     = landed_vote == NULL ? 0 : landed_vote->latency;
     563             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L683
     564          33 :   ulong              max_credits = deprecate_unused_legacy_vote_plumbing ?
     565          33 :                                    VOTE_CREDITS_MAXIMUM_PER_SLOT : VOTE_CREDITS_MAXIMUM_PER_SLOT_OLD;
     566             : 
     567             :   // If latency is 0, this means that the Lockout was created and stored from a software version
     568             :   // that did not store vote latencies; in this case, 1 credit is awarded
     569             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L691
     570          33 :   if( FD_UNLIKELY( latency == 0 || (deprecate_unused_legacy_vote_plumbing && !timely_vote_credits) ) ) {
     571          33 :     return 1;
     572          33 :   }
     573             : 
     574           0 :   ulong diff = 0;
     575           0 :   int   cf   = fd_ulong_checked_sub( latency, VOTE_CREDITS_GRACE_SLOTS, &diff );
     576           0 :   if( cf != 0 || diff == 0 ) {
     577             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L697
     578           0 :     return max_credits;
     579           0 :   }
     580             : 
     581           0 :   ulong credits = 0;
     582           0 :   cf = fd_ulong_checked_sub( max_credits, diff, &credits );
     583           0 :   if( cf != 0 || credits == 0 ) {
     584             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L705
     585           0 :     return 1;
     586           0 :   }
     587             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L707
     588           0 :   return credits;
     589           0 : }
     590             : 
     591             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L639
     592             : static void
     593          24 : increment_credits( fd_vote_state_t * self, ulong epoch, ulong credits ) {
     594             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L643
     595          24 :   if( FD_UNLIKELY( deq_fd_vote_epoch_credits_t_empty( self->epoch_credits ) ) ) {
     596             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L644
     597           0 :     deq_fd_vote_epoch_credits_t_push_tail(
     598           0 :         self->epoch_credits,
     599           0 :         ( fd_vote_epoch_credits_t ){ .epoch = epoch, .credits = 0, .prev_credits = 0 } );
     600          24 :   } else if( FD_LIKELY( epoch !=
     601          24 :                         deq_fd_vote_epoch_credits_t_peek_tail( self->epoch_credits )->epoch ) ) {
     602           0 :     fd_vote_epoch_credits_t * last = deq_fd_vote_epoch_credits_t_peek_tail( self->epoch_credits );
     603             : 
     604           0 :     ulong credits      = last->credits;
     605           0 :     ulong prev_credits = last->prev_credits;
     606             : 
     607             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L648
     608           0 :     if( FD_LIKELY( credits != prev_credits ) ) {
     609           0 :       deq_fd_vote_epoch_credits_t_push_tail(
     610           0 :           self->epoch_credits,
     611           0 :           ( fd_vote_epoch_credits_t ){
     612           0 :               .epoch = epoch, .credits = credits, .prev_credits = credits } );
     613           0 :     } else {
     614             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L654
     615           0 :       deq_fd_vote_epoch_credits_t_peek_tail( self->epoch_credits )->epoch = epoch;
     616           0 :     }
     617             : 
     618             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L658
     619           0 :     if( FD_UNLIKELY( deq_fd_vote_epoch_credits_t_cnt( self->epoch_credits ) >
     620           0 :                      MAX_EPOCH_CREDITS_HISTORY ) ) {
     621           0 :       deq_fd_vote_epoch_credits_t_pop_head( self->epoch_credits );
     622           0 :     }
     623           0 :   }
     624             : 
     625             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L663
     626          24 :   deq_fd_vote_epoch_credits_t_peek_tail( self->epoch_credits )->credits = fd_ulong_sat_add(
     627          24 :       deq_fd_vote_epoch_credits_t_peek_tail( self->epoch_credits )->credits, credits );
     628          24 : }
     629             : 
     630             : static inline ulong *
     631             : last_voted_slot( fd_vote_state_t * self );
     632             : 
     633             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L595
     634             : static void
     635             : process_next_vote_slot( fd_vote_state_t * self,
     636             :                         ulong             next_vote_slot,
     637             :                         ulong             epoch,
     638             :                         ulong             current_slot,
     639             :                         int               timely_vote_credits,
     640             :                         int               deprecate_unused_legacy_vote_plumbing
     641             : 
     642          24 :  ) {
     643          24 :   ulong * last_voted_slot_ = last_voted_slot( self );
     644          24 :   if( FD_UNLIKELY( last_voted_slot_ && next_vote_slot <= *last_voted_slot_ ) ) return;
     645             : 
     646           9 :   pop_expired_votes( self, next_vote_slot );
     647             : 
     648           9 :   fd_landed_vote_t landed_vote = { .latency = (timely_vote_credits || !deprecate_unused_legacy_vote_plumbing) ?
     649             :                                    // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L615
     650           3 :                                    compute_vote_latency( next_vote_slot, current_slot ) :
     651             :                                    // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L617
     652           9 :                                    0,
     653           9 :                                    ( fd_vote_lockout_t ){ .slot = next_vote_slot } };
     654             : 
     655             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L623
     656           9 :   if( FD_UNLIKELY( deq_fd_landed_vote_t_cnt( self->votes ) == MAX_LOCKOUT_HISTORY ) ) {
     657           0 :     ulong            credits     = credits_for_vote_at_index( self, 0, timely_vote_credits, deprecate_unused_legacy_vote_plumbing);
     658           0 :     fd_landed_vote_t landed_vote = deq_fd_landed_vote_t_pop_head( self->votes );
     659           0 :     self->has_root_slot = 1;
     660           0 :     self->root_slot     = landed_vote.lockout.slot;
     661             : 
     662           0 :     increment_credits( self, epoch, credits );
     663           0 :   }
     664             : 
     665             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L634
     666           9 :   deq_fd_landed_vote_t_push_tail( self->votes, landed_vote );
     667           9 :   double_lockouts( self );
     668           9 : }
     669             : 
     670             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L828
     671             : static int
     672             : get_and_update_authorized_voter( fd_vote_state_t *           self,
     673             :                                  ulong                       current_epoch,
     674        3372 :                                  fd_pubkey_t **              pubkey /* out */ ) {
     675             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L832
     676        3372 :   fd_vote_authorized_voter_t * authorized_voter =
     677        3372 :       authorized_voters_get_and_cache_authorized_voter_for_epoch( &self->authorized_voters,
     678        3372 :                                                                   current_epoch );
     679             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L835
     680        3372 :   if( FD_UNLIKELY( !authorized_voter ) ) return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
     681        3027 :   *pubkey = &authorized_voter->pubkey;
     682             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L837
     683        3027 :   authorized_voters_purge_authorized_voters( &self->authorized_voters, current_epoch );
     684        3027 :   return FD_EXECUTOR_INSTR_SUCCESS;
     685        3372 : }
     686             : 
     687             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L768
     688             : static int
     689             : set_new_authorized_voter( fd_vote_state_t *                          self,
     690             :                           fd_pubkey_t const *                        authorized_pubkey,
     691             :                           ulong                                      current_epoch,
     692             :                           ulong                                      target_epoch,
     693             :                           /* "verify" closure */ int                 authorized_withdrawer_signer,
     694             :                           /* "verify" closure */ fd_pubkey_t const * signers[static FD_TXN_SIG_MAX],
     695         855 :                           fd_exec_instr_ctx_t const *                ctx ) {
     696         855 :   int           rc;
     697         855 :   fd_pubkey_t * epoch_authorized_voter = NULL;
     698             : 
     699             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L778
     700         855 :   rc = get_and_update_authorized_voter( self, current_epoch, &epoch_authorized_voter );
     701         855 :   if( FD_UNLIKELY( rc ) ) return rc;
     702             : 
     703             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L779
     704         807 :   rc = verify( epoch_authorized_voter, authorized_withdrawer_signer, signers );
     705         807 :   if( FD_UNLIKELY( rc ) ) return rc;
     706             : 
     707             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L786
     708         402 :   if( FD_UNLIKELY( authorized_voters_contains( &self->authorized_voters, target_epoch ) ) ) {
     709           6 :     ctx->txn_ctx->custom_err = FD_VOTE_ERR_TOO_SOON_TO_REAUTHORIZE;
     710           6 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     711           6 :   }
     712             : 
     713             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L791
     714         396 :   fd_vote_authorized_voter_t * latest_authorized =
     715         396 :       authorized_voters_last( &self->authorized_voters );
     716             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L794
     717         396 :   if( FD_UNLIKELY( ( !latest_authorized ) ) ) return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
     718         396 :   ulong         latest_epoch             = latest_authorized->epoch;
     719         396 :   fd_pubkey_t * latest_authorized_pubkey = &latest_authorized->pubkey;
     720             : 
     721             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L799
     722         396 :   if( 0 != memcmp( latest_authorized_pubkey, authorized_pubkey, sizeof( fd_pubkey_t ) ) ) {
     723         273 :     fd_vote_prior_voters_t * prior_voters = &self->prior_voters;
     724             : 
     725             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L801
     726         273 :     ulong epoch_of_last_authorized_switch = 0UL;
     727         273 :     if( (!prior_voters->is_empty) & (prior_voters->idx < 32) ) {
     728          45 :       epoch_of_last_authorized_switch = prior_voters->buf[prior_voters->idx].epoch_end;
     729          45 :     }
     730             : 
     731             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L810
     732         273 :     if( target_epoch <= latest_epoch )
     733         141 :       return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
     734             : 
     735             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L815
     736         132 :     prior_voters->idx += 1UL;
     737         132 :     prior_voters->idx %= 32UL;
     738         132 :     prior_voters->buf[prior_voters->idx] =
     739         132 :         ( fd_vote_prior_voter_t ){ .pubkey      = *latest_authorized_pubkey,
     740         132 :                                    .epoch_start = epoch_of_last_authorized_switch,
     741         132 :                                    .epoch_end   = target_epoch };
     742         132 :     prior_voters->is_empty = 0;
     743         132 :   }
     744             : 
     745             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L822
     746         255 :   if( 0 == fd_vote_authorized_voters_pool_free( self->authorized_voters.pool) ) {
     747           0 :     FD_LOG_ERR(( "Authorized_voter pool is empty" ));
     748           0 :   }
     749             : 
     750         255 :   fd_vote_authorized_voter_t * ele =
     751         255 :       fd_vote_authorized_voters_pool_ele_acquire( self->authorized_voters.pool );
     752         255 :   ele->epoch = target_epoch;
     753         255 :   memcpy( &ele->pubkey, authorized_pubkey, sizeof( fd_pubkey_t ) );
     754         255 :   ele->prio = (ulong)&ele->pubkey;
     755         255 :   fd_vote_authorized_voters_treap_ele_insert(
     756         255 :       self->authorized_voters.treap, ele, self->authorized_voters.pool );
     757             : 
     758         255 :   return 0;
     759         255 : }
     760             : 
     761             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L869
     762             : static int
     763             : process_timestamp( fd_vote_state_t *           self,
     764             :                    ulong                       slot,
     765             :                    long                        timestamp,
     766          36 :                    fd_exec_instr_ctx_t const * ctx ) {
     767          36 :   if( FD_UNLIKELY(
     768          36 :           ( slot < self->last_timestamp.slot || timestamp < self->last_timestamp.timestamp ) ||
     769          36 :           ( slot == self->last_timestamp.slot &&
     770          36 :             ( slot != self->last_timestamp.slot || timestamp != self->last_timestamp.timestamp ) &&
     771          36 :             self->last_timestamp.slot != 0 ) ) ) {
     772           9 :     ctx->txn_ctx->custom_err = FD_VOTE_ERR_TIMESTAMP_TOO_OLD;
     773           9 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     774           9 :   }
     775          27 :   self->last_timestamp.slot      = slot;
     776          27 :   self->last_timestamp.timestamp = timestamp;
     777             : 
     778          27 :   return 0;
     779          36 : }
     780             : 
     781             : /**********************************************************************/
     782             : /* mod vote_state                                                    */
     783             : /**********************************************************************/
     784             : 
     785             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L166
     786             : __attribute__((warn_unused_result)) static int
     787             : set_vote_account_state( ulong                       vote_acct_idx,
     788             :                         fd_borrowed_account_t *     vote_account,
     789             :                         fd_vote_state_t *           vote_state,
     790        1158 :                         fd_exec_instr_ctx_t const * ctx /* feature_set */ ) {
     791             : 
     792        1158 :   if( FD_FEATURE_ACTIVE( ctx->slot_ctx, vote_state_add_vote_latency ) ) {
     793             :     /* This is a horrible conditional expression in Agave.
     794             :        The terms were broken up into their own variables. */
     795             : 
     796        1158 :     ulong vsz = size_of_versioned( 1 );
     797             : 
     798             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L175
     799        1158 :     int resize_needed      = vote_account->const_meta->dlen < vsz;
     800        1158 :     fd_epoch_bank_t const * epoch_bank = fd_exec_epoch_ctx_epoch_bank_const( ctx->epoch_ctx );
     801        1158 :     int resize_rent_exempt = fd_rent_exempt_minimum_balance( &epoch_bank->rent, vsz ) <= vote_account->const_meta->info.lamports;
     802             : 
     803             :     /* The resize operation itself is part of the horrible conditional,
     804             :        but behind a short-circuit operator. */
     805        1158 :     int resize_failed = 0;
     806        1158 :     if( resize_needed && resize_rent_exempt ) {
     807             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L179
     808         903 :       resize_failed =
     809         903 :         fd_account_set_data_length( ctx, vote_acct_idx, vsz ) != FD_EXECUTOR_INSTR_SUCCESS;
     810         903 :     }
     811             : 
     812        1158 :     if( FD_UNLIKELY( resize_needed && ( !resize_rent_exempt || resize_failed ) ) ) {
     813             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L184
     814         351 :       fd_vote_state_versioned_t v1_14_11;
     815         351 :       fd_vote_state_versioned_new_disc( &v1_14_11, fd_vote_state_versioned_enum_v1_14_11 );
     816         351 :       from_vote_state_1_14_11( vote_state, &v1_14_11.inner.v1_14_11, fd_scratch_virtual() );
     817         351 :       return set_state( vote_acct_idx, vote_account, &v1_14_11, ctx );
     818         351 :     }
     819             : 
     820             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L189
     821             :     // TODO: This is stupid...  optimize this...
     822         807 :     fd_vote_state_versioned_t new_current = { .discriminant = fd_vote_state_versioned_enum_current,
     823         807 :                                               .inner        = { .current = *vote_state } };
     824         807 :     return set_state( vote_acct_idx, vote_account, &new_current, ctx );
     825        1158 :   } else {
     826             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L192
     827           0 :     fd_vote_state_versioned_t v1_14_11;
     828           0 :     fd_vote_state_versioned_new_disc( &v1_14_11, fd_vote_state_versioned_enum_v1_14_11 );
     829             : 
     830           0 :     from_vote_state_1_14_11( vote_state, &v1_14_11.inner.v1_14_11, fd_scratch_virtual() );
     831           0 :     return set_state( vote_acct_idx, vote_account, &v1_14_11, ctx );
     832           0 :   }
     833        1158 : }
     834             : 
     835             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L727
     836             : static inline fd_vote_lockout_t *
     837       50430 : last_lockout( fd_vote_state_t * self ) {
     838       50430 :   if( deq_fd_landed_vote_t_empty( self->votes ) ) return NULL;
     839       37038 :   fd_landed_vote_t * last_vote = deq_fd_landed_vote_t_peek_tail( self->votes );
     840       37038 :   return &last_vote->lockout;
     841       50430 : }
     842             : 
     843             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L731
     844             : static inline ulong *
     845       50430 : last_voted_slot( fd_vote_state_t * self ) {
     846       50430 :   fd_vote_lockout_t * last_lockout_ = last_lockout( self );
     847       50430 :   if( FD_UNLIKELY( !last_lockout_ ) ) return NULL;
     848       37038 :   return &last_lockout_->slot;
     849       50430 : }
     850             : 
     851             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L573
     852             : static uchar
     853         423 : contains_slot( fd_vote_state_t * vote_state, ulong slot ) {
     854             :   /* Logic is copied from slice::binary_search_by() in Rust */
     855         423 :   ulong start = 0UL;
     856         423 :   ulong end   = deq_fd_landed_vote_t_cnt( vote_state->votes );
     857             : 
     858        2241 :   while( start < end ) {
     859        1845 :     ulong mid      = start + ( end - start ) / 2UL;
     860        1845 :     ulong mid_slot = deq_fd_landed_vote_t_peek_index_const( vote_state->votes, mid )->lockout.slot;
     861        1845 :     if( mid_slot == slot ) {
     862          27 :       return 1;
     863        1818 :     } else if( mid_slot < slot ) {
     864         564 :       start = mid + 1UL;
     865        1254 :     } else {
     866        1254 :       end = mid;
     867        1254 :     }
     868        1845 :   }
     869         396 :   return 0;
     870         423 : }
     871             : 
     872             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L201
     873             : static int
     874             : check_and_filter_proposed_vote_state( fd_vote_state_t *           vote_state,
     875             :                                       fd_vote_lockout_t *         proposed_lockouts,
     876             :                                       uchar *                     proposed_has_root,
     877             :                                       ulong *                     proposed_root,
     878             :                                       fd_hash_t const *           proposed_hash,
     879             :                                       fd_slot_hashes_t const *    slot_hashes,
     880         507 :                                       fd_exec_instr_ctx_t const * ctx ) {
     881             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L208
     882         507 :   if( FD_UNLIKELY( deq_fd_vote_lockout_t_empty( proposed_lockouts ) ) ) {
     883          45 :     ctx->txn_ctx->custom_err = FD_VOTE_ERR_EMPTY_SLOTS;
     884          45 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     885          45 :   }
     886         462 :   fd_landed_vote_t const * last_vote = NULL;
     887         462 :   if( !deq_fd_landed_vote_t_empty( vote_state->votes ) ) {
     888             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L212
     889         393 :     last_vote = deq_fd_landed_vote_t_peek_tail( vote_state->votes );
     890         393 :   }
     891             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L218
     892         462 :   if( FD_LIKELY( last_vote ) ) {
     893         393 :     if( FD_UNLIKELY( deq_fd_vote_lockout_t_peek_tail_const( proposed_lockouts )->slot <=
     894         393 :                      last_vote->lockout.slot ) ) {
     895           9 :       ctx->txn_ctx->custom_err = FD_VOTE_ERROR_VOTE_TOO_OLD;
     896           9 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     897           9 :     }
     898         393 :   }
     899             : 
     900             :   /* must be nonempty, checked above */
     901         453 :   ulong last_vote_state_update_slot = deq_fd_vote_lockout_t_peek_tail_const( proposed_lockouts )->slot;
     902             : 
     903             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L224
     904         453 :   if( FD_UNLIKELY( deq_fd_slot_hash_t_empty( slot_hashes->hashes ) ) ) {
     905          36 :     ctx->txn_ctx->custom_err = FD_VOTE_ERR_SLOTS_MISMATCH;
     906          36 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     907          36 :   }
     908             : 
     909             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L227
     910         417 :   ulong earliest_slot_hash_in_history = deq_fd_slot_hash_t_peek_tail_const( slot_hashes->hashes )->slot;
     911             : 
     912             :   /* Check if the proposed vote is too old to be in the SlotHash history */
     913             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L230
     914         417 :   if( FD_UNLIKELY( last_vote_state_update_slot < earliest_slot_hash_in_history ) ) {
     915          27 :     ctx->txn_ctx->custom_err = FD_VOTE_ERROR_VOTE_TOO_OLD;
     916          27 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     917          27 :   }
     918             : 
     919             :   /* Check if the proposed root is too old */
     920             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L237
     921         390 :   if( *proposed_has_root ) {
     922         246 :     ulong const proposed_root_ = *proposed_root;
     923             :     /* If the new proposed root `R` is less than the earliest slot hash in the history
     924             :        such that we cannot verify whether the slot was actually was on this fork, set
     925             :        the root to the latest vote in the current vote that's less than R. */
     926             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L242
     927         246 :     if( proposed_root_ < earliest_slot_hash_in_history ) {
     928         165 :       *proposed_has_root = vote_state->has_root_slot;
     929         165 :       *proposed_root     = vote_state->root_slot;
     930         165 :       for( deq_fd_landed_vote_t_iter_t iter =
     931         165 :                deq_fd_landed_vote_t_iter_init_rev( vote_state->votes );
     932        1689 :            !deq_fd_landed_vote_t_iter_done_rev( vote_state->votes, iter );
     933        1584 :            iter = deq_fd_landed_vote_t_iter_prev( vote_state->votes, iter ) ) {
     934             :         /* Ensure we're iterating from biggest to smallest vote in the
     935             :            current vote state */
     936        1584 :         fd_landed_vote_t const * vote = deq_fd_landed_vote_t_iter_ele_const( vote_state->votes, iter );
     937             :         // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L248
     938        1584 :         if( vote->lockout.slot <= proposed_root_ ) {
     939          60 :           *proposed_has_root = 1;
     940          60 :           *proposed_root     = vote->lockout.slot;
     941          60 :           break;
     942          60 :         }
     943             : 
     944        1584 :       }
     945         165 :     }
     946         246 :   }
     947             : 
     948         390 :   FD_SCRATCH_SCOPE_BEGIN {
     949             : 
     950             :     /* Index into the new proposed vote state's slots, starting with the root if it exists then
     951             :        we use this mutable root to fold checking the root slot into the below loop for performance */
     952         390 :     int     has_root_to_check       = *proposed_has_root;
     953             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L259
     954         390 :     ulong   root_to_check           = *proposed_root;
     955         390 :     ulong   proposed_lockouts_index = 0UL;
     956         390 :     ulong   lockouts_len = deq_fd_vote_lockout_t_cnt( proposed_lockouts );
     957             : 
     958             :     /* Index into the slot_hashes, starting at the oldest known slot hash */
     959             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L264
     960         390 :     ulong   slot_hashes_index = deq_fd_slot_hash_t_cnt( slot_hashes->hashes );
     961         390 :     ulong * proposed_lockouts_indexes_to_filter = fd_scratch_alloc( alignof(ulong), lockouts_len * sizeof(ulong) );
     962         390 :     ulong   filter_index = 0UL;
     963             : 
     964             : 
     965             :     /* Note:
     966             : 
     967             :        1) `vote_state_update.lockouts` is sorted from oldest/smallest vote to newest/largest
     968             :        vote, due to the way votes are applied to the vote state (newest votes
     969             :        pushed to the back).
     970             : 
     971             :        2) Conversely, `slot_hashes` is sorted from newest/largest vote to
     972             :        the oldest/smallest vote
     973             : 
     974             :        Unlike for vote updates, vote state updates here can't only check votes older than the last vote
     975             :        because have to ensure that every slot is actually part of the history, not just the most
     976             :        recent ones */
     977             : 
     978             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L279
     979       29658 :     while( proposed_lockouts_index < lockouts_len && slot_hashes_index > 0 ) {
     980       29556 :       ulong proposed_vote_slot =
     981       29556 :         fd_ulong_if( has_root_to_check,
     982             :           // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L281
     983       29556 :           root_to_check,
     984             :           // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L283
     985       29556 :           deq_fd_vote_lockout_t_peek_index_const( proposed_lockouts,
     986       29556 :             proposed_lockouts_index )
     987       29556 :           ->slot );
     988             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L285
     989       29556 :       if( !has_root_to_check && proposed_lockouts_index > 0UL &&
     990       29556 :         proposed_vote_slot <=
     991        1200 :         deq_fd_vote_lockout_t_peek_index_const(
     992        1200 :           proposed_lockouts,
     993        1200 :             fd_ulong_checked_sub_expect(
     994        1200 :               proposed_lockouts_index,
     995        1200 :                 1,
     996        1200 :                 "`proposed_lockouts_index` is positive when checking `SlotsNotOrdered`" ) )
     997        1200 :         ->slot ) {
     998             :         // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L293
     999           9 :         ctx->txn_ctx->custom_err = FD_VOTE_ERR_SLOTS_NOT_ORDERED;
    1000           9 :         return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1001           9 :       }
    1002             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L295
    1003       29547 :       ulong ancestor_slot =
    1004       29547 :         deq_fd_slot_hash_t_peek_index_const(
    1005       29547 :           slot_hashes->hashes,
    1006       29547 :             fd_ulong_checked_sub_expect(
    1007       29547 :               slot_hashes_index,
    1008       29547 :                 1UL,
    1009       29547 :                 "`slot_hashes_index` is positive when computing `ancestor_slot`" ) )
    1010       29547 :         ->slot;
    1011             :       /* Find if this slot in the proposed vote state exists in the SlotHashes history
    1012             :          to confirm if it was a valid ancestor on this fork */
    1013             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L303
    1014       29547 :       if( proposed_vote_slot < ancestor_slot ) {
    1015         702 :         if( slot_hashes_index == deq_fd_slot_hash_t_cnt( slot_hashes->hashes ) ) {
    1016             :           /* The vote slot does not exist in the SlotHashes history because it's too old,
    1017             :              i.e. older than the oldest slot in the history. */
    1018         423 :           if( proposed_vote_slot >= earliest_slot_hash_in_history ) {
    1019           0 :             ctx->txn_ctx->custom_err = 0;
    1020           0 :             return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1021           0 :           }
    1022             :           // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L310
    1023         423 :           if( !contains_slot( vote_state, proposed_vote_slot ) && !has_root_to_check ) {
    1024             :             /* If the vote slot is both:
    1025             :                1) Too old
    1026             :                2) Doesn't already exist in vote state
    1027             :                Then filter it out */
    1028         327 :             proposed_lockouts_indexes_to_filter[filter_index++] = proposed_lockouts_index;        }
    1029             :           // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L318
    1030         423 :           if( has_root_to_check ) {
    1031          93 :             ulong new_proposed_root = root_to_check;
    1032             :             /* 1. Because `root_to_check.is_some()`, then we know that
    1033             :                we haven't checked the root yet in this loop, so
    1034             :                `proposed_vote_slot` == `new_proposed_root` == `vote_state_update.root` */
    1035          93 :             FD_TEST( new_proposed_root == proposed_vote_slot );
    1036             :             /* 2. We know from the assert earlier in the function that
    1037             :                `proposed_vote_slot < earliest_slot_hash_in_history`,
    1038             :                so from 1. we know that `new_proposed_root < earliest_slot_hash_in_history` */
    1039          93 :             if( new_proposed_root >= earliest_slot_hash_in_history ) {
    1040           0 :               ctx->txn_ctx->custom_err = 0;
    1041           0 :               return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1042           0 :             }
    1043             : 
    1044             :             // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L329
    1045          93 :             has_root_to_check = 0;
    1046          93 :             root_to_check     = ULONG_MAX;
    1047         330 :           } else {
    1048             :             // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L331
    1049         330 :             proposed_lockouts_index = fd_ulong_checked_add_expect(
    1050         330 :               proposed_lockouts_index,
    1051         330 :                 1,
    1052         330 :                 "`proposed_lockouts_index` is bounded by `MAX_LOCKOUT_HISTORY` when "
    1053         330 :                 "`proposed_vote_slot` is too old to be in SlotHashes history" );
    1054         330 :           }
    1055         423 :           continue;
    1056         423 :         } else {
    1057             :           /* If the vote slot is new enough to be in the slot history,
    1058             :              but is not part of the slot history, then it must belong to another fork,
    1059             :              which means this vote state update is invalid. */
    1060             :           // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L340
    1061         279 :           if( has_root_to_check ) {
    1062          87 :             ctx->txn_ctx->custom_err = FD_VOTE_ERR_ROOT_ON_DIFFERENT_FORK;
    1063          87 :             return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1064         192 :           } else {
    1065         192 :             ctx->txn_ctx->custom_err = FD_VOTE_ERR_SLOTS_MISMATCH;
    1066         192 :             return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1067         192 :           }
    1068         279 :         }
    1069       28845 :       } else if( proposed_vote_slot > ancestor_slot ) {
    1070             :         // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L347
    1071             : 
    1072             :         /* Decrement `slot_hashes_index` to find newer slots in the SlotHashes history */
    1073       28029 :         slot_hashes_index = fd_ulong_checked_sub_expect(
    1074       28029 :           slot_hashes_index,
    1075       28029 :             1,
    1076       28029 :             "`slot_hashes_index` is positive when finding newer slots in SlotHashes history" );
    1077       28029 :         continue;
    1078       28029 :       } else {
    1079             :         // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L354
    1080             : 
    1081             :         /* Once the slot in `vote_state_update.lockouts` is found, bump to the next slot
    1082             :            in `vote_state_update.lockouts` and continue. If we were checking the root,
    1083             :            start checking the vote state instead. */
    1084         816 :         if( has_root_to_check ) {
    1085          24 :           has_root_to_check = 0;
    1086          24 :           root_to_check     = ULONG_MAX;
    1087         792 :         } else {
    1088         792 :           proposed_lockouts_index = fd_ulong_checked_add_expect(
    1089         792 :             proposed_lockouts_index,
    1090         792 :               1,
    1091         792 :               "`proposed_lockouts_index` is bounded by `MAX_LOCKOUT_HISTORY` "
    1092         792 :               "when match is found in SlotHashes history" );
    1093         792 :           slot_hashes_index = fd_ulong_checked_sub_expect(
    1094         792 :             slot_hashes_index,
    1095         792 :               1,
    1096         792 :               "`slot_hashes_index` is positive when match is found in SlotHashes history" );
    1097         792 :         }
    1098         816 :       }
    1099       29547 :     }
    1100             : 
    1101             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L372
    1102         102 :     if( proposed_lockouts_index != deq_fd_vote_lockout_t_cnt( proposed_lockouts ) ) {
    1103             :       /* The last vote slot in the update did not exist in SlotHashes */
    1104          39 :       ctx->txn_ctx->custom_err = FD_VOTE_ERR_SLOTS_MISMATCH;
    1105          39 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1106          39 :     }
    1107             : 
    1108             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L401
    1109          63 :     if( memcmp( &deq_fd_slot_hash_t_peek_index_const( slot_hashes->hashes, slot_hashes_index )->hash,
    1110          63 :         proposed_hash,
    1111          63 :         sizeof( fd_hash_t ) ) != 0 ) {
    1112             :       /* This means the newest vote in the slot has a match that
    1113             :          doesn't match the expected hash for that slot on this fork */
    1114           6 :       ctx->txn_ctx->custom_err = FD_VOTE_ERR_SLOTS_HASH_MISMATCH;
    1115           6 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1116           6 :     }
    1117             : 
    1118             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L418
    1119             :     /* Filter out the irrelevant votes */
    1120          57 :     proposed_lockouts_index = 0UL;
    1121          57 :     ulong filter_votes_index = deq_fd_vote_lockout_t_cnt( proposed_lockouts );
    1122             : 
    1123             :     /* We need to iterate backwards here because proposed_lockouts_indexes_to_filter[ i ] is a
    1124             :        strictly increasing value. Forward iterating can lead to the proposed lockout indicies to get
    1125             :        shifted leading to popping the wrong proposed lockouts or out of bounds accessing. We need
    1126             :        to be sure of handling underflow in this case. */
    1127             : 
    1128         270 :     for( ulong i=filter_index; i>0UL && filter_votes_index>0UL; i-- ) {
    1129         213 :       proposed_lockouts_index = i - 1UL;
    1130         213 :       if( FD_UNLIKELY(proposed_lockouts_indexes_to_filter[ proposed_lockouts_index ]>=filter_votes_index ) ) {
    1131           0 :         return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_PROGRAM_ID;
    1132           0 :       }
    1133             : 
    1134         213 :       deq_fd_vote_lockout_t_pop_idx_tail( proposed_lockouts, proposed_lockouts_indexes_to_filter[ proposed_lockouts_index ] );
    1135         213 :       filter_votes_index--;
    1136         213 :     }
    1137         390 :   } FD_SCRATCH_SCOPE_END;
    1138             : 
    1139          57 :   return FD_EXECUTOR_INSTR_SUCCESS;
    1140         390 : }
    1141             : 
    1142             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L440
    1143             : static int
    1144             : check_slots_are_valid( fd_vote_state_t *        vote_state,
    1145             :                        ulong const *            vote_slots,
    1146             :                        fd_hash_t const *        vote_hash,
    1147             :                        fd_slot_hashes_t const * slot_hashes,
    1148         396 :                        fd_exec_instr_ctx_t const * ctx ) {
    1149         396 :   ulong i              = 0;
    1150         396 :   ulong j              = deq_fd_slot_hash_t_cnt( slot_hashes->hashes );
    1151         396 :   ulong vote_slots_len = deq_ulong_cnt( vote_slots );
    1152             : 
    1153             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L462
    1154       50802 :   while( i < vote_slots_len && j > 0 ) {
    1155       50406 :     ulong * last_voted_slot_ = last_voted_slot( vote_state );
    1156       50406 :     if( FD_UNLIKELY( last_voted_slot_ &&
    1157       50406 :                      *deq_ulong_peek_index_const( vote_slots, i ) <= *last_voted_slot_ ) ) {
    1158             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L469
    1159        1755 :       i = fd_ulong_checked_add_expect(
    1160        1755 :           i, 1, "`i` is bounded by `MAX_LOCKOUT_HISTORY` when finding larger slots" );
    1161        1755 :       continue;
    1162        1755 :     }
    1163             : 
    1164             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L476
    1165       48651 :     if( FD_UNLIKELY(
    1166       48651 :             *deq_ulong_peek_index_const( vote_slots, i ) !=
    1167       48651 :             deq_fd_slot_hash_t_peek_index( slot_hashes->hashes,
    1168       48651 :                                            fd_ulong_checked_sub_expect( j, 1, "`j` is positive" ) )
    1169       48651 :                 ->slot ) ) {
    1170       48531 :       j = fd_ulong_checked_sub_expect( j, 1, "`j` is positive when finding newer slots" );
    1171       48531 :       continue;
    1172       48531 :     }
    1173             : 
    1174             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L486
    1175         120 :     i = fd_ulong_checked_add_expect(
    1176         120 :         i, 1, "`i` is bounded by `MAX_LOCKOUT_HISTORY` when hash is found" );
    1177         120 :     j = fd_ulong_checked_sub_expect( j, 1, "`j` is positive when hash is found" );
    1178         120 :   }
    1179             : 
    1180             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L494
    1181         396 :   if( FD_UNLIKELY( j == deq_fd_slot_hash_t_cnt( slot_hashes->hashes ) ) ) {
    1182         111 :     ctx->txn_ctx->custom_err = FD_VOTE_ERROR_VOTE_TOO_OLD;
    1183         111 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1184         111 :   }
    1185         285 :   if( FD_UNLIKELY( i != vote_slots_len ) ) {
    1186         273 :     ctx->txn_ctx->custom_err = FD_VOTE_ERR_SLOTS_MISMATCH;
    1187         273 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1188         273 :   }
    1189             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L514
    1190          12 :   if( FD_UNLIKELY( 0 != memcmp( &deq_fd_slot_hash_t_peek_index( slot_hashes->hashes, j )->hash,
    1191          12 :                                 vote_hash,
    1192          12 :                                 32UL ) ) ) {
    1193           3 :     ctx->txn_ctx->custom_err = FD_VOTE_ERR_SLOTS_HASH_MISMATCH;
    1194           3 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1195           3 :   }
    1196           9 :   return 0;
    1197          12 : }
    1198             : 
    1199             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L565
    1200             : static int
    1201             : process_new_vote_state( fd_vote_state_t *           vote_state,
    1202             :                         fd_landed_vote_t *          new_state,
    1203             :                         int                         has_new_root,
    1204             :                         ulong                       new_root,
    1205             :                         int                         has_timestamp,
    1206             :                         long                        timestamp,
    1207             :                         ulong                       epoch,
    1208             :                         ulong                       current_slot,
    1209          57 :                         fd_exec_instr_ctx_t const * ctx /* feature_set */ ) {
    1210          57 :   int rc;
    1211             : 
    1212          57 :   FD_TEST( !deq_fd_landed_vote_t_empty( new_state ) );
    1213             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L575
    1214          57 :   if( FD_UNLIKELY( deq_fd_landed_vote_t_cnt( new_state ) > MAX_LOCKOUT_HISTORY ) ) {
    1215           0 :     ctx->txn_ctx->custom_err = FD_VOTE_ERR_TOO_MANY_VOTES;
    1216           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1217          57 :   };
    1218             : 
    1219             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L579
    1220          57 :   if( FD_UNLIKELY( has_new_root && vote_state->has_root_slot ) ) {
    1221             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L581
    1222          24 :     if( FD_UNLIKELY( new_root < vote_state->root_slot ) ) {
    1223           0 :       ctx->txn_ctx->custom_err = FD_VOTE_ERR_ROOT_ROLL_BACK;
    1224           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1225           0 :     }
    1226          33 :   } else if( FD_UNLIKELY( !has_new_root && vote_state->has_root_slot ) ) {
    1227             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L586
    1228           6 :     ctx->txn_ctx->custom_err = FD_VOTE_ERR_ROOT_ROLL_BACK;
    1229           6 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1230          27 :   } else {
    1231             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L588
    1232             :     /* no-op */
    1233          27 :   }
    1234             : 
    1235          51 :   fd_landed_vote_t * previous_vote = NULL;
    1236          51 :   for( deq_fd_landed_vote_t_iter_t iter = deq_fd_landed_vote_t_iter_init( new_state );
    1237         822 :        !deq_fd_landed_vote_t_iter_done( new_state, iter );
    1238         774 :        iter = deq_fd_landed_vote_t_iter_next( new_state, iter ) ) {
    1239         774 :     fd_landed_vote_t * vote = deq_fd_landed_vote_t_iter_ele( new_state, iter );
    1240         774 :     if( FD_LIKELY( vote->lockout.confirmation_count == 0 ) ) {
    1241           0 :       ctx->txn_ctx->custom_err = FD_VOTE_ERR_ZERO_CONFIRMATIONS;
    1242           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1243         774 :     } else if( FD_UNLIKELY( vote->lockout.confirmation_count > MAX_LOCKOUT_HISTORY ) ) {
    1244           0 :       ctx->txn_ctx->custom_err = FD_VOTE_ERR_CONFIRMATION_TOO_LARGE;
    1245           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1246         774 :     } else if( FD_LIKELY( has_new_root ) ) {
    1247         744 :       if( FD_UNLIKELY( vote->lockout.slot <= new_root && new_root != SLOT_DEFAULT ) ) {
    1248           0 :         ctx->txn_ctx->custom_err = FD_VOTE_ERR_SLOT_SMALLER_THAN_ROOT;
    1249           0 :         return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1250           0 :       }
    1251         744 :     }
    1252             : 
    1253         774 :     if( FD_LIKELY( previous_vote ) ) {
    1254         723 :       if( FD_UNLIKELY( previous_vote->lockout.slot >= vote->lockout.slot ) ) {
    1255           0 :         ctx->txn_ctx->custom_err = FD_VOTE_ERR_SLOTS_NOT_ORDERED;
    1256           0 :         return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1257         723 :       } else if( FD_UNLIKELY( previous_vote->lockout.confirmation_count <=
    1258         723 :                               vote->lockout.confirmation_count ) ) {
    1259           0 :         ctx->txn_ctx->custom_err = FD_VOTE_ERR_CONFIRMATIONS_NOT_ORDERED;
    1260           0 :         return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1261         723 :       } else if( FD_UNLIKELY( vote->lockout.slot >
    1262         723 :                               last_locked_out_slot( &previous_vote->lockout ) ) ) {
    1263           3 :         ctx->txn_ctx->custom_err = FD_VOTE_ERR_NEW_VOTE_STATE_LOCKOUT_MISMATCH;
    1264           3 :         return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1265           3 :       }
    1266         723 :     }
    1267         771 :     previous_vote = vote;
    1268         771 :   }
    1269             : 
    1270          48 :   ulong current_vote_state_index = 0;
    1271          48 :   ulong new_vote_state_index     = 0;
    1272             : 
    1273             :   /* Accumulate credits earned by newly rooted slots.  The behavior changes with
    1274             :      timely_vote_credits: prior to this feature, there was a bug that counted a new root slot as 1
    1275             :      credit even if it had never been voted on. timely_vote_credits fixes this bug by only awarding
    1276             :      credits for slots actually voted on and finalized. */
    1277             : 
    1278             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L635
    1279          48 :   int   timely_vote_credits = FD_FEATURE_ACTIVE( ctx->slot_ctx, timely_vote_credits );
    1280          48 :   int   deprecate_unused_legacy_vote_plumbing = FD_FEATURE_ACTIVE( ctx->slot_ctx, deprecate_unused_legacy_vote_plumbing );
    1281             : 
    1282             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L641
    1283          48 :   ulong earned_credits      = timely_vote_credits ? 0 : 1;
    1284             : 
    1285          48 :   if( FD_LIKELY( has_new_root ) ) {
    1286          24 :     for( deq_fd_landed_vote_t_iter_t iter = deq_fd_landed_vote_t_iter_init( vote_state->votes );
    1287          81 :          !deq_fd_landed_vote_t_iter_done( vote_state->votes, iter );
    1288          81 :          iter = deq_fd_landed_vote_t_iter_next( vote_state->votes, iter ) ) {
    1289          81 :       fd_landed_vote_t * current_vote = deq_fd_landed_vote_t_iter_ele( vote_state->votes, iter );
    1290             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L647
    1291          81 :       if( FD_UNLIKELY( current_vote->lockout.slot <= new_root ) ) {
    1292             :         // this is safe because we're inside if has_new_root
    1293          57 :         if( FD_LIKELY( timely_vote_credits || ( current_vote->lockout.slot != new_root ) ) ) {
    1294          33 :           earned_credits = fd_ulong_checked_add_expect(
    1295          33 :               credits_for_vote_at_index( vote_state,
    1296          33 :                 current_vote_state_index,
    1297          33 :                 timely_vote_credits,
    1298          33 :                 deprecate_unused_legacy_vote_plumbing
    1299          33 :                 ),
    1300          33 :               earned_credits,
    1301          33 :               "`earned_credits` does not overflow" );
    1302          33 :         }
    1303          57 :         current_vote_state_index = fd_ulong_checked_add_expect(
    1304          57 :             current_vote_state_index,
    1305          57 :             1,
    1306          57 :             "`current_vote_state_index` is bounded by `MAX_LOCKOUT_HISTORY` "
    1307          57 :             "when processing new root" );
    1308          57 :         continue;
    1309          57 :       }
    1310          24 :       break;
    1311          81 :     }
    1312          24 :   }
    1313             : 
    1314             :   // For any slots newly added to the new vote state, the vote latency of that slot is not provided by the
    1315             :   // vote instruction contents, but instead is computed from the actual latency of the vote
    1316             :   // instruction. This prevents other validators from manipulating their own vote latencies within their vote states
    1317             :   // and forcing the rest of the cluster to accept these possibly fraudulent latency values.  If the
    1318             :   // timly_vote_credits feature is not enabled then vote latency is set to 0 for new votes.
    1319             :   //
    1320             :   // For any slot that is in both the new state and the current state, the vote latency of the new state is taken
    1321             :   // from the current state.
    1322             :   //
    1323             :   // Thus vote latencies are set here for any newly vote-on slots when a vote instruction is received.
    1324             :   // They are copied into the new vote state after every vote for already voted-on slots.
    1325             :   // And when voted-on slots are rooted, the vote latencies stored in the vote state of all the rooted slots is used
    1326             :   // to compute credits earned.
    1327             :   // All validators compute the same vote latencies because all process the same vote instruction at the
    1328             :   // same slot, and the only time vote latencies are ever computed is at the time that their slot is first voted on;
    1329             :   // after that, the latencies are retained unaltered until the slot is rooted.
    1330             : 
    1331             :   // All the votes in our current vote state that are missing from the new vote state
    1332             :   // must have been expired by later votes. Check that the lockouts match this assumption.
    1333             : 
    1334             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L686
    1335         774 :   while( current_vote_state_index < deq_fd_landed_vote_t_cnt( vote_state->votes ) &&
    1336         774 :          new_vote_state_index < deq_fd_landed_vote_t_cnt( new_state ) ) {
    1337         726 :     fd_landed_vote_t * current_vote =
    1338         726 :         deq_fd_landed_vote_t_peek_index( vote_state->votes, current_vote_state_index );
    1339             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L690
    1340         726 :     fd_landed_vote_t * new_vote =
    1341         726 :         deq_fd_landed_vote_t_peek_index( new_state, new_vote_state_index );
    1342             : 
    1343             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L696
    1344         726 :     if( FD_LIKELY( current_vote->lockout.slot < new_vote->lockout.slot ) ) {
    1345          30 :       ulong last_locked_out_slot =
    1346          30 :           current_vote->lockout.slot +
    1347          30 :           (ulong)pow( INITIAL_LOCKOUT, current_vote->lockout.confirmation_count );
    1348             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L697
    1349          30 :       if( last_locked_out_slot >= new_vote->lockout.slot ) {
    1350             :         // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L698
    1351           0 :         ctx->txn_ctx->custom_err = FD_VOTE_ERR_LOCKOUT_CONFLICT;
    1352           0 :         return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1353           0 :       }
    1354             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L700
    1355          30 :       current_vote_state_index =
    1356          30 :           fd_ulong_checked_add_expect( current_vote_state_index,
    1357          30 :                                        1,
    1358          30 :                                        "`current_vote_state_index` is bounded by "
    1359          30 :                                        "`MAX_LOCKOUT_HISTORY` when slot is less than proposed" );
    1360             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L704
    1361         696 :     } else if( FD_UNLIKELY( current_vote->lockout.slot == new_vote->lockout.slot ) ) {
    1362             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L707
    1363         687 :       if( new_vote->lockout.confirmation_count < current_vote->lockout.confirmation_count ) {
    1364           0 :         ctx->txn_ctx->custom_err = FD_VOTE_ERR_CONFIRMATION_ROLL_BACK;
    1365           0 :         return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1366           0 :       }
    1367             : 
    1368             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L712
    1369         687 :       new_vote->latency =
    1370         687 :           deq_fd_landed_vote_t_peek_index( vote_state->votes, current_vote_state_index )->latency;
    1371             : 
    1372             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L714
    1373         687 :       current_vote_state_index =
    1374         687 :           fd_ulong_checked_add_expect( current_vote_state_index,
    1375         687 :                                        1,
    1376         687 :                                        "`current_vote_state_index` is bounded by "
    1377         687 :                                        "`MAX_LOCKOUT_HISTORY` when slot is equal to proposed" );
    1378             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L717
    1379         687 :       new_vote_state_index =
    1380         687 :           fd_ulong_checked_add_expect( new_vote_state_index,
    1381         687 :                                        1,
    1382         687 :                                        "`new_vote_state_index` is bounded by `MAX_LOCKOUT_HISTORY` "
    1383         687 :                                        "when slot is equal to proposed" );
    1384         687 :     } else {
    1385             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L722
    1386           9 :       new_vote_state_index =
    1387           9 :           fd_ulong_checked_add_expect( new_vote_state_index,
    1388           9 :                                        1,
    1389           9 :                                        "`new_vote_state_index` is bounded by `MAX_LOCKOUT_HISTORY` "
    1390           9 :                                        "when slot is greater than proposed" );
    1391           9 :     }
    1392         726 :   }
    1393             : 
    1394             :   // Comment:
    1395             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L736
    1396          48 :   if( FD_LIKELY( timely_vote_credits ) ) {
    1397             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L737
    1398           3 :     for( deq_fd_landed_vote_t_iter_t iter = deq_fd_landed_vote_t_iter_init( new_state );
    1399           6 :          !deq_fd_landed_vote_t_iter_done( new_state, iter );
    1400           3 :          iter = deq_fd_landed_vote_t_iter_next( new_state, iter ) ) {
    1401           3 :       fd_landed_vote_t * new_vote = deq_fd_landed_vote_t_iter_ele( new_state, iter );
    1402             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L738
    1403           3 :       if( FD_UNLIKELY( new_vote->latency == 0 ) ) {
    1404             :         // this is unlikely because as validators upgrade, it should converge to the new vote state
    1405             :         // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L739
    1406           3 :         new_vote->latency = compute_vote_latency( new_vote->lockout.slot, current_slot );
    1407           3 :       }
    1408           3 :     }
    1409           3 :   }
    1410             : 
    1411             :   // doesn't matter what the value of slot if `is_some = 0` i.e. `Option::None`
    1412             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L744
    1413          48 :   int both_none = !vote_state->has_root_slot && !has_new_root;
    1414          48 :   if( ( !both_none && ( vote_state->has_root_slot != has_new_root ||
    1415          24 :                         vote_state->root_slot != new_root ) ) ) {
    1416          24 :     increment_credits( vote_state, epoch, earned_credits );
    1417          24 :   }
    1418             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L750
    1419          48 :   if( FD_LIKELY( has_timestamp ) ) {
    1420             :     /* new_state asserted nonempty at function beginning */
    1421          33 :     if( deq_fd_landed_vote_t_empty( new_state ) ) {
    1422           0 :       FD_LOG_ERR(( "solana panic" ));
    1423             :       // TODO: solana panics ...  unclear what to return
    1424           0 :       ctx->txn_ctx->custom_err = 0;
    1425           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1426           0 :     }
    1427          33 :     ulong last_slot = deq_fd_landed_vote_t_peek_tail( new_state )->lockout.slot;
    1428          33 :     rc              = process_timestamp( vote_state, last_slot, timestamp, ctx );
    1429          33 :     if( FD_UNLIKELY( rc ) ) { return rc; }
    1430          24 :     vote_state->last_timestamp.timestamp = timestamp;
    1431          24 :   }
    1432             : 
    1433             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L754
    1434          39 :   vote_state->has_root_slot = (uchar)has_new_root;
    1435          39 :   vote_state->root_slot     = new_root;
    1436             : 
    1437             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L755
    1438          39 :   deq_fd_landed_vote_t_remove_all( vote_state->votes );
    1439          39 :   for( deq_fd_landed_vote_t_iter_t iter = deq_fd_landed_vote_t_iter_init( new_state );
    1440         798 :        !deq_fd_landed_vote_t_iter_done( new_state, iter );
    1441         759 :        iter = deq_fd_landed_vote_t_iter_next( new_state, iter ) ) {
    1442         759 :     fd_landed_vote_t * landed_vote = deq_fd_landed_vote_t_iter_ele( new_state, iter );
    1443         759 :     deq_fd_landed_vote_t_push_tail( vote_state->votes, *landed_vote );
    1444         759 :   }
    1445             : 
    1446          39 :   return FD_EXECUTOR_INSTR_SUCCESS;
    1447          48 : }
    1448             : 
    1449             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L849
    1450             : static int
    1451             : authorize( ulong                         vote_acct_idx,
    1452             :            fd_borrowed_account_t *       vote_account,
    1453             :            fd_pubkey_t const *           authorized,
    1454             :            fd_vote_authorize_t           vote_authorize,
    1455             :            fd_pubkey_t const *           signers[static FD_TXN_SIG_MAX],
    1456             :            fd_sol_sysvar_clock_t const * clock,
    1457        1935 :            fd_exec_instr_ctx_t const *   ctx /* feature_set */ ) {
    1458        1935 :   int rc;
    1459             : 
    1460        1935 :   fd_valloc_t scratch_valloc = fd_scratch_virtual();
    1461             : 
    1462             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L857
    1463        1935 :   fd_vote_state_versioned_t vote_state_versioned;
    1464        1935 :   rc = get_state( vote_account, scratch_valloc, &vote_state_versioned );
    1465        1935 :   if( FD_UNLIKELY( rc ) ) return rc;
    1466        1380 :   convert_to_current( &vote_state_versioned, scratch_valloc );
    1467        1380 :   fd_vote_state_t * vote_state = &vote_state_versioned.inner.current;
    1468             : 
    1469             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L861
    1470        1380 :   switch( vote_authorize.discriminant ) {
    1471             : 
    1472             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L862
    1473         855 :   case fd_vote_authorize_enum_voter:;
    1474             : 
    1475             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L863
    1476         855 :     int authorized_withdrawer_signer =
    1477         855 :         FD_EXECUTOR_INSTR_SUCCESS ==
    1478         855 :         verify_authorized_signer( &vote_state->authorized_withdrawer, signers );
    1479             : 
    1480             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L866
    1481         855 :     rc = set_new_authorized_voter( vote_state,
    1482         855 :                                    authorized,
    1483         855 :                                    clock->epoch,
    1484         855 :                                    clock->leader_schedule_epoch + 1UL,
    1485         855 :                                    authorized_withdrawer_signer,
    1486         855 :                                    signers,
    1487         855 :                                    ctx );
    1488         855 :     if( FD_UNLIKELY( rc ) ) return rc;
    1489         255 :     break;
    1490             : 
    1491             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L883
    1492         525 :   case fd_vote_authorize_enum_withdrawer:
    1493         525 :     rc = verify_authorized_signer( &vote_state->authorized_withdrawer, signers );
    1494         525 :     if( FD_UNLIKELY( rc ) ) return rc;
    1495         234 :     memcpy( &vote_state->authorized_withdrawer, authorized, sizeof( fd_pubkey_t ) );
    1496         234 :     break;
    1497             : 
    1498             :   // failing exhaustive check is fatal
    1499           0 :   default:
    1500           0 :     __builtin_unreachable();
    1501        1380 :   }
    1502             : 
    1503             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L890
    1504         489 :   return set_vote_account_state( vote_acct_idx, vote_account, vote_state, ctx );
    1505        1380 : }
    1506             : 
    1507             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L894
    1508             : static int
    1509             : update_validator_identity( ulong                       vote_acct_idx,
    1510             :                            fd_borrowed_account_t *     vote_account,
    1511             :                            fd_pubkey_t const *         node_pubkey,
    1512             :                            fd_pubkey_t const *         signers[static FD_TXN_SIG_MAX],
    1513        1323 :                            fd_exec_instr_ctx_t const * ctx /* feature_set */ ) {
    1514        1323 :   int rc;
    1515             : 
    1516        1323 :   fd_valloc_t scratch_valloc = fd_scratch_virtual();
    1517             : 
    1518             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L900
    1519        1323 :   fd_vote_state_versioned_t vote_state_versioned;
    1520        1323 :   rc = get_state( vote_account, scratch_valloc, &vote_state_versioned );
    1521        1323 :   if( FD_UNLIKELY( rc ) ) return rc;
    1522         777 :   convert_to_current( &vote_state_versioned, scratch_valloc );
    1523         777 :   fd_vote_state_t * vote_state = &vote_state_versioned.inner.current;
    1524             : 
    1525             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L905
    1526         777 :   rc = verify_authorized_signer( &vote_state->authorized_withdrawer, signers );
    1527         777 :   if( FD_UNLIKELY( rc ) ) return rc;
    1528             : 
    1529             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L908
    1530         393 :   rc = verify_authorized_signer( node_pubkey, signers );
    1531         393 :   if( FD_UNLIKELY( rc ) ) return rc;
    1532             : 
    1533             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L910
    1534         327 :   vote_state->node_pubkey = *node_pubkey;
    1535             : 
    1536             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L912
    1537         327 :   return set_vote_account_state( vote_acct_idx, vote_account, vote_state, ctx );
    1538         393 : }
    1539             : 
    1540             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L971
    1541             : static int
    1542         459 : is_commission_update_allowed( ulong slot, fd_epoch_schedule_t const * epoch_schedule ) {
    1543         459 :   if( FD_LIKELY( epoch_schedule->slots_per_epoch > 0UL ) ) {
    1544         459 :     ulong relative_slot = fd_ulong_sat_sub( slot, epoch_schedule->first_normal_slot );
    1545             :     // TODO underflow and overflow edge cases in addition to div by 0
    1546         459 :     relative_slot %= epoch_schedule->slots_per_epoch;
    1547         459 :     return fd_ulong_sat_mul( relative_slot, 2 ) <= epoch_schedule->slots_per_epoch;
    1548         459 :   } else {
    1549           0 :     return 1;
    1550           0 :   }
    1551         459 : }
    1552             : 
    1553             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L916
    1554             : static int
    1555             : update_commission( ulong                       vote_acct_idx,
    1556             :                    fd_borrowed_account_t *     vote_account,
    1557             :                    uchar                       commission,
    1558             :                    fd_pubkey_t const *         signers[static FD_TXN_SIG_MAX],
    1559             :                    fd_epoch_schedule_t const * epoch_schedule,
    1560             :                    fd_sol_sysvar_clock_t const * clock,
    1561        1404 :                    fd_exec_instr_ctx_t const * ctx /* feature_set */ ) {
    1562        1404 :   int rc;
    1563             : 
    1564        1404 :   fd_valloc_t scratch_valloc = fd_scratch_virtual();
    1565             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L925
    1566        1404 :   fd_vote_state_versioned_t vote_state_versioned;
    1567        1404 :   fd_vote_state_t * vote_state = NULL;
    1568             : 
    1569             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L927
    1570        1404 :   int enforce_commission_update_rule = 1;
    1571        1404 :   if (FD_FEATURE_ACTIVE( ctx->slot_ctx, allow_commission_decrease_at_any_time )) {
    1572         648 :     rc = get_state( vote_account, scratch_valloc, &vote_state_versioned );
    1573         648 :     if ( FD_LIKELY( rc==FD_EXECUTOR_INSTR_SUCCESS ) ) {
    1574          54 :       convert_to_current( &vote_state_versioned, scratch_valloc );
    1575          54 :       vote_state = &vote_state_versioned.inner.current;
    1576          54 :       enforce_commission_update_rule = commission > vote_state->commission;
    1577          54 :     }
    1578         648 :   }
    1579             : 
    1580             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L940
    1581        1404 :   if( FD_LIKELY( enforce_commission_update_rule && FD_FEATURE_ACTIVE( ctx->slot_ctx,
    1582        1404 :         commission_updates_only_allowed_in_first_half_of_epoch ) ) ) {
    1583         459 :     if( FD_UNLIKELY( !is_commission_update_allowed( clock->slot, epoch_schedule ) ) ) {
    1584         120 :       ctx->txn_ctx->custom_err = FD_VOTE_ERR_COMMISSION_UPDATE_TOO_LATE;
    1585         120 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1586         120 :     }
    1587         459 :   }
    1588             : 
    1589             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L949
    1590        1284 :   if (NULL == vote_state) {
    1591        1236 :     rc = get_state( vote_account, scratch_valloc, &vote_state_versioned );
    1592        1236 :     if( FD_UNLIKELY( rc ) ) return rc;
    1593         417 :     convert_to_current( &vote_state_versioned, scratch_valloc );
    1594         417 :     vote_state = &vote_state_versioned.inner.current;
    1595         417 :   }
    1596             : 
    1597             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L957
    1598         465 :   rc = verify_authorized_signer( &vote_state->authorized_withdrawer, signers );
    1599         465 :   if( FD_UNLIKELY( rc ) ) return rc;
    1600             : 
    1601             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L959
    1602         219 :   vote_state->commission = commission;
    1603             : 
    1604             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L961
    1605         219 :   return set_vote_account_state( vote_acct_idx, vote_account, vote_state, ctx );
    1606         465 : }
    1607             : 
    1608             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L997
    1609             : static int
    1610             : withdraw(
    1611             :     /* transaction_context */
    1612             :     fd_exec_instr_ctx_t const *   ctx,
    1613             :     ulong                         vote_acct_idx,
    1614             :     fd_borrowed_account_t *       vote_account,
    1615             :     ulong                         lamports,
    1616             :     ulong                         to_account_index,
    1617             :     fd_pubkey_t const *           signers[static FD_TXN_SIG_MAX],
    1618             :     fd_rent_t const *             rent_sysvar,
    1619             :     fd_sol_sysvar_clock_t const * clock
    1620             :     /* feature_set */
    1621         903 : ) {
    1622         903 :   int rc;
    1623             : 
    1624         903 :   fd_valloc_t scratch_valloc = fd_scratch_virtual();
    1625             : 
    1626             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1010
    1627         903 :   fd_vote_state_versioned_t vote_state_versioned;
    1628         903 :   rc = get_state( vote_account, scratch_valloc, &vote_state_versioned );
    1629         903 :   if( FD_UNLIKELY( rc ) ) return rc;
    1630         540 :   convert_to_current( &vote_state_versioned, scratch_valloc );
    1631         540 :   fd_vote_state_t * vote_state = &vote_state_versioned.inner.current;
    1632             : 
    1633             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1014
    1634         540 :   rc = verify_authorized_signer( &vote_state->authorized_withdrawer, signers );
    1635         540 :   if( FD_UNLIKELY( rc ) ) return rc;
    1636             : 
    1637             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1016
    1638         156 :   if( FD_UNLIKELY( lamports > vote_account->const_meta->info.lamports ) )
    1639          18 :     return FD_EXECUTOR_INSTR_ERR_INSUFFICIENT_FUNDS;
    1640         138 :   ulong remaining_balance = vote_account->const_meta->info.lamports - lamports;
    1641             : 
    1642             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1021
    1643         138 :   if( FD_UNLIKELY( remaining_balance == 0 ) ) {
    1644             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1014
    1645          84 :     int reject_active_vote_account_close = 0;
    1646             : 
    1647          84 :     ulong last_epoch_with_credits;
    1648          84 :     if( FD_LIKELY( !deq_fd_vote_epoch_credits_t_empty( vote_state->epoch_credits ) ) ) {
    1649          60 :       last_epoch_with_credits =
    1650          60 :           deq_fd_vote_epoch_credits_t_peek_tail_const( vote_state->epoch_credits )->epoch;
    1651          60 :       ulong current_epoch = clock->epoch;
    1652          60 :       reject_active_vote_account_close =
    1653          60 :           fd_ulong_sat_sub( current_epoch, last_epoch_with_credits ) < 2;
    1654          60 :     }
    1655             : 
    1656             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1034
    1657          84 :     if( FD_UNLIKELY( reject_active_vote_account_close ) ) {
    1658             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1036
    1659          18 :       ctx->txn_ctx->custom_err = FD_VOTE_ERR_ACTIVE_VOTE_ACCOUNT_CLOSE;
    1660          18 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1661          66 :     } else {
    1662             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1040
    1663          66 :       fd_vote_state_versioned_t vote_state_versions;
    1664          66 :       fd_vote_state_versioned_new_disc( &vote_state_versions,
    1665          66 :                                         fd_vote_state_versioned_enum_current );
    1666          66 :       vote_state_versions.inner.current.prior_voters.idx      = 31;
    1667          66 :       vote_state_versions.inner.current.prior_voters.is_empty = 1;
    1668          66 :       fd_vote_state_t * default_vote_state                    = &vote_state_versions.inner.current;
    1669          66 :       rc                                                      = 0;
    1670          66 :       rc = set_vote_account_state( vote_acct_idx, vote_account, default_vote_state, ctx );
    1671          66 :       if( FD_UNLIKELY( rc != 0 ) ) return rc;
    1672          66 :     }
    1673          84 :   } else {
    1674             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1043
    1675          54 :     ulong min_rent_exempt_balance =
    1676          54 :         fd_rent_exempt_minimum_balance( rent_sysvar, vote_account->const_meta->dlen );
    1677          54 :     if( remaining_balance < min_rent_exempt_balance ) {
    1678           9 :       return FD_EXECUTOR_INSTR_ERR_INSUFFICIENT_FUNDS;
    1679           9 :     }
    1680          54 :   }
    1681             : 
    1682             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1049
    1683          90 :   rc = fd_account_checked_sub_lamports(ctx, vote_acct_idx, lamports);
    1684          90 :   if( FD_UNLIKELY( rc ) ) return rc;
    1685             : 
    1686             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1053
    1687          75 :   rc = fd_account_checked_add_lamports(ctx, to_account_index, lamports);
    1688          75 :   if( FD_UNLIKELY( rc ) ) return rc;
    1689             : 
    1690          27 :   return 0;
    1691          75 : }
    1692             : 
    1693             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L760
    1694             : static int
    1695             : process_vote_unfiltered( fd_vote_state_t *           vote_state,
    1696             :                          ulong *                     vote_slots,
    1697             :                          fd_vote_t const *           vote,
    1698             :                          fd_slot_hashes_t const *    slot_hashes,
    1699             :                          ulong                       epoch,
    1700             :                          ulong                       current_slot,
    1701             :                          int                         timely_vote_credits,
    1702             :                          int                         deprecate_unused_legacy_vote_plumbing,
    1703         396 :                          fd_exec_instr_ctx_t const * ctx ) {
    1704         396 :   int rc;
    1705             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L770
    1706         396 :   rc = check_slots_are_valid( vote_state, vote_slots, &vote->hash, slot_hashes, ctx );
    1707         396 :   if( FD_UNLIKELY( rc ) ) return rc;
    1708           9 :   for( deq_ulong_iter_t iter = deq_ulong_iter_init( vote_slots );
    1709          33 :        !deq_ulong_iter_done( vote_slots, iter );
    1710          24 :        iter = deq_ulong_iter_next( vote_slots, iter ) ) {
    1711          24 :     ulong * ele = deq_ulong_iter_ele( vote_slots, iter );
    1712             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L772
    1713          24 :     process_next_vote_slot( vote_state, *ele, epoch, current_slot, timely_vote_credits, deprecate_unused_legacy_vote_plumbing);
    1714          24 :   }
    1715           9 :   return 0;
    1716         396 : }
    1717             : 
    1718             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L783
    1719             : static int
    1720             : process_vote( fd_vote_state_t *           vote_state,
    1721             :               fd_vote_t const *           vote,
    1722             :               fd_slot_hashes_t const *    slot_hashes,
    1723             :               ulong                       epoch,
    1724             :               ulong                       current_slot,
    1725             :               int                         timely_vote_credits,
    1726             :               int                         deprecate_unused_legacy_vote_plumbing,
    1727         465 :               fd_exec_instr_ctx_t const * ctx ) {
    1728             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L792
    1729         465 :   if( FD_UNLIKELY( deq_ulong_empty( vote->slots ) ) ) {
    1730           9 :     ctx->txn_ctx->custom_err = FD_VOTE_ERR_EMPTY_SLOTS;
    1731           9 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1732           9 :   }
    1733             : 
    1734             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L795
    1735         456 :   ulong earliest_slot_in_history = 0;
    1736         456 :   if( FD_UNLIKELY( !deq_fd_slot_hash_t_empty( slot_hashes->hashes ) ) ) {
    1737         444 :     earliest_slot_in_history = deq_fd_slot_hash_t_peek_tail_const( slot_hashes->hashes )->slot;
    1738         444 :   }
    1739             : 
    1740         456 :   ulong   vote_slots_cnt = deq_ulong_cnt( vote->slots );
    1741         456 :   uchar * vote_slots_mem = fd_scratch_alloc( deq_ulong_align(), deq_ulong_footprint( vote_slots_cnt ) );
    1742             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L796
    1743         456 :   ulong * vote_slots     = deq_ulong_join( deq_ulong_new( vote_slots_mem, vote_slots_cnt ) );
    1744         456 :   for( deq_ulong_iter_t iter = deq_ulong_iter_init( vote->slots );
    1745        7872 :        !deq_ulong_iter_done( vote->slots, iter );
    1746        7416 :        iter = deq_ulong_iter_next( vote->slots, iter ) ) {
    1747        7416 :     ulong * ele = deq_ulong_iter_ele( vote->slots, iter );
    1748        7416 :     if( FD_UNLIKELY( *ele >= earliest_slot_in_history ) ) {
    1749        6027 :       vote_slots = deq_ulong_push_tail( vote_slots, *ele );
    1750        6027 :     }
    1751        7416 :   }
    1752             : 
    1753             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L802
    1754         456 :   if( FD_UNLIKELY( deq_ulong_cnt( vote_slots ) == 0 ) ) {
    1755          60 :     ctx->txn_ctx->custom_err = FD_VOTE_ERR_VOTES_TOO_OLD_ALL_FILTERED;
    1756          60 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1757          60 :   }
    1758             : 
    1759             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L805
    1760         396 :   return process_vote_unfiltered(
    1761         396 :       vote_state, vote_slots, vote, slot_hashes, epoch, current_slot,
    1762         396 :         timely_vote_credits, deprecate_unused_legacy_vote_plumbing, ctx );
    1763         456 : }
    1764             : 
    1765             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1060
    1766             : static int
    1767             : initialize_account( ulong                         vote_acct_idx,
    1768             :                     fd_borrowed_account_t *       vote_account,
    1769             :                     fd_vote_init_t *              vote_init,
    1770             :                     fd_pubkey_t const *           signers[static FD_TXN_SIG_MAX],
    1771             :                     fd_sol_sysvar_clock_t const * clock,
    1772         225 :                     fd_exec_instr_ctx_t const *   ctx /* feature_set */ ) {
    1773         225 :   int rc;
    1774             : 
    1775         225 :   fd_valloc_t scratch_valloc = fd_scratch_virtual();
    1776             : 
    1777             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1067
    1778         225 :   ulong data_len = vote_account->const_meta->dlen;
    1779         225 :   if( FD_UNLIKELY( data_len != size_of_versioned( FD_FEATURE_ACTIVE(
    1780         225 :                                    ctx->slot_ctx, vote_state_add_vote_latency ) ) ) ) {
    1781         216 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
    1782         216 :   }
    1783             : 
    1784             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1074
    1785           9 :   fd_vote_state_versioned_t versioned;
    1786           9 :   rc = get_state( vote_account, scratch_valloc, &versioned );
    1787           9 :   if( FD_UNLIKELY( rc ) ) return rc;
    1788             : 
    1789             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1076
    1790           9 :   if( FD_UNLIKELY( !is_uninitialized( &versioned ) ) )
    1791           0 :     return FD_EXECUTOR_INSTR_ERR_ACC_ALREADY_INITIALIZED;
    1792             : 
    1793             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1081
    1794           9 :   rc = verify_authorized_signer( &vote_init->node_pubkey, signers );
    1795           9 :   if( FD_UNLIKELY( rc ) ) return rc;
    1796             : 
    1797             :   // reset the object
    1798           9 :   fd_vote_state_versioned_new( &versioned );
    1799             : 
    1800             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1083
    1801           9 :   vote_state_new( vote_init, clock, scratch_valloc, &versioned.inner.current );
    1802           9 :   return set_vote_account_state( vote_acct_idx, vote_account, &versioned.inner.current, ctx );
    1803           9 : }
    1804             : 
    1805             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1086
    1806             : static int
    1807             : verify_and_get_vote_state( fd_borrowed_account_t *       vote_account,
    1808             :                            fd_sol_sysvar_clock_t const * clock,
    1809             :                            fd_pubkey_t const *           signers[FD_TXN_SIG_MAX],
    1810        2997 :                            fd_vote_state_t *             vote_state /* out */ ) {
    1811        2997 :   int                       rc;
    1812        2997 :   fd_vote_state_versioned_t versioned;
    1813             : 
    1814        2997 :   fd_valloc_t scratch_valloc = fd_scratch_virtual();
    1815             : 
    1816             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1091
    1817        2997 :   rc = get_state( vote_account, scratch_valloc, &versioned );
    1818        2997 :   if( FD_UNLIKELY( rc ) ) return rc;
    1819             : 
    1820             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1093
    1821        2592 :   if( FD_UNLIKELY( is_uninitialized( &versioned ) ) )
    1822          75 :     return FD_EXECUTOR_INSTR_ERR_UNINITIALIZED_ACCOUNT;
    1823             : 
    1824             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1097
    1825        2517 :   convert_to_current( &versioned, scratch_valloc );
    1826        2517 :   memcpy( vote_state, &versioned.inner.current, sizeof( fd_vote_state_t ) );
    1827             : 
    1828             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1098
    1829        2517 :   fd_pubkey_t * authorized_voter = NULL;
    1830        2517 :   rc = get_and_update_authorized_voter( vote_state, clock->epoch, &authorized_voter );
    1831        2517 :   if( FD_UNLIKELY( rc ) ) return rc;
    1832             : 
    1833             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1099
    1834        2220 :   rc = verify_authorized_signer( authorized_voter, signers );
    1835        2220 :   if( FD_UNLIKELY( rc ) ) return rc;
    1836             : 
    1837         972 :   return FD_EXECUTOR_INSTR_SUCCESS;
    1838        2220 : }
    1839             : 
    1840             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1104
    1841             : static int
    1842             : process_vote_with_account( ulong                         vote_acct_idx,
    1843             :                            fd_borrowed_account_t *       vote_account,
    1844             :                            fd_slot_hashes_t const *      slot_hashes,
    1845             :                            fd_sol_sysvar_clock_t const * clock,
    1846             :                            fd_vote_t *                   vote,
    1847             :                            fd_pubkey_t const *           signers[static FD_TXN_SIG_MAX],
    1848        1161 :                            fd_exec_instr_ctx_t const *   ctx ) {
    1849             : 
    1850        1161 :   int             rc;
    1851        1161 :   fd_vote_state_t vote_state;
    1852             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1112
    1853        1161 :   rc = verify_and_get_vote_state( vote_account, clock, signers, &vote_state );
    1854        1161 :   if( FD_UNLIKELY( rc ) ) return rc;
    1855             : 
    1856             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1114
    1857         465 :   int   timely_vote_credits = FD_FEATURE_ACTIVE( ctx->slot_ctx, timely_vote_credits );
    1858         465 :   int   deprecate_unused_legacy_vote_plumbing = FD_FEATURE_ACTIVE( ctx->slot_ctx, deprecate_unused_legacy_vote_plumbing );
    1859             : 
    1860             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1117
    1861         465 :   rc = process_vote( &vote_state, vote, slot_hashes, clock->epoch, clock->slot, timely_vote_credits, deprecate_unused_legacy_vote_plumbing, ctx );
    1862         465 :   if( FD_UNLIKELY( rc ) ) return rc;
    1863             : 
    1864             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1126
    1865           9 :   if( FD_LIKELY( vote->timestamp ) ) {
    1866           3 :     if( FD_UNLIKELY( deq_ulong_cnt( vote->slots ) == 0 ) ) {
    1867           0 :       ctx->txn_ctx->custom_err = FD_VOTE_ERR_EMPTY_SLOTS;
    1868           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1869           0 :     }
    1870             : 
    1871           3 :     ulong * max = deq_ulong_peek_head( vote->slots ) ? deq_ulong_peek_head( vote->slots ) : NULL;
    1872             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1127
    1873           3 :     for( deq_ulong_iter_t iter = deq_ulong_iter_init( vote->slots );
    1874          21 :          !deq_ulong_iter_done( vote->slots, iter );
    1875          18 :          iter = deq_ulong_iter_next( vote->slots, iter ) ) {
    1876          18 :       ulong * ele = deq_ulong_iter_ele( vote->slots, iter );
    1877          18 :       *max        = fd_ulong_max( *max, *ele );
    1878          18 :     }
    1879           3 :     if( FD_UNLIKELY( !max ) ) {
    1880           0 :       ctx->txn_ctx->custom_err = FD_VOTE_ERR_EMPTY_SLOTS;
    1881           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1882           0 :     }
    1883             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1131
    1884           3 :     rc = process_timestamp( &vote_state, *max, *vote->timestamp, ctx );
    1885           3 :     if( FD_UNLIKELY( rc ) ) return rc;
    1886           3 :   }
    1887             : 
    1888             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1133
    1889           9 :   return set_vote_account_state( vote_acct_idx, vote_account, &vote_state, ctx );
    1890           9 : }
    1891             : 
    1892             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1156
    1893             : static int
    1894             : do_process_vote_state_update( fd_vote_state_t *           vote_state,
    1895             :                               fd_slot_hashes_t const *    slot_hashes,
    1896             :                               ulong                       epoch,
    1897             :                               ulong                       slot,
    1898             :                               fd_vote_state_update_t *    vote_state_update,
    1899         498 :                               fd_exec_instr_ctx_t const * ctx /* feature_set */ ) {
    1900         498 :   int rc;
    1901             : 
    1902         498 :   fd_valloc_t scratch_valloc = fd_scratch_virtual();
    1903             : 
    1904             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1164
    1905         498 :   rc = check_and_filter_proposed_vote_state(
    1906         498 :       vote_state,
    1907         498 :       vote_state_update->lockouts, &vote_state_update->has_root, &vote_state_update->root, &vote_state_update->hash,
    1908         498 :       slot_hashes, ctx );
    1909         498 :   if( FD_UNLIKELY( rc ) ) return rc;
    1910             : 
    1911             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1177
    1912          54 :   fd_landed_vote_t * landed_votes = deq_fd_landed_vote_t_alloc( scratch_valloc, deq_fd_vote_lockout_t_cnt( vote_state_update->lockouts ) );
    1913          54 :   for( deq_fd_vote_lockout_t_iter_t iter =
    1914          54 :            deq_fd_vote_lockout_t_iter_init( vote_state_update->lockouts );
    1915         828 :        !deq_fd_vote_lockout_t_iter_done( vote_state_update->lockouts, iter );
    1916         774 :        iter = deq_fd_vote_lockout_t_iter_next( vote_state_update->lockouts, iter ) ) {
    1917         774 :     fd_vote_lockout_t * lockout =
    1918         774 :         deq_fd_vote_lockout_t_iter_ele( vote_state_update->lockouts, iter );
    1919         774 :     deq_fd_landed_vote_t_push_tail( landed_votes,
    1920         774 :                                     ( fd_landed_vote_t ){ .latency = 0, .lockout = *lockout } );
    1921         774 :   }
    1922             : 
    1923             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1171
    1924          54 :   return process_new_vote_state( vote_state,
    1925          54 :                                  landed_votes,
    1926          54 :                                  vote_state_update->has_root,
    1927          54 :                                  vote_state_update->root,
    1928          54 :                                  vote_state_update->has_timestamp,
    1929          54 :                                  vote_state_update->timestamp,
    1930          54 :                                  epoch,
    1931          54 :                                  slot,
    1932          54 :                                  ctx );
    1933         498 : }
    1934             : 
    1935             : // ??
    1936             : static ulong
    1937           0 : query_pubkey_stake( fd_pubkey_t const * pubkey, fd_vote_accounts_t const * vote_accounts ) {
    1938           0 :   fd_vote_accounts_pair_t_mapnode_t key         = { 0 };
    1939           0 :   key.elem.key                                  = *pubkey;
    1940           0 :   fd_vote_accounts_pair_t_mapnode_t * vote_node = fd_vote_accounts_pair_t_map_find(
    1941           0 :       vote_accounts->vote_accounts_pool, vote_accounts->vote_accounts_root, &key );
    1942           0 :   return vote_node ? vote_node->elem.stake : 0;
    1943           0 : }
    1944             : 
    1945             : static int
    1946             : process_vote_state_update( ulong                         vote_acct_idx,
    1947             :                            fd_borrowed_account_t *       vote_account,
    1948             :                            fd_slot_hashes_t const *      slot_hashes,
    1949             :                            fd_sol_sysvar_clock_t const * clock,
    1950             :                            fd_vote_state_update_t *      vote_state_update,
    1951             :                            fd_pubkey_t const *           signers[static FD_TXN_SIG_MAX],
    1952        1809 :                            fd_exec_instr_ctx_t const *   ctx /* feature_set */ ) {
    1953        1809 :   int rc;
    1954             : 
    1955             :   // tie in code for fd_bank_hash_cmp that helps us detect if we have forked from the cluster.
    1956             :   //
    1957             :   // There is no corresponding code in anza
    1958        1809 :   if( !deq_fd_vote_lockout_t_empty( vote_state_update->lockouts ) ) {
    1959        1680 :     fd_vote_lockout_t * lockout = deq_fd_vote_lockout_t_peek_tail( vote_state_update->lockouts );
    1960        1680 :     fd_bank_hash_cmp_t * bank_hash_cmp = ctx->slot_ctx->epoch_ctx->bank_hash_cmp;
    1961        1680 :     if( FD_LIKELY( lockout && bank_hash_cmp ) ) {
    1962           0 :       fd_bank_hash_cmp_lock( bank_hash_cmp );
    1963           0 :       fd_bank_hash_cmp_insert(
    1964           0 :         bank_hash_cmp,
    1965           0 :           lockout->slot,
    1966           0 :           &vote_state_update->hash,
    1967           0 :           0,
    1968           0 :           query_pubkey_stake( vote_account->pubkey,
    1969           0 :             &ctx->epoch_ctx->epoch_bank.stakes.vote_accounts ) );
    1970             : 
    1971           0 :       if( FD_LIKELY( vote_state_update->has_root ) ) {
    1972           0 :         fd_bank_hash_cmp_entry_t * cmp =
    1973           0 :           fd_bank_hash_cmp_map_query( bank_hash_cmp->map, vote_state_update->root, NULL );
    1974           0 :         if( FD_LIKELY( cmp ) ) cmp->rooted = 1;
    1975           0 :       }
    1976             : 
    1977           0 :       fd_bank_hash_cmp_unlock( bank_hash_cmp );
    1978           0 :     }
    1979        1680 :   }
    1980             : 
    1981        1809 :   fd_vote_state_t vote_state;
    1982             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1144
    1983        1809 :   rc = verify_and_get_vote_state( vote_account, clock, signers, &vote_state );
    1984        1809 :   if( FD_UNLIKELY( rc ) ) return rc;
    1985             : 
    1986             : 
    1987             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1145
    1988         498 :   rc = do_process_vote_state_update(
    1989         498 :       &vote_state, slot_hashes, clock->epoch, clock->slot, vote_state_update, ctx );
    1990         498 :   if( FD_UNLIKELY( rc ) ) {
    1991         459 :     return rc;
    1992         459 :   }
    1993             : 
    1994             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1153
    1995          39 :   rc = set_vote_account_state( vote_acct_idx, vote_account, &vote_state, ctx );
    1996             : 
    1997          39 :   return rc;
    1998         498 : }
    1999             : 
    2000             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1206
    2001             : static int
    2002             : do_process_tower_sync( fd_vote_state_t *           vote_state,
    2003             :                        fd_slot_hashes_t const *    slot_hashes,
    2004             :                        ulong                       epoch,
    2005             :                        ulong                       slot,
    2006             :                        fd_tower_sync_t *           tower_sync,
    2007           9 :                        fd_exec_instr_ctx_t const * ctx /* feature_set */ ) {
    2008             : 
    2009           9 :   do {
    2010             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1214
    2011           9 :     int err = check_and_filter_proposed_vote_state(
    2012           9 :         vote_state,
    2013           9 :         tower_sync->lockouts, &tower_sync->has_root, &tower_sync->root, &tower_sync->hash,
    2014           9 :         slot_hashes, ctx );
    2015           9 :     if( FD_UNLIKELY( err ) ) return err;
    2016           9 :   } while(0);
    2017             : 
    2018           3 :   fd_scratch_push();
    2019             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1221
    2020           3 :   int err = process_new_vote_state(
    2021           3 :       vote_state,
    2022           3 :       landed_votes_from_lockouts( tower_sync->lockouts, fd_scratch_virtual() ),
    2023           3 :       tower_sync->has_root,
    2024           3 :       tower_sync->root,
    2025           3 :       tower_sync->has_timestamp,
    2026           3 :       tower_sync->timestamp,
    2027           3 :       epoch,
    2028           3 :       slot,
    2029           3 :       ctx );
    2030           3 :   fd_scratch_pop();
    2031             : 
    2032           3 :   return err;
    2033           9 : }
    2034             : 
    2035             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1186
    2036             : static int
    2037             : process_tower_sync( ulong                         vote_acct_idx,
    2038             :                     fd_borrowed_account_t *       vote_account,
    2039             :                     fd_slot_hashes_t const *      slot_hashes,
    2040             :                     fd_sol_sysvar_clock_t const * clock,
    2041             :                     fd_tower_sync_t *             tower_sync,
    2042             :                     fd_pubkey_t const *           signers[static FD_TXN_SIG_MAX],
    2043          27 :                     fd_exec_instr_ctx_t const *   ctx /* feature_set */ ) {
    2044             : 
    2045             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1194
    2046          27 :   fd_vote_state_t vote_state;
    2047          27 :   do {
    2048          27 :     int err = verify_and_get_vote_state( vote_account, clock, signers, &vote_state );
    2049          27 :     if( FD_UNLIKELY( err ) ) return err;
    2050          27 :   } while(0);
    2051             : 
    2052             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1195
    2053           9 :   do {
    2054           9 :     int err = do_process_tower_sync( &vote_state, slot_hashes, clock->epoch, clock->slot, tower_sync, ctx );
    2055           9 :     if( FD_UNLIKELY( err ) ) return err;
    2056           9 :   } while(0);
    2057             : 
    2058             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1203
    2059           0 :   return set_vote_account_state( vote_acct_idx, vote_account, &vote_state, ctx );
    2060           9 : }
    2061             : 
    2062             : /**********************************************************************/
    2063             : /* FD-only encoders / decoders (doesn't map directly to Labs impl)    */
    2064             : /**********************************************************************/
    2065             : 
    2066             : int
    2067             : fd_vote_decode_compact_update( fd_compact_vote_state_update_t * compact_update,
    2068         402 :                                fd_vote_state_update_t *         vote_update ) {
    2069             :   // Taken from:
    2070             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L954
    2071         402 :   if( compact_update->root != ULONG_MAX ) {
    2072         225 :     vote_update->has_root = 1;
    2073         225 :     vote_update->root     = compact_update->root;
    2074         225 :   } else {
    2075         177 :     vote_update->has_root = 0;
    2076         177 :     vote_update->root     = ULONG_MAX;
    2077         177 :   }
    2078             : 
    2079         402 :   fd_valloc_t valloc = fd_scratch_virtual();
    2080             : 
    2081         402 :   ulong lockouts_len = compact_update->lockouts_len;
    2082         402 :   ulong lockouts_max = fd_ulong_max( lockouts_len, MAX_LOCKOUT_HISTORY );
    2083             : 
    2084         402 :   vote_update->lockouts = deq_fd_vote_lockout_t_alloc( valloc, lockouts_max );
    2085         402 :   ulong slot            = fd_ulong_if( vote_update->has_root, vote_update->root, 0 );
    2086             : 
    2087        4752 :   for( ulong i=0; i < lockouts_len; ++i ) {
    2088        4392 :     fd_vote_lockout_t * elem = deq_fd_vote_lockout_t_push_tail_nocopy( vote_update->lockouts );
    2089        4392 :     fd_vote_lockout_new( elem );
    2090             : 
    2091        4392 :     fd_lockout_offset_t * lock_offset = &compact_update->lockouts[i];
    2092             : 
    2093        4392 :     ulong next_slot;
    2094        4392 :     if( FD_UNLIKELY( __builtin_uaddl_overflow( slot, lock_offset->offset, &next_slot ) ) )
    2095          42 :       return 0;
    2096             : 
    2097        4350 :     elem->slot = slot        = next_slot;
    2098        4350 :     elem->confirmation_count = (uint)lock_offset->confirmation_count;
    2099        4350 :   }
    2100             : 
    2101         360 :   vote_update->hash          = compact_update->hash;
    2102         360 :   vote_update->has_timestamp = compact_update->has_timestamp;
    2103         360 :   vote_update->timestamp     = compact_update->timestamp;
    2104             : 
    2105         360 :   return 1;
    2106         402 : }
    2107             : 
    2108             : void
    2109             : fd_vote_record_timestamp_vote( fd_exec_slot_ctx_t * slot_ctx,
    2110             :                                fd_pubkey_t const *  vote_acc,
    2111           0 :                                long                 timestamp ) {
    2112           0 :   fd_vote_record_timestamp_vote_with_slot(
    2113           0 :       slot_ctx, vote_acc, timestamp, slot_ctx->slot_bank.slot );
    2114           0 : }
    2115             : 
    2116             : void
    2117             : fd_vote_record_timestamp_vote_with_slot( fd_exec_slot_ctx_t * slot_ctx,
    2118             :                                          fd_pubkey_t const *  vote_acc,
    2119             :                                          long                 timestamp,
    2120           0 :                                          ulong                slot ) {
    2121           0 :   fd_clock_timestamp_vote_t_mapnode_t * root = slot_ctx->slot_bank.timestamp_votes.votes_root;
    2122           0 :   fd_clock_timestamp_vote_t_mapnode_t * pool = slot_ctx->slot_bank.timestamp_votes.votes_pool;
    2123           0 :   if( NULL == pool )
    2124           0 :     pool = slot_ctx->slot_bank.timestamp_votes.votes_pool =
    2125           0 :         fd_clock_timestamp_vote_t_map_alloc( slot_ctx->valloc, 15000 );
    2126             : 
    2127           0 :   fd_clock_timestamp_vote_t timestamp_vote = {
    2128           0 :       .pubkey    = *vote_acc,
    2129           0 :       .timestamp = (long)timestamp,
    2130           0 :       .slot      = slot,
    2131           0 :   };
    2132           0 :   fd_clock_timestamp_vote_t_mapnode_t   key = { .elem = timestamp_vote };
    2133           0 :   fd_clock_timestamp_vote_t_mapnode_t * node =
    2134           0 :       fd_clock_timestamp_vote_t_map_find( pool, root, &key );
    2135           0 :   if( NULL != node ) {
    2136           0 :     node->elem = timestamp_vote;
    2137           0 :   } else {
    2138           0 :     node = fd_clock_timestamp_vote_t_map_acquire( pool );
    2139           0 :     FD_TEST( node != NULL );
    2140           0 :     node->elem = timestamp_vote;
    2141           0 :     fd_clock_timestamp_vote_t_map_insert( pool, &root, node );
    2142           0 :     slot_ctx->slot_bank.timestamp_votes.votes_root = root;
    2143           0 :   }
    2144           0 : }
    2145             : 
    2146             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L751
    2147             : int
    2148             : fd_vote_acc_credits( fd_exec_instr_ctx_t const * ctx,
    2149             :                      fd_account_meta_t const *   vote_acc_meta,
    2150             :                      uchar const *               vote_acc_data,
    2151           0 :                      ulong *                     result ) {
    2152           0 :   int rc;
    2153             : 
    2154           0 :   fd_valloc_t scratch_valloc = fd_scratch_virtual();
    2155             : 
    2156           0 :   fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock( ctx->slot_ctx->sysvar_cache );
    2157           0 :   if( FD_UNLIKELY( !clock ) ) return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2158             : 
    2159             :   /* Read vote account */
    2160           0 :   fd_borrowed_account_t vote_account = {
    2161             :       // FIXME call sites
    2162           0 :       .const_meta = vote_acc_meta,
    2163           0 :       .const_data = vote_acc_data,
    2164           0 :   };
    2165             : 
    2166           0 :   rc = 0;
    2167           0 :   fd_vote_state_versioned_t vote_state_versioned;
    2168           0 :   rc = get_state( &vote_account, scratch_valloc, &vote_state_versioned );
    2169           0 :   if( FD_UNLIKELY( rc ) ) return rc;
    2170           0 :   convert_to_current( &vote_state_versioned, scratch_valloc );
    2171           0 :   fd_vote_state_t * state = &vote_state_versioned.inner.current;
    2172           0 :   if( deq_fd_vote_epoch_credits_t_empty( state->epoch_credits ) ) {
    2173           0 :     *result = 0;
    2174           0 :   } else {
    2175           0 :     *result = deq_fd_vote_epoch_credits_t_peek_tail_const( state->epoch_credits )->credits;
    2176           0 :   }
    2177             : 
    2178           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
    2179           0 : }
    2180             : 
    2181             : /// returns commission split as (voter_portion, staker_portion, was_split) tuple
    2182             : ///
    2183             : ///  if commission calculation is 100% one way or other, indicate with false for was_split
    2184             : 
    2185             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L543
    2186             : void
    2187             : fd_vote_commission_split( fd_vote_state_versioned_t * vote_state_versioned,
    2188             :                           ulong                       on,
    2189           0 :                           fd_commission_split_t *     result ) {
    2190           0 :   uchar * commission = NULL;
    2191           0 :   switch( vote_state_versioned->discriminant ) {
    2192           0 :   case fd_vote_state_versioned_enum_current:
    2193           0 :     commission = &vote_state_versioned->inner.current.commission;
    2194           0 :     break;
    2195           0 :   case fd_vote_state_versioned_enum_v0_23_5:
    2196           0 :     commission = &vote_state_versioned->inner.v0_23_5.commission;
    2197           0 :     break;
    2198           0 :   case fd_vote_state_versioned_enum_v1_14_11:
    2199           0 :     commission = &vote_state_versioned->inner.v1_14_11.commission;
    2200           0 :     break;
    2201           0 :   default:
    2202           0 :     __builtin_unreachable();
    2203           0 :   }
    2204           0 :   uchar deref_commision = *commission;
    2205           0 :   uint commission_split = fd_uint_min( (uint)deref_commision, 100 );
    2206           0 :   result->is_split      = ( commission_split != 0 && commission_split != 100 );
    2207             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L545
    2208           0 :   if( commission_split == 0 ) {
    2209           0 :     result->voter_portion  = 0;
    2210           0 :     result->staker_portion = on;
    2211           0 :     return;
    2212           0 :   }
    2213             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L546
    2214           0 :   if( commission_split == 100 ) {
    2215           0 :     result->voter_portion  = on;
    2216           0 :     result->staker_portion = 0;
    2217           0 :     return;
    2218           0 :   }
    2219             :   /* Note: order of operations may matter for int division. That's why I didn't make the
    2220             :    * optimization of getting out the common calculations */
    2221             : 
    2222             :   // ... This is copied from the solana comments...
    2223             :   //
    2224             :   // Calculate mine and theirs independently and symmetrically instead
    2225             :   // of using the remainder of the other to treat them strictly
    2226             :   // equally. This is also to cancel the rewarding if either of the
    2227             :   // parties should receive only fractional lamports, resulting in not
    2228             :   // being rewarded at all. Thus, note that we intentionally discard
    2229             :   // any residual fractional lamports.
    2230             : 
    2231             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L548
    2232           0 :   result->voter_portion =
    2233           0 :       (ulong)( (uint128)on * (uint128)commission_split / (uint128)100 );
    2234           0 :   result->staker_portion =
    2235           0 :       (ulong)( (uint128)on * (uint128)( 100 - commission_split ) / (uint128)100 );
    2236           0 : }
    2237             : 
    2238             : /**********************************************************************/
    2239             : /* mod vote_processor                                                 */
    2240             : /**********************************************************************/
    2241             : 
    2242             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L21
    2243             : static int
    2244             : process_authorize_with_seed_instruction(
    2245             :     /* invoke_context */
    2246             :     fd_exec_instr_ctx_t const * ctx,
    2247             :     /* transaction_context */
    2248             :     ulong                   vote_acct_idx,
    2249             :     fd_borrowed_account_t * vote_account,
    2250             :     fd_pubkey_t const *     new_authority,
    2251             :     fd_vote_authorize_t     authorization_type,
    2252             :     fd_pubkey_t const *     current_authority_derived_key_owner,
    2253             :     uchar const *           current_authority_derived_key_seed,
    2254         276 :     ulong                   current_authority_derived_key_seed_len ) {
    2255         276 :   int rc = 0;
    2256             : 
    2257             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L31
    2258         276 :   fd_sol_sysvar_clock_t const * clock = fd_sysvar_from_instr_acct_clock( ctx, 1, &rc );
    2259         276 :   if( FD_UNLIKELY( !clock ) ) return rc;
    2260             : 
    2261         246 :   fd_pubkey_t * expected_authority_keys[FD_TXN_SIG_MAX] = { 0 };
    2262         246 :   fd_pubkey_t   single_signer                        = { 0 };
    2263             : 
    2264         246 :   if( ctx->instr->acct_cnt < 3 )
    2265           0 :     return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
    2266             : 
    2267             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L33
    2268         246 :   if( fd_instr_acc_is_signer_idx( ctx->instr, 2 ) ) {
    2269             : 
    2270             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L35
    2271         180 :     fd_pubkey_t const * base_pubkey = &ctx->instr->acct_pubkeys[2];
    2272             : 
    2273             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L37
    2274         180 :     expected_authority_keys[0] = &single_signer;
    2275         180 :     rc = fd_pubkey_create_with_seed( ctx,
    2276         180 :                                      base_pubkey->uc,
    2277         180 :                                      (char const *)current_authority_derived_key_seed,
    2278         180 :                                      current_authority_derived_key_seed_len,
    2279         180 :                                      current_authority_derived_key_owner->uc,
    2280         180 :                                      /* insert */ expected_authority_keys[0]->uc );
    2281         180 :     if( FD_UNLIKELY( rc ) ) return rc;
    2282         180 :   }
    2283             : 
    2284             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L43
    2285         234 :   return authorize( vote_acct_idx,
    2286         234 :                     vote_account,
    2287         234 :                     new_authority,
    2288         234 :                     authorization_type,
    2289         234 :                     (fd_pubkey_t const **)expected_authority_keys,
    2290         234 :                     clock,
    2291         234 :                     ctx );
    2292         246 : }
    2293             : 
    2294             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/vote_state_versions.rs#L90
    2295           0 : uint vote_state_versions_is_correct_and_initialized( fd_borrowed_account_t * vote_account ) {
    2296             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L885
    2297           0 :   uint data_len_check = vote_account->const_meta->dlen == FD_VOTE_STATE_V3_SZ;
    2298           0 :   uchar test_data[DEFAULT_PRIOR_VOTERS_OFFSET] = {0};
    2299           0 :   uint data_check = memcmp((
    2300           0 :     (uchar*)vote_account->const_data + VERSION_OFFSET), test_data, DEFAULT_PRIOR_VOTERS_OFFSET) != 0;
    2301           0 :   if (data_check && data_len_check) {
    2302           0 :     return 1;
    2303           0 :   }
    2304             : 
    2305             :   // VoteState1_14_11::is_correct_size_and_initialized
    2306             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/vote_state_1_14_11.rs#L58
    2307           0 :   data_len_check = vote_account->const_meta->dlen == FD_VOTE_STATE_V2_SZ;
    2308           0 :   uchar test_data_1_14_11[DEFAULT_PRIOR_VOTERS_OFFSET_1_14_11] = {0};
    2309           0 :   data_check = memcmp(
    2310           0 :     ((uchar*)vote_account->const_data + VERSION_OFFSET), test_data_1_14_11, DEFAULT_PRIOR_VOTERS_OFFSET_1_14_11) != 0;
    2311           0 :   return data_check && data_len_check;
    2312           0 : }
    2313             : 
    2314             : /**********************************************************************/
    2315             : /* Entry point for the Vote Program                                   */
    2316             : /**********************************************************************/
    2317             : 
    2318             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L57
    2319             : int
    2320       23931 : fd_vote_program_execute( fd_exec_instr_ctx_t * ctx ) {
    2321             :   /* FD-specific init */
    2322       23931 :   int rc = FD_EXECUTOR_INSTR_SUCCESS;
    2323             : 
    2324             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L57
    2325       23931 :   FD_EXEC_CU_UPDATE( ctx, DEFAULT_COMPUTE_UNITS );
    2326             : 
    2327             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L64
    2328       19419 :   if( FD_UNLIKELY( ctx->instr->acct_cnt < 1 ) ) {
    2329         366 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
    2330         366 :   }
    2331             : 
    2332       19053 :   fd_borrowed_account_t * me = NULL;
    2333       19053 :   rc                         = fd_instr_borrowed_account_view_idx( ctx, 0, &me );
    2334             : 
    2335       19053 :   switch( rc ) {
    2336       19053 :   case FD_ACC_MGR_SUCCESS:
    2337       19053 :     break;
    2338           0 :   case FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT:
    2339             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/src/transaction_context.rs#L637
    2340           0 :     return FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
    2341           0 :   default:
    2342             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/src/transaction_context.rs#L639
    2343           0 :     return FD_EXECUTOR_INSTR_ERR_ACC_BORROW_FAILED;
    2344       19053 :   }
    2345             : 
    2346             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L65
    2347       19053 :   if( FD_UNLIKELY( 0 != memcmp( &me->const_meta->info.owner,
    2348       19053 :                                 fd_solana_vote_program_id.key,
    2349       19053 :                                 sizeof( fd_pubkey_t ) ) ) ) {
    2350             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L66
    2351        5364 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_OWNER;
    2352        5364 :   }
    2353             : 
    2354             :   /* Replicate vote account changes to bank caches after processing the
    2355             :      transaction's instructions. */
    2356       13689 :   ctx->txn_ctx->dirty_vote_acc = 1;
    2357             : 
    2358             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L69
    2359       13689 :   fd_pubkey_t const * signers[FD_TXN_SIG_MAX] = { 0 };
    2360       13689 :   fd_instr_get_signers( ctx->instr, signers );
    2361             : 
    2362             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L70
    2363       13689 :   if( FD_UNLIKELY( ctx->instr->data==NULL ) ) {
    2364          21 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    2365          21 :   }
    2366       13668 :   fd_vote_instruction_t   instruction;
    2367       13668 :   fd_bincode_decode_ctx_t decode = {
    2368       13668 :       .data    = ctx->instr->data,
    2369       13668 :       .dataend = ctx->instr->data + ctx->instr->data_sz,
    2370       13668 :       .valloc  = fd_scratch_virtual()
    2371       13668 :   };
    2372       13668 :   int decode_result = fd_vote_instruction_decode( &instruction, &decode );
    2373       13668 :   if( decode_result != FD_BINCODE_SUCCESS ||
    2374       13668 :       (ulong)ctx->instr->data + 1232UL < (ulong)decode.data )
    2375        3822 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    2376             : 
    2377             :   /* PLEASE PRESERVE SWITCH-CASE ORDERING TO MIRROR LABS IMPL:
    2378             :    */
    2379        9846 :   switch( instruction.discriminant ) {
    2380             : 
    2381             :   /* InitializeAccount
    2382             :    *
    2383             :    * Instruction:
    2384             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L32
    2385             :    *
    2386             :    * Processor:
    2387             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L71
    2388             :    */
    2389         279 :   case fd_vote_instruction_enum_initialize_account: {
    2390             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L72
    2391         279 :     fd_rent_t const * rent = fd_sysvar_from_instr_acct_rent( ctx, 1UL, &rc );
    2392         279 :     if( FD_UNLIKELY( !rent ) ) return rc;
    2393             : 
    2394         252 :     if( FD_UNLIKELY( me->const_meta->info.lamports <
    2395         252 :                      fd_rent_exempt_minimum_balance( rent, me->const_meta->dlen ) ) )
    2396           6 :       return FD_EXECUTOR_INSTR_ERR_INSUFFICIENT_FUNDS;
    2397             : 
    2398             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L76
    2399         246 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_from_instr_acct_clock( ctx, 2, &rc );
    2400         246 :     if( !clock ) return rc;
    2401             : 
    2402             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L78
    2403         225 :     rc = initialize_account( 0, me, &instruction.inner.initialize_account, signers, clock, ctx );
    2404             : 
    2405         225 :     break;
    2406         246 :   }
    2407             : 
    2408             :   /* Authorize
    2409             :    *
    2410             :    * Instruction:
    2411             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L40
    2412             :    *
    2413             :    * Processor:
    2414             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L86
    2415             :    *
    2416             :    * Notes:
    2417             :    * - Up to two signers: the vote authority and the authorized withdrawer.
    2418             :    */
    2419        1257 :   case fd_vote_instruction_enum_authorize: {
    2420             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L87
    2421        1257 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_from_instr_acct_clock( ctx, 1, &rc );
    2422        1257 :     if( !clock ) return rc;
    2423             : 
    2424             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L89
    2425        1236 :     fd_pubkey_t const * voter_pubkey   = &instruction.inner.authorize.pubkey;
    2426        1236 :     fd_vote_authorize_t vote_authorize = instruction.inner.authorize.vote_authorize;
    2427             : 
    2428        1236 :     rc = authorize( 0, me, voter_pubkey, vote_authorize, signers, clock, ctx );
    2429             : 
    2430        1236 :     break;
    2431        1257 :   }
    2432             : 
    2433             :   /* AuthorizeWithSeed
    2434             :    *
    2435             :    * Instruction:
    2436             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L117
    2437             :    *
    2438             :    * Processor:
    2439             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L98
    2440             :    */
    2441         228 :   case fd_vote_instruction_enum_authorize_with_seed: {
    2442             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L99
    2443         228 :     if( FD_UNLIKELY( ctx->instr->acct_cnt < 3 ) ) {
    2444           9 :       rc = FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
    2445           9 :       break;
    2446           9 :     }
    2447             : 
    2448             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L100
    2449         219 :     fd_vote_authorize_with_seed_args_t * args = &instruction.inner.authorize_with_seed;
    2450             : 
    2451         219 :     rc = process_authorize_with_seed_instruction( ctx,
    2452         219 :                                                   0, me,
    2453         219 :                                                   &args->new_authority,
    2454         219 :                                                   args->authorization_type,
    2455         219 :                                                   &args->current_authority_derived_key_owner,
    2456         219 :                                                   args->current_authority_derived_key_seed,
    2457         219 :                                                   args->current_authority_derived_key_seed_len );
    2458             : 
    2459         219 :     break;
    2460         228 :   }
    2461             : 
    2462             :   /* AuthorizeCheckedWithSeed
    2463             :    *
    2464             :    * Instruction:
    2465             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L131
    2466             :    *
    2467             :    * Processor:
    2468             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L111
    2469             :    */
    2470         114 :   case fd_vote_instruction_enum_authorize_checked_with_seed: {
    2471         114 :     fd_vote_authorize_checked_with_seed_args_t const * args =
    2472         114 :         &instruction.inner.authorize_checked_with_seed;
    2473             : 
    2474             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L112
    2475         114 :     if( FD_UNLIKELY( ctx->instr->acct_cnt < 4 ) ) {
    2476           9 :       rc = FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
    2477           9 :       break;
    2478           9 :     }
    2479             : 
    2480             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L116
    2481         105 :     fd_pubkey_t const * new_authority = &ctx->instr->acct_pubkeys[3];
    2482             : 
    2483         105 :     if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( ctx->instr, 3 ) ) ) {
    2484             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L117
    2485          48 :       rc = FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
    2486          48 :       break;
    2487          48 :     }
    2488             : 
    2489             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L119
    2490          57 :     rc = process_authorize_with_seed_instruction( ctx,
    2491          57 :                                                   0, me,
    2492          57 :                                                   new_authority,
    2493          57 :                                                   args->authorization_type,
    2494          57 :                                                   &args->current_authority_derived_key_owner,
    2495          57 :                                                   args->current_authority_derived_key_seed,
    2496          57 :                                                   args->current_authority_derived_key_seed_len );
    2497             : 
    2498          57 :     break;
    2499         105 :   }
    2500             : 
    2501             :   /* UpdateValidatorIdentity
    2502             :    *
    2503             :    * Instruction:
    2504             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L65
    2505             :    *
    2506             :    * Processor:
    2507             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L130
    2508             :    */
    2509        1326 :   case fd_vote_instruction_enum_update_validator_identity: {
    2510             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L131
    2511        1326 :     if( FD_UNLIKELY( ctx->instr->acct_cnt < 2 ) ) {
    2512           3 :       rc = FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
    2513           3 :       break;
    2514           3 :     }
    2515             : 
    2516             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L132
    2517        1323 :     fd_pubkey_t const * node_pubkey = &ctx->instr->acct_pubkeys[1];
    2518             : 
    2519             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L135
    2520        1323 :     rc = update_validator_identity( 0, me, node_pubkey, signers, ctx );
    2521             : 
    2522        1323 :     break;
    2523        1326 :   }
    2524             : 
    2525             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L142
    2526        1404 :   case fd_vote_instruction_enum_update_commission: {
    2527             : 
    2528             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L149
    2529        1404 :     fd_epoch_schedule_t const * epoch_schedule = fd_sysvar_cache_epoch_schedule( ctx->slot_ctx->sysvar_cache );
    2530        1404 :     if( FD_UNLIKELY( !epoch_schedule ) )
    2531           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2532             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L150
    2533        1404 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock( ctx->slot_ctx->sysvar_cache );
    2534        1404 :     if( FD_UNLIKELY( !clock ) )
    2535           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2536             : 
    2537             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L145
    2538        1404 :     rc = update_commission( 0, me, instruction.inner.update_commission, signers, epoch_schedule, clock, ctx );
    2539             : 
    2540        1404 :     break;
    2541        1404 :   }
    2542             : 
    2543             :   /* Vote
    2544             :    *
    2545             :    * Instruction:
    2546             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L49
    2547             :    */
    2548         666 :   case fd_vote_instruction_enum_vote:;
    2549             :     /* clang-format off */
    2550         666 :     __attribute__((fallthrough));
    2551             :     /* clang-format on */
    2552             : 
    2553             :   /* VoteSwitch
    2554             :    *
    2555             :    * Instruction:
    2556             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L81
    2557             :    *
    2558             :    * Processor:
    2559             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L154
    2560             :    */
    2561        1308 :   case fd_vote_instruction_enum_vote_switch: {
    2562        1308 :     if( FD_FEATURE_ACTIVE( ctx->slot_ctx, deprecate_legacy_vote_ixs ) &&
    2563        1308 :         FD_FEATURE_ACTIVE( ctx->slot_ctx, enable_tower_sync_ix ) ) {
    2564           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    2565           0 :     }
    2566             : 
    2567        1308 :     fd_vote_t * vote;
    2568        1308 :     if( instruction.discriminant == fd_vote_instruction_enum_vote ) {
    2569         666 :       vote = &instruction.inner.vote;
    2570         666 :     } else if( instruction.discriminant == fd_vote_instruction_enum_vote_switch ) {
    2571         642 :       vote = &instruction.inner.vote_switch.vote;
    2572         642 :     } else {
    2573           0 :       __builtin_unreachable();
    2574           0 :     }
    2575             : 
    2576             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L155
    2577        1308 :     int err;
    2578        1308 :     fd_slot_hashes_t const * slot_hashes = fd_sysvar_from_instr_acct_slot_hashes( ctx, 1, &err );
    2579        1308 :     if( FD_UNLIKELY( !slot_hashes ) ) return err;
    2580             : 
    2581             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L157
    2582        1173 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_from_instr_acct_clock( ctx, 2, &err );
    2583        1173 :     if( FD_UNLIKELY( !clock ) ) return err;
    2584             : 
    2585        1161 :     rc = process_vote_with_account( 0, me, slot_hashes, clock, vote, signers, ctx );
    2586             : 
    2587        1161 :     break;
    2588        1173 :   }
    2589             : 
    2590             :   /* UpdateVoteState
    2591             :    *
    2592             :    * Instruction:
    2593             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L100
    2594             :    */
    2595         831 :   case fd_vote_instruction_enum_update_vote_state:;
    2596             :     /* clang-format off */
    2597         831 :     __attribute__((fallthrough));
    2598             :     /* clang-format on */
    2599             : 
    2600             :   /* UpdateVoteStateSwitch
    2601             :    *
    2602             :    * Instruction:
    2603             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L107
    2604             :    *
    2605             :    * Processor:
    2606             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L169
    2607             :    */
    2608        1566 :   case fd_vote_instruction_enum_update_vote_state_switch: {
    2609        1566 :     if( FD_FEATURE_ACTIVE( ctx->slot_ctx, deprecate_legacy_vote_ixs ) &&
    2610        1566 :         FD_FEATURE_ACTIVE( ctx->slot_ctx, enable_tower_sync_ix ) ) {
    2611           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    2612           0 :     }
    2613             : 
    2614        1566 :     fd_vote_state_update_t * vote_state_update;
    2615        1566 :     switch( instruction.discriminant ) {
    2616         831 :     case fd_vote_instruction_enum_update_vote_state:
    2617         831 :       vote_state_update = &instruction.inner.update_vote_state;
    2618         831 :       break;
    2619         735 :     case fd_vote_instruction_enum_update_vote_state_switch:
    2620         735 :       vote_state_update = &instruction.inner.update_vote_state_switch.vote_state_update;
    2621         735 :       break;
    2622           0 :     default:
    2623           0 :       __builtin_unreachable();
    2624        1566 :     }
    2625             : 
    2626             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L171
    2627        1566 :     fd_slot_hashes_t const * slot_hashes = fd_sysvar_cache_slot_hashes( ctx->slot_ctx->sysvar_cache );
    2628        1566 :     if( FD_UNLIKELY( !slot_hashes ) )
    2629          60 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2630             : 
    2631             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L172
    2632        1506 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock( ctx->slot_ctx->sysvar_cache );
    2633        1506 :     if( FD_UNLIKELY( !clock ) )
    2634           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2635             : 
    2636             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L173
    2637        1506 :     rc = process_vote_state_update( 0, me, slot_hashes, clock, vote_state_update, signers, ctx );
    2638             : 
    2639        1506 :     break;
    2640        1506 :   }
    2641             : 
    2642             :   /* CompactUpdateVoteState
    2643             :    *
    2644             :    * Instruction:
    2645             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L139
    2646             :    *
    2647             :    * Notes:
    2648             :    * - Up to three signers: the vote authority, the authorized withdrawer, and the new authority.
    2649             :    * - Feature gated, but live on mainnet.
    2650             :    */
    2651         240 :   case fd_vote_instruction_enum_compact_update_vote_state:;
    2652         240 :     __attribute__((fallthrough));
    2653             : 
    2654             :   /* CompactUpdateVoteStateSwitch
    2655             :    *
    2656             :    * Instruction:
    2657             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L146
    2658             :    *
    2659             :    * Processor:
    2660             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L183
    2661             :    *
    2662             :    * Notes:
    2663             :    * - Up to three signers: the vote authority, the authorized withdrawer, and the new authority.
    2664             :    * - Feature gated, but live on mainnet.
    2665             :    */
    2666         402 :   case fd_vote_instruction_enum_compact_update_vote_state_switch: {
    2667             :     /* https://github.com/anza-xyz/agave/blob/dc4b9dcbbf859ff48f40d00db824bde063fdafcc/programs/vote/src/vote_processor.rs#L183-L191 */
    2668         402 :     if( FD_FEATURE_ACTIVE( ctx->slot_ctx, deprecate_legacy_vote_ixs ) &&
    2669         402 :         FD_FEATURE_ACTIVE( ctx->slot_ctx, enable_tower_sync_ix ) ) {
    2670           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    2671           0 :     }
    2672             : 
    2673         402 :     fd_compact_vote_state_update_t * vote_state_update = NULL;
    2674         402 :     if( instruction.discriminant == fd_vote_instruction_enum_compact_update_vote_state ) {
    2675         240 :       vote_state_update = &instruction.inner.compact_update_vote_state;
    2676         240 :     } else if( instruction.discriminant ==
    2677         162 :                fd_vote_instruction_enum_compact_update_vote_state_switch ) {
    2678         162 :       vote_state_update =
    2679         162 :           &instruction.inner.compact_update_vote_state_switch.compact_vote_state_update;
    2680         162 :     }
    2681             : 
    2682         402 :     fd_vote_state_update_t vote_update;
    2683         402 :     fd_vote_state_update_new( &vote_update );
    2684         402 :     if( FD_UNLIKELY( !fd_vote_decode_compact_update( vote_state_update, &vote_update ) ) )
    2685          42 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    2686             : 
    2687             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L185
    2688         360 :     fd_slot_hashes_t const * slot_hashes = fd_sysvar_cache_slot_hashes( ctx->slot_ctx->sysvar_cache );
    2689         360 :     if( FD_UNLIKELY( !slot_hashes ) )
    2690          57 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2691             : 
    2692         303 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock( ctx->slot_ctx->sysvar_cache );
    2693         303 :     if( FD_UNLIKELY( !clock ) )
    2694           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2695             : 
    2696             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L187
    2697         303 :     rc = process_vote_state_update( 0, me, slot_hashes, clock, &vote_update, signers, ctx );
    2698             : 
    2699         303 :     break;
    2700         303 :   }
    2701             : 
    2702             :   /* TowerSync(Switch)
    2703             :    *
    2704             :    * Instruction:
    2705             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L151-L157
    2706             :    *
    2707             :    * Processor:
    2708             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L196-L215
    2709             :    */
    2710             : 
    2711         105 :   case fd_vote_instruction_enum_tower_sync:
    2712         165 :   case fd_vote_instruction_enum_tower_sync_switch: {
    2713         165 :     if( !FD_FEATURE_ACTIVE( ctx->slot_ctx, enable_tower_sync_ix ) ) {
    2714         132 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    2715         132 :     }
    2716             : 
    2717          33 :     fd_tower_sync_t * tower_sync = (instruction.discriminant == fd_vote_instruction_enum_tower_sync)
    2718          33 :         ? &instruction.inner.tower_sync
    2719          33 :         : &instruction.inner.tower_sync_switch.tower_sync;
    2720             : 
    2721          33 :     fd_slot_hashes_t const *      slot_hashes = fd_sysvar_cache_slot_hashes( ctx->slot_ctx->sysvar_cache );
    2722          33 :     fd_sol_sysvar_clock_t const * clock       = fd_sysvar_cache_clock( ctx->slot_ctx->sysvar_cache );
    2723          33 :     if( FD_UNLIKELY( !slot_hashes || !clock ) ) {
    2724           6 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2725           6 :     }
    2726             : 
    2727          27 :     rc = process_tower_sync( 0, me, slot_hashes, clock, tower_sync, signers, ctx );
    2728          27 :     break;
    2729          33 :   }
    2730             : 
    2731             :   /* Withdraw
    2732             :    *
    2733             :    * Instruction:
    2734             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L57
    2735             :    *
    2736             :    * Processor:
    2737             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L216
    2738             :    */
    2739         906 :   case fd_vote_instruction_enum_withdraw: {
    2740         906 :     if( FD_UNLIKELY( ctx->instr->acct_cnt < 2 ) ) {
    2741           3 :       rc = FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
    2742           3 :       break;
    2743           3 :     }
    2744         903 :     fd_rent_t const * rent_sysvar = fd_sysvar_cache_rent( ctx->slot_ctx->sysvar_cache );
    2745         903 :     if( FD_UNLIKELY( !rent_sysvar ) )
    2746           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2747         903 :     fd_sol_sysvar_clock_t const * clock_sysvar = fd_sysvar_cache_clock( ctx->slot_ctx->sysvar_cache );
    2748         903 :     if( FD_UNLIKELY( !clock_sysvar ) )
    2749           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2750             : 
    2751         903 :     rc = withdraw( ctx, 0, me, instruction.inner.withdraw, 1, signers, rent_sysvar, clock_sysvar );
    2752             : 
    2753         903 :     break;
    2754         903 :   }
    2755             : 
    2756             :   /* AuthorizeChecked
    2757             :    *
    2758             :    * Instruction:
    2759             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L93
    2760             :    *
    2761             :    * Processor:
    2762             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L234
    2763             :    *
    2764             :    * Notes:
    2765             :    * - Up to three signers: the vote authority, the authorized withdrawer, and the new authority.
    2766             :    * - Feature gated, but live on mainnet.
    2767             :    */
    2768         891 :   case fd_vote_instruction_enum_authorize_checked: {
    2769         891 :     if( FD_UNLIKELY( ctx->instr->acct_cnt < 4 ) ) {
    2770          18 :       rc = FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
    2771          18 :       break;
    2772          18 :     }
    2773             : 
    2774             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L236
    2775         873 :     fd_pubkey_t const * voter_pubkey = &ctx->instr->acct_pubkeys[3];
    2776             : 
    2777             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L239
    2778         873 :     if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( ctx->instr, 3 ) ) ) {
    2779         330 :       rc = FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
    2780         330 :       break;
    2781         330 :     }
    2782             : 
    2783             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L242
    2784         543 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_from_instr_acct_clock( ctx, 1, &rc );
    2785         543 :     if( FD_UNLIKELY( !clock ) ) return rc;
    2786             : 
    2787         465 :     rc = authorize( 0, me, voter_pubkey, instruction.inner.authorize_checked, signers, clock, ctx );
    2788         465 :     break;
    2789         543 :   }
    2790             : 
    2791           0 :   default:
    2792           0 :     FD_LOG_ERR(( "unsupported vote instruction: %u", instruction.discriminant ));
    2793        9846 :   }
    2794             : 
    2795        9249 :   return rc;
    2796        9846 : }
    2797             : 
    2798             : /**********************************************************************/
    2799             : /* Public API                                                         */
    2800             : /**********************************************************************/
    2801             : 
    2802             : int
    2803             : fd_vote_get_state( fd_borrowed_account_t const * self,
    2804             :                    fd_valloc_t                   valloc,
    2805        2961 :                    fd_vote_state_versioned_t *   versioned /* out */ ) {
    2806        2961 :   return get_state( self, valloc, versioned );
    2807        2961 : }
    2808             : 
    2809             : void
    2810             : fd_vote_convert_to_current( fd_vote_state_versioned_t * self,
    2811        1848 :                             fd_valloc_t                 valloc ) {
    2812        1848 :   convert_to_current( self, valloc );
    2813        1848 : }
    2814             : 
    2815             : static void
    2816           0 : remove_vote_account( fd_exec_slot_ctx_t * slot_ctx, fd_borrowed_account_t * vote_account ) {
    2817           0 :   fd_vote_accounts_pair_t_mapnode_t key;
    2818           0 :   fd_memcpy( key.elem.key.uc, vote_account->pubkey->uc, sizeof(fd_pubkey_t) );
    2819             : 
    2820           0 :   fd_epoch_bank_t * epoch_bank = fd_exec_epoch_ctx_epoch_bank( slot_ctx->epoch_ctx );
    2821           0 :   fd_vote_accounts_t * epoch_vote_accounts = &epoch_bank->stakes.vote_accounts;
    2822           0 :   if (epoch_vote_accounts->vote_accounts_pool == NULL) {
    2823           0 :     FD_LOG_DEBUG(("Vote accounts pool does not exist"));
    2824           0 :     return;
    2825           0 :   }
    2826           0 :   fd_vote_accounts_pair_t_mapnode_t * entry = fd_vote_accounts_pair_t_map_find(epoch_vote_accounts->vote_accounts_pool, epoch_vote_accounts->vote_accounts_root, &key);
    2827           0 :   if (FD_LIKELY( entry )) {
    2828           0 :     fd_vote_accounts_pair_t_map_remove( epoch_vote_accounts->vote_accounts_pool, &epoch_vote_accounts->vote_accounts_root, entry);
    2829           0 :   }
    2830             : 
    2831           0 :   if (slot_ctx->slot_bank.vote_account_keys.vote_accounts_pool == NULL) {
    2832           0 :     FD_LOG_DEBUG(("Vote accounts pool does not exist"));
    2833           0 :     return;
    2834           0 :   }
    2835           0 :   entry = fd_vote_accounts_pair_t_map_find(slot_ctx->slot_bank.vote_account_keys.vote_accounts_pool, slot_ctx->slot_bank.vote_account_keys.vote_accounts_root, &key);
    2836           0 :   if (FD_UNLIKELY( entry )) {
    2837           0 :     fd_vote_accounts_pair_t_map_remove( slot_ctx->slot_bank.vote_account_keys.vote_accounts_pool, &slot_ctx->slot_bank.vote_account_keys.vote_accounts_root, entry);
    2838           0 :   }
    2839           0 : }
    2840             : 
    2841             : void
    2842           0 : upsert_vote_account( fd_exec_slot_ctx_t * slot_ctx, fd_borrowed_account_t * vote_account ) {
    2843           0 :   FD_SCRATCH_SCOPE_BEGIN {
    2844             : 
    2845           0 :     fd_bincode_decode_ctx_t decode = {
    2846           0 :       .data    = vote_account->const_data,
    2847           0 :       .dataend = vote_account->const_data + vote_account->const_meta->dlen,
    2848           0 :       .valloc  = slot_ctx->valloc,
    2849           0 :     };
    2850           0 :     fd_bincode_destroy_ctx_t destroy = {
    2851           0 :       .valloc = slot_ctx->valloc,
    2852           0 :     };
    2853           0 :     fd_vote_state_versioned_t vote_state[1] = {0};
    2854           0 :     if( FD_UNLIKELY( 0!=fd_vote_state_versioned_decode( vote_state, &decode ) ) ) {
    2855           0 :       remove_vote_account( slot_ctx, vote_account );
    2856           0 :       fd_vote_state_versioned_destroy( vote_state, &destroy );
    2857           0 :       return;
    2858           0 :     }
    2859             : 
    2860           0 :     if ( vote_state_versions_is_correct_and_initialized( vote_account ) ) {
    2861           0 :       fd_epoch_bank_t * epoch_bank = fd_exec_epoch_ctx_epoch_bank( slot_ctx->epoch_ctx );
    2862           0 :       fd_stakes_t * stakes = &epoch_bank->stakes;
    2863             : 
    2864           0 :       fd_vote_accounts_pair_t_mapnode_t key;
    2865           0 :       fd_memcpy(&key.elem.key, vote_account->pubkey->uc, sizeof(fd_pubkey_t));
    2866           0 :       if (stakes->vote_accounts.vote_accounts_pool == NULL) {
    2867           0 :         FD_LOG_DEBUG(("Vote accounts pool does not exist"));
    2868           0 :         fd_vote_state_versioned_destroy( vote_state, &destroy );
    2869           0 :         return;
    2870           0 :       }
    2871           0 :       fd_vote_accounts_pair_t_mapnode_t * entry = fd_vote_accounts_pair_t_map_find( stakes->vote_accounts.vote_accounts_pool, stakes->vote_accounts.vote_accounts_root, &key);
    2872           0 :       if ( FD_UNLIKELY( !entry ) ) {
    2873           0 :         if (slot_ctx->slot_bank.vote_account_keys.vote_accounts_pool == NULL) {
    2874           0 :           FD_LOG_DEBUG(("Vote accounts pool does not exist"));
    2875           0 :           return;
    2876           0 :         }
    2877           0 :         fd_vote_accounts_pair_t_mapnode_t * existing = fd_vote_accounts_pair_t_map_find( slot_ctx->slot_bank.vote_account_keys.vote_accounts_pool, slot_ctx->slot_bank.vote_account_keys.vote_accounts_root, &key );
    2878           0 :         if ( !existing ) {
    2879           0 :           fd_vote_accounts_pair_t_mapnode_t * new_node = fd_vote_accounts_pair_t_map_acquire( slot_ctx->slot_bank.vote_account_keys.vote_accounts_pool );
    2880           0 :           if (!new_node) {
    2881           0 :             FD_LOG_ERR(("Map full"));
    2882           0 :           }
    2883             : 
    2884           0 :           fd_vote_block_timestamp_t last_timestamp;
    2885           0 :           fd_pubkey_t node_pubkey;
    2886             : 
    2887           0 :           switch( vote_state->discriminant ) {
    2888           0 :             case fd_vote_state_versioned_enum_current:
    2889           0 :               last_timestamp = vote_state->inner.current.last_timestamp;
    2890           0 :               node_pubkey    = vote_state->inner.current.node_pubkey;
    2891           0 :               break;
    2892           0 :             case fd_vote_state_versioned_enum_v0_23_5:
    2893           0 :               last_timestamp = vote_state->inner.v0_23_5.last_timestamp;
    2894           0 :               node_pubkey    = vote_state->inner.v0_23_5.node_pubkey;
    2895           0 :               break;
    2896           0 :             case fd_vote_state_versioned_enum_v1_14_11:
    2897           0 :               last_timestamp = vote_state->inner.v1_14_11.last_timestamp;
    2898           0 :               node_pubkey    = vote_state->inner.v1_14_11.node_pubkey;
    2899           0 :               break;
    2900           0 :             default:
    2901           0 :               __builtin_unreachable();
    2902           0 :           }
    2903             : 
    2904           0 :           fd_memcpy( &new_node->elem.key, vote_account->pubkey, sizeof(fd_pubkey_t));
    2905           0 :           new_node->elem.value.lamports = vote_account->const_meta->info.lamports;
    2906             : 
    2907           0 :           fd_memcpy(new_node->elem.value.node_pubkey.uc, node_pubkey.uc, sizeof(fd_pubkey_t));
    2908           0 :           new_node->elem.value.last_timestamp_ts   = last_timestamp.timestamp;
    2909           0 :           new_node->elem.value.last_timestamp_slot = last_timestamp.slot;
    2910             : 
    2911           0 :           fd_memcpy( &new_node->elem.value.owner, vote_account->const_meta->info.owner, sizeof(fd_pubkey_t) );
    2912           0 :           new_node->elem.value.executable = (uchar)vote_account->const_meta->info.executable;
    2913           0 :           new_node->elem.value.rent_epoch = vote_account->const_meta->info.rent_epoch;
    2914           0 :           new_node->elem.stake            = 0UL;
    2915           0 :           fd_vote_accounts_pair_t_map_insert( slot_ctx->slot_bank.vote_account_keys.vote_accounts_pool, &slot_ctx->slot_bank.vote_account_keys.vote_accounts_root, new_node );
    2916           0 :         } else {
    2917           0 :           existing->elem.value.lamports = vote_account->const_meta->info.lamports;
    2918           0 :         }
    2919           0 :       } else {
    2920           0 :         entry->elem.value.lamports = vote_account->const_meta->info.lamports;
    2921           0 :       }
    2922           0 :     } else {
    2923           0 :       remove_vote_account( slot_ctx, vote_account );
    2924           0 :     }
    2925             : 
    2926           0 :     fd_vote_state_versioned_destroy( vote_state, &destroy );
    2927           0 :   } FD_SCRATCH_SCOPE_END;
    2928           0 : }
    2929             : 
    2930             : void
    2931           0 : fd_vote_store_account( fd_exec_slot_ctx_t * slot_ctx, fd_borrowed_account_t * vote_account ) {
    2932           0 :   fd_pubkey_t const * owner = (fd_pubkey_t const *)vote_account->const_meta->info.owner;
    2933             : 
    2934           0 :   if (memcmp(owner->uc, fd_solana_vote_program_id.key, sizeof(fd_pubkey_t)) != 0) {
    2935           0 :       return;
    2936           0 :   }
    2937           0 :   if (vote_account->const_meta->info.lamports == 0) {
    2938           0 :     remove_vote_account( slot_ctx, vote_account );
    2939           0 :   } else {
    2940           0 :     upsert_vote_account( slot_ctx, vote_account );
    2941           0 :   }
    2942           0 : }

Generated by: LCOV version 1.14