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 : void 9 : fd_vote_state_v4_create_new( fd_pubkey_t const * vote_pubkey, 10 : fd_vote_init_t const * vote_init, 11 : fd_sol_sysvar_clock_t const * clock, 12 : uchar * authorized_voters_mem, 13 0 : fd_vote_state_versioned_t * versioned /* out */ ) { 14 0 : versioned->discriminant = fd_vote_state_versioned_enum_v4; 15 : 16 0 : fd_vote_state_v4_t * vote_state = &versioned->inner.v4; 17 0 : vote_state->node_pubkey = vote_init->node_pubkey; 18 0 : vote_state->authorized_voters = *fd_authorized_voters_new(clock->epoch, &vote_init->authorized_voter, authorized_voters_mem); 19 0 : vote_state->authorized_withdrawer = vote_init->authorized_withdrawer; 20 0 : vote_state->inflation_rewards_commission_bps = (ushort)( vote_init->commission * 100 ); 21 0 : vote_state->inflation_rewards_collector = *vote_pubkey; 22 0 : vote_state->block_revenue_collector = vote_init->node_pubkey; 23 0 : vote_state->block_revenue_commission_bps = DEFAULT_BLOCK_REVENUE_COMMISSION_BPS; 24 0 : } 25 : 26 : int 27 : fd_vote_state_v4_set_vote_account_state( fd_exec_instr_ctx_t const * ctx, 28 : fd_borrowed_account_t * vote_account, 29 0 : fd_vote_state_versioned_t * versioned ) { 30 : /* This is a horrible conditional expression in Agave. 31 : The terms were broken up into their own variables. */ 32 : 33 : /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L582-L586 */ 34 0 : fd_rent_t const rent = fd_sysvar_cache_rent_read_nofail( ctx->sysvar_cache ); 35 0 : int resize_needed = fd_borrowed_account_get_data_len( vote_account ) < FD_VOTE_STATE_V4_SZ; 36 0 : int resize_rent_exempt = fd_rent_exempt_minimum_balance( &rent, FD_VOTE_STATE_V4_SZ ) <= fd_borrowed_account_get_lamports( vote_account ); 37 : 38 : /* The resize operation itself is part of the horrible conditional, 39 : but behind a short-circuit operator. */ 40 0 : int resize_failed = 0; 41 0 : if( resize_needed && resize_rent_exempt ) { 42 : /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L584-L586 */ 43 0 : resize_failed = 44 0 : fd_borrowed_account_set_data_length( vote_account, FD_VOTE_STATE_V4_SZ ) != FD_EXECUTOR_INSTR_SUCCESS; 45 0 : } 46 : 47 0 : if( FD_UNLIKELY( resize_needed && ( !resize_rent_exempt || resize_failed ) ) ) { 48 : /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L590 */ 49 0 : return FD_EXECUTOR_INSTR_ERR_ACC_NOT_RENT_EXEMPT; 50 0 : } 51 : 52 : /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L593 */ 53 0 : return fd_vsv_set_state( vote_account, versioned ); 54 0 : } 55 : 56 : int 57 : fd_vote_state_v4_get_and_update_authorized_voter( fd_vote_state_v4_t * self, 58 : ulong current_epoch, 59 0 : fd_pubkey_t ** pubkey /* out */ ) { 60 : /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L327-L330 */ 61 0 : fd_vote_authorized_voter_t * authorized_voter = 62 0 : fd_authorized_voters_get_and_cache_authorized_voter_for_epoch( &self->authorized_voters, 63 0 : current_epoch ); 64 0 : if( FD_UNLIKELY( !authorized_voter ) ) return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA; 65 0 : *pubkey = &authorized_voter->pubkey; 66 : 67 : /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L331-L332 */ 68 0 : fd_authorized_voters_purge_authorized_voters( &self->authorized_voters, fd_ulong_sat_sub( current_epoch, 1UL ) ); 69 0 : return FD_EXECUTOR_INSTR_SUCCESS; 70 0 : } 71 : 72 : int 73 : fd_vote_state_v4_set_new_authorized_voter( fd_exec_instr_ctx_t * ctx, 74 : fd_vote_state_v4_t * self, 75 : fd_pubkey_t const * authorized_pubkey, 76 : ulong current_epoch, 77 : ulong target_epoch, 78 : int authorized_withdrawer_signer, 79 0 : fd_pubkey_t const * signers[static FD_TXN_SIG_MAX] ) { 80 0 : int rc; 81 0 : fd_pubkey_t * epoch_authorized_voter = NULL; 82 : 83 : /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L462 */ 84 0 : rc = fd_vote_state_v4_get_and_update_authorized_voter( self, current_epoch, &epoch_authorized_voter ); 85 0 : if( FD_UNLIKELY( rc ) ) return rc; 86 : 87 : /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L463 */ 88 0 : rc = fd_vote_signature_verify( epoch_authorized_voter, authorized_withdrawer_signer, signers ); 89 0 : if( FD_UNLIKELY( rc ) ) return rc; 90 : 91 : /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L470-L472 */ 92 0 : if( FD_UNLIKELY( fd_authorized_voters_contains( &self->authorized_voters, target_epoch ) ) ) { 93 0 : ctx->txn_out->err.custom_err = FD_VOTE_ERR_TOO_SOON_TO_REAUTHORIZE; 94 0 : return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; 95 0 : } 96 : 97 : /* https://github.com/anza-xyz/agave/blob/v3.1.1/programs/vote/src/vote_state/handler.rs#L474-L475 */ 98 0 : if( FD_UNLIKELY( !fd_vote_authorized_voters_pool_free( self->authorized_voters.pool ) ) ) { 99 0 : FD_LOG_CRIT(( "invariant violation: max authorized voter count of vote account exceeded" )); 100 0 : } 101 : 102 0 : fd_vote_authorized_voter_t * ele = 103 0 : fd_vote_authorized_voters_pool_ele_acquire( self->authorized_voters.pool ); 104 0 : ele->epoch = target_epoch; 105 0 : ele->pubkey = *authorized_pubkey; 106 0 : ele->prio = (ulong)&ele->pubkey; 107 0 : fd_vote_authorized_voters_treap_ele_insert( 108 0 : self->authorized_voters.treap, ele, self->authorized_voters.pool ); 109 : 110 0 : return 0; 111 0 : }