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 0 : ulong epoch ) { 9 0 : for( ulong i=0UL; i<self->authorized_voters_len; i++ ) { 10 0 : if( self->authorized_voters[ i ].epoch==epoch ) return i; 11 0 : } 12 0 : return ULONG_MAX; 13 0 : } 14 : 15 : static int 16 : insert_authorized_voter( fd_vote_state_v5_t * self, 17 : ulong epoch, 18 0 : fd_pubkey_t const * pubkey ) { 19 0 : ulong cnt = self->authorized_voters_len; 20 0 : if( FD_UNLIKELY( cnt>=MAX_AUTHORIZED_VOTERS ) ) return FD_EXECUTOR_INSTR_ERR_INVALID_INSTR_DATA; 21 : 22 0 : ulong i = cnt; 23 0 : for( ; i && self->authorized_voters[ i-1UL ].epoch>epoch; i-- ) { 24 0 : self->authorized_voters[ i ] = self->authorized_voters[ i-1UL ]; 25 0 : } 26 0 : self->authorized_voters[ i ] = (fd_vote_state_v5_authorized_voter_t){ .epoch=epoch, .pubkey=*pubkey }; 27 0 : self->authorized_voters_len = (uint)( cnt+1UL ); 28 0 : return FD_EXECUTOR_INSTR_SUCCESS; 29 0 : } 30 : 31 : static void 32 : purge_authorized_voters( fd_vote_state_v5_t * self, 33 0 : ulong epoch ) { 34 0 : ulong cnt = self->authorized_voters_len; 35 0 : ulong skip = 0UL; 36 0 : while( skip<cnt && self->authorized_voters[ skip ].epoch<epoch ) skip++; 37 0 : memmove( self->authorized_voters, self->authorized_voters+skip, (cnt-skip)*sizeof(fd_vote_state_v5_authorized_voter_t) ); 38 0 : fd_memset( self->authorized_voters+cnt-skip, 0, skip*sizeof(fd_vote_state_v5_authorized_voter_t) ); 39 0 : self->authorized_voters_len = (uint)( cnt-skip ); 40 0 : } 41 : 42 : int 43 : fd_vote_state_v5_get_and_update_authorized_voter( fd_vote_state_v5_t * self, 44 : ulong current_epoch, 45 0 : fd_pubkey_t ** pubkey ) { 46 0 : ulong idx = ULONG_MAX; 47 0 : for( ulong i=0UL; i<self->authorized_voters_len; i++ ) { 48 0 : if( self->authorized_voters[ i ].epoch<=current_epoch ) idx = i; 49 0 : } 50 0 : if( FD_UNLIKELY( idx==ULONG_MAX ) ) return FD_EXECUTOR_INSTR_ERR_INVALID_ACC_DATA; 51 : 52 0 : fd_pubkey_t voter = self->authorized_voters[ idx ].pubkey; 53 0 : int existed = self->authorized_voters[ idx ].epoch==current_epoch; 54 0 : purge_authorized_voters( self, fd_ulong_sat_sub( current_epoch, 1UL ) ); 55 0 : if( !existed ) { 56 0 : int rc = insert_authorized_voter( self, current_epoch, &voter ); 57 0 : if( FD_UNLIKELY( rc ) ) return rc; 58 0 : } 59 : 60 0 : *pubkey = &self->authorized_voters[ authorized_voter_idx( self, current_epoch ) ].pubkey; 61 0 : return FD_EXECUTOR_INSTR_SUCCESS; 62 0 : } 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 0 : ulong signers_cnt ) { 74 0 : fd_pubkey_t * epoch_authorized_voter = NULL; 75 0 : int rc = fd_vote_state_v5_get_and_update_authorized_voter( self, current_epoch, &epoch_authorized_voter ); 76 0 : if( FD_UNLIKELY( rc ) ) return rc; 77 : 78 0 : rc = fd_vote_signature_verify( epoch_authorized_voter, authorized_withdrawer_signer, signers, signers_cnt ); 79 0 : if( FD_UNLIKELY( rc ) ) return rc; 80 : 81 0 : if( FD_UNLIKELY( authorized_voter_idx( self, target_epoch )!=ULONG_MAX ) ) { 82 0 : ctx->txn_out->err.custom_err = FD_VOTE_ERR_TOO_SOON_TO_REAUTHORIZE; 83 0 : return FD_EXECUTOR_INSTR_ERR_CUSTOM_ERR; 84 0 : } 85 : 86 0 : rc = insert_authorized_voter( self, target_epoch, authorized_pubkey ); 87 0 : if( FD_UNLIKELY( rc ) ) return rc; 88 : 89 0 : if( FD_LIKELY( bls_pubkey ) ) memcpy( self->bls_pubkey_compressed, bls_pubkey, FD_BLS_PUBKEY_COMPRESSED_SZ ); 90 0 : return FD_EXECUTOR_INSTR_SUCCESS; 91 0 : }