LCOV - code coverage report
Current view: top level - flamenco/runtime/program - fd_vote_program.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 1103 1385 79.6 %
Date: 2026-10-22 18:10:43 Functions: 23 29 79.3 %

          Line data    Source code
       1             : #include "fd_vote_program.h"
       2             : #include "../fd_runtime.h"
       3             : #include "../fd_borrowed_account.h"
       4             : #include "../fd_executor.h"
       5             : #include "../fd_pubkey_utils.h"
       6             : #include "../sysvar/fd_sysvar_rent.h"
       7             : #include "../sysvar/fd_sysvar_cache.h"
       8             : #include "../sysvar/fd_sysvar.h"
       9             : #include "../fd_system_ids.h"
      10             : #include "vote/fd_authorized_voters.h"
      11             : #include "vote/fd_vote_utils.h"
      12             : #include "vote/fd_vote_codec_tmpl.h"
      13             : #include "vote/fd_vote_codec.h"
      14             : #include "vote/fd_vote_state_versioned.h"
      15             : #include "vote/fd_vote_state_v4.h"
      16             : #include "../../../ballet/bls/fd_bls12_381.h"
      17             : 
      18             : #include <limits.h>
      19             : #include <math.h>
      20             : #include <stdio.h>
      21             : #include <string.h>
      22             : 
      23             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L36
      24         416 : #define INITIAL_LOCKOUT 2UL
      25             : 
      26             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L51
      27             : #define VOTE_CREDITS_MAXIMUM_PER_SLOT_OLD 8
      28             : 
      29             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/clock.rs#L147
      30             : #define SLOT_DEFAULT 0UL
      31             : 
      32             : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/clock.rs#L147
      33             : #define SLOT_MAX ULONG_MAX
      34             : 
      35             : #define ACCOUNTS_MAX 4 /* Vote instructions take in at most 4 accounts */
      36             : 
      37             : #define DEFAULT_COMPUTE_UNITS 2100UL
      38             : #define COMPUTE_UNITS_POP    34500UL
      39             : 
      40             : /**********************************************************************/
      41             : /* VoteStateHandler                                                   */
      42             : /**********************************************************************/
      43             : 
      44             : /* Check the vote state, deserialize it as V4 and convert older versions
      45             :    to V4 in-place.
      46             :    https://github.com/anza-xyz/agave/blob/v4.1.0-alpha.0/programs/vote/src/vote_state/mod.rs#L45-L77 */
      47             : static int
      48             : get_vote_state_handler_checked( fd_borrowed_account_t const * vote_account,
      49             :                                 int                           target_version,
      50             :                                 uchar                         check_initialized,
      51        4169 :                                 fd_vote_state_versioned_t *   vote_state_versioned ) {
      52        4169 :   (void)target_version;
      53        4169 :   (void)check_initialized; /* V4 vote states are always initialized */
      54             : 
      55        4169 :   int rc = fd_vsv_deserialize( vote_account->acc, vote_state_versioned );
      56        4169 :   if( FD_UNLIKELY( rc ) ) return rc;
      57             : 
      58        2983 :   if( FD_UNLIKELY( fd_vsv_is_uninitialized( vote_state_versioned ) ) ) {
      59          69 :     return FD_EXECUTOR_INSTR_ERR_UNINITIALIZED_ACCOUNT;
      60          69 :   }
      61             : 
      62        2914 :   rc = fd_vsv_try_convert_to_v4( vote_state_versioned, (fd_pubkey_t*)vote_account->acc->pubkey );
      63        2914 :   if( FD_UNLIKELY( rc ) ) return rc;
      64             : 
      65        2914 :   return FD_EXECUTOR_INSTR_SUCCESS;
      66        2914 : }
      67             : 
      68             : /* https://github.com/anza-xyz/agave/blob/v4.1.0-alpha.0/programs/vote/src/vote_state/handler.rs#L379-L393 */
      69             : static int
      70             : check_vote_account_length( fd_borrowed_account_t const * vote_account,
      71         185 :                            int                           target_version ) {
      72         185 :   (void)target_version;
      73         185 :   ulong length = fd_borrowed_account_get_data_len( vote_account );
      74         185 :   if( FD_UNLIKELY( length!=FD_VOTE_STATE_V4_SZ ) ) {
      75          18 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
      76          18 :   }
      77         167 :   return FD_EXECUTOR_INSTR_SUCCESS;
      78         185 : }
      79             : 
      80             : /* https://github.com/anza-xyz/agave/blob/v4.1.0-alpha.0/programs/vote/src/vote_state/handler.rs#L327-L342 */
      81             : static int
      82             : init_vote_account_state( fd_exec_instr_ctx_t *         ctx,
      83             :                          fd_borrowed_account_t *       vote_account,
      84             :                          fd_vote_state_versioned_t *   versioned,
      85             :                          int                           target_version,
      86             :                          fd_vote_init_t *              vote_init,
      87         165 :                          fd_sol_sysvar_clock_t const * clock ) {
      88         165 :   (void)target_version;
      89         165 :   fd_vote_state_v4_create_new_with_defaults( (fd_pubkey_t*)vote_account->acc->pubkey, vote_init, clock, versioned );
      90         165 :   return fd_vote_state_v4_set_vote_account_state( ctx, vote_account, versioned );
      91         165 : }
      92             : 
      93             : /* https://github.com/anza-xyz/agave/blob/v4.1.0-alpha.0/programs/vote/src/vote_state/handler.rs#L344-L362 */
      94             : static int
      95             : init_vote_account_state_v2( fd_exec_instr_ctx_t *         ctx,
      96             :                             fd_borrowed_account_t *       vote_account,
      97             :                             fd_vote_state_versioned_t *   versioned,
      98             :                             int                           target_version,
      99             :                             fd_vote_init_v2_t *           vote_init_v2,
     100           0 :                             fd_sol_sysvar_clock_t const * clock ) {
     101           0 :   (void)target_version;
     102           0 :   fd_vote_state_v4_create_new( vote_init_v2, clock, versioned );
     103           0 :   return fd_vote_state_v4_set_vote_account_state( ctx, vote_account, versioned );
     104           0 : }
     105             : 
     106             : /**********************************************************************/
     107             : /* mod vote_state                                                    */
     108             : /**********************************************************************/
     109             : 
     110             : /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L82-L324 */
     111             : static int
     112             : check_and_filter_proposed_vote_state( fd_exec_instr_ctx_t *       ctx,
     113             :                                       fd_vote_state_versioned_t * versioned,
     114             :                                       fd_vote_lockout_t *         proposed_lockouts,
     115             :                                       uchar *                     proposed_has_root,
     116             :                                       ulong *                     proposed_root,
     117             :                                       fd_hash_t const *           proposed_hash,
     118         681 :                                       fd_slot_hashes_t const *    slot_hashes ) {
     119         681 :   fd_landed_vote_t const * votes         = fd_vsv_get_votes( versioned );
     120         681 :   ulong const *            root_slot     = fd_vsv_get_root_slot( versioned );
     121         681 :   uchar                    has_root_slot = !!(root_slot!=NULL);
     122             : 
     123             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L208
     124         681 :   if( FD_UNLIKELY( deq_fd_vote_lockout_t_empty( proposed_lockouts ) ) ) {
     125           6 :     ctx->txn_out->err.custom_err = FD_VOTE_ERR_EMPTY_SLOTS;
     126           6 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     127           6 :   }
     128         675 :   fd_landed_vote_t const * last_vote = NULL;
     129         675 :   if( !deq_fd_landed_vote_t_empty( votes ) ) {
     130             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L212
     131         646 :     last_vote = deq_fd_landed_vote_t_peek_tail_const( votes );
     132         646 :   }
     133             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L218
     134         675 :   if( FD_LIKELY( last_vote ) ) {
     135         647 :     if( FD_UNLIKELY( deq_fd_vote_lockout_t_peek_tail_const( proposed_lockouts )->slot <=
     136         647 :                      last_vote->lockout.slot ) ) {
     137           5 :       ctx->txn_out->err.custom_err = FD_VOTE_ERR_VOTE_TOO_OLD;
     138           5 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     139           5 :     }
     140         647 :   }
     141             : 
     142             :   /* must be nonempty, checked above */
     143         670 :   ulong last_vote_state_update_slot = deq_fd_vote_lockout_t_peek_tail_const( proposed_lockouts )->slot;
     144             : 
     145             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L224
     146         670 :   if( FD_UNLIKELY( !slot_hashes->cnt ) ) {
     147           7 :     ctx->txn_out->err.custom_err = FD_VOTE_ERR_SLOTS_MISMATCH;
     148           7 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     149           7 :   }
     150             : 
     151             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L227
     152         663 :   ulong earliest_slot_hash_in_history = slot_hashes->elems[ slot_hashes->cnt-1UL ].slot;
     153             : 
     154             :   /* Check if the proposed vote is too old to be in the SlotHash history */
     155             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L230
     156         663 :   if( FD_UNLIKELY( last_vote_state_update_slot < earliest_slot_hash_in_history ) ) {
     157           6 :     ctx->txn_out->err.custom_err = FD_VOTE_ERR_VOTE_TOO_OLD;
     158           6 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     159           6 :   }
     160             : 
     161             :   /* Check if the proposed root is too old */
     162             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L237
     163         657 :   if( *proposed_has_root ) {
     164         421 :     ulong const proposed_root_ = *proposed_root;
     165             :     /* If the new proposed root `R` is less than the earliest slot hash in the history
     166             :        such that we cannot verify whether the slot was actually was on this fork, set
     167             :        the root to the latest vote in the current vote that's less than R. */
     168             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L242
     169         421 :     if( proposed_root_ < earliest_slot_hash_in_history ) {
     170         108 :       *proposed_has_root = has_root_slot;
     171         108 :       if( has_root_slot ) {
     172          57 :         *proposed_root   = *root_slot;
     173          57 :       }
     174         108 :       for( deq_fd_landed_vote_t_iter_t iter = deq_fd_landed_vote_t_iter_init_rev( votes );
     175         714 :                                              !deq_fd_landed_vote_t_iter_done_rev( votes, iter );
     176         684 :                                        iter = deq_fd_landed_vote_t_iter_prev( votes, iter ) ) {
     177             :         /* Ensure we're iterating from biggest to smallest vote in the
     178             :            current vote state */
     179         684 :         fd_landed_vote_t const * vote = deq_fd_landed_vote_t_iter_ele_const( votes, iter );
     180             :         // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L248
     181         684 :         if( vote->lockout.slot <= proposed_root_ ) {
     182          78 :           *proposed_has_root = 1;
     183          78 :           *proposed_root     = vote->lockout.slot;
     184          78 :           break;
     185          78 :         }
     186         684 :       }
     187         108 :     }
     188         421 :   }
     189             : 
     190             :   /* Index into the new proposed vote state's slots, starting with the root if it exists then
     191             :      we use this mutable root to fold checking the root slot into the below loop for performance */
     192         657 :   int   has_root_to_check       = *proposed_has_root;
     193             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L259
     194         657 :   ulong root_to_check           = *proposed_root;
     195         657 :   ulong proposed_lockouts_index = 0UL;
     196         657 :   ulong lockouts_len = deq_fd_vote_lockout_t_cnt( proposed_lockouts );
     197             : 
     198             :   /* Index into the slot_hashes, starting at the oldest known slot hash */
     199             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L264
     200         657 :   ulong slot_hashes_index = slot_hashes->cnt;
     201             : 
     202             :   /* proposed_lockouts_indexes_to_filter's size is bounded by the length
     203             :      of the proposed lockouts provided in the instruction data. */
     204         657 :   ulong proposed_lockouts_indexes_to_filter[ FD_VOTE_INSTR_MAX_LOCKOUT_OFFSETS_LEN ];
     205         657 :   ulong filter_index = 0UL;
     206             : 
     207             :   /* Note:
     208             : 
     209             :     1) `vote_state_update.lockouts` is sorted from oldest/smallest vote to newest/largest
     210             :     vote, due to the way votes are applied to the vote state (newest votes
     211             :     pushed to the back).
     212             : 
     213             :     2) Conversely, `slot_hashes` is sorted from newest/largest vote to
     214             :     the oldest/smallest vote.
     215             : 
     216             :     Unlike for vote updates, vote state updates here can't only check votes older than the last vote
     217             :     because have to ensure that every slot is actually part of the history, not just the most
     218             :     recent ones */
     219             : 
     220             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L279
     221      192683 :   while( proposed_lockouts_index < lockouts_len && slot_hashes_index > 0 ) {
     222      192032 :     ulong proposed_vote_slot =
     223      192032 :       fd_ulong_if( has_root_to_check,
     224             :         // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L281
     225      192032 :         root_to_check,
     226             :         // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L283
     227      192032 :         deq_fd_vote_lockout_t_peek_index_const( proposed_lockouts,
     228      192032 :           proposed_lockouts_index )
     229      192032 :         ->slot );
     230             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L285
     231      192032 :     if( !has_root_to_check && proposed_lockouts_index > 0UL &&
     232      192032 :       proposed_vote_slot <=
     233       44108 :       deq_fd_vote_lockout_t_peek_index_const(
     234       44108 :         proposed_lockouts,
     235       44108 :           fd_ulong_checked_sub_expect(
     236       44108 :             proposed_lockouts_index,
     237       44108 :               1,
     238       44108 :               "`proposed_lockouts_index` is positive when checking `SlotsNotOrdered`" ) )
     239       44108 :       ->slot ) {
     240             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L293
     241           0 :       ctx->txn_out->err.custom_err = FD_VOTE_ERR_SLOTS_NOT_ORDERED;
     242           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     243           0 :     }
     244             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L295
     245      192032 :     ulong ancestor_slot =
     246      192032 :       slot_hashes->elems[
     247      192032 :           fd_ulong_checked_sub_expect(
     248      192032 :             slot_hashes_index,
     249      192032 :               1UL,
     250      192032 :               "`slot_hashes_index` is positive when computing `ancestor_slot`" ) ]
     251      192032 :       .slot;
     252             :     /* Find if this slot in the proposed vote state exists in the SlotHashes history
     253             :        to confirm if it was a valid ancestor on this fork */
     254             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L303
     255      192032 :     if( proposed_vote_slot < ancestor_slot ) {
     256       15768 :       if( slot_hashes_index == slot_hashes->cnt ) {
     257             :         /* The vote slot does not exist in the SlotHashes history because it's too old,
     258             :            i.e. older than the oldest slot in the history. */
     259       15762 :         if( proposed_vote_slot >= earliest_slot_hash_in_history ) {
     260           0 :           ctx->txn_out->err.custom_err = 0;
     261           0 :           return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     262           0 :         }
     263             :         // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L310
     264       15762 :         if( !fd_vote_contains_slot( votes, proposed_vote_slot ) && !has_root_to_check ) {
     265             :           /* If the vote slot is both:
     266             :              1) Too old
     267             :              2) Doesn't already exist in vote state
     268             :              Then filter it out */
     269       15581 :           proposed_lockouts_indexes_to_filter[filter_index++] = proposed_lockouts_index;        }
     270             :         // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L318
     271       15762 :         if( has_root_to_check ) {
     272          85 :           ulong new_proposed_root = root_to_check;
     273             :           /* 1. Because `root_to_check.is_some()`, then we know that
     274             :              we haven't checked the root yet in this loop, so
     275             :              `proposed_vote_slot` == `new_proposed_root` == `vote_state_update.root` */
     276          85 :           FD_TEST( new_proposed_root == proposed_vote_slot );
     277             :           /* 2. We know from the assert earlier in the function that
     278             :              `proposed_vote_slot < earliest_slot_hash_in_history`,
     279             :              so from 1. we know that `new_proposed_root < earliest_slot_hash_in_history` */
     280          85 :           if( new_proposed_root >= earliest_slot_hash_in_history ) {
     281           0 :             ctx->txn_out->err.custom_err = 0;
     282           0 :             return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     283           0 :           }
     284             : 
     285             :           // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L329
     286          85 :           has_root_to_check = 0;
     287          85 :           root_to_check     = ULONG_MAX;
     288       15677 :         } else {
     289             :           // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L331
     290       15677 :           proposed_lockouts_index = fd_ulong_checked_add_expect(
     291       15677 :             proposed_lockouts_index,
     292       15677 :               1,
     293       15677 :               "`proposed_lockouts_index` is bounded by `MAX_LOCKOUT_HISTORY` when "
     294       15677 :               "`proposed_vote_slot` is too old to be in SlotHashes history" );
     295       15677 :         }
     296       15762 :         continue;
     297       15762 :       } else {
     298             :         /* If the vote slot is new enough to be in the slot history,
     299             :            but is not part of the slot history, then it must belong to another fork,
     300             :            which means this vote state update is invalid. */
     301             :         // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L340
     302           6 :         if( has_root_to_check ) {
     303           3 :           ctx->txn_out->err.custom_err = FD_VOTE_ERR_ROOT_ON_DIFFERENT_FORK;
     304           3 :           return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     305           3 :         } else {
     306           3 :           ctx->txn_out->err.custom_err = FD_VOTE_ERR_SLOTS_MISMATCH;
     307           3 :           return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     308           3 :         }
     309           6 :       }
     310      176264 :     } else if( proposed_vote_slot > ancestor_slot ) {
     311             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L347
     312             : 
     313             :       /* Decrement `slot_hashes_index` to find newer slots in the SlotHashes history */
     314      166510 :       slot_hashes_index = fd_ulong_checked_sub_expect(
     315      166510 :         slot_hashes_index,
     316      166510 :           1,
     317      166510 :           "`slot_hashes_index` is positive when finding newer slots in SlotHashes history" );
     318      166510 :       continue;
     319      166510 :     } else {
     320             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L354
     321             : 
     322             :       /* Once the slot in `vote_state_update.lockouts` is found, bump to the next slot
     323             :          in `vote_state_update.lockouts` and continue. If we were checking the root,
     324             :          start checking the vote state instead. */
     325        9754 :       if( has_root_to_check ) {
     326         310 :         has_root_to_check = 0;
     327         310 :         root_to_check     = ULONG_MAX;
     328        9444 :       } else {
     329        9444 :         proposed_lockouts_index = fd_ulong_checked_add_expect(
     330        9444 :           proposed_lockouts_index,
     331        9444 :             1,
     332        9444 :             "`proposed_lockouts_index` is bounded by `MAX_LOCKOUT_HISTORY` "
     333        9444 :             "when match is found in SlotHashes history" );
     334        9444 :         slot_hashes_index = fd_ulong_checked_sub_expect(
     335        9444 :           slot_hashes_index,
     336        9444 :             1,
     337        9444 :             "`slot_hashes_index` is positive when match is found in SlotHashes history" );
     338        9444 :       }
     339        9754 :     }
     340      192032 :   }
     341             : 
     342             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L372
     343         651 :   if( proposed_lockouts_index != deq_fd_vote_lockout_t_cnt( proposed_lockouts ) ) {
     344             :     /* The last vote slot in the update did not exist in SlotHashes */
     345           7 :     ctx->txn_out->err.custom_err = FD_VOTE_ERR_SLOTS_MISMATCH;
     346           7 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     347           7 :   }
     348             : 
     349             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L401
     350         644 :   if( memcmp( &slot_hashes->elems[ slot_hashes_index ].hash,
     351         644 :       proposed_hash,
     352         644 :       sizeof( fd_hash_t ) ) != 0 ) {
     353             :     /* This means the newest vote in the slot has a match that
     354             :        doesn't match the expected hash for that slot on this fork */
     355           2 :     ctx->txn_out->err.custom_err = FD_VOTE_ERR_SLOTS_HASH_MISMATCH;
     356           2 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     357           2 :   }
     358             : 
     359             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L418
     360             :   /* Filter out the irrelevant votes */
     361         642 :   proposed_lockouts_index = 0UL;
     362         642 :   ulong filter_votes_index = deq_fd_vote_lockout_t_cnt( proposed_lockouts );
     363             : 
     364             :   /* We need to iterate backwards here because proposed_lockouts_indexes_to_filter[ i ] is a
     365             :      strictly increasing value. Forward iterating can lead to the proposed lockout indices to get
     366             :      shifted leading to popping the wrong proposed lockouts or out of bounds accessing. We need
     367             :      to be sure of handling underflow in this case. */
     368             : 
     369       16226 :   for( ulong i=filter_index; i>0UL && filter_votes_index>0UL; i-- ) {
     370       15584 :     proposed_lockouts_index = i - 1UL;
     371       15584 :     if( FD_UNLIKELY( proposed_lockouts_indexes_to_filter[ proposed_lockouts_index ]>=filter_votes_index ) ) {
     372           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_PROGRAM_ID;
     373           0 :     }
     374             : 
     375       15584 :     deq_fd_vote_lockout_t_pop_idx_tail( proposed_lockouts, proposed_lockouts_indexes_to_filter[ proposed_lockouts_index ] );
     376       15584 :     filter_votes_index--;
     377       15584 :   }
     378             : 
     379         642 :   return FD_EXECUTOR_INSTR_SUCCESS;
     380         642 : }
     381             : 
     382             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L440
     383             : static int
     384             : check_slots_are_valid( fd_exec_instr_ctx_t *       ctx,
     385             :                        fd_vote_state_versioned_t * versioned,
     386             :                        ulong const *               vote_slots,
     387             :                        fd_hash_t const *           vote_hash,
     388         341 :                        fd_slot_hashes_t const *    slot_hashes ) {
     389         341 :   ulong i              = 0;
     390         341 :   ulong j              = slot_hashes->cnt;
     391         341 :   ulong vote_slots_len = deq_ulong_cnt( vote_slots );
     392             : 
     393             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L462
     394       20068 :   while( i < vote_slots_len && j > 0 ) {
     395       19727 :     ulong const * last_voted_slot_ = fd_vsv_get_last_voted_slot( versioned );
     396       19727 :     if( FD_UNLIKELY( last_voted_slot_ &&
     397       19727 :                      *deq_ulong_peek_index_const( vote_slots, i ) <= *last_voted_slot_ ) ) {
     398             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L469
     399          52 :       i = fd_ulong_checked_add_expect(
     400          52 :           i, 1, "`i` is bounded by `MAX_LOCKOUT_HISTORY` when finding larger slots" );
     401          52 :       continue;
     402          52 :     }
     403             : 
     404             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L476
     405       19675 :     if( FD_UNLIKELY(
     406       19675 :             *deq_ulong_peek_index_const( vote_slots, i ) !=
     407       19675 :             slot_hashes->elems[
     408       19675 :               fd_ulong_checked_sub_expect( j, 1, "`j` is positive" ) ]
     409       19675 :                 .slot ) ) {
     410        3615 :       j = fd_ulong_checked_sub_expect( j, 1, "`j` is positive when finding newer slots" );
     411        3615 :       continue;
     412        3615 :     }
     413             : 
     414             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L486
     415       16060 :     i = fd_ulong_checked_add_expect(
     416       16060 :         i, 1, "`i` is bounded by `MAX_LOCKOUT_HISTORY` when hash is found" );
     417       16060 :     j = fd_ulong_checked_sub_expect( j, 1, "`j` is positive when hash is found" );
     418       16060 :   }
     419             : 
     420             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L494
     421         341 :   if( FD_UNLIKELY( j == slot_hashes->cnt ) ) {
     422           4 :     ctx->txn_out->err.custom_err = FD_VOTE_ERR_VOTE_TOO_OLD;
     423           4 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     424           4 :   }
     425         337 :   if( FD_UNLIKELY( i != vote_slots_len ) ) {
     426          24 :     ctx->txn_out->err.custom_err = FD_VOTE_ERR_SLOTS_MISMATCH;
     427          24 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     428          24 :   }
     429             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L514
     430         313 :   if( FD_UNLIKELY( 0 != memcmp( &slot_hashes->elems[ j ].hash,
     431         313 :                                 vote_hash,
     432         313 :                                 32UL ) ) ) {
     433           0 :     ctx->txn_out->err.custom_err = FD_VOTE_ERR_SLOTS_HASH_MISMATCH;
     434           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     435           0 :   }
     436         313 :   return 0;
     437         313 : }
     438             : 
     439             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L565
     440             : static int
     441             : process_new_vote_state( fd_exec_instr_ctx_t *       ctx,
     442             :                         fd_vote_state_versioned_t * versioned,
     443             :                         fd_landed_vote_t *          new_state,
     444             :                         int                         has_new_root,
     445             :                         ulong                       new_root,
     446             :                         int                         has_timestamp,
     447             :                         long                        timestamp,
     448             :                         ulong                       epoch,
     449         642 :                         ulong                       current_slot ) {
     450         642 :   int rc;
     451         642 :   fd_landed_vote_t * votes         = fd_vsv_get_votes_mutable( versioned );
     452         642 :   ulong const *      root_slot     = fd_vsv_get_root_slot( versioned );
     453         642 :   uchar              has_root_slot = !!(root_slot!=NULL);
     454             : 
     455         642 :   FD_TEST( !deq_fd_landed_vote_t_empty( new_state ) );
     456             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L575
     457         642 :   if( FD_UNLIKELY( deq_fd_landed_vote_t_cnt( new_state ) > MAX_LOCKOUT_HISTORY ) ) {
     458           0 :     ctx->txn_out->err.custom_err = FD_VOTE_ERR_TOO_MANY_VOTES;
     459           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     460         642 :   };
     461             : 
     462             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L579
     463         642 :   if( FD_UNLIKELY( has_new_root && has_root_slot ) ) {
     464             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L581
     465         359 :     if( FD_UNLIKELY( new_root<*root_slot ) ) {
     466          31 :       ctx->txn_out->err.custom_err = FD_VOTE_ERR_ROOT_ROLL_BACK;
     467          31 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     468          31 :     }
     469         359 :   } else if( FD_UNLIKELY( !has_new_root && has_root_slot ) ) {
     470             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L586
     471         101 :     ctx->txn_out->err.custom_err = FD_VOTE_ERR_ROOT_ROLL_BACK;
     472         101 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     473         182 :   } else {
     474             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L588
     475             :     /* no-op */
     476         182 :   }
     477             : 
     478         510 :   fd_landed_vote_t * previous_vote = NULL;
     479         510 :   for( deq_fd_landed_vote_t_iter_t iter = deq_fd_landed_vote_t_iter_init( new_state );
     480       10342 :        !deq_fd_landed_vote_t_iter_done( new_state, iter );
     481        9844 :        iter = deq_fd_landed_vote_t_iter_next( new_state, iter ) ) {
     482        9844 :     fd_landed_vote_t * vote = deq_fd_landed_vote_t_iter_ele( new_state, iter );
     483        9844 :     if( FD_LIKELY( vote->lockout.confirmation_count == 0 ) ) {
     484           7 :       ctx->txn_out->err.custom_err = FD_VOTE_ERR_ZERO_CONFIRMATIONS;
     485           7 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     486        9837 :     } else if( FD_UNLIKELY( vote->lockout.confirmation_count > MAX_LOCKOUT_HISTORY ) ) {
     487           0 :       ctx->txn_out->err.custom_err = FD_VOTE_ERR_CONFIRMATION_TOO_LARGE;
     488           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     489        9837 :     } else if( FD_LIKELY( has_new_root ) ) {
     490        9675 :       if( FD_UNLIKELY( vote->lockout.slot <= new_root && new_root != SLOT_DEFAULT ) ) {
     491           0 :         ctx->txn_out->err.custom_err = FD_VOTE_ERR_SLOT_SMALLER_THAN_ROOT;
     492           0 :         return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     493           0 :       }
     494        9675 :     }
     495             : 
     496        9837 :     if( FD_LIKELY( previous_vote ) ) {
     497        9344 :       if( FD_UNLIKELY( previous_vote->lockout.slot >= vote->lockout.slot ) ) {
     498           0 :         ctx->txn_out->err.custom_err = FD_VOTE_ERR_SLOTS_NOT_ORDERED;
     499           0 :         return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     500        9344 :       } else if( FD_UNLIKELY( previous_vote->lockout.confirmation_count <=
     501        9344 :                               vote->lockout.confirmation_count ) ) {
     502           5 :         ctx->txn_out->err.custom_err = FD_VOTE_ERR_CONFIRMATIONS_NOT_ORDERED;
     503           5 :         return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     504        9339 :       } else if( FD_UNLIKELY( vote->lockout.slot >
     505        9339 :                               fd_vote_lockout_last_locked_out_slot( &previous_vote->lockout ) ) ) {
     506           0 :         ctx->txn_out->err.custom_err = FD_VOTE_ERR_NEW_VOTE_STATE_LOCKOUT_MISMATCH;
     507           0 :         return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     508           0 :       }
     509        9344 :     }
     510        9832 :     previous_vote = vote;
     511        9832 :   }
     512             : 
     513         498 :   ulong current_vote_state_index = 0;
     514         498 :   ulong new_vote_state_index     = 0;
     515             : 
     516             :   /* Accumulate credits earned by newly rooted slots.  The behavior changes with
     517             :      timely_vote_credits: prior to this feature, there was a bug that counted a new root slot as 1
     518             :      credit even if it had never been voted on. timely_vote_credits fixes this bug by only awarding
     519             :      credits for slots actually voted on and finalized. */
     520             : 
     521             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L635
     522             : 
     523             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L641
     524         498 :   ulong earned_credits      = 0;
     525             : 
     526         498 :   if( FD_LIKELY( has_new_root ) ) {
     527         361 :     for( deq_fd_landed_vote_t_iter_t iter = deq_fd_landed_vote_t_iter_init( votes );
     528         753 :                                            !deq_fd_landed_vote_t_iter_done( votes, iter );
     529         753 :                                      iter = deq_fd_landed_vote_t_iter_next( votes, iter ) ) {
     530         753 :       fd_landed_vote_t const * current_vote = deq_fd_landed_vote_t_iter_ele_const( votes, iter );
     531             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L647
     532         753 :       if( FD_UNLIKELY( current_vote->lockout.slot <= new_root ) ) {
     533             :         // this is safe because we're inside if has_new_root
     534         392 :         earned_credits = fd_ulong_checked_add_expect(
     535         392 :             fd_vote_credits_for_vote_at_index(
     536         392 :                 votes,
     537         392 :                 current_vote_state_index
     538         392 :             ),
     539         392 :             earned_credits,
     540         392 :             "`earned_credits` does not overflow" );
     541         392 :         current_vote_state_index = fd_ulong_checked_add_expect(
     542         392 :             current_vote_state_index,
     543         392 :             1,
     544         392 :             "`current_vote_state_index` is bounded by `MAX_LOCKOUT_HISTORY` "
     545         392 :             "when processing new root" );
     546         392 :         continue;
     547         392 :       }
     548         361 :       break;
     549         753 :     }
     550         361 :   }
     551             : 
     552             :   // For any slots newly added to the new vote state, the vote latency of that slot is not provided by the
     553             :   // vote instruction contents, but instead is computed from the actual latency of the vote
     554             :   // instruction. This prevents other validators from manipulating their own vote latencies within their vote states
     555             :   // and forcing the rest of the cluster to accept these possibly fraudulent latency values.  If the
     556             :   // timly_vote_credits feature is not enabled then vote latency is set to 0 for new votes.
     557             :   //
     558             :   // For any slot that is in both the new state and the current state, the vote latency of the new state is taken
     559             :   // from the current state.
     560             :   //
     561             :   // Thus vote latencies are set here for any newly vote-on slots when a vote instruction is received.
     562             :   // They are copied into the new vote state after every vote for already voted-on slots.
     563             :   // And when voted-on slots are rooted, the vote latencies stored in the vote state of all the rooted slots is used
     564             :   // to compute credits earned.
     565             :   // All validators compute the same vote latencies because all process the same vote instruction at the
     566             :   // same slot, and the only time vote latencies are ever computed is at the time that their slot is first voted on;
     567             :   // after that, the latencies are retained unaltered until the slot is rooted.
     568             : 
     569             :   // All the votes in our current vote state that are missing from the new vote state
     570             :   // must have been expired by later votes. Check that the lockouts match this assumption.
     571             : 
     572             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L686
     573       10316 :   while( current_vote_state_index < deq_fd_landed_vote_t_cnt( votes ) &&
     574       10316 :          new_vote_state_index < deq_fd_landed_vote_t_cnt( new_state ) ) {
     575        9835 :     fd_landed_vote_t const * current_vote = deq_fd_landed_vote_t_peek_index_const( votes, current_vote_state_index );
     576             : 
     577             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L690
     578        9835 :     fd_landed_vote_t * new_vote =
     579        9835 :         deq_fd_landed_vote_t_peek_index( new_state, new_vote_state_index );
     580             : 
     581             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L696
     582        9835 :     if( FD_LIKELY( current_vote->lockout.slot < new_vote->lockout.slot ) ) {
     583             :       /* The agave implementation of calculating the last locked out
     584             :          slot does not calculate a min between the current vote's
     585             :          confirmation count and max lockout history. The reason we do
     586             :          this is to make sure that the fuzzers continue working:
     587             :          the max lockout history can not be > MAX_LOCKOUT_HISTORY. */
     588         416 :       ulong confirmation_count   = fd_ulong_min( current_vote->lockout.confirmation_count, MAX_LOCKOUT_HISTORY );
     589         416 :       ulong last_locked_out_slot = fd_ulong_sat_add( current_vote->lockout.slot,
     590         416 :                                                      (ulong)pow( INITIAL_LOCKOUT, (double)confirmation_count ) );
     591             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L697
     592         416 :       if( last_locked_out_slot >= new_vote->lockout.slot ) {
     593             :         // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L698
     594          17 :         ctx->txn_out->err.custom_err = FD_VOTE_ERR_LOCKOUT_CONFLICT;
     595          17 :         return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     596          17 :       }
     597             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L700
     598         399 :       current_vote_state_index =
     599         399 :           fd_ulong_checked_add_expect( current_vote_state_index,
     600         399 :                                        1,
     601         399 :                                        "`current_vote_state_index` is bounded by "
     602         399 :                                        "`MAX_LOCKOUT_HISTORY` when slot is less than proposed" );
     603             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L704
     604        9419 :     } else if( FD_UNLIKELY( current_vote->lockout.slot == new_vote->lockout.slot ) ) {
     605             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L707
     606        9251 :       if( new_vote->lockout.confirmation_count < current_vote->lockout.confirmation_count ) {
     607           0 :         ctx->txn_out->err.custom_err = FD_VOTE_ERR_CONFIRMATION_ROLL_BACK;
     608           0 :         return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     609           0 :       }
     610             : 
     611             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L712
     612        9251 :       new_vote->latency = deq_fd_landed_vote_t_peek_index_const( votes, current_vote_state_index )->latency;
     613             : 
     614             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L714
     615        9251 :       current_vote_state_index =
     616        9251 :           fd_ulong_checked_add_expect( current_vote_state_index,
     617        9251 :                                        1,
     618        9251 :                                        "`current_vote_state_index` is bounded by "
     619        9251 :                                        "`MAX_LOCKOUT_HISTORY` when slot is equal to proposed" );
     620             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L717
     621        9251 :       new_vote_state_index =
     622        9251 :           fd_ulong_checked_add_expect( new_vote_state_index,
     623        9251 :                                        1,
     624        9251 :                                        "`new_vote_state_index` is bounded by `MAX_LOCKOUT_HISTORY` "
     625        9251 :                                        "when slot is equal to proposed" );
     626        9251 :     } else {
     627             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L722
     628         168 :       new_vote_state_index =
     629         168 :           fd_ulong_checked_add_expect( new_vote_state_index,
     630         168 :                                        1,
     631         168 :                                        "`new_vote_state_index` is bounded by `MAX_LOCKOUT_HISTORY` "
     632         168 :                                        "when slot is greater than proposed" );
     633         168 :     }
     634        9835 :   }
     635             : 
     636             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L737
     637         481 :   for( deq_fd_landed_vote_t_iter_t iter = deq_fd_landed_vote_t_iter_init( new_state );
     638       10292 :         !deq_fd_landed_vote_t_iter_done( new_state, iter );
     639        9811 :         iter = deq_fd_landed_vote_t_iter_next( new_state, iter ) ) {
     640        9811 :     fd_landed_vote_t * new_vote = deq_fd_landed_vote_t_iter_ele( new_state, iter );
     641             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L738
     642        9811 :     if( FD_UNLIKELY( new_vote->latency == 0 ) ) {
     643             :       // this is unlikely because as validators upgrade, it should converge to the new vote state
     644             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L739
     645         808 :       new_vote->latency = fd_vote_compute_vote_latency( new_vote->lockout.slot, current_slot );
     646         808 :     }
     647        9811 :   }
     648             : 
     649             :   // doesn't matter what the value of slot if `is_some = 0` i.e. `Option::None`
     650             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L744
     651         481 :   int both_none = !has_root_slot && !has_new_root;
     652         481 :   if( ( !both_none && ( has_root_slot!=has_new_root ||
     653         355 :                         *root_slot!=new_root ) ) ) {
     654         351 :     fd_vsv_increment_credits( versioned, epoch, earned_credits );
     655         351 :   }
     656             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L750
     657         481 :   if( FD_LIKELY( has_timestamp ) ) {
     658             :     /* new_state asserted nonempty at function beginning */
     659         391 :     if( FD_UNLIKELY( deq_fd_landed_vote_t_empty( new_state ) ) ) {
     660           0 :       FD_LOG_CRIT(( "invariant violation: landed votes is empty" ));
     661           0 :     }
     662         391 :     ulong last_slot = deq_fd_landed_vote_t_peek_tail( new_state )->lockout.slot;
     663         391 :     rc              = fd_vsv_process_timestamp( ctx, versioned, last_slot, timestamp );
     664         391 :     if( FD_UNLIKELY( rc ) ) { return rc; }
     665         391 :   }
     666             : 
     667             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L754
     668         427 :   fd_vsv_set_root_slot( versioned, has_new_root ? &new_root : NULL );
     669             : 
     670             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L755
     671         427 :   deq_fd_landed_vote_t_remove_all( votes );
     672         427 :   for( deq_fd_landed_vote_t_iter_t iter = deq_fd_landed_vote_t_iter_init( new_state );
     673       10116 :        !deq_fd_landed_vote_t_iter_done( new_state, iter );
     674        9689 :        iter = deq_fd_landed_vote_t_iter_next( new_state, iter ) ) {
     675        9689 :     fd_landed_vote_t * landed_vote = deq_fd_landed_vote_t_iter_ele( new_state, iter );
     676        9689 :     deq_fd_landed_vote_t_push_tail_wrap( votes, *landed_vote );
     677        9689 :   }
     678             : 
     679         427 :   return FD_EXECUTOR_INSTR_SUCCESS;
     680         481 : }
     681             : 
     682             : __attribute__((weak)) int
     683             : fd_bls12_381_proof_of_possession_verify( uchar const msg[],
     684             :                                          ulong       msg_sz,
     685             :                                          uchar const proof[ static FD_BLS_PROOF_OF_POSSESSION_COMPRESSED_SZ ],
     686           0 :                                          uchar const public_key[ static FD_BLS_PUBKEY_COMPRESSED_SZ ] ) {
     687           0 :   (void)msg; (void)msg_sz; (void)proof; (void)public_key;
     688           0 :   FD_LOG_ERR(( "This build does not include BLST, which is required to run a validator.\n"
     689           0 :                "Rebuild with a MACHINE config that enables config/extra/with-blst.mk" ));
     690           0 : }
     691             : 
     692             : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/mod.rs#L1059-L1108 */
     693             : #define FD_VOTE_BLS_MSG_SZ ( 9 + 32 + 48 )
     694             : static int
     695             : fd_vote_verify_bls_proof_of_possession( fd_exec_instr_ctx_t * ctx,
     696             :                                         uchar const           vote_account_pubkey[ static 32 ],
     697             :                                         uchar const           bls_pubkey[ static FD_BLS_PUBKEY_COMPRESSED_SZ ],
     698         187 :                                         uchar const           bls_proof[ static FD_BLS_PROOF_OF_POSSESSION_COMPRESSED_SZ ] ) {
     699             :   /* Consume CUs for proof of possession */
     700         187 :   FD_EXEC_CU_UPDATE( ctx, COMPUTE_UNITS_POP );
     701             : 
     702             :   /* Build message */
     703         182 :   uchar msg[ FD_VOTE_BLS_MSG_SZ ];
     704         182 :   memcpy( msg, "ALPENGLOW", 9 );
     705         182 :   memcpy( msg+9, vote_account_pubkey, 32 );
     706         182 :   memcpy( msg+9+32, bls_pubkey, 48 );
     707             : 
     708             :   /* Verify */
     709         182 :   if( FD_UNLIKELY( fd_bls12_381_proof_of_possession_verify(
     710         182 :     msg,
     711         182 :     FD_VOTE_BLS_MSG_SZ,
     712         182 :     bls_proof,
     713         182 :     bls_pubkey
     714         182 :   )!=FD_BLS_SUCCESS ) ) {
     715         182 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
     716         182 :   }
     717           0 :   return 0;
     718         182 : }
     719             : #undef FD_VOTE_BLS_MSG_SZ
     720             : 
     721             : /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L716-L759 */
     722             : static int
     723             : authorize( fd_exec_instr_ctx_t *         ctx,
     724             :            fd_borrowed_account_t *       vote_account,
     725             :            int                           target_version,
     726             :            fd_pubkey_t const *           authorized,
     727             :            fd_vote_authorize_t const *   vote_authorize,
     728             :            fd_pubkey_t const *           signers[static FD_INSTR_SIGNERS_MAX],
     729             :            ulong                         signers_cnt,
     730             :            fd_sol_sysvar_clock_t const * clock,
     731         867 :            int                           is_vote_authorize_with_bls_enabled ) {
     732         867 :   fd_vote_state_versioned_t * vote_state_versioned = &ctx->runtime->vote_program.authorize.vote_state;
     733             : 
     734             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L724-L727 */
     735         867 :   int rc = get_vote_state_handler_checked( vote_account, target_version, 0, vote_state_versioned );
     736         867 :   if( FD_UNLIKELY( rc ) ) return rc;
     737             : 
     738             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L729-L756 */
     739         667 :   switch( vote_authorize->discriminant ) {
     740             : 
     741             :     /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L730-L750 */
     742         238 :     case fd_vote_authorize_enum_voter: {
     743             : 
     744             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/mod.rs#L741-L743 */
     745         238 :       if( FD_UNLIKELY( is_vote_authorize_with_bls_enabled && fd_vsv_has_bls_pubkey( vote_state_versioned ) ) ) {
     746          22 :         return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
     747          22 :       }
     748             : 
     749             :       /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L731-L732 */
     750         216 :       int authorized_withdrawer_signer = !fd_vote_verify_authorized_signer(
     751         216 :           fd_vsv_get_authorized_withdrawer( vote_state_versioned ),
     752         216 :           signers,
     753         216 :           signers_cnt
     754         216 :       );
     755             : 
     756             :       /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L737-L740 */
     757         216 :       ulong target_epoch;
     758         216 :       rc = fd_ulong_checked_add( clock->leader_schedule_epoch, 1UL, &target_epoch );
     759         216 :       if( FD_UNLIKELY( rc!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
     760           0 :         return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
     761           0 :       }
     762             : 
     763             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/mod.rs#L747 */
     764         216 :       rc = fd_vsv_set_new_authorized_voter(
     765         216 :           ctx,
     766         216 :           vote_state_versioned,
     767         216 :           authorized,
     768         216 :           clock->epoch,
     769         216 :           target_epoch,
     770         216 :           NULL, /* no BLS pubkey */
     771         216 :           authorized_withdrawer_signer,
     772         216 :           signers,
     773         216 :           signers_cnt
     774         216 :       );
     775         216 :       if( FD_UNLIKELY( rc ) ) return rc;
     776         101 :       break;
     777         216 :     }
     778             : 
     779             :     /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L751-L756 */
     780         242 :     case fd_vote_authorize_enum_withdrawer: {
     781         242 :       rc = fd_vote_verify_authorized_signer(
     782         242 :           fd_vsv_get_authorized_withdrawer( vote_state_versioned ),
     783         242 :           signers,
     784         242 :           signers_cnt
     785         242 :       );
     786         242 :       if( FD_UNLIKELY( rc ) ) return rc;
     787         130 :       fd_vsv_set_authorized_withdrawer( vote_state_versioned, authorized );
     788         130 :       break;
     789         242 :     }
     790             : 
     791             :     /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/mod.rs#L770 */
     792         187 :     case fd_vote_authorize_enum_voter_with_bls: {
     793             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/mod.rs#L771-L773 */
     794         187 :       if( FD_UNLIKELY( !is_vote_authorize_with_bls_enabled ) ) {
     795           0 :         return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
     796           0 :       }
     797             : 
     798             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/mod.rs#L774-L775 */
     799         187 :       int authorized_withdrawer_signer = !fd_vote_verify_authorized_signer(
     800         187 :           fd_vsv_get_authorized_withdrawer( vote_state_versioned ),
     801         187 :           signers,
     802         187 :           signers_cnt
     803         187 :       );
     804             : 
     805             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/mod.rs#L777-L782 */
     806         187 :       rc = fd_vote_verify_bls_proof_of_possession(
     807         187 :         ctx,
     808         187 :         vote_account->acc->pubkey,
     809         187 :         vote_authorize->voter_with_bls.bls_pubkey,
     810         187 :         vote_authorize->voter_with_bls.bls_proof_of_possession
     811         187 :       );
     812         187 :       if( FD_UNLIKELY( rc ) ) {
     813         187 :         return rc;
     814         187 :       }
     815             : 
     816             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/mod.rs#L787-L790 */
     817           0 :       ulong target_epoch;
     818           0 :       rc = fd_ulong_checked_add( clock->leader_schedule_epoch, 1UL, &target_epoch );
     819           0 :       if( FD_UNLIKELY( rc!=FD_EXECUTOR_INSTR_SUCCESS ) ) {
     820           0 :         return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
     821           0 :       }
     822             : 
     823             :       /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/mod.rs#L784 */
     824           0 :       rc = fd_vsv_set_new_authorized_voter(
     825           0 :           ctx,
     826           0 :           vote_state_versioned,
     827           0 :           authorized,
     828           0 :           clock->epoch,
     829           0 :           target_epoch,
     830           0 :           vote_authorize->voter_with_bls.bls_pubkey,
     831           0 :           authorized_withdrawer_signer,
     832           0 :           signers,
     833           0 :           signers_cnt
     834           0 :       );
     835           0 :       if( FD_UNLIKELY( rc ) ) return rc;
     836             : 
     837           0 :       break;
     838           0 :     }
     839             : 
     840           0 :     default:
     841           0 :       FD_LOG_CRIT(( "unsupported vote_authorize discriminant: %u", vote_authorize->discriminant ));
     842         667 :   }
     843             : 
     844             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L758 */
     845         231 :   return fd_vsv_set_vote_account_state( ctx, vote_account, vote_state_versioned );
     846         667 : }
     847             : 
     848             : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/mod.rs#L808-L835 */
     849             : static int
     850             : update_validator_identity( fd_exec_instr_ctx_t *   ctx,
     851             :                            int                     target_version,
     852             :                            fd_borrowed_account_t * vote_account,
     853             :                            fd_pubkey_t const *     node_pubkey,
     854             :                            fd_pubkey_t const *     signers[static FD_INSTR_SIGNERS_MAX],
     855             :                            ulong                   signers_cnt,
     856         402 :                            int                     custom_commission_collector_enabled ) {
     857         402 :   fd_vote_state_versioned_t * vote_state_versioned = &ctx->runtime->vote_program.update_validator_identity.vote_state;
     858             : 
     859             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L768-L771 */
     860         402 :   int rc = get_vote_state_handler_checked( vote_account, target_version, 0, vote_state_versioned );
     861         402 :   if( FD_UNLIKELY( rc ) ) return rc;
     862             : 
     863             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L774 */
     864         191 :   rc = fd_vote_verify_authorized_signer(
     865         191 :       fd_vsv_get_authorized_withdrawer( vote_state_versioned ),
     866         191 :       signers,
     867         191 :       signers_cnt
     868         191 :   );
     869         191 :   if( FD_UNLIKELY( rc ) ) return rc;
     870             : 
     871             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L777 */
     872         176 :   rc = fd_vote_verify_authorized_signer( node_pubkey, signers, signers_cnt );
     873         176 :   if( FD_UNLIKELY( rc ) ) return rc;
     874             : 
     875             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/mod.rs#L826 */
     876         175 :   fd_vsv_set_node_pubkey( vote_state_versioned, node_pubkey );
     877             : 
     878             :   /* Before SIMD-0232, block_revenue_collector is always synced with node_pubkey.
     879             :      After SIMD-0232, the collector can be set independently.
     880             :      https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/mod.rs#L828-L832 */
     881         175 :   if( !custom_commission_collector_enabled ) {
     882         175 :     fd_vsv_set_block_revenue_collector( vote_state_versioned, node_pubkey );
     883         175 :   }
     884             : 
     885             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/mod.rs#L834 */
     886         175 :   return fd_vsv_set_vote_account_state( ctx, vote_account, vote_state_versioned );
     887         176 : }
     888             : 
     889             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L971
     890             : static int
     891           0 : is_commission_update_allowed( ulong slot, fd_epoch_schedule_t const * epoch_schedule ) {
     892           0 :   if( FD_LIKELY( epoch_schedule->slots_per_epoch > 0UL ) ) {
     893           0 :     ulong relative_slot = fd_ulong_sat_sub( slot, epoch_schedule->first_normal_slot );
     894           0 :     relative_slot %= epoch_schedule->slots_per_epoch;
     895           0 :     return fd_ulong_sat_mul( relative_slot, 2 ) <= epoch_schedule->slots_per_epoch;
     896           0 :   } else {
     897           0 :     return 1;
     898           0 :   }
     899           0 : }
     900             : 
     901             : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/mod.rs#L838-L869 */
     902             : static int
     903             : update_commission( fd_exec_instr_ctx_t *         ctx,
     904             :                    int                           target_version,
     905             :                    fd_borrowed_account_t *       vote_account,
     906             :                    uchar                         commission,
     907             :                    fd_pubkey_t const *           signers[static FD_INSTR_SIGNERS_MAX],
     908             :                    ulong                         signers_cnt,
     909             :                    fd_epoch_schedule_t const *   epoch_schedule,
     910             :                    fd_sol_sysvar_clock_t const * clock,
     911         494 :                    int                           disable_commission_update_rule ) {
     912             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L796-L799 */
     913         494 :   int rc         = 0;
     914         494 :   int get_vsv_rc = get_vote_state_handler_checked(
     915         494 :       vote_account,
     916         494 :       target_version,
     917         494 :       false,
     918         494 :       &ctx->runtime->vote_program.update_commission.vote_state
     919         494 :   );
     920             : 
     921             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/mod.rs#L851-L855 */
     922         494 :   fd_vote_state_versioned_t * vote_state_versioned           = NULL;
     923         494 :   int                         enforce_commission_update_rule = !disable_commission_update_rule;
     924         494 :   if( FD_LIKELY( get_vsv_rc==FD_EXECUTOR_INSTR_SUCCESS ) ) {
     925         190 :     vote_state_versioned           = &ctx->runtime->vote_program.update_commission.vote_state;
     926         190 :     enforce_commission_update_rule = (!disable_commission_update_rule) && (commission>fd_vsv_get_commission( vote_state_versioned ));
     927         190 :   }
     928             : 
     929             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L806-L808 */
     930         494 :   if( FD_UNLIKELY( enforce_commission_update_rule && !is_commission_update_allowed( clock->slot, epoch_schedule ) ) ) {
     931           0 :     ctx->txn_out->err.custom_err = FD_VOTE_ERR_COMMISSION_UPDATE_TOO_LATE;
     932           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     933           0 :   }
     934             : 
     935             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L810 */
     936         494 :   if( FD_UNLIKELY( get_vsv_rc ) ) return get_vsv_rc;
     937             : 
     938             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L813 */
     939         190 :   rc = fd_vote_verify_authorized_signer(
     940         190 :       fd_vsv_get_authorized_withdrawer( vote_state_versioned ),
     941         190 :       signers,
     942         190 :       signers_cnt
     943         190 :   );
     944         190 :   if( FD_UNLIKELY( rc ) ) return rc;
     945             : 
     946             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L815 */
     947         179 :   fd_vsv_set_commission( vote_state_versioned, commission );
     948             : 
     949             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L817 */
     950         179 :   return fd_vsv_set_vote_account_state( ctx, vote_account, vote_state_versioned );
     951         190 : }
     952             : 
     953             : /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.6/programs/vote/src/vote_state/mod.rs#L871-L906 */
     954             : static int
     955             : update_commission_bps( fd_exec_instr_ctx_t *                    ctx,
     956             :                        fd_borrowed_account_t *                  vote_account,
     957             :                        int                                      target_version,
     958             :                        fd_update_commission_bps_args_t const *  args,
     959             :                        fd_pubkey_t const *                      signers[static FD_INSTR_SIGNERS_MAX],
     960             :                        ulong                                    signers_cnt,
     961           0 :                        int                                      block_revenue_sharing ) {
     962           0 :   fd_vote_state_versioned_t * vote_state_versioned = &ctx->runtime->vote_program.update_commission_bps.vote_state;
     963             : 
     964             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.6/programs/vote/src/vote_state/mod.rs#L882-L884 */
     965           0 :   if( FD_UNLIKELY( args->kind.discriminant==fd_commission_kind_enum_block_revenue && !block_revenue_sharing ) ) {
     966           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
     967           0 :   }
     968             : 
     969             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.6/programs/vote/src/vote_state/mod.rs#L886-L889 */
     970           0 :   int rc = get_vote_state_handler_checked( vote_account, target_version, false, vote_state_versioned );
     971           0 :   if( FD_UNLIKELY( rc ) ) return rc;
     972             : 
     973             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.6/programs/vote/src/vote_state/mod.rs#L894 */
     974           0 :   rc = fd_vote_verify_authorized_signer(
     975           0 :     fd_vsv_get_authorized_withdrawer( vote_state_versioned ),
     976           0 :     signers,
     977           0 :     signers_cnt
     978           0 :   );
     979           0 :   if( FD_UNLIKELY( rc ) ) return rc;
     980             : 
     981             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-beta.6/programs/vote/src/vote_state/mod.rs#L896-L903 */
     982           0 :   switch( args->kind.discriminant ) {
     983           0 :     case fd_commission_kind_enum_inflation_rewards: {
     984           0 :       fd_vsv_set_inflation_rewards_commission_bps( vote_state_versioned, args->commission_bps );
     985           0 :       break;
     986           0 :     }
     987           0 :     case fd_commission_kind_enum_block_revenue: {
     988           0 :       fd_vsv_set_block_revenue_commission_bps( vote_state_versioned, args->commission_bps );
     989           0 :       break;
     990           0 :     }
     991           0 :     default: {
     992           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
     993           0 :     }
     994           0 :   }
     995             : 
     996           0 :   return fd_vsv_set_vote_account_state( ctx, vote_account, vote_state_versioned );
     997           0 : }
     998             : 
     999             : /* Updates the vote account's commission collector (SIMD-0232).
    1000             :    collector_account==NULL means the collector is the vote account
    1001             :    itself, which is exempt from the collector constraints.
    1002             :    https://github.com/anza-xyz/agave/blob/v4.2.0-beta.2/programs/vote/src/vote_state/mod.rs#L907-L935 */
    1003             : static int
    1004             : update_commission_collector( fd_exec_instr_ctx_t *         ctx,
    1005             :                              fd_borrowed_account_t *       vote_account,
    1006             :                              int                           target_version,
    1007             :                              fd_borrowed_account_t const * collector_account,
    1008             :                              fd_commission_kind_t const *  kind,
    1009             :                              fd_pubkey_t const *           signers[static FD_INSTR_SIGNERS_MAX],
    1010             :                              ulong                         signers_cnt,
    1011           0 :                              fd_rent_t const *             rent ) {
    1012           0 :   fd_vote_state_versioned_t * vote_state_versioned = &ctx->runtime->vote_program.update_commission_collector.vote_state;
    1013             : 
    1014             :   /* https://github.com/anza-xyz/agave/blob/v4.2.0-beta.2/programs/vote/src/vote_state/mod.rs#L916 */
    1015           0 :   int rc = get_vote_state_handler_checked( vote_account, target_version, 0, vote_state_versioned );
    1016           0 :   if( FD_UNLIKELY( rc ) ) return rc;
    1017             : 
    1018             :   /* https://github.com/anza-xyz/agave/blob/v4.2.0-beta.2/programs/vote/src/vote_state/mod.rs#L918-L919 */
    1019           0 :   rc = fd_vote_verify_authorized_signer(
    1020           0 :       fd_vsv_get_authorized_withdrawer( vote_state_versioned ),
    1021           0 :       signers,
    1022           0 :       signers_cnt
    1023           0 :   );
    1024           0 :   if( FD_UNLIKELY( rc ) ) return rc;
    1025             : 
    1026             :   /* An external collector must be system program owned, rent-exempt,
    1027             :      and not reserved (checked via the writable flag).
    1028             :      https://github.com/anza-xyz/agave/blob/v4.2.0-beta.2/programs/vote/src/vote_state/mod.rs#L866-L905 */
    1029           0 :   fd_pubkey_t const * new_collector_key;
    1030           0 :   if( !collector_account ) {
    1031           0 :     new_collector_key = (fd_pubkey_t const *)vote_account->acc->pubkey;
    1032           0 :   } else {
    1033           0 :     if( FD_UNLIKELY( !fd_pubkey_eq( fd_borrowed_account_get_owner( collector_account ), &fd_solana_system_program_id ) ) ) {
    1034           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_OWNER;
    1035           0 :     }
    1036             : 
    1037           0 :     if( FD_UNLIKELY( fd_borrowed_account_get_lamports( collector_account ) <
    1038           0 :                      fd_rent_exempt_minimum_balance( rent, fd_borrowed_account_get_data_len( collector_account ) ) ) ) {
    1039           0 :       return FD_EXECUTOR_INSTR_ERR_INSUFFICIENT_FUNDS;
    1040           0 :     }
    1041             : 
    1042           0 :     if( FD_UNLIKELY( !fd_borrowed_account_is_writable( collector_account ) ) ) {
    1043           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
    1044           0 :     }
    1045             : 
    1046           0 :     new_collector_key = (fd_pubkey_t const *)collector_account->acc->pubkey;
    1047           0 :   }
    1048             : 
    1049             :   /* https://github.com/anza-xyz/agave/blob/v4.2.0-beta.2/programs/vote/src/vote_state/mod.rs#L923-L930 */
    1050           0 :   switch( kind->discriminant ) {
    1051           0 :     case fd_commission_kind_enum_inflation_rewards: {
    1052           0 :       fd_vsv_set_inflation_rewards_collector( vote_state_versioned, new_collector_key );
    1053           0 :       break;
    1054           0 :     }
    1055           0 :     case fd_commission_kind_enum_block_revenue: {
    1056           0 :       fd_vsv_set_block_revenue_collector( vote_state_versioned, new_collector_key );
    1057           0 :       break;
    1058           0 :     }
    1059           0 :     default: {
    1060           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    1061           0 :     }
    1062           0 :   }
    1063             : 
    1064             :   /* https://github.com/anza-xyz/agave/blob/v4.2.0-beta.2/programs/vote/src/vote_state/mod.rs#L934 */
    1065           0 :   return fd_vsv_set_vote_account_state( ctx, vote_account, vote_state_versioned );
    1066           0 : }
    1067             : 
    1068             : /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L848C8-L903 */
    1069             : static int
    1070             : withdraw( fd_exec_instr_ctx_t *         ctx,
    1071             :           fd_borrowed_account_t *       vote_account,
    1072             :           int                           target_version,
    1073             :           ulong                         lamports,
    1074             :           ushort                        to_account_index,
    1075             :           fd_pubkey_t const *           signers[static FD_INSTR_SIGNERS_MAX],
    1076             :           ulong                         signers_cnt,
    1077             :           fd_rent_t const *             rent_sysvar,
    1078             :           fd_sol_sysvar_clock_t const * clock,
    1079         366 :           int *                         deinitialized ) {
    1080         366 :   fd_vote_state_versioned_t * versioned = &ctx->runtime->vote_program.withdraw.vote_state;
    1081         366 :   *deinitialized = 0;
    1082             : 
    1083             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L860-L863 */
    1084         366 :   int rc = get_vote_state_handler_checked( vote_account, target_version, 0, versioned );
    1085         366 :   if( FD_UNLIKELY( rc ) ) return rc;
    1086             : 
    1087             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L865 */
    1088         196 :   rc = fd_vote_verify_authorized_signer(
    1089         196 :       fd_vsv_get_authorized_withdrawer( versioned ),
    1090         196 :       signers,
    1091         196 :       signers_cnt
    1092         196 :   );
    1093         196 :   if( FD_UNLIKELY( rc ) ) return rc;
    1094             : 
    1095             :   /* Always zero until SIMD-0123 is activated.
    1096             :      https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/mod.rs#L1136 */
    1097         180 :   ulong pending_delegator_rewards = fd_vsv_get_pending_delegator_rewards( versioned );
    1098             : 
    1099             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L867-L870 */
    1100         180 :   ulong vote_account_lamports = fd_borrowed_account_get_lamports( vote_account );
    1101         180 :   if( FD_UNLIKELY( lamports>vote_account_lamports ) ) {
    1102           9 :     return FD_EXECUTOR_INSTR_ERR_INSUFFICIENT_FUNDS;
    1103           9 :   }
    1104         171 :   ulong remaining_balance = vote_account_lamports-lamports;
    1105             : 
    1106             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L872-L896 */
    1107         171 :   if( FD_UNLIKELY( remaining_balance==0UL ) ) {
    1108             :     /* SIMD-0123: vote account cannot be closed if pending_delegator_rewards > 0.
    1109             :        https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/mod.rs#L1139-L1143 */
    1110          17 :     if( FD_UNLIKELY( pending_delegator_rewards > 0 ) ) {
    1111           8 :       return FD_EXECUTOR_INSTR_ERR_INSUFFICIENT_FUNDS;
    1112           8 :     }
    1113             : 
    1114             :     /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L873-L883 */
    1115           9 :     fd_vote_epoch_credits_t const * epoch_credits = fd_vsv_get_epoch_credits( versioned );
    1116           9 :     ulong                           last_epoch_with_credits;
    1117           9 :     int                             reject_active_vote_account_close = 0;
    1118           9 :     if( FD_LIKELY( !deq_fd_vote_epoch_credits_t_empty( epoch_credits ) ) ) {
    1119           6 :       ulong current_epoch              = clock->epoch;
    1120           6 :       last_epoch_with_credits          = deq_fd_vote_epoch_credits_t_peek_tail_const( epoch_credits )->epoch;
    1121           6 :       reject_active_vote_account_close = fd_ulong_sat_sub( current_epoch, last_epoch_with_credits )<2UL;
    1122           6 :     }
    1123             : 
    1124             :     /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L885-L890 */
    1125           9 :     if( FD_UNLIKELY( reject_active_vote_account_close ) ) {
    1126           0 :       ctx->txn_out->err.custom_err = FD_VOTE_ERR_ACTIVE_VOTE_ACCOUNT_CLOSE;
    1127           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1128           9 :     } else {
    1129           9 :       rc = fd_vsv_deinitialize_vote_account_state(
    1130           9 :           ctx,
    1131           9 :           vote_account,
    1132           9 :           target_version
    1133           9 :       );
    1134           9 :       if( FD_UNLIKELY( rc ) ) return rc;
    1135           8 :       *deinitialized = 1;
    1136           8 :     }
    1137         154 :   } else {
    1138             :     /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L892-L895 */
    1139         154 :     ulong min_rent_exempt_balance = fd_rent_exempt_minimum_balance( rent_sysvar, fd_borrowed_account_get_data_len( vote_account ) );
    1140             : 
    1141             :     /* SIMD-0123: withdrawable balance when pending_delegator_rewards > 0
    1142             :        is lamports - pending_delegator_rewards - rent_exempt_minimum.
    1143             :        https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/mod.rs#L1164-L1169 */
    1144         154 :     ulong min_balance;
    1145         154 :     if( FD_UNLIKELY( fd_ulong_checked_add( min_rent_exempt_balance, pending_delegator_rewards, &min_balance ) ) ) {
    1146           0 :       return FD_EXECUTOR_INSTR_ERR_ARITHMETIC_OVERFLOW;
    1147           0 :     }
    1148             : 
    1149         154 :     if( FD_UNLIKELY( remaining_balance<min_balance ) ) {
    1150          71 :       return FD_EXECUTOR_INSTR_ERR_INSUFFICIENT_FUNDS;
    1151          71 :     }
    1152         154 :   }
    1153             : 
    1154             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L898 */
    1155          91 :   rc = fd_borrowed_account_checked_sub_lamports( vote_account, lamports );
    1156          91 :   if( FD_UNLIKELY( rc ) ) return rc;
    1157             : 
    1158             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L899 */
    1159          91 :   fd_borrowed_account_drop( vote_account );
    1160             : 
    1161             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L900 */
    1162          91 :   fd_guarded_borrowed_account_t to = {0};
    1163          91 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, to_account_index, &to );
    1164             : 
    1165             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L901 */
    1166          91 :   rc = fd_borrowed_account_checked_add_lamports( &to, lamports );
    1167          91 :   if( FD_UNLIKELY( rc ) ) return rc;
    1168             : 
    1169          90 :   return FD_EXECUTOR_INSTR_SUCCESS;
    1170          91 : }
    1171             : 
    1172             : /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L638-L651 */
    1173             : static int
    1174             : process_vote_unfiltered( fd_exec_instr_ctx_t *       ctx,
    1175             :                          fd_vote_state_versioned_t * versioned,
    1176             :                          ulong *                     vote_slots,
    1177             :                          fd_vote_t const *           vote,
    1178             :                          fd_slot_hashes_t const *    slot_hashes,
    1179             :                          ulong                       epoch,
    1180         341 :                          ulong                       current_slot ) {
    1181         341 :   int rc;
    1182             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L770
    1183         341 :   rc = check_slots_are_valid( ctx, versioned, vote_slots, &vote->hash, slot_hashes );
    1184         341 :   if( FD_UNLIKELY( rc ) ) return rc;
    1185         313 :   for( deq_ulong_iter_t iter = deq_ulong_iter_init( vote_slots );
    1186       16373 :        !deq_ulong_iter_done( vote_slots, iter );
    1187       16060 :        iter = deq_ulong_iter_next( vote_slots, iter ) ) {
    1188       16060 :     ulong * ele = deq_ulong_iter_ele( vote_slots, iter );
    1189             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L772
    1190       16060 :     fd_vsv_process_next_vote_slot( versioned, *ele, epoch, current_slot );
    1191       16060 :   }
    1192         313 :   return 0;
    1193         341 : }
    1194             : 
    1195             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L783
    1196             : static int
    1197             : process_vote( fd_exec_instr_ctx_t *       ctx,
    1198             :               fd_vote_state_versioned_t * versioned,
    1199             :               fd_vote_t const *           vote,
    1200             :               fd_slot_hashes_t const *    slot_hashes,
    1201             :               ulong                       epoch,
    1202         346 :               ulong                       current_slot ) {
    1203             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L792
    1204         346 :   if( FD_UNLIKELY( deq_ulong_empty( vote->slots ) ) ) {
    1205           1 :     ctx->txn_out->err.custom_err = FD_VOTE_ERR_EMPTY_SLOTS;
    1206           1 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1207           1 :   }
    1208             : 
    1209             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L795
    1210         345 :   ulong earliest_slot_in_history = 0;
    1211         345 :   if( FD_UNLIKELY( !!slot_hashes->cnt ) ) {
    1212         343 :     earliest_slot_in_history = slot_hashes->elems[ slot_hashes->cnt-1UL ].slot;
    1213         343 :   }
    1214             : 
    1215             :   /* We know that the size of the vote_slots is bounded by the number of
    1216             :      slots that can fit inside of an instruction.  Because the
    1217             :      instructions are deserialized with
    1218             :      limited_deserialize(data, PACKET_DATA_SIZE), we can use
    1219             :      FD_TXN_MTU_V0 as a bound on the size of the instruction. If this
    1220             :      instruction is filled only with a vote slot deque, we get
    1221             :      (1232/8) == 154 slots.
    1222             :      The footprint of a deque is as follows:
    1223             :      fd_ulong_align_up( fd_ulong_align_up( 32UL, alignof(DEQUE_T) ) + sizeof(DEQUE_T)*max, alignof(DEQUE_(private_t)) );
    1224             :      So, the footprint in our case is:
    1225             :      fd_ulong_align_up( fd_ulong_align_up( 32UL, alignof(ulong) ) + sizeof(ulong)*154, alignof(DEQUE_(private_t)) );
    1226             :      Which is equal to
    1227             :      fd_ulong_align_up( 32UL + 154 * 8UL, 8UL ) = 1264UL; */
    1228         345 :   #define VOTE_SLOTS_MAX             (FD_TXN_MTU_V0/sizeof(ulong))
    1229         345 :   #define VOTE_SLOTS_DEQUE_FOOTPRINT (1264UL )
    1230         345 :   #define VOTE_SLOTS_DEQUE_ALIGN     (8UL)
    1231         345 :   FD_TEST( deq_ulong_footprint( VOTE_SLOTS_MAX ) == VOTE_SLOTS_DEQUE_FOOTPRINT );
    1232         345 :   FD_TEST( deq_ulong_align()                     == 8UL );
    1233         345 :   FD_TEST( deq_ulong_cnt( vote->slots )          <= VOTE_SLOTS_MAX );
    1234         345 :   uchar * vote_slots_mem[ VOTE_SLOTS_DEQUE_FOOTPRINT ] __attribute__((aligned(VOTE_SLOTS_DEQUE_ALIGN)));
    1235             : 
    1236             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L796
    1237         345 :   ulong * vote_slots = deq_ulong_join( deq_ulong_new( vote_slots_mem, deq_ulong_cnt( vote->slots ) ) );
    1238         345 :   for( deq_ulong_iter_t iter = deq_ulong_iter_init( vote->slots );
    1239       24509 :        !deq_ulong_iter_done( vote->slots, iter );
    1240       24164 :        iter = deq_ulong_iter_next( vote->slots, iter ) ) {
    1241       24164 :     ulong * ele = deq_ulong_iter_ele( vote->slots, iter );
    1242       24164 :     if( FD_UNLIKELY( *ele >= earliest_slot_in_history ) ) {
    1243       16626 :       vote_slots = deq_ulong_push_tail_wrap( vote_slots, *ele );
    1244       16626 :     }
    1245       24164 :   }
    1246             : 
    1247             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L802
    1248         345 :   if( FD_UNLIKELY( deq_ulong_cnt( vote_slots ) == 0 ) ) {
    1249           4 :     ctx->txn_out->err.custom_err = FD_VOTE_ERR_VOTES_TOO_OLD_ALL_FILTERED;
    1250           4 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1251           4 :   }
    1252             : 
    1253             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L805
    1254         341 :   return process_vote_unfiltered(
    1255         341 :       ctx,
    1256         341 :       versioned,
    1257         341 :       vote_slots,
    1258         341 :       vote,
    1259         341 :       slot_hashes,
    1260         341 :       epoch,
    1261         341 :       current_slot
    1262         341 :   );
    1263         345 : }
    1264             : 
    1265             : /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L905-L926 */
    1266             : static int
    1267             : initialize_account( fd_exec_instr_ctx_t *         ctx,
    1268             :                     fd_borrowed_account_t *       vote_account,
    1269             :                     int                           target_version,
    1270             :                     fd_vote_init_t *              vote_init,
    1271             :                     fd_pubkey_t const *           signers[static FD_INSTR_SIGNERS_MAX],
    1272             :                     ulong                         signers_cnt,
    1273         185 :                     fd_sol_sysvar_clock_t const * clock ) {
    1274         185 :   int rc;
    1275         185 :   fd_vote_state_versioned_t * versioned = &ctx->runtime->vote_program.init_account.vote_state;
    1276             : 
    1277             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L915 */
    1278         185 :   rc = check_vote_account_length( vote_account, target_version );
    1279         185 :   if( FD_UNLIKELY( rc ) ) return rc;
    1280             : 
    1281             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L916 */
    1282         167 :   rc = fd_vsv_get_state( vote_account->acc, versioned );
    1283         167 :   if( FD_UNLIKELY( rc ) ) return rc;
    1284             : 
    1285             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L918-L920 */
    1286         167 :   if( FD_UNLIKELY( !fd_vsv_is_uninitialized( versioned ) ) ) {
    1287           0 :     return FD_EXECUTOR_INSTR_ERR_ACC_ALREADY_INITIALIZED;
    1288           0 :   }
    1289             : 
    1290             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L923 */
    1291         167 :   rc = fd_vote_verify_authorized_signer( &vote_init->node_pubkey, signers, signers_cnt );
    1292         167 :   if( FD_UNLIKELY( rc ) ) {
    1293           2 :     return rc;
    1294           2 :   }
    1295             : 
    1296             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L925 */
    1297         165 :   return init_vote_account_state( ctx, vote_account, versioned, target_version, vote_init, clock );
    1298         167 : }
    1299             : 
    1300             : /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/mod.rs#L1182-L1216
    1301             :    Note: this is very similar to initialize_account() but also does verify_bls_proof_of_possession() */
    1302             : static int
    1303             : initialize_account_v2( fd_exec_instr_ctx_t *         ctx,
    1304             :                        fd_borrowed_account_t *       vote_account,
    1305             :                        int                           target_version,
    1306             :                        fd_vote_init_v2_t *           vote_init_v2,
    1307             :                        fd_pubkey_t const *           signers[static FD_INSTR_SIGNERS_MAX],
    1308             :                        ulong                         signers_cnt,
    1309           0 :                        fd_sol_sysvar_clock_t const * clock ) {
    1310           0 :   int rc;
    1311           0 :   fd_vote_state_versioned_t * versioned = &ctx->runtime->vote_program.init_account.vote_state;
    1312             : 
    1313             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/mod.rs#L1198 */
    1314           0 :   rc = check_vote_account_length( vote_account, target_version );
    1315           0 :   if( FD_UNLIKELY( rc ) ) return rc;
    1316             : 
    1317           0 :   rc = fd_vsv_get_state( vote_account->acc, versioned );
    1318           0 :   if( FD_UNLIKELY( rc ) ) return rc;
    1319             : 
    1320           0 :   if( FD_UNLIKELY( !fd_vsv_is_uninitialized( versioned ) ) ) {
    1321           0 :     return FD_EXECUTOR_INSTR_ERR_ACC_ALREADY_INITIALIZED;
    1322           0 :   }
    1323             : 
    1324           0 :   rc = fd_vote_verify_authorized_signer( &vote_init_v2->node_pubkey, signers, signers_cnt );
    1325           0 :   if( FD_UNLIKELY( rc ) ) {
    1326           0 :     return rc;
    1327           0 :   }
    1328             : 
    1329             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/mod.rs#L1208-L1213 */
    1330           0 :   rc = fd_vote_verify_bls_proof_of_possession(
    1331           0 :     ctx,
    1332           0 :     vote_account->acc->pubkey,
    1333           0 :     vote_init_v2->authorized_voter_bls_pubkey,
    1334           0 :     vote_init_v2->authorized_voter_bls_proof_of_possession
    1335           0 :   );
    1336           0 :   if( FD_UNLIKELY( rc ) ) {
    1337           0 :     return rc;
    1338           0 :   }
    1339             : 
    1340             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/mod.rs#L1215 */
    1341           0 :   return init_vote_account_state_v2( ctx, vote_account, versioned, target_version, vote_init_v2, clock );
    1342           0 : }
    1343             : 
    1344             : /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L928-L953 */
    1345             : static int
    1346             : process_vote_with_account( fd_exec_instr_ctx_t *         ctx,
    1347             :                            fd_borrowed_account_t *       vote_account,
    1348             :                            int                           target_version,
    1349             :                            fd_slot_hashes_t const *      slot_hashes,
    1350             :                            fd_sol_sysvar_clock_t const * clock,
    1351             :                            fd_vote_t *                   vote,
    1352             :                            fd_pubkey_t const *           signers[static FD_INSTR_SIGNERS_MAX],
    1353         477 :                            ulong                         signers_cnt ) {
    1354         477 :   fd_vote_state_versioned_t * versioned = &ctx->runtime->vote_program.process_vote.vote_state;
    1355             : 
    1356             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L936-L939 */
    1357         477 :   int rc = get_vote_state_handler_checked( vote_account, target_version, 1, versioned );
    1358         477 :   if( FD_UNLIKELY( rc ) ) return rc;
    1359             : 
    1360             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L941 */
    1361         361 :   fd_pubkey_t * authorized_voter = NULL;
    1362         361 :   rc = fd_authorized_voters_get_and_update_authorized_voter( versioned, clock->epoch, &authorized_voter );
    1363         361 :   if( FD_UNLIKELY( rc ) ) return rc;
    1364             : 
    1365             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L942 */
    1366         361 :   rc = fd_vote_verify_authorized_signer( authorized_voter, signers, signers_cnt );
    1367         361 :   if( FD_UNLIKELY( rc ) ) return rc;
    1368             : 
    1369             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L944 */
    1370         346 :   rc = process_vote( ctx, versioned, vote, slot_hashes, clock->epoch, clock->slot );
    1371         346 :   if( FD_UNLIKELY( rc ) ) return rc;
    1372             : 
    1373             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L945-L951 */
    1374         313 :   if( FD_LIKELY( vote->has_timestamp ) ) {
    1375             :     /* Calling max() on an empty iterator returns None */
    1376         144 :     if( FD_UNLIKELY( deq_ulong_cnt( vote->slots )==0 ) ) {
    1377           0 :       ctx->txn_out->err.custom_err = FD_VOTE_ERR_EMPTY_SLOTS;
    1378           0 :       return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
    1379           0 :     }
    1380             : 
    1381             :     /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L948 */
    1382         144 :     ulong max = 0UL;
    1383         144 :     for( deq_ulong_iter_t iter = deq_ulong_iter_init( vote->slots );
    1384       10583 :                                 !deq_ulong_iter_done( vote->slots, iter );
    1385       10439 :                           iter = deq_ulong_iter_next( vote->slots, iter ) ) {
    1386       10439 :       ulong * ele = deq_ulong_iter_ele( vote->slots, iter );
    1387       10439 :       max         = fd_ulong_max( max, *ele );
    1388       10439 :     }
    1389             : 
    1390             :     /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L950 */
    1391         144 :     rc = fd_vsv_process_timestamp( ctx, versioned, max, vote->timestamp );
    1392         144 :     if( FD_UNLIKELY( rc ) ) return rc;
    1393         144 :   }
    1394             : 
    1395             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L952 */
    1396         219 :   return fd_vsv_set_vote_account_state( ctx, vote_account, versioned );
    1397         313 : }
    1398             : 
    1399             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1156
    1400             : static int
    1401             : do_process_vote_state_update( fd_exec_instr_ctx_t *       ctx,
    1402             :                               fd_vote_state_versioned_t * versioned,
    1403             :                               fd_slot_hashes_t const *    slot_hashes,
    1404             :                               ulong                       epoch,
    1405             :                               ulong                       slot,
    1406          45 :                               fd_vote_state_update_t *    vote_state_update ) {
    1407          45 :   int rc;
    1408             : 
    1409             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1164
    1410          45 :   rc = check_and_filter_proposed_vote_state(
    1411          45 :       ctx,
    1412          45 :       versioned,
    1413          45 :       vote_state_update->lockouts,
    1414          45 :       &vote_state_update->has_root,
    1415          45 :       &vote_state_update->root,
    1416          45 :       &vote_state_update->hash,
    1417          45 :       slot_hashes
    1418          45 :   );
    1419          45 :   if( FD_UNLIKELY( rc ) ) return rc;
    1420             : 
    1421             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1177
    1422          20 :   fd_landed_vote_t * landed_votes = deq_fd_landed_vote_t_join( deq_fd_landed_vote_t_new( ctx->runtime->vote_program.process_vote.vs_update_landed_votes_mem, deq_fd_vote_lockout_t_cnt( vote_state_update->lockouts ) ) );
    1423          20 :   for( deq_fd_vote_lockout_t_iter_t iter =
    1424          20 :            deq_fd_vote_lockout_t_iter_init( vote_state_update->lockouts );
    1425         438 :        !deq_fd_vote_lockout_t_iter_done( vote_state_update->lockouts, iter );
    1426         418 :        iter = deq_fd_vote_lockout_t_iter_next( vote_state_update->lockouts, iter ) ) {
    1427         418 :     fd_vote_lockout_t * lockout =
    1428         418 :         deq_fd_vote_lockout_t_iter_ele( vote_state_update->lockouts, iter );
    1429         418 :     deq_fd_landed_vote_t_push_tail_wrap( landed_votes,
    1430         418 :                                     ( fd_landed_vote_t ){ .latency = 0, .lockout = *lockout } );
    1431         418 :   }
    1432             : 
    1433             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L1171
    1434          20 :   return process_new_vote_state(
    1435          20 :       ctx,
    1436          20 :       versioned,
    1437          20 :       landed_votes,
    1438          20 :       vote_state_update->has_root,
    1439          20 :       vote_state_update->root,
    1440          20 :       vote_state_update->has_timestamp,
    1441          20 :       vote_state_update->timestamp,
    1442          20 :       epoch,
    1443          20 :       slot
    1444          20 :   );
    1445          45 : }
    1446             : 
    1447             : /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L955-L979 */
    1448             : static int
    1449             : process_vote_state_update( fd_exec_instr_ctx_t *         ctx,
    1450             :                            fd_borrowed_account_t *       vote_account,
    1451             :                            int                           target_version,
    1452             :                            fd_slot_hashes_t const *      slot_hashes,
    1453             :                            fd_sol_sysvar_clock_t const * clock,
    1454             :                            fd_vote_state_update_t *      vote_state_update,
    1455             :                            fd_pubkey_t const *           signers[static FD_INSTR_SIGNERS_MAX],
    1456         895 :                            ulong                         signers_cnt ) {
    1457         895 :   fd_vote_state_versioned_t * versioned = &ctx->runtime->vote_program.process_vote.vote_state;
    1458             : 
    1459             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L963-L966 */
    1460         895 :   int rc = get_vote_state_handler_checked( vote_account, target_version, 1, versioned );
    1461         895 :   if( FD_UNLIKELY( rc ) ) return rc;
    1462             : 
    1463             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L968 */
    1464         668 :   fd_pubkey_t * authorized_voter = NULL;
    1465         668 :   rc = fd_authorized_voters_get_and_update_authorized_voter( versioned, clock->epoch, &authorized_voter );
    1466         668 :   if( FD_UNLIKELY( rc ) ) return rc;
    1467             : 
    1468             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L969 */
    1469         667 :   rc = fd_vote_verify_authorized_signer( authorized_voter, signers, signers_cnt );
    1470         667 :   if( FD_UNLIKELY( rc ) ) return rc;
    1471             : 
    1472             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L971-L977 */
    1473          44 :   rc = do_process_vote_state_update(
    1474          44 :       ctx,
    1475          44 :       versioned,
    1476          44 :       slot_hashes,
    1477          44 :       clock->epoch,
    1478          44 :       clock->slot,
    1479          44 :       vote_state_update
    1480          44 :   );
    1481          44 :   if( FD_UNLIKELY( rc ) ) {
    1482          30 :     return rc;
    1483          30 :   }
    1484             : 
    1485             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L978 */
    1486          14 :   return fd_vsv_set_vote_account_state( ctx, vote_account, versioned );
    1487          44 : }
    1488             : 
    1489             : /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L1035-L1061 */
    1490             : static int
    1491             : do_process_tower_sync( fd_exec_instr_ctx_t *       ctx,
    1492             :                        fd_vote_state_versioned_t * versioned,
    1493             :                        fd_slot_hashes_t const *    slot_hashes,
    1494             :                        ulong                       epoch,
    1495             :                        ulong                       slot,
    1496         636 :                        fd_tower_sync_t *           tower_sync ) {
    1497             : 
    1498             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L1042-L1048 */
    1499         636 :   int rc = check_and_filter_proposed_vote_state(
    1500         636 :       ctx,
    1501         636 :       versioned,
    1502         636 :       tower_sync->lockouts,
    1503         636 :       &tower_sync->has_root,
    1504         636 :       &tower_sync->root,
    1505         636 :       &tower_sync->hash,
    1506         636 :       slot_hashes
    1507         636 :   );
    1508         636 :   if( FD_UNLIKELY( rc ) ) return rc;
    1509             : 
    1510             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L1049-L1060 */
    1511         622 :   return process_new_vote_state(
    1512         622 :       ctx,
    1513         622 :       versioned,
    1514         622 :       fd_vote_lockout_landed_votes_from_lockouts( tower_sync->lockouts, ctx->runtime->vote_program.tower_sync.tower_sync_landed_votes_mem ),
    1515         622 :       tower_sync->has_root,
    1516         622 :       tower_sync->root,
    1517         622 :       tower_sync->has_timestamp,
    1518         622 :       tower_sync->timestamp,
    1519         622 :       epoch,
    1520         622 :       slot
    1521         622 :   );
    1522         636 : }
    1523             : 
    1524             : /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L1009-L1033 */
    1525             : static int
    1526             : process_tower_sync( fd_exec_instr_ctx_t *         ctx,
    1527             :                     fd_borrowed_account_t *       vote_account,
    1528             :                     int                           target_version,
    1529             :                     fd_slot_hashes_t const *      slot_hashes,
    1530             :                     fd_sol_sysvar_clock_t const * clock,
    1531             :                     fd_tower_sync_t *             tower_sync,
    1532             :                     fd_pubkey_t const *           signers[static FD_INSTR_SIGNERS_MAX],
    1533         671 :                     ulong                         signers_cnt ) {
    1534         671 :   fd_vote_state_versioned_t * versioned = &ctx->runtime->vote_program.tower_sync.vote_state;
    1535             : 
    1536             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L1017-L1020 */
    1537         671 :   int rc = get_vote_state_handler_checked( vote_account, target_version, 1, versioned );
    1538         671 :   if( FD_UNLIKELY( rc ) ) return rc;
    1539             : 
    1540             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L1022 */
    1541         644 :   fd_pubkey_t * authorized_voter = NULL;
    1542         644 :   rc = fd_authorized_voters_get_and_update_authorized_voter( versioned, clock->epoch, &authorized_voter );
    1543         644 :   if( FD_UNLIKELY( rc ) ) return rc;
    1544             : 
    1545             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L1023 */
    1546         644 :   rc = fd_vote_verify_authorized_signer( authorized_voter, signers, signers_cnt );
    1547         644 :   if( FD_UNLIKELY( rc ) ) return rc;
    1548             : 
    1549             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L1025-L1031 */
    1550         636 :   rc = do_process_tower_sync(
    1551         636 :       ctx,
    1552         636 :       versioned,
    1553         636 :       slot_hashes,
    1554         636 :       clock->epoch,
    1555         636 :       clock->slot,
    1556         636 :       tower_sync
    1557         636 :   );
    1558         636 :   if( FD_UNLIKELY( rc ) ) return rc;
    1559             : 
    1560             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/mod.rs#L1032 */
    1561         412 :   return fd_vsv_set_vote_account_state( ctx, vote_account, versioned );
    1562         636 : }
    1563             : 
    1564             : /**********************************************************************/
    1565             : /* FD-only encoders / decoders (doesn't map directly to Labs impl)    */
    1566             : /**********************************************************************/
    1567             : 
    1568             : int
    1569             : fd_vote_decode_compact_update( fd_compact_vote_state_update_t * compact_update,
    1570             :                                fd_vote_state_update_t *         vote_update,
    1571         108 :                                fd_exec_instr_ctx_t const *      ctx ) {
    1572             :   // Taken from:
    1573             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L954
    1574         108 :   if( compact_update->root != ULONG_MAX ) {
    1575          84 :     vote_update->has_root = 1;
    1576          84 :     vote_update->root     = compact_update->root;
    1577          84 :   } else {
    1578          24 :     vote_update->has_root = 0;
    1579          24 :     vote_update->root     = ULONG_MAX;
    1580          24 :   }
    1581             : 
    1582         108 :   ulong lockouts_len = compact_update->lockouts_len;
    1583         108 :   ulong lockouts_max = fd_ulong_max( lockouts_len, MAX_LOCKOUT_HISTORY );
    1584             : 
    1585         108 :   vote_update->lockouts = deq_fd_vote_lockout_t_join( deq_fd_vote_lockout_t_new( ctx->runtime->vote_program.process_vote.compact_vs_lockout_mem, lockouts_max ) );
    1586         108 :   ulong slot            = fd_ulong_if( vote_update->has_root, vote_update->root, 0 );
    1587             : 
    1588        2182 :   for( ulong i=0; i < lockouts_len; ++i ) {
    1589        2074 :     fd_vote_lockout_t *   elem        = deq_fd_vote_lockout_t_push_tail_nocopy( vote_update->lockouts );
    1590        2074 :     fd_lockout_offset_t * lock_offset = &compact_update->lockouts[i];
    1591             : 
    1592        2074 :     ulong next_slot;
    1593        2074 :     if( FD_UNLIKELY( __builtin_uaddl_overflow( slot, lock_offset->offset, &next_slot ) ) ) {
    1594           0 :       return 0;
    1595           0 :     }
    1596             : 
    1597        2074 :     elem->slot = slot        = next_slot;
    1598        2074 :     elem->confirmation_count = (uint)lock_offset->confirmation_count;
    1599        2074 :   }
    1600             : 
    1601         108 :   vote_update->hash          = compact_update->hash;
    1602         108 :   vote_update->has_timestamp = compact_update->has_timestamp;
    1603         108 :   vote_update->timestamp     = compact_update->timestamp;
    1604             : 
    1605         108 :   return 1;
    1606         108 : }
    1607             : 
    1608             : /**********************************************************************/
    1609             : /* mod vote_processor                                                 */
    1610             : /**********************************************************************/
    1611             : 
    1612             : /* https://github.com/anza-xyz/agave/blob/v4.3.0-beta.3/programs/vote/src/vote_processor.rs#L78-L81 */
    1613             : static inline int
    1614        1406 : should_reject_legacy_vote_instructions( fd_exec_instr_ctx_t const * ctx ) {
    1615        1406 :   return FD_FEATURE_ACTIVE_BANK( ctx->bank, deprecate_legacy_vote_ixs ) ||
    1616        1406 :          ctx->bank->f.alpenglow_migration_slot!=ULONG_MAX;
    1617        1406 : }
    1618             : 
    1619             : /* https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L21-L51 */
    1620             : static int
    1621             : process_authorize_with_seed_instruction( /* invoke_context */
    1622             :                                          fd_exec_instr_ctx_t *       ctx,
    1623             :                                          int                         target_version,
    1624             :                                          fd_borrowed_account_t *     vote_account,
    1625             :                                          fd_pubkey_t const *         new_authority,
    1626             :                                          fd_vote_authorize_t const * authorization_type,
    1627             :                                          fd_pubkey_t const *         current_authority_derived_key_owner,
    1628             :                                          uchar const *               current_authority_derived_key_seed,
    1629             :                                          ulong                       current_authority_derived_key_seed_len,
    1630         358 :                                          int                         is_vote_authorize_with_bls_enabled ) {
    1631         358 :   int rc = 0;
    1632             : 
    1633             :   /* https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L31 */
    1634         358 :   rc = fd_sysvar_instr_acct_check( ctx, 1, &fd_sysvar_clock_id );
    1635         358 :   if( FD_UNLIKELY( rc ) ) return rc;
    1636             : 
    1637         352 :   fd_sol_sysvar_clock_t clock_;
    1638         352 :   fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock_read( ctx->sysvar_cache, &clock_ );
    1639         352 :   if( FD_UNLIKELY( !clock ) ) return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    1640             : 
    1641         352 :   fd_pubkey_t * expected_authority_keys[FD_INSTR_SIGNERS_MAX] = { 0 };
    1642         352 :   ulong         expected_authority_keys_cnt             = 0UL;
    1643         352 :   fd_pubkey_t   single_signer                           = { 0 };
    1644             : 
    1645             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_processor.rs#L30-L42 */
    1646         352 :   if( fd_instr_acc_is_signer_idx( ctx->instr, 2, &rc ) ) {
    1647             : 
    1648             :     /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_processor.rs#L31 */
    1649         337 :     fd_pubkey_t const * base_pubkey = NULL;
    1650         337 :     rc = fd_exec_instr_ctx_get_key_of_account_at_index( ctx, 2UL, &base_pubkey );
    1651         337 :     if( FD_UNLIKELY( rc ) ) return rc;
    1652             : 
    1653             :     /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_processor.rs#L34-L40 */
    1654         337 :     expected_authority_keys[0] = &single_signer;
    1655         337 :     rc = fd_pubkey_create_with_seed( ctx,
    1656         337 :                                      base_pubkey->uc,
    1657         337 :                                      (char const *)current_authority_derived_key_seed,
    1658         337 :                                      current_authority_derived_key_seed_len,
    1659         337 :                                      current_authority_derived_key_owner->uc,
    1660         337 :                                      /* insert */ expected_authority_keys[0]->uc );
    1661         337 :     if( FD_UNLIKELY( rc ) ) return rc;
    1662         333 :     expected_authority_keys_cnt = 1UL;
    1663         333 :   }
    1664             : 
    1665             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_processor.rs#L43-L50 */
    1666         348 :   return authorize(
    1667         348 :       ctx,
    1668         348 :       vote_account,
    1669         348 :       target_version,
    1670         348 :       new_authority,
    1671         348 :       authorization_type,
    1672         348 :       (fd_pubkey_t const **)expected_authority_keys,
    1673         348 :       expected_authority_keys_cnt,
    1674         348 :       clock,
    1675         348 :       is_vote_authorize_with_bls_enabled
    1676         348 :   );
    1677         352 : }
    1678             : 
    1679             : /**********************************************************************/
    1680             : /* Entry point for the Vote Program                                   */
    1681             : /**********************************************************************/
    1682             : 
    1683             : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L57
    1684             : int
    1685        9064 : fd_vote_program_execute( fd_exec_instr_ctx_t * ctx ) {
    1686             :   /* FD-specific init */
    1687        9064 :   int rc = FD_EXECUTOR_INSTR_SUCCESS;
    1688             : 
    1689             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L57
    1690        9064 :   FD_EXEC_CU_UPDATE( ctx, DEFAULT_COMPUTE_UNITS );
    1691             : 
    1692             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_processor.rs#L64-L67 */
    1693        7849 :   fd_guarded_borrowed_account_t me = {0};
    1694        7849 :   FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, 0, &me );
    1695        7726 :   if( FD_UNLIKELY( !fd_pubkey_eq( fd_borrowed_account_get_owner( &me ), &fd_solana_vote_program_id ) ) ) {
    1696        2495 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_OWNER;
    1697        2495 :   }
    1698             : 
    1699             :   /* https://github.com/anza-xyz/agave/blob/v4.1.0-alpha.0/programs/vote/src/vote_processor.rs#L118-L119 */
    1700        5231 :   int target_version = VOTE_STATE_TARGET_VERSION_V4;
    1701             : 
    1702             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L69
    1703        5231 :   fd_pubkey_t const * signers[FD_INSTR_SIGNERS_MAX] = { 0 };
    1704        5231 :   ulong               signers_cnt                   = 0UL;
    1705        5231 :   fd_exec_instr_ctx_get_signers( ctx, signers, &signers_cnt );
    1706             : 
    1707        5231 :   int bls_pubkey_management_in_vote_account = FD_FEATURE_ACTIVE_BANK( ctx->bank, bls_pubkey_management_in_vote_account );
    1708        5231 :   int delay_commission_updates              = FD_FEATURE_ACTIVE_BANK( ctx->bank, delay_commission_updates );
    1709        5231 :   int commission_rate_in_basis_points       = FD_FEATURE_ACTIVE_BANK( ctx->bank, commission_rate_in_basis_points );
    1710        5231 :   int custom_commission_collector           = FD_FEATURE_ACTIVE_BANK( ctx->bank, custom_commission_collector );
    1711        5231 :   int block_revenue_sharing                 = FD_FEATURE_ACTIVE_BANK( ctx->bank, block_revenue_sharing );
    1712        5231 :   int vote_account_initialize_v2            = 0;
    1713             : 
    1714             :   /* https://github.com/anza-xyz/agave/blob/v4.1.0-alpha.0/programs/vote/src/vote_processor.rs#L72-L76 */
    1715        5231 :   int is_vote_authorize_with_bls_enabled = bls_pubkey_management_in_vote_account;
    1716             : 
    1717             :   /* https://github.com/anza-xyz/agave/blob/v4.1.0-alpha.0/programs/vote/src/vote_processor.rs#L63-L70 */
    1718        5231 :   int is_init_account_v2_enabled =
    1719        5231 :       bls_pubkey_management_in_vote_account &&
    1720        5235 :       commission_rate_in_basis_points &&
    1721        5235 :       custom_commission_collector &&
    1722        5231 :       block_revenue_sharing &&
    1723        5231 :       vote_account_initialize_v2;
    1724             : 
    1725        5231 :   fd_vote_instruction_t instruction[1];
    1726        5231 :   if( FD_UNLIKELY( !fd_vote_instruction_deserialize( instruction, ctx->instr->data, ctx->instr->data_sz ) ) ) {
    1727         742 :     return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    1728         742 :   }
    1729             : 
    1730             :   /* PLEASE PRESERVE SWITCH-CASE ORDERING TO MIRROR LABS IMPL:
    1731             :    */
    1732        4489 :   switch( instruction->discriminant ) {
    1733             : 
    1734             :   /* InitializeAccount
    1735             :    *
    1736             :    * Instruction:
    1737             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L32
    1738             :    *
    1739             :    * Processor:
    1740             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L71
    1741             :    */
    1742         190 :   case fd_vote_instruction_enum_initialize_account: {
    1743             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L72
    1744         190 :     rc = fd_sysvar_instr_acct_check( ctx, 1, &fd_sysvar_rent_id );
    1745         190 :     if( FD_UNLIKELY( rc ) ) return rc;
    1746         186 :     fd_rent_t rent_;
    1747         186 :     fd_rent_t const * rent = fd_sysvar_cache_rent_read( ctx->sysvar_cache, &rent_ );
    1748         186 :     if( FD_UNLIKELY( !rent ) ) return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    1749             : 
    1750         186 :     if( FD_UNLIKELY( fd_borrowed_account_get_lamports( &me ) <
    1751         186 :                      fd_rent_exempt_minimum_balance( rent, fd_borrowed_account_get_data_len( &me ) ) ) )
    1752           1 :       return FD_EXECUTOR_INSTR_ERR_INSUFFICIENT_FUNDS;
    1753             : 
    1754             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L76
    1755         185 :     rc = fd_sysvar_instr_acct_check( ctx, 2, &fd_sysvar_clock_id );
    1756         185 :     if( FD_UNLIKELY( rc ) ) return rc;
    1757         185 :     fd_sol_sysvar_clock_t clock_;
    1758         185 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock_read( ctx->sysvar_cache, &clock_ );
    1759         185 :     if( FD_UNLIKELY( !clock ) ) return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    1760             : 
    1761             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L78
    1762         185 :     rc = initialize_account( ctx, &me, target_version, &instruction->initialize_account, signers, signers_cnt, clock );
    1763             : 
    1764         185 :     if( FD_LIKELY( !rc ) ) {
    1765         165 :       ctx->txn_out->accounts.new_vote[ ctx->instr->accounts[0].index_in_transaction ] = 1;
    1766         165 :       ctx->txn_out->accounts.rm_vote[ ctx->instr->accounts[0].index_in_transaction ] = 0;
    1767         165 :     }
    1768             : 
    1769         185 :     break;
    1770         185 :   }
    1771             : 
    1772             :   /* Authorize
    1773             :    *
    1774             :    * Instruction:
    1775             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L40
    1776             :    *
    1777             :    * Processor:
    1778             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L86
    1779             :    *
    1780             :    * Notes:
    1781             :    * - Up to two signers: the vote authority and the authorized withdrawer.
    1782             :    */
    1783         308 :   case fd_vote_instruction_enum_authorize: {
    1784         308 :     fd_pubkey_t const * voter_pubkey   = &instruction->authorize.pubkey;
    1785             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L87
    1786         308 :     rc = fd_sysvar_instr_acct_check( ctx, 1, &fd_sysvar_clock_id );
    1787         308 :     if( FD_UNLIKELY( rc ) ) return rc;
    1788         305 :     fd_sol_sysvar_clock_t clock_;
    1789         305 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock_read( ctx->sysvar_cache, &clock_ );
    1790         305 :     if( FD_UNLIKELY( !clock ) ) return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    1791             : 
    1792         305 :     rc = authorize( ctx, &me, target_version, voter_pubkey, &instruction->authorize.vote_authorize, signers, signers_cnt, clock, is_vote_authorize_with_bls_enabled );
    1793             : 
    1794         305 :     break;
    1795         305 :   }
    1796             : 
    1797             :   /* AuthorizeWithSeed
    1798             :    *
    1799             :    * Instruction:
    1800             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L117
    1801             :    *
    1802             :    * Processor:
    1803             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L98
    1804             :    */
    1805         200 :   case fd_vote_instruction_enum_authorize_with_seed: {
    1806         200 :     fd_vote_authorize_with_seed_args_t * args = &instruction->authorize_with_seed;
    1807             : 
    1808             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L99
    1809         200 :     if( FD_UNLIKELY( ctx->instr->acct_cnt < 3 ) ) {
    1810           1 :       rc = FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
    1811           1 :       break;
    1812           1 :     }
    1813             : 
    1814         199 :     rc = process_authorize_with_seed_instruction(
    1815         199 :         ctx,
    1816         199 :         target_version,
    1817         199 :         &me,
    1818         199 :         &args->new_authority,
    1819         199 :         &args->authorization_type,
    1820         199 :         &args->current_authority_derived_key_owner,
    1821         199 :         args->current_authority_derived_key_seed,
    1822         199 :         args->current_authority_derived_key_seed_len,
    1823         199 :         is_vote_authorize_with_bls_enabled
    1824         199 :     );
    1825             : 
    1826         199 :     break;
    1827         200 :   }
    1828             : 
    1829             :   /* AuthorizeCheckedWithSeed
    1830             :    *
    1831             :    * Instruction:
    1832             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L131
    1833             :    *
    1834             :    * Processor:
    1835             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L111
    1836             :    */
    1837         174 :   case fd_vote_instruction_enum_authorize_checked_with_seed: {
    1838         174 :     fd_vote_authorize_checked_with_seed_args_t const * args = &instruction->authorize_checked_with_seed;
    1839             : 
    1840             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L112
    1841         174 :     if( FD_UNLIKELY( ctx->instr->acct_cnt < 4 ) ) {
    1842           3 :       rc = FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
    1843           3 :       break;
    1844           3 :     }
    1845             : 
    1846             :     // https://github.com/anza-xyz/agave/blob/v2.1.14/programs/vote/src/vote_processor.rs#L99-L100
    1847         171 :     fd_pubkey_t const * new_authority = NULL;
    1848         171 :     rc = fd_exec_instr_ctx_get_key_of_account_at_index( ctx, 3UL, &new_authority );
    1849         171 :     if( FD_UNLIKELY( rc ) ) return rc;
    1850             : 
    1851             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L116
    1852         171 :     if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( ctx->instr, 3, &rc ) ) ) {
    1853             :       /* https://github.com/anza-xyz/agave/blob/v3.0.3/transaction-context/src/lib.rs#L789 */
    1854          12 :       if( FD_UNLIKELY( !!rc ) ) break;
    1855             :       // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L117
    1856          12 :       rc = FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
    1857          12 :       break;
    1858          12 :     }
    1859             : 
    1860             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L119
    1861         159 :     rc = process_authorize_with_seed_instruction(
    1862         159 :         ctx,
    1863         159 :         target_version,
    1864         159 :         &me,
    1865         159 :         new_authority,
    1866         159 :         &args->authorization_type,
    1867         159 :         &args->current_authority_derived_key_owner,
    1868         159 :         args->current_authority_derived_key_seed,
    1869         159 :         args->current_authority_derived_key_seed_len,
    1870         159 :         is_vote_authorize_with_bls_enabled );
    1871             : 
    1872         159 :     break;
    1873         171 :   }
    1874             : 
    1875             :   /* UpdateValidatorIdentity
    1876             :    *
    1877             :    * Instruction:
    1878             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L65
    1879             :    *
    1880             :    * Processor:
    1881             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L130
    1882             :    */
    1883         402 :   case fd_vote_instruction_enum_update_validator_identity: {
    1884             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L131
    1885         402 :     if( FD_UNLIKELY( ctx->instr->acct_cnt < 2 ) ) {
    1886           0 :       rc = FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
    1887           0 :       break;
    1888           0 :     }
    1889             : 
    1890             :     // https://github.com/anza-xyz/agave/blob/v2.1.14/programs/vote/src/vote_processor.rs#L118-L120
    1891         402 :     fd_pubkey_t const * node_pubkey = NULL;
    1892         402 :     rc = fd_exec_instr_ctx_get_key_of_account_at_index( ctx, 1UL, &node_pubkey );
    1893         402 :     if( FD_UNLIKELY( rc ) ) return rc;
    1894             : 
    1895             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L135
    1896         402 :     rc = update_validator_identity( ctx, target_version, &me, node_pubkey, signers, signers_cnt, custom_commission_collector );
    1897             : 
    1898         402 :     break;
    1899         402 :   }
    1900             : 
    1901             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L142
    1902         494 :   case fd_vote_instruction_enum_update_commission: {
    1903             : 
    1904             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L149
    1905         494 :     fd_epoch_schedule_t epoch_schedule_;
    1906         494 :     fd_epoch_schedule_t const * epoch_schedule = fd_sysvar_cache_epoch_schedule_read( ctx->sysvar_cache, &epoch_schedule_ );
    1907         494 :     if( FD_UNLIKELY( !epoch_schedule ) ) {
    1908           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    1909           0 :     }
    1910             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L150
    1911             : 
    1912         494 :     fd_sol_sysvar_clock_t clock_;
    1913         494 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock_read( ctx->sysvar_cache, &clock_ );
    1914         494 :     if( FD_UNLIKELY( !clock ) ) {
    1915           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    1916           0 :     }
    1917             : 
    1918             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L145
    1919         494 :     rc = update_commission(
    1920         494 :         ctx,
    1921         494 :         target_version,
    1922         494 :         &me,
    1923         494 :         instruction->update_commission,
    1924         494 :         signers,
    1925         494 :         signers_cnt,
    1926         494 :         epoch_schedule,
    1927         494 :         clock,
    1928         494 :         delay_commission_updates
    1929         494 :     );
    1930             : 
    1931         494 :     break;
    1932         494 :   }
    1933             : 
    1934             :   /* Vote
    1935             :    *
    1936             :    * Instruction:
    1937             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L49
    1938             :    */
    1939         266 :   case fd_vote_instruction_enum_vote:;
    1940             :     /* clang-format off */
    1941         266 :     __attribute__((fallthrough));
    1942             :     /* clang-format on */
    1943             : 
    1944             :   /* VoteSwitch
    1945             :    *
    1946             :    * Instruction:
    1947             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L81
    1948             :    *
    1949             :    * Processor:
    1950             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L154
    1951             :    */
    1952         502 :   case fd_vote_instruction_enum_vote_switch: {
    1953             :     /* https://github.com/anza-xyz/agave/blob/v4.3.0-beta.3/programs/vote/src/vote_processor.rs#L222-L224 */
    1954         502 :     if( should_reject_legacy_vote_instructions( ctx ) ) {
    1955           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    1956           0 :     }
    1957             : 
    1958         502 :     fd_vote_t * vote;
    1959         502 :     if( instruction->discriminant == fd_vote_instruction_enum_vote ) {
    1960         266 :       vote = &instruction->vote;
    1961         266 :     } else if( instruction->discriminant == fd_vote_instruction_enum_vote_switch ) {
    1962         236 :       vote = &instruction->vote_switch.vote;
    1963         236 :     } else {
    1964           0 :       FD_LOG_CRIT(( "unsupported instruction discriminant: %u", instruction->discriminant ));
    1965           0 :     }
    1966             : 
    1967             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L155
    1968         502 :     int err;
    1969         502 :     err = fd_sysvar_instr_acct_check( ctx, 1, &fd_sysvar_slot_hashes_id );
    1970         502 :     if( FD_UNLIKELY( err ) ) return err;
    1971             : 
    1972         479 :     if( FD_UNLIKELY( !fd_sysvar_cache_slot_hashes_is_valid( ctx->sysvar_cache ) ) ) {
    1973           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    1974           0 :     }
    1975             : 
    1976             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L157
    1977         479 :     err = fd_sysvar_instr_acct_check( ctx, 2, &fd_sysvar_clock_id );
    1978         479 :     if( FD_UNLIKELY( err ) ) return err;
    1979         477 :     fd_sol_sysvar_clock_t clock_;
    1980         477 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock_read( ctx->sysvar_cache, &clock_ );
    1981         477 :     if( FD_UNLIKELY( !clock ) ) return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    1982             : 
    1983         477 :     fd_slot_hashes_t slot_hashes_[1];
    1984         477 :     fd_slot_hashes_t const * slot_hashes = fd_sysvar_cache_slot_hashes_view( ctx->sysvar_cache, slot_hashes_ );
    1985         477 :     if( FD_UNLIKELY( !slot_hashes ) ) return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    1986         477 :     rc = process_vote_with_account(
    1987         477 :         ctx,
    1988         477 :         &me,
    1989         477 :         target_version,
    1990         477 :         slot_hashes,
    1991         477 :         clock,
    1992         477 :         vote,
    1993         477 :         signers,
    1994         477 :         signers_cnt
    1995         477 :     );
    1996             : 
    1997         477 :     break;
    1998         477 :   }
    1999             : 
    2000             :   /* UpdateVoteState
    2001             :    *
    2002             :    * Instruction:
    2003             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L100
    2004             :    */
    2005         406 :   case fd_vote_instruction_enum_update_vote_state:;
    2006             :     /* clang-format off */
    2007         406 :     __attribute__((fallthrough));
    2008             :     /* clang-format on */
    2009             : 
    2010             :   /* UpdateVoteStateSwitch
    2011             :    *
    2012             :    * Instruction:
    2013             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L107
    2014             :    *
    2015             :    * Processor:
    2016             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L169
    2017             :    */
    2018         796 :   case fd_vote_instruction_enum_update_vote_state_switch: {
    2019             :     /* https://github.com/anza-xyz/agave/blob/v4.3.0-beta.3/programs/vote/src/vote_processor.rs#L243-L245 */
    2020         796 :     if( should_reject_legacy_vote_instructions( ctx ) ) {
    2021           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    2022           0 :     }
    2023             : 
    2024         796 :     fd_vote_state_update_t * vote_state_update;
    2025         796 :     switch( instruction->discriminant ) {
    2026         406 :     case fd_vote_instruction_enum_update_vote_state:
    2027         406 :       vote_state_update = &instruction->update_vote_state;
    2028         406 :       break;
    2029         390 :     case fd_vote_instruction_enum_update_vote_state_switch:
    2030         390 :       vote_state_update = &instruction->update_vote_state_switch.vote_state_update;
    2031         390 :       break;
    2032           0 :     default:
    2033           0 :       FD_LOG_CRIT(( "unsupported instruction discriminant: %u", instruction->discriminant ));
    2034         796 :     }
    2035             : 
    2036             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L171
    2037         795 :     if( FD_UNLIKELY( !fd_sysvar_cache_slot_hashes_is_valid( ctx->sysvar_cache ) ) ) {
    2038           8 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2039           8 :     }
    2040             : 
    2041             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L172
    2042         787 :     fd_sol_sysvar_clock_t clock_;
    2043         787 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock_read( ctx->sysvar_cache, &clock_ );
    2044         787 :     if( FD_UNLIKELY( !clock ) )
    2045           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2046             : 
    2047             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L173
    2048         787 :     fd_slot_hashes_t slot_hashes_[1];
    2049         787 :     fd_slot_hashes_t const * slot_hashes = fd_sysvar_cache_slot_hashes_view( ctx->sysvar_cache, slot_hashes_ );
    2050         787 :     if( FD_UNLIKELY( !slot_hashes ) ) return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2051         787 :     rc = process_vote_state_update(
    2052         787 :         ctx,
    2053         787 :         &me,
    2054         787 :         target_version,
    2055         787 :         slot_hashes,
    2056         787 :         clock,
    2057         787 :         vote_state_update,
    2058         787 :         signers,
    2059         787 :         signers_cnt
    2060         787 :     );
    2061             : 
    2062         787 :     break;
    2063         787 :   }
    2064             : 
    2065             :   /* CompactUpdateVoteState
    2066             :    *
    2067             :    * Instruction:
    2068             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L139
    2069             :    *
    2070             :    * Notes:
    2071             :    * - Up to three signers: the vote authority, the authorized withdrawer, and the new authority.
    2072             :    * - Feature gated, but live on mainnet.
    2073             :    */
    2074          52 :   case fd_vote_instruction_enum_compact_update_vote_state:;
    2075          52 :     __attribute__((fallthrough));
    2076             : 
    2077             :   /* CompactUpdateVoteStateSwitch
    2078             :    *
    2079             :    * Instruction:
    2080             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L146
    2081             :    *
    2082             :    * Processor:
    2083             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L183
    2084             :    *
    2085             :    * Notes:
    2086             :    * - Up to three signers: the vote authority, the authorized withdrawer, and the new authority.
    2087             :    * - Feature gated, but live on mainnet.
    2088             :    */
    2089         108 :   case fd_vote_instruction_enum_compact_update_vote_state_switch: {
    2090             :     /* https://github.com/anza-xyz/agave/blob/v4.3.0-beta.3/programs/vote/src/vote_processor.rs#L260-L262 */
    2091         108 :     if( should_reject_legacy_vote_instructions( ctx ) ) {
    2092           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    2093           0 :     }
    2094             : 
    2095         108 :     fd_compact_vote_state_update_t * vote_state_update = NULL;
    2096         108 :     if( instruction->discriminant == fd_vote_instruction_enum_compact_update_vote_state ) {
    2097          52 :       vote_state_update = &instruction->compact_update_vote_state;
    2098          56 :     } else if( instruction->discriminant ==
    2099          56 :                fd_vote_instruction_enum_compact_update_vote_state_switch ) {
    2100          56 :       vote_state_update =
    2101          56 :           &instruction->compact_update_vote_state_switch.compact_vote_state_update;
    2102          56 :     }
    2103             : 
    2104         108 :     fd_vote_state_update_t vote_update = {0};
    2105         108 :     if( FD_UNLIKELY( !fd_vote_decode_compact_update( vote_state_update, &vote_update, ctx ) ) )
    2106           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    2107             : 
    2108             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L185
    2109         108 :     if( FD_UNLIKELY( !fd_sysvar_cache_slot_hashes_is_valid( ctx->sysvar_cache ) ) ) {
    2110           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2111           0 :     }
    2112             : 
    2113         108 :     fd_sol_sysvar_clock_t clock_;
    2114         108 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock_read( ctx->sysvar_cache, &clock_ );
    2115         108 :     if( FD_UNLIKELY( !clock ) )
    2116           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2117             : 
    2118             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L187
    2119         108 :     fd_slot_hashes_t slot_hashes_[1];
    2120         108 :     fd_slot_hashes_t const * slot_hashes = fd_sysvar_cache_slot_hashes_view( ctx->sysvar_cache, slot_hashes_ );
    2121         108 :     if( FD_UNLIKELY( !slot_hashes ) ) return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2122         108 :     rc = process_vote_state_update(
    2123         108 :         ctx,
    2124         108 :         &me,
    2125         108 :         target_version,
    2126         108 :         slot_hashes,
    2127         108 :         clock,
    2128         108 :         &vote_update,
    2129         108 :         signers,
    2130         108 :         signers_cnt
    2131         108 :     );
    2132             : 
    2133         108 :     break;
    2134         108 :   }
    2135             : 
    2136             :   /* TowerSync(Switch)
    2137             :    *
    2138             :    * Instruction:
    2139             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L151-L157
    2140             :    *
    2141             :    * Processor:
    2142             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L196-L215
    2143             :    */
    2144             : 
    2145         483 :   case fd_vote_instruction_enum_tower_sync:
    2146         672 :   case fd_vote_instruction_enum_tower_sync_switch: {
    2147             :     /* https://github.com/anza-xyz/agave/blob/v4.3.0-beta.3/programs/vote/src/vote_processor.rs#L277-L279 */
    2148         672 :     if( FD_UNLIKELY( ctx->bank->f.alpenglow_migration_slot!=ULONG_MAX ) ) {
    2149           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    2150           0 :     }
    2151             : 
    2152         672 :     fd_tower_sync_t * tower_sync = (instruction->discriminant == fd_vote_instruction_enum_tower_sync)
    2153         672 :         ? &instruction->tower_sync
    2154         672 :         : &instruction->tower_sync_switch.tower_sync;
    2155             : 
    2156         672 :     if( FD_UNLIKELY( !fd_sysvar_cache_slot_hashes_is_valid( ctx->sysvar_cache ) ) ) {
    2157           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2158           0 :     }
    2159             : 
    2160         672 :     fd_sol_sysvar_clock_t clock_;
    2161         672 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock_read( ctx->sysvar_cache, &clock_ );
    2162         672 :     if( FD_UNLIKELY( !clock ) ) {
    2163           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2164           0 :     }
    2165             : 
    2166         672 :     fd_slot_hashes_t slot_hashes_[1];
    2167         672 :     fd_slot_hashes_t const * slot_hashes = fd_sysvar_cache_slot_hashes_view( ctx->sysvar_cache, slot_hashes_ );
    2168         672 :     if( FD_UNLIKELY( !slot_hashes ) ) return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2169         672 :     rc = process_tower_sync(
    2170         672 :         ctx,
    2171         672 :         &me,
    2172         672 :         target_version,
    2173         672 :         slot_hashes,
    2174         672 :         clock,
    2175         672 :         tower_sync,
    2176         672 :         signers,
    2177         672 :         signers_cnt
    2178         672 :     );
    2179             : 
    2180         672 :     break;
    2181         672 :   }
    2182             : 
    2183             :   /* Withdraw
    2184             :    *
    2185             :    * Instruction:
    2186             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L57
    2187             :    *
    2188             :    * Processor:
    2189             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L216
    2190             :    */
    2191         367 :   case fd_vote_instruction_enum_withdraw: {
    2192         367 :     if( FD_UNLIKELY( ctx->instr->acct_cnt < 2 ) ) {
    2193           1 :       rc = FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
    2194           1 :       break;
    2195           1 :     }
    2196         366 :     fd_rent_t rent_;
    2197         366 :     fd_rent_t const * rent_sysvar = fd_sysvar_cache_rent_read( ctx->sysvar_cache, &rent_ );
    2198         366 :     if( FD_UNLIKELY( !rent_sysvar ) )
    2199           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2200         366 :     fd_sol_sysvar_clock_t clock_;
    2201         366 :     fd_sol_sysvar_clock_t const * clock_sysvar = fd_sysvar_cache_clock_read( ctx->sysvar_cache, &clock_ );
    2202         366 :     if( FD_UNLIKELY( !clock_sysvar ) )
    2203           0 :       return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2204             : 
    2205         366 :     int deinitialized = 0;
    2206         366 :     rc = withdraw(
    2207         366 :         ctx,
    2208         366 :         &me,
    2209         366 :         target_version,
    2210         366 :         instruction->withdraw,
    2211         366 :         1UL,
    2212         366 :         signers,
    2213         366 :         signers_cnt,
    2214         366 :         rent_sysvar,
    2215         366 :         clock_sysvar,
    2216         366 :         &deinitialized
    2217         366 :     );
    2218             : 
    2219         366 :     if( FD_LIKELY( !rc && deinitialized ) ) {
    2220           7 :       ctx->txn_out->accounts.new_vote[ ctx->instr->accounts[0].index_in_transaction ] = 0;
    2221           7 :       ctx->txn_out->accounts.rm_vote[ ctx->instr->accounts[0].index_in_transaction ] = 1;
    2222           7 :     }
    2223             : 
    2224             : 
    2225         366 :     break;
    2226         366 :   }
    2227             : 
    2228             :   /* AuthorizeChecked
    2229             :    *
    2230             :    * Instruction:
    2231             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/instruction.rs#L93
    2232             :    *
    2233             :    * Processor:
    2234             :    * https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L234
    2235             :    *
    2236             :    * Notes:
    2237             :    * - Up to three signers: the vote authority, the authorized withdrawer, and the new authority.
    2238             :    * - Feature gated, but live on mainnet.
    2239             :    */
    2240         294 :   case fd_vote_instruction_enum_authorize_checked: {
    2241         294 :     if( FD_UNLIKELY( ctx->instr->acct_cnt < 4 ) ) {
    2242           5 :       rc = FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
    2243           5 :       break;
    2244           5 :     }
    2245             : 
    2246             :     // https://github.com/anza-xyz/agave/blob/v2.1.14/programs/vote/src/vote_processor.rs#L243-L245
    2247         289 :     fd_pubkey_t const * voter_pubkey = NULL;
    2248         289 :     rc = fd_exec_instr_ctx_get_key_of_account_at_index( ctx, 3UL, &voter_pubkey );
    2249         289 :     if( FD_UNLIKELY( rc ) ) return rc;
    2250             : 
    2251             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L239
    2252         289 :     if( FD_UNLIKELY( !fd_instr_acc_is_signer_idx( ctx->instr, 3, &rc ) ) ) {
    2253             :       /* https://github.com/anza-xyz/agave/blob/v3.0.3/transaction-context/src/lib.rs#L789 */
    2254          57 :       if( FD_UNLIKELY( !!rc ) ) break;
    2255             : 
    2256          57 :       rc = FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE;
    2257          57 :       break;
    2258          57 :     }
    2259             : 
    2260             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_processor.rs#L242
    2261         232 :     rc = fd_sysvar_instr_acct_check( ctx, 1, &fd_sysvar_clock_id );
    2262         232 :     if( FD_UNLIKELY( rc ) ) return rc;
    2263         214 :     fd_sol_sysvar_clock_t clock_;
    2264         214 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock_read( ctx->sysvar_cache, &clock_ );
    2265         214 :     if( FD_UNLIKELY( !clock ) ) return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2266             : 
    2267         214 :     rc = authorize(
    2268         214 :         ctx,
    2269         214 :         &me,
    2270         214 :         target_version,
    2271         214 :         voter_pubkey,
    2272         214 :         &instruction->authorize_checked,
    2273         214 :         signers,
    2274         214 :         signers_cnt,
    2275         214 :         clock,
    2276         214 :         is_vote_authorize_with_bls_enabled
    2277         214 :     );
    2278         214 :     break;
    2279         214 :   }
    2280             : 
    2281             :   /* InitializeAccountV2
    2282             :    *
    2283             :    * Instruction:
    2284             :    * https://github.com/anza-xyz/solana-sdk/blob/vote-interface%40v5.0.0/vote-interface/src/instruction.rs#L195-L200
    2285             :    *
    2286             :    * Processor:
    2287             :    * https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_processor.rs#L307-L324
    2288             :    *
    2289             :    * Notes:
    2290             :    * - The code is identical to InitializeAccount, except calling the actual initialize_account_v2
    2291             :    * - Feature gated.
    2292             :    */
    2293           1 :   case fd_vote_instruction_enum_initialize_account_v2: {
    2294             :     /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_processor.rs#L308-L310 */
    2295           1 :     if( FD_UNLIKELY( !is_init_account_v2_enabled ) ) {
    2296           1 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    2297           1 :     }
    2298             : 
    2299           0 :     rc = fd_sysvar_instr_acct_check( ctx, 1, &fd_sysvar_rent_id );
    2300           0 :     if( FD_UNLIKELY( rc ) ) return rc;
    2301           0 :     fd_rent_t rent_;
    2302           0 :     fd_rent_t const * rent = fd_sysvar_cache_rent_read( ctx->sysvar_cache, &rent_ );
    2303           0 :     if( FD_UNLIKELY( !rent ) ) return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2304             : 
    2305           0 :     if( FD_UNLIKELY( fd_borrowed_account_get_lamports( &me ) <
    2306           0 :                      fd_rent_exempt_minimum_balance( rent, fd_borrowed_account_get_data_len( &me ) ) ) )
    2307           0 :       return FD_EXECUTOR_INSTR_ERR_INSUFFICIENT_FUNDS;
    2308             : 
    2309           0 :     rc = fd_sysvar_instr_acct_check( ctx, 2, &fd_sysvar_clock_id );
    2310           0 :     if( FD_UNLIKELY( rc ) ) return rc;
    2311           0 :     fd_sol_sysvar_clock_t clock_;
    2312           0 :     fd_sol_sysvar_clock_t const * clock = fd_sysvar_cache_clock_read( ctx->sysvar_cache, &clock_ );
    2313           0 :     if( FD_UNLIKELY( !clock ) ) return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2314             : 
    2315           0 :     rc = initialize_account_v2( ctx, &me, target_version, &instruction->initialize_account_v2, signers, signers_cnt, clock );
    2316             : 
    2317           0 :     if( FD_LIKELY( !rc ) ) {
    2318           0 :       ctx->txn_out->accounts.new_vote[ ctx->instr->accounts[0].index_in_transaction ] = 1;
    2319           0 :       ctx->txn_out->accounts.rm_vote[ ctx->instr->accounts[0].index_in_transaction ] = 0;
    2320           0 :     }
    2321             : 
    2322           0 :     break;
    2323           0 :   }
    2324             : 
    2325             :   /* UpdateCommissionBps (commission_rate_in_basis_points feature)
    2326             :    *
    2327             :    * Instruction:
    2328             :    * https://github.com/anza-xyz/solana-sdk/blob/vote-interface%40v5.0.0/vote-interface/src/instruction.rs#L212-L221
    2329             :    *
    2330             :    * Processor:
    2331             :    * https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_processor.rs#L325-L347
    2332             :    *
    2333             :    */
    2334           0 :   case fd_vote_instruction_enum_update_commission_bps: {
    2335           0 :     if( FD_UNLIKELY( !commission_rate_in_basis_points
    2336           0 :                   || !delay_commission_updates ) ) {
    2337           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    2338           0 :     }
    2339             : 
    2340           0 :     rc = update_commission_bps( ctx, &me, target_version, &instruction->update_commission_bps, signers, signers_cnt, block_revenue_sharing );
    2341             : 
    2342           0 :     break;
    2343           0 :   }
    2344             : 
    2345             :   /* UpdateCommissionCollector (SIMD-0232)
    2346             :    *
    2347             :    * Instruction:
    2348             :    * https://github.com/anza-xyz/solana-sdk/blob/vote-interface%40v5.0.0/vote-interface/src/instruction.rs#L202-L210
    2349             :    *
    2350             :    * Processor:
    2351             :    * https://github.com/anza-xyz/agave/blob/v4.2.0-beta.2/programs/vote/src/vote_processor.rs#L383-L408
    2352             :    *
    2353             :    * Notes:
    2354             :    * - Feature gated on custom_commission_collector
    2355             :    */
    2356           0 :   case fd_vote_instruction_enum_update_commission_collector: {
    2357             :     /* https://github.com/anza-xyz/agave/blob/v4.2.0-beta.2/programs/vote/src/vote_processor.rs#L384-L390 */
    2358           0 :     if( FD_UNLIKELY( !custom_commission_collector ) ) {
    2359           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    2360           0 :     }
    2361             : 
    2362             :     /* https://github.com/anza-xyz/agave/blob/v4.2.0-beta.2/programs/vote/src/vote_processor.rs#L392 */
    2363           0 :     if( FD_UNLIKELY( ctx->instr->acct_cnt < 3 ) ) {
    2364           0 :       rc = FD_EXECUTOR_INSTR_ERR_MISSING_ACC;
    2365           0 :       break;
    2366           0 :     }
    2367             : 
    2368             :     /* If instruction account 1 is the vote account itself, no account
    2369             :        is borrowed.
    2370             :        https://github.com/anza-xyz/agave/blob/v4.2.0-beta.2/programs/vote/src/vote_processor.rs#L83-L98 */
    2371           0 :     fd_pubkey_t const * collector_key = NULL;
    2372           0 :     rc = fd_exec_instr_ctx_get_key_of_account_at_index( ctx, 1, &collector_key );
    2373           0 :     if( FD_UNLIKELY( rc ) ) return rc;
    2374             : 
    2375           0 :     fd_guarded_borrowed_account_t collector = {0};
    2376           0 :     fd_borrowed_account_t const * collector_account = NULL;
    2377           0 :     if( !fd_pubkey_eq( collector_key, (fd_pubkey_t const *)me.acc->pubkey ) ) {
    2378           0 :       FD_TRY_BORROW_INSTR_ACCOUNT_DEFAULT_ERR_CHECK( ctx, 1, &collector );
    2379           0 :       collector_account = &collector;
    2380           0 :     }
    2381             : 
    2382             :     /* https://github.com/anza-xyz/agave/blob/v4.2.0-beta.2/programs/vote/src/vote_processor.rs#L395-L398 */
    2383           0 :     fd_rent_t rent_;
    2384           0 :     fd_rent_t const * rent = fd_sysvar_cache_rent_read( ctx->sysvar_cache, &rent_ );
    2385           0 :     if( FD_UNLIKELY( !rent ) ) return FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
    2386             : 
    2387           0 :     rc = update_commission_collector(
    2388           0 :         ctx,
    2389           0 :         &me,
    2390           0 :         target_version,
    2391           0 :         collector_account,
    2392           0 :         &instruction->update_commission_collector,
    2393           0 :         signers,
    2394           0 :         signers_cnt,
    2395           0 :         rent
    2396           0 :     );
    2397             : 
    2398           0 :     break;
    2399           0 :   }
    2400             : 
    2401             :   /* DepositDelegatorRewards (SIMD-0123)
    2402             :    *
    2403             :    * Instruction:
    2404             :    * https://github.com/anza-xyz/solana-sdk/blob/vote-interface%40v5.0.0/vote-interface/src/instruction.rs#L223-L228
    2405             :    *
    2406             :    * Processor:
    2407             :    * https://github.com/anza-xyz/agave/blob/b76028e061ed3bc794d1d802429b3315f02e5a51/programs/vote/src/vote_processor.rs#L391-L393
    2408             :    *
    2409             :    * Notes:
    2410             :    * - Disabled, always fails with InvalidInstructionData
    2411             :    */
    2412           0 :   case fd_vote_instruction_enum_deposit_delegator_rewards: {
    2413           0 :     rc = FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA;
    2414           0 :     break;
    2415           0 :   }
    2416             : 
    2417           0 :   default:
    2418           0 :     FD_LOG_CRIT(( "unsupported vote instruction: %u", instruction->discriminant ));
    2419        4489 :   }
    2420             : 
    2421        4447 :   return rc;
    2422        4489 : }

Generated by: LCOV version 1.14