Line data Source code
1 : #include "fd_vote_state_v5.h" 2 : #include "fd_vote_utils.h" 3 : #include "../fd_vote_program.h" 4 : #include "../../fd_runtime.h" 5 : 6 : static ulong 7 : authorized_voter_idx( fd_vote_state_v5_t const * self, 8 48 : ulong epoch ) { 9 84 : for( ulong i=0UL; i<self->authorized_voters_len; i++ ) { 10 72 : if( self->authorized_voters[ i ].epoch==epoch ) return i; 11 72 : } 12 12 : return ULONG_MAX; 13 48 : } 14 : 15 : static int 16 : insert_authorized_voter( fd_vote_state_v5_t * self, 17 : ulong epoch, 18 24 : fd_pubkey_t const * pubkey ) { 19 24 : ulong cnt = self->authorized_voters_len; 20 24 : if( FD_UNLIKELY( cnt>=MAX_AUTHORIZED_VOTERS ) ) return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA; 21 : 22 15 : ulong i = cnt; 23 15 : for( ; i && self->authorized_voters[ i-1UL ].epoch>epoch; i-- ) { 24 0 : self->authorized_voters[ i ] = self->authorized_voters[ i-1UL ]; 25 0 : } 26 15 : self->authorized_voters[ i ] = (fd_vote_state_v5_authorized_voter_t){ .epoch=epoch, .pubkey=*pubkey }; 27 15 : self->authorized_voters_len = (uint)( cnt+1UL ); 28 15 : return FD_EXECUTOR_INSTR_SUCCESS; 29 24 : } 30 : 31 : static void 32 : purge_authorized_voters( fd_vote_state_v5_t * self, 33 36 : ulong epoch ) { 34 36 : ulong cnt = self->authorized_voters_len; 35 36 : ulong skip = 0UL; 36 57 : while( skip<cnt && self->authorized_voters[ skip ].epoch<epoch ) skip++; 37 36 : memmove( self->authorized_voters, self->authorized_voters+skip, (cnt-skip)*sizeof(fd_vote_state_v5_authorized_voter_t) ); 38 36 : fd_memset( self->authorized_voters+cnt-skip, 0, skip*sizeof(fd_vote_state_v5_authorized_voter_t) ); 39 36 : self->authorized_voters_len = (uint)( cnt-skip ); 40 36 : } 41 : 42 : int 43 : fd_vote_state_v5_get_and_update_authorized_voter( fd_vote_state_v5_t * self, 44 : ulong current_epoch, 45 39 : fd_pubkey_t ** pubkey ) { 46 39 : ulong idx = ULONG_MAX; 47 126 : for( ulong i=0UL; i<self->authorized_voters_len; i++ ) { 48 87 : if( self->authorized_voters[ i ].epoch<=current_epoch ) idx = i; 49 87 : } 50 39 : if( FD_UNLIKELY( idx==ULONG_MAX ) ) return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA; 51 : 52 36 : fd_pubkey_t voter = self->authorized_voters[ idx ].pubkey; 53 36 : int existed = self->authorized_voters[ idx ].epoch==current_epoch; 54 36 : purge_authorized_voters( self, fd_ulong_sat_sub( current_epoch, 1UL ) ); 55 36 : if( !existed ) { 56 12 : int rc = insert_authorized_voter( self, current_epoch, &voter ); 57 12 : if( FD_UNLIKELY( rc ) ) return rc; 58 12 : } 59 : 60 33 : *pubkey = &self->authorized_voters[ authorized_voter_idx( self, current_epoch ) ].pubkey; 61 33 : return FD_EXECUTOR_INSTR_SUCCESS; 62 36 : } 63 : 64 : int 65 : fd_vote_state_v5_set_new_authorized_voter( fd_exec_instr_ctx_t * ctx, 66 : fd_vote_state_v5_t * self, 67 : fd_pubkey_t const * authorized_pubkey, 68 : ulong current_epoch, 69 : ulong target_epoch, 70 : uchar const * bls_pubkey, 71 : int authorized_withdrawer_signer, 72 : fd_pubkey_t const * signers[ FD_INSTR_SIGNERS_MAX ], 73 15 : ulong signers_cnt ) { 74 15 : fd_pubkey_t * epoch_authorized_voter = NULL; 75 15 : int rc = fd_vote_state_v5_get_and_update_authorized_voter( self, current_epoch, &epoch_authorized_voter ); 76 15 : if( FD_UNLIKELY( rc ) ) return rc; 77 : 78 15 : rc = fd_vote_signature_verify( epoch_authorized_voter, authorized_withdrawer_signer, signers, signers_cnt ); 79 15 : if( FD_UNLIKELY( rc ) ) return rc; 80 : 81 15 : if( FD_UNLIKELY( authorized_voter_idx( self, target_epoch )!=ULONG_MAX ) ) { 82 3 : ctx->txn_out->err.custom_err = FD_VOTE_ERR_TOO_SOON_TO_REAUTHORIZE; 83 3 : return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; 84 3 : } 85 : 86 12 : rc = insert_authorized_voter( self, target_epoch, authorized_pubkey ); 87 12 : if( FD_UNLIKELY( rc ) ) return rc; 88 : 89 6 : if( FD_LIKELY( bls_pubkey ) ) memcpy( self->bls_pubkey_compressed, bls_pubkey, FD_BLS_PUBKEY_COMPRESSED_SZ ); 90 6 : return FD_EXECUTOR_INSTR_SUCCESS; 91 12 : }