LCOV - code coverage report
Current view: top level - flamenco/runtime/program/vote - fd_vote_state_v4.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 21 75 28.0 %
Date: 2026-03-19 18:19:27 Functions: 2 5 40.0 %

          Line data    Source code
       1             : #include "fd_vote_state_v4.h"
       2             : #include "fd_authorized_voters.h"
       3             : #include "fd_vote_state_versioned.h"
       4             : #include "fd_vote_common.h"
       5             : #include "../fd_vote_program.h"
       6             : #include "../../fd_runtime.h"
       7             : 
       8             : /* https://github.com/anza-xyz/solana-sdk/blob/vote-interface%40v5.0.0/vote-interface/src/state/vote_state_v4.rs#L80 */
       9             : void
      10             : fd_vote_state_v4_create_new_with_defaults( fd_pubkey_t const *           vote_pubkey,
      11             :                                            fd_vote_init_t const *        vote_init,
      12             :                                            fd_sol_sysvar_clock_t const * clock,
      13             :                                            uchar *                       authorized_voters_mem,
      14           0 :                                            fd_vote_state_versioned_t *   versioned /* out */ ) {
      15           0 :   versioned->discriminant = fd_vote_state_versioned_enum_v4;
      16             : 
      17           0 :   fd_vote_state_v4_t * vote_state              = &versioned->inner.v4;
      18           0 :   vote_state->node_pubkey                      = vote_init->node_pubkey;
      19           0 :   vote_state->authorized_voters                = *fd_authorized_voters_new(clock->epoch, &vote_init->authorized_voter, authorized_voters_mem);
      20           0 :   vote_state->authorized_withdrawer            = vote_init->authorized_withdrawer;
      21           0 :   vote_state->inflation_rewards_commission_bps = (ushort)( vote_init->commission * 100 );
      22           0 :   vote_state->inflation_rewards_collector      = *vote_pubkey;
      23           0 :   vote_state->block_revenue_collector          = vote_init->node_pubkey;
      24           0 :   vote_state->block_revenue_commission_bps     = DEFAULT_BLOCK_REVENUE_COMMISSION_BPS;
      25           0 :   vote_state->has_bls_pubkey_compressed        = 0;
      26           0 : }
      27             : 
      28             : /* https://github.com/anza-xyz/solana-sdk/blob/vote-interface%40v5.0.0/vote-interface/src/state/vote_state_v4.rs#L95 */
      29             : void
      30             : fd_vote_state_v4_create_new( fd_vote_init_v2_t const *     vote_init_v2,
      31             :                              fd_sol_sysvar_clock_t const * clock,
      32             :                              uchar *                       authorized_voters_mem,
      33           0 :                              fd_vote_state_versioned_t *   versioned /* out */ ) {
      34           0 :   versioned->discriminant = fd_vote_state_versioned_enum_v4;
      35             : 
      36           0 :   fd_vote_state_v4_t * vote_state              = &versioned->inner.v4;
      37           0 :   vote_state->node_pubkey                      = vote_init_v2->node_pubkey;
      38           0 :   vote_state->authorized_voters                = *fd_authorized_voters_new(clock->epoch, &vote_init_v2->authorized_voter, authorized_voters_mem);
      39             : 
      40             :   /* Important: BLS pubkey proof of possesion MUST be validated first */
      41           0 :   vote_state->has_bls_pubkey_compressed        = 1;
      42           0 :   vote_state->bls_pubkey_compressed = vote_init_v2->authorized_voter_bls_pubkey;
      43             : 
      44           0 :   vote_state->authorized_withdrawer            = vote_init_v2->authorized_withdrawer;
      45           0 :   vote_state->inflation_rewards_commission_bps = vote_init_v2->inflation_rewards_commission_bps;
      46           0 :   vote_state->inflation_rewards_collector      = vote_init_v2->inflation_rewards_collector;
      47           0 :   vote_state->block_revenue_commission_bps     = vote_init_v2->block_revenue_commission_bps;
      48           0 :   vote_state->block_revenue_collector          = vote_init_v2->block_revenue_collector;
      49           0 : }
      50             : 
      51             : int
      52             : fd_vote_state_v4_set_vote_account_state( fd_exec_instr_ctx_t const * ctx,
      53             :                                          fd_borrowed_account_t *     vote_account,
      54         300 :                                          fd_vote_state_versioned_t * versioned ) {
      55             :   /* This is a horrible conditional expression in Agave.
      56             :      The terms were broken up into their own variables. */
      57             : 
      58             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L582-L586 */
      59         300 :   fd_rent_t const * rent               = fd_bank_rent_query( ctx->bank );
      60         300 :   int               resize_needed      = fd_borrowed_account_get_data_len( vote_account ) < FD_VOTE_STATE_V4_SZ;
      61         300 :   int               resize_rent_exempt = fd_rent_exempt_minimum_balance( rent, FD_VOTE_STATE_V4_SZ ) <= fd_borrowed_account_get_lamports( vote_account );
      62             : 
      63             :   /* The resize operation itself is part of the horrible conditional,
      64             :      but behind a short-circuit operator. */
      65         300 :   int resize_failed = 0;
      66         300 :   if( resize_needed && resize_rent_exempt ) {
      67             :     /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L584-L586 */
      68           1 :     resize_failed =
      69           1 :       fd_borrowed_account_set_data_length( vote_account, FD_VOTE_STATE_V4_SZ ) != FD_EXECUTOR_INSTR_SUCCESS;
      70           1 :   }
      71             : 
      72         300 :   if( FD_UNLIKELY( resize_needed && ( !resize_rent_exempt || resize_failed ) ) ) {
      73             :     /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L590 */
      74           0 :     return FD_EXECUTOR_INSTR_ERR_ACC_NOT_RENT_EXEMPT;
      75           0 :   }
      76             : 
      77             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L593 */
      78         300 :   return fd_vsv_set_state( vote_account, versioned );
      79         300 : }
      80             : 
      81             : int
      82             : fd_vote_state_v4_get_and_update_authorized_voter( fd_vote_state_v4_t * self,
      83             :                                                   ulong                current_epoch,
      84         299 :                                                   fd_pubkey_t **       pubkey /* out */ ) {
      85             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L327-L330 */
      86         299 :   fd_vote_authorized_voter_t * authorized_voter =
      87         299 :       fd_authorized_voters_get_and_cache_authorized_voter_for_epoch( &self->authorized_voters,
      88         299 :                                                                   current_epoch );
      89         299 :   if( FD_UNLIKELY( !authorized_voter ) ) return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA;
      90         299 :   *pubkey = &authorized_voter->pubkey;
      91             : 
      92             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L331-L332 */
      93         299 :   fd_authorized_voters_purge_authorized_voters( &self->authorized_voters, fd_ulong_sat_sub( current_epoch, 1UL ) );
      94         299 :   return FD_EXECUTOR_INSTR_SUCCESS;
      95         299 : }
      96             : 
      97             : int
      98             : fd_vote_state_v4_set_new_authorized_voter( fd_exec_instr_ctx_t *              ctx,
      99             :                                            fd_vote_state_v4_t *               self,
     100             :                                            fd_pubkey_t const *                authorized_pubkey,
     101             :                                            ulong                              current_epoch,
     102             :                                            ulong                              target_epoch,
     103             :                                            fd_bls_pubkey_compressed_t const * bls_pubkey,
     104             :                                            int                                authorized_withdrawer_signer,
     105             :                                            fd_pubkey_t const *                signers[ FD_TXN_SIG_MAX ],
     106           0 :                                            ulong                              signers_cnt ) {
     107           0 :   int           rc;
     108           0 :   fd_pubkey_t * epoch_authorized_voter = NULL;
     109             : 
     110             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L462 */
     111           0 :   rc = fd_vote_state_v4_get_and_update_authorized_voter( self, current_epoch, &epoch_authorized_voter );
     112           0 :   if( FD_UNLIKELY( rc ) ) return rc;
     113             : 
     114             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L463 */
     115           0 :   rc = fd_vote_signature_verify( epoch_authorized_voter, authorized_withdrawer_signer, signers, signers_cnt );
     116           0 :   if( FD_UNLIKELY( rc ) ) return rc;
     117             : 
     118             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L470-L472 */
     119           0 :   if( FD_UNLIKELY( fd_authorized_voters_contains( &self->authorized_voters, target_epoch ) ) ) {
     120           0 :     ctx->txn_out->err.custom_err = FD_VOTE_ERR_TOO_SOON_TO_REAUTHORIZE;
     121           0 :     return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR;
     122           0 :   }
     123             : 
     124             :   /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L474-L475 */
     125           0 :   if( FD_UNLIKELY( !fd_vote_authorized_voters_pool_free( self->authorized_voters.pool ) ) ) {
     126           0 :     FD_LOG_CRIT(( "invariant violation: max authorized voter count of vote account exceeded" ));
     127           0 :   }
     128             : 
     129           0 :   fd_vote_authorized_voter_t * ele =
     130           0 :       fd_vote_authorized_voters_pool_ele_acquire( self->authorized_voters.pool );
     131           0 :   ele->epoch  = target_epoch;
     132           0 :   ele->pubkey = *authorized_pubkey;
     133           0 :   ele->prio   = (ulong)&ele->pubkey;
     134           0 :   fd_vote_authorized_voters_treap_ele_insert(
     135           0 :       self->authorized_voters.treap, ele, self->authorized_voters.pool );
     136             : 
     137             :   /* https://github.com/anza-xyz/agave/blob/v4.0.0-alpha.0/programs/vote/src/vote_state/handler.rs#L528-L530 */
     138           0 :   if( FD_LIKELY( bls_pubkey!=NULL ) ) {
     139           0 :     self->has_bls_pubkey_compressed = 1;
     140           0 :     self->bls_pubkey_compressed = *bls_pubkey;
     141           0 :   }
     142             : 
     143           0 :   return 0;
     144           0 : }

Generated by: LCOV version 1.14