Line data Source code
1 : #include "fd_vote_utils.h" 2 : #include "fd_vote_codec_tmpl.h" 3 : #include "../fd_vote_program.h" 4 : #include "../fd_program_util.h" 5 : 6 : /**********************************************************************/ 7 : /* Lockout utilities */ 8 : /**********************************************************************/ 9 : 10 : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L104 11 : ulong 12 29957 : fd_vote_lockout_get_lockout( fd_vote_lockout_t * self ) { 13 : /* Confirmation count can never be greater than MAX_LOCKOUT_HISTORY, preventing overflow. 14 : Although Agave does not consider overflow, we do for fuzzing conformance. */ 15 29957 : ulong confirmation_count = fd_ulong_min( self->confirmation_count, MAX_LOCKOUT_HISTORY ); 16 29957 : return 1UL<<confirmation_count; 17 29957 : } 18 : 19 : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L110 20 : ulong 21 29957 : fd_vote_lockout_last_locked_out_slot( fd_vote_lockout_t * self ) { 22 29957 : return fd_ulong_sat_add( self->slot, fd_vote_lockout_get_lockout( self ) ); 23 29957 : } 24 : 25 : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L114 26 : ulong 27 20617 : fd_vote_lockout_is_locked_out_at_slot( fd_vote_lockout_t * self, ulong slot ) { 28 20617 : return fd_vote_lockout_last_locked_out_slot( self ) >= slot; 29 20617 : } 30 : 31 : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L122 32 : void 33 361145 : fd_vote_lockout_increase_confirmation_count( fd_vote_lockout_t * self, uint by ) { 34 361145 : self->confirmation_count = fd_uint_sat_add( self->confirmation_count, by ); 35 361145 : } 36 : 37 : fd_landed_vote_t * 38 : fd_vote_lockout_landed_votes_from_lockouts( fd_vote_lockout_t * lockouts, 39 623 : uchar * mem ) { 40 623 : if( !lockouts ) return NULL; 41 : 42 623 : ulong cnt = deq_fd_vote_lockout_t_cnt( lockouts ); 43 623 : cnt = fd_ulong_max( cnt, MAX_LOCKOUT_HISTORY ); 44 : 45 623 : fd_landed_vote_t * landed_votes = deq_fd_landed_vote_t_join( deq_fd_landed_vote_t_new( mem, cnt ) ); 46 623 : if( FD_UNLIKELY( !landed_votes ) ) { 47 0 : FD_LOG_CRIT(( "failed to join landed votes" )); 48 0 : } 49 : 50 623 : for( deq_fd_vote_lockout_t_iter_t iter = deq_fd_vote_lockout_t_iter_init( lockouts ); 51 10299 : !deq_fd_vote_lockout_t_iter_done( lockouts, iter ); 52 9676 : iter = deq_fd_vote_lockout_t_iter_next( lockouts, iter ) ) { 53 9676 : fd_vote_lockout_t const * ele = deq_fd_vote_lockout_t_iter_ele_const( lockouts, iter ); 54 : 55 9676 : fd_landed_vote_t * elem = deq_fd_landed_vote_t_push_tail_nocopy( landed_votes ); 56 : 57 9676 : elem->latency = 0; 58 9676 : elem->lockout.slot = ele->slot; 59 9676 : elem->lockout.confirmation_count = ele->confirmation_count; 60 9676 : } 61 : 62 623 : return landed_votes; 63 623 : } 64 : 65 : /**********************************************************************/ 66 : /* Vote state utilities */ 67 : /**********************************************************************/ 68 : 69 : int 70 : fd_vote_verify_authorized_signer( fd_pubkey_t const * authorized, 71 : fd_pubkey_t const * signers[static FD_INSTR_SIGNERS_MAX], 72 3361 : ulong signers_cnt ) { 73 : // https://github.com/anza-xyz/agave/blob/v2.0.1/programs/vote/src/vote_state/mod.rs#L989 74 3361 : return fd_signers_contains( signers, signers_cnt, authorized ) ? 75 2227 : FD_EXECUTOR_INSTR_SUCCESS : 76 3361 : FD_EXECUTOR_INSTR_ERR_MISSING_REQUIRED_SIGNATURE; 77 3361 : } 78 : 79 : int 80 : fd_vote_signature_verify( fd_pubkey_t * epoch_authorized_voter, 81 : int authorized_withdrawer_signer, 82 : fd_pubkey_t const * signers[static FD_INSTR_SIGNERS_MAX], 83 216 : ulong signers_cnt ) { 84 216 : return authorized_withdrawer_signer ? 0 : fd_vote_verify_authorized_signer( epoch_authorized_voter, signers, signers_cnt ); 85 216 : } 86 : 87 : uchar 88 : fd_vote_compute_vote_latency( ulong voted_for_slot, 89 16868 : ulong current_slot ) { 90 16868 : return (uchar)fd_ulong_min( fd_ulong_sat_sub( current_slot, voted_for_slot ), UCHAR_MAX ); 91 16868 : } 92 : 93 : ulong 94 : fd_vote_credits_for_vote_at_index( fd_landed_vote_t const * votes, 95 7645 : ulong index ) { 96 : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L679 97 7645 : fd_landed_vote_t const * landed_vote = deq_fd_landed_vote_t_peek_index_const( votes, index ); 98 7645 : ulong latency = landed_vote == NULL ? 0 : landed_vote->latency; 99 : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L683 100 7645 : ulong max_credits = VOTE_CREDITS_MAXIMUM_PER_SLOT; 101 : 102 : /* If latency is 0, this means that the Lockout was created and stored 103 : from a software version that did not store vote latencies; in this 104 : case, 1 credit is awarded. 105 : https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L691 */ 106 7645 : if( FD_UNLIKELY( latency==0UL ) ) { 107 7279 : return 1; 108 7279 : } 109 : 110 366 : ulong diff = 0; 111 366 : int cf = fd_ulong_checked_sub( latency, VOTE_CREDITS_GRACE_SLOTS, &diff ); 112 366 : if( cf || diff==0UL ) { 113 : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L697 114 299 : return max_credits; 115 299 : } 116 : 117 67 : ulong credits = 0; 118 67 : cf = fd_ulong_checked_sub( max_credits, diff, &credits ); 119 67 : if( cf != 0 || credits == 0 ) { 120 : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L705 121 53 : return 1; 122 53 : } 123 : // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/state/mod.rs#L707 124 14 : return credits; 125 67 : } 126 : 127 : int 128 : fd_vote_contains_slot( fd_landed_vote_t const * votes, 129 15763 : ulong slot ) { 130 : /* Logic is copied from slice::binary_search_by() in Rust. While not fully optimized, 131 : it aims to achieve fuzzing conformance for both sorted and unsorted inputs. */ 132 15763 : ulong size = deq_fd_landed_vote_t_cnt( votes ); 133 15763 : if( FD_UNLIKELY( size==0UL ) ) return 0; 134 : 135 15320 : ulong base = 0UL; 136 78262 : while( size>1UL ) { 137 62942 : ulong half = size / 2UL; 138 62942 : ulong mid = base + half; 139 62942 : ulong mid_slot = deq_fd_landed_vote_t_peek_index_const( votes, mid )->lockout.slot; 140 62942 : base = (slot<mid_slot) ? base : mid; 141 62942 : size -= half; 142 62942 : } 143 : 144 15320 : return deq_fd_landed_vote_t_peek_index_const( votes, base )->lockout.slot==slot; 145 15763 : }