LCOV - code coverage report
Current view: top level - flamenco/runtime/program/vote - fd_vote_state_v5.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 54 56 96.4 %
Date: 2026-11-12 04:25:03 Functions: 5 5 100.0 %

          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 : }

Generated by: LCOV version 1.14