LCOV - code coverage report
Current view: top level - flamenco/runtime/program/vote - fd_vote_state_v3.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 87 0.0 %
Date: 2026-11-11 12:40:43 Functions: 0 4 0.0 %

          Line data    Source code
       1             : #include "fd_vote_state_v3.h"
       2             : #include "fd_vote_codec_tmpl.h"
       3             : #include "fd_authorized_voters.h"
       4             : #include "fd_vote_utils.h"
       5             : #include "fd_vote_state_versioned.h"
       6             : #include "../fd_vote_program.h"
       7             : #include "../../fd_runtime.h"
       8             : 
       9             : /* to_vote_state_1_14_11 converts a "v3" vote state object into the
      10             :    older "v1.14.11" version.  This destroys the "v3" object in the
      11             :    process.
      12             :    https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/vote_state_1_14_11.rs#L67 */
      13             : static void
      14             : to_vote_state_1_14_11( fd_vote_state_v3_t *      vote_state,
      15           0 :                        fd_vote_state_1_14_11_t * vote_state_1_14_11 /* out */ ) {
      16           0 :   vote_state_1_14_11->node_pubkey           = vote_state->node_pubkey;
      17           0 :   vote_state_1_14_11->authorized_withdrawer = vote_state->authorized_withdrawer;
      18           0 :   vote_state_1_14_11->commission            = vote_state->commission;
      19           0 :   vote_state_1_14_11->votes                 = vote_state->votes;
      20           0 :   vote_state_1_14_11->has_root_slot         = vote_state->has_root_slot;
      21           0 :   vote_state_1_14_11->root_slot             = vote_state->root_slot;
      22           0 :   vote_state_1_14_11->authorized_voters     = vote_state->authorized_voters;
      23           0 :   vote_state_1_14_11->prior_voters          = vote_state->prior_voters;
      24           0 :   vote_state_1_14_11->epoch_credits         = vote_state->epoch_credits;
      25           0 :   vote_state_1_14_11->last_timestamp        = vote_state->last_timestamp;
      26           0 : }
      27             : 
      28             : int
      29             : fd_vote_state_v3_set_vote_account_state( fd_exec_instr_ctx_t const * ctx,
      30             :                                          fd_borrowed_account_t *     vote_account,
      31           0 :                                          fd_vote_state_versioned_t * versioned ) {
      32             :   /* This is a horrible conditional expression in Agave.
      33             :      The terms were broken up into their own variables. */
      34           0 :   fd_vote_state_v3_t * v3_vote_state = &versioned->v3;
      35             : 
      36             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L420-L424 */
      37           0 :   fd_rent_t const * rent               = &ctx->bank->f.rent;
      38           0 :   int               resize_needed      = fd_borrowed_account_get_data_len( vote_account ) < FD_VOTE_STATE_V3_SZ;
      39           0 :   int               resize_rent_exempt = fd_rent_exempt_minimum_balance( rent, FD_VOTE_STATE_V3_SZ ) <= fd_borrowed_account_get_lamports( vote_account );
      40             : 
      41             :   /* The resize operation itself is part of the horrible conditional,
      42             :      but behind a short-circuit operator. */
      43           0 :   int resize_failed = 0;
      44           0 :   if( resize_needed && resize_rent_exempt ) {
      45             :     /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L422-L424 */
      46           0 :     resize_failed =
      47           0 :       fd_borrowed_account_set_data_length( vote_account, FD_VOTE_STATE_V3_SZ ) != FD_EXECUTOR_INSTR_SUCCESS;
      48           0 :   }
      49             : 
      50           0 :   if( FD_UNLIKELY( resize_needed && ( !resize_rent_exempt || resize_failed ) ) ) {
      51             :     /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L426-L430 */
      52           0 :     fd_vote_state_versioned_t vsv[1];
      53           0 :     fd_vote_state_versioned_new( vsv, fd_vote_state_versioned_enum_v1_14_11 );
      54           0 :     to_vote_state_1_14_11( v3_vote_state, &vsv->v1_14_11 );
      55           0 :     return fd_vsv_set_state( vote_account, vsv );
      56           0 :   }
      57             : 
      58             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L432-L433 */
      59           0 :   return fd_vsv_set_state( vote_account, versioned );
      60           0 : }
      61             : 
      62             : int
      63             : fd_vote_state_v3_get_and_update_authorized_voter( fd_vote_state_v3_t * self,
      64             :                                                   ulong                current_epoch,
      65           0 :                                                   fd_pubkey_t **       pubkey /* out */ ) {
      66             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L832
      67           0 :   fd_vote_authorized_voter_t * authorized_voter = fd_authorized_voters_get_and_cache_authorized_voter_for_epoch(
      68           0 :       &self->authorized_voters,
      69           0 :       current_epoch
      70           0 :   );
      71             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L835
      72           0 :   if( FD_UNLIKELY( !authorized_voter ) ) return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
      73           0 :   *pubkey = &authorized_voter->pubkey;
      74             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L837
      75           0 :   fd_authorized_voters_purge_authorized_voters( &self->authorized_voters, current_epoch );
      76           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
      77           0 : }
      78             : 
      79             : int
      80             : fd_vote_state_v3_set_new_authorized_voter( fd_exec_instr_ctx_t * ctx,
      81             :                                            fd_vote_state_v3_t *  self,
      82             :                                            fd_pubkey_t const *   authorized_pubkey,
      83             :                                            ulong                 current_epoch,
      84             :                                            ulong                 target_epoch,
      85             :                                            uchar const *         bls_pubkey,
      86             :                                            int                   authorized_withdrawer_signer,
      87             :                                            fd_pubkey_t const *   signers[ FD_INSTR_SIGNERS_MAX ],
      88           0 :                                            ulong                 signers_cnt ) {
      89           0 :   int           rc;
      90           0 :   fd_pubkey_t * epoch_authorized_voter = NULL;
      91             : 
      92             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/handler.rs#L287-L292 */
      93           0 :   if( FD_UNLIKELY( bls_pubkey!=NULL ) ) {
      94           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
      95           0 :   }
      96             : 
      97             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L778
      98           0 :   rc = fd_vote_state_v3_get_and_update_authorized_voter( self, current_epoch, &epoch_authorized_voter );
      99           0 :   if( FD_UNLIKELY( rc ) ) return rc;
     100             : 
     101             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L779
     102           0 :   rc = fd_vote_signature_verify( epoch_authorized_voter, authorized_withdrawer_signer, signers, signers_cnt );
     103           0 :   if( FD_UNLIKELY( rc ) ) return rc;
     104             : 
     105             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L786
     106           0 :   if( FD_UNLIKELY( fd_authorized_voters_contains( &self->authorized_voters, target_epoch ) ) ) {
     107           0 :     ctx->txn_out->err.custom_err = FD_VOTE_ERR_TOO_SOON_TO_REAUTHORIZE;
     108           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     109           0 :   }
     110             : 
     111             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L791
     112           0 :   fd_vote_authorized_voter_t * latest_authorized =
     113           0 :       fd_authorized_voters_last( &self->authorized_voters );
     114             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L794
     115           0 :   if( FD_UNLIKELY( ( !latest_authorized ) ) ) return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
     116           0 :   ulong         latest_epoch             = latest_authorized->epoch;
     117           0 :   fd_pubkey_t * latest_authorized_pubkey = &latest_authorized->pubkey;
     118             : 
     119             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L799
     120           0 :   if( !fd_pubkey_eq( latest_authorized_pubkey, authorized_pubkey ) ) {
     121           0 :     fd_vote_prior_voters_t * prior_voters = &self->prior_voters;
     122             : 
     123             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L801
     124           0 :     ulong epoch_of_last_authorized_switch = 0UL;
     125           0 :     if( (!prior_voters->is_empty) & (prior_voters->idx < 32) ) {
     126           0 :       epoch_of_last_authorized_switch = prior_voters->buf[prior_voters->idx].epoch_end;
     127           0 :     }
     128             : 
     129             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L810
     130           0 :     if( target_epoch <= latest_epoch )
     131           0 :       return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
     132             : 
     133             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L815
     134           0 :     prior_voters->idx += 1UL;
     135           0 :     prior_voters->idx %= 32UL;
     136           0 :     prior_voters->buf[prior_voters->idx] =
     137           0 :         ( fd_vote_prior_voter_t ){ .pubkey      = *latest_authorized_pubkey,
     138           0 :                                    .epoch_start = epoch_of_last_authorized_switch,
     139           0 :                                    .epoch_end   = target_epoch };
     140           0 :     prior_voters->is_empty = 0;
     141           0 :   }
     142             : 
     143             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L822
     144           0 :   if( FD_UNLIKELY( !fd_vote_authorized_voters_pool_free( self->authorized_voters.pool ) ) ) {
     145           0 :     FD_LOG_CRIT(( "invariant violation: max authorized voter count of vote account exceeded" ));
     146           0 :   }
     147             : 
     148           0 :   fd_vote_authorized_voter_t * ele =
     149           0 :       fd_vote_authorized_voters_pool_ele_acquire( self->authorized_voters.pool );
     150           0 :   ele->epoch  = target_epoch;
     151           0 :   ele->pubkey = *authorized_pubkey;
     152           0 :   ele->prio   = ele->pubkey.uc[0];
     153           0 :   fd_vote_authorized_voters_treap_ele_insert(
     154           0 :       self->authorized_voters.treap, ele, self->authorized_voters.pool );
     155             : 
     156           0 :   return 0;
     157           0 : }
     158             : 

Generated by: LCOV version 1.14