LCOV - code coverage report
Current view: top level - flamenco/runtime/program/vote - fd_authorized_voters.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 108 0.0 %
Date: 2026-01-27 05:09:45 Functions: 0 9 0.0 %

          Line data    Source code
       1             : #include "fd_authorized_voters.h"
       2             : #include "fd_vote_state_v3.h"
       3             : #include "fd_vote_state_v4.h"
       4             : 
       5             : fd_vote_authorized_voters_t *
       6             : fd_authorized_voters_new( ulong               epoch,
       7             :                           fd_pubkey_t const * pubkey,
       8           0 :                           uchar *             mem ) {
       9             : 
      10           0 :   FD_SCRATCH_ALLOC_INIT( l, mem );
      11           0 :   fd_vote_authorized_voters_t * authorized_voters = FD_SCRATCH_ALLOC_APPEND( l, fd_vote_authorized_voters_align(),       sizeof(fd_vote_authorized_voters_t) );
      12           0 :   void *                        pool_mem          = FD_SCRATCH_ALLOC_APPEND( l, fd_vote_authorized_voters_pool_align(),  fd_vote_authorized_voters_pool_footprint( FD_VOTE_AUTHORIZED_VOTERS_MIN ) );
      13           0 :   void *                        treap_mem         = FD_SCRATCH_ALLOC_APPEND( l, fd_vote_authorized_voters_treap_align(), fd_vote_authorized_voters_treap_footprint( FD_VOTE_AUTHORIZED_VOTERS_MIN ) );
      14             : 
      15           0 :   authorized_voters->pool  = fd_vote_authorized_voters_pool_join( fd_vote_authorized_voters_pool_new( pool_mem, FD_VOTE_AUTHORIZED_VOTERS_MIN ) );
      16           0 :   authorized_voters->treap = fd_vote_authorized_voters_treap_join( fd_vote_authorized_voters_treap_new( treap_mem, FD_VOTE_AUTHORIZED_VOTERS_MIN ) );
      17           0 :   if( FD_UNLIKELY( !fd_vote_authorized_voters_pool_free( authorized_voters->pool ) ) ) {
      18           0 :     FD_LOG_CRIT(( "invariant violation: max authorized voter count of vote account exceeded" ));
      19           0 :   }
      20           0 :   fd_vote_authorized_voter_t * ele = fd_vote_authorized_voters_pool_ele_acquire( authorized_voters->pool );
      21           0 :   ele->epoch  = epoch;
      22           0 :   ele->pubkey = *pubkey;
      23           0 :   ele->prio   = (ulong)&ele->pubkey;
      24           0 :   fd_vote_authorized_voters_treap_ele_insert( authorized_voters->treap, ele, authorized_voters->pool );
      25           0 :   return authorized_voters;
      26           0 : }
      27             : 
      28             : fd_vote_authorized_voters_t *
      29           0 : fd_authorized_voters_new_empty( uchar * mem ) {
      30           0 :   FD_SCRATCH_ALLOC_INIT( l, mem );
      31           0 :   fd_vote_authorized_voters_t * authorized_voters = FD_SCRATCH_ALLOC_APPEND( l, fd_vote_authorized_voters_align(),       sizeof(fd_vote_authorized_voters_t) );
      32           0 :   void *                        pool_mem          = FD_SCRATCH_ALLOC_APPEND( l, fd_vote_authorized_voters_pool_align(),  fd_vote_authorized_voters_pool_footprint( FD_VOTE_AUTHORIZED_VOTERS_MIN ) );
      33           0 :   void *                        treap_mem         = FD_SCRATCH_ALLOC_APPEND( l, fd_vote_authorized_voters_treap_align(), fd_vote_authorized_voters_treap_footprint( FD_VOTE_AUTHORIZED_VOTERS_MIN ) );
      34             : 
      35           0 :   authorized_voters->pool  = fd_vote_authorized_voters_pool_join( fd_vote_authorized_voters_pool_new( pool_mem, FD_VOTE_AUTHORIZED_VOTERS_MIN ) );
      36           0 :   authorized_voters->treap = fd_vote_authorized_voters_treap_join( fd_vote_authorized_voters_treap_new( treap_mem, FD_VOTE_AUTHORIZED_VOTERS_MIN ) );
      37           0 :   return authorized_voters;
      38           0 : }
      39             : 
      40             : int
      41           0 : fd_authorized_voters_is_empty( fd_vote_authorized_voters_t * self ) {
      42           0 :   return fd_vote_authorized_voters_treap_ele_cnt( self->treap ) == 0;
      43           0 : }
      44             : 
      45             : int
      46           0 : fd_authorized_voters_contains( fd_vote_authorized_voters_t * self, ulong epoch ) {
      47           0 :   return !!fd_vote_authorized_voters_treap_ele_query( self->treap, epoch, self->pool );
      48           0 : }
      49             : 
      50             : fd_vote_authorized_voter_t *
      51           0 : fd_authorized_voters_last( fd_vote_authorized_voters_t * self ) {
      52           0 :   fd_vote_authorized_voters_treap_rev_iter_t iter =
      53           0 :       fd_vote_authorized_voters_treap_rev_iter_init( self->treap, self->pool );
      54           0 :   return fd_vote_authorized_voters_treap_rev_iter_ele( iter, self->pool );
      55           0 : }
      56             : 
      57             : void
      58             : fd_authorized_voters_purge_authorized_voters( fd_vote_authorized_voters_t * self,
      59           0 :                                               ulong                         current_epoch ) {
      60             : 
      61             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L46
      62           0 :   ulong expired_keys[ FD_VOTE_AUTHORIZED_VOTERS_MIN ];
      63           0 :   ulong key_cnt                                     = 0;
      64           0 :   for( fd_vote_authorized_voters_treap_fwd_iter_t iter =
      65           0 :            fd_vote_authorized_voters_treap_fwd_iter_init( self->treap, self->pool );
      66           0 :        !fd_vote_authorized_voters_treap_fwd_iter_done( iter );
      67           0 :        iter = fd_vote_authorized_voters_treap_fwd_iter_next( iter, self->pool ) ) {
      68           0 :     fd_vote_authorized_voter_t * ele =
      69           0 :         fd_vote_authorized_voters_treap_fwd_iter_ele( iter, self->pool );
      70           0 :     if( ele->epoch < current_epoch ) expired_keys[key_cnt++] = ele->epoch;
      71           0 :   }
      72             : 
      73             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L52
      74           0 :   for( ulong i = 0; i < key_cnt; i++ ) {
      75           0 :     fd_vote_authorized_voter_t * ele =
      76           0 :         fd_vote_authorized_voters_treap_ele_query( self->treap, expired_keys[i], self->pool );
      77           0 :     fd_vote_authorized_voters_treap_ele_remove( self->treap, ele, self->pool );
      78           0 :     fd_vote_authorized_voters_pool_ele_release( self->pool, ele );
      79           0 :   }
      80             : 
      81             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L60
      82           0 :   FD_TEST( !fd_authorized_voters_is_empty( self ) );
      83             : 
      84           0 : }
      85             : 
      86             : fd_vote_authorized_voter_t *
      87             : fd_authorized_voters_get_or_calculate_authorized_voter_for_epoch( fd_vote_authorized_voters_t * self,
      88             :                                                                   ulong                         epoch,
      89           0 :                                                                   int *                         existed ) {
      90           0 :   *existed                                  = 0;
      91           0 :   ulong                        latest_epoch = 0;
      92           0 :   fd_vote_authorized_voter_t * res =
      93           0 :       fd_vote_authorized_voters_treap_ele_query( self->treap, epoch, self->pool );
      94             :   // "predecessor" would be more big-O optimal here, but mirroring labs logic
      95             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L93
      96           0 :   if( FD_UNLIKELY( !res ) ) {
      97           0 :     for( fd_vote_authorized_voters_treap_fwd_iter_t iter =
      98           0 :              fd_vote_authorized_voters_treap_fwd_iter_init( self->treap, self->pool );
      99           0 :          !fd_vote_authorized_voters_treap_fwd_iter_done( iter );
     100           0 :          iter = fd_vote_authorized_voters_treap_fwd_iter_next( iter, self->pool ) ) {
     101           0 :       fd_vote_authorized_voter_t * ele =
     102           0 :           fd_vote_authorized_voters_treap_fwd_iter_ele( iter, self->pool );
     103           0 :       if( ele->epoch < epoch && ( latest_epoch == 0 || ele->epoch > latest_epoch ) ) {
     104           0 :         latest_epoch = ele->epoch;
     105           0 :         res          = ele;
     106           0 :       }
     107           0 :     }
     108           0 :     *existed = 0;
     109           0 :     return res;
     110           0 :   } else {
     111           0 :     *existed = 1;
     112           0 :     return res;
     113           0 :   }
     114           0 :   return res;
     115           0 : }
     116             : 
     117             : fd_vote_authorized_voter_t *
     118             : fd_authorized_voters_get_and_cache_authorized_voter_for_epoch( fd_vote_authorized_voters_t * self,
     119           0 :                                                                ulong                         epoch ) {
     120           0 :   int                          existed = 0;
     121             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L29
     122           0 :   fd_vote_authorized_voter_t * res =
     123           0 :       fd_authorized_voters_get_or_calculate_authorized_voter_for_epoch( self, epoch, &existed );
     124           0 :   if( !res ) return NULL;
     125             :   // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L32
     126           0 :   if( !existed ) {
     127             :     /* insert cannot fail because !existed */
     128           0 :     if( FD_UNLIKELY( !fd_vote_authorized_voters_pool_free( self->pool ) ) ) {
     129           0 :       FD_LOG_CRIT(( "invariant violation: max authorized voter count of vote account exceeded" ));
     130           0 :     }
     131           0 :     fd_vote_authorized_voter_t * ele = fd_vote_authorized_voters_pool_ele_acquire( self->pool );
     132           0 :     ele->epoch                       = epoch;
     133           0 :     ele->pubkey                      = res->pubkey;
     134           0 :     ele->prio                        = (ulong)&res->pubkey;
     135             :     // https://github.com/anza-xyz/agave/blob/v2.0.1/sdk/program/src/vote/authorized_voters.rs#L33
     136           0 :     fd_vote_authorized_voters_treap_ele_insert( self->treap, ele, self->pool );
     137           0 :   }
     138           0 :   return res;
     139           0 : }
     140             : 
     141             : int
     142             : fd_authorized_voters_get_and_update_authorized_voter( fd_vote_state_versioned_t * self,
     143             :                                                       ulong                       current_epoch,
     144           0 :                                                       fd_pubkey_t **              pubkey /* out */ ) {
     145           0 :   switch( self->discriminant ) {
     146           0 :     case fd_vote_state_versioned_enum_v3:
     147           0 :       return fd_vote_state_v3_get_and_update_authorized_voter( &self->inner.v3, current_epoch, pubkey );
     148           0 :     case fd_vote_state_versioned_enum_v4:
     149           0 :       return fd_vote_state_v4_get_and_update_authorized_voter( &self->inner.v4, current_epoch, pubkey );
     150           0 :     default:
     151           0 :       FD_LOG_CRIT(( "unsupported vote state versioned discriminant: %u", self->discriminant ));
     152           0 :   }
     153           0 : }

Generated by: LCOV version 1.14