LCOV - code coverage report
Current view: top level - choreo/tower - fd_tower_stakes.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 69 93 74.2 %
Date: 2026-03-31 06:22:16 Functions: 6 6 100.0 %

          Line data    Source code
       1             : #include "fd_tower_stakes.h"
       2             : 
       3             : void *
       4             : fd_tower_stakes_new( void * shmem,
       5             :                      ulong  slot_max,
       6             :                      ulong  vtr_max,
       7          27 :                      ulong  seed ) {
       8             : 
       9          27 :   if( FD_UNLIKELY( !shmem ) ) {
      10           0 :     FD_LOG_WARNING(( "NULL mem" ));
      11           0 :     return NULL;
      12           0 :   }
      13             : 
      14          27 :   ulong footprint = fd_tower_stakes_footprint( slot_max, vtr_max );
      15          27 :   if( FD_UNLIKELY( !footprint ) ) {
      16           0 :     FD_LOG_WARNING(( "bad slot_max (%lu) or vtr_max (%lu)", slot_max, vtr_max ));
      17           0 :     return NULL;
      18           0 :   }
      19             : 
      20          27 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_tower_stakes_align() ) ) ) {
      21           0 :     FD_LOG_WARNING(( "misaligned mem" ));
      22           0 :     return NULL;
      23           0 :   }
      24             : 
      25          27 :   int lg_slot_cnt = fd_ulong_find_msb( fd_ulong_pow2_up( slot_max ) ) + 1;
      26          27 :   ulong vtr_stake_chain_cnt = fd_tower_stakes_vtr_map_chain_cnt_est( vtr_max * slot_max );
      27             : 
      28          27 :   FD_SCRATCH_ALLOC_INIT( l, shmem );
      29          27 :   fd_tower_stakes_t * tower_stakes      = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_tower_stakes_t),       sizeof(fd_tower_stakes_t)                                  );
      30          27 :   void *              voter_stake_map   = FD_SCRATCH_ALLOC_APPEND( l, fd_tower_stakes_vtr_map_align(),  fd_tower_stakes_vtr_map_footprint ( vtr_stake_chain_cnt )  );
      31          27 :   void *              voter_stake_pool  = FD_SCRATCH_ALLOC_APPEND( l, fd_tower_stakes_vtr_pool_align(), fd_tower_stakes_vtr_pool_footprint( vtr_max * slot_max )   );
      32          27 :   void *              tower_stakes_slot = FD_SCRATCH_ALLOC_APPEND( l, fd_tower_stakes_slot_align(),     fd_tower_stakes_slot_footprint( lg_slot_cnt )              );
      33          27 :   void *              used_acc_scratch  = FD_SCRATCH_ALLOC_APPEND( l, fd_used_acc_scratch_align(),      fd_used_acc_scratch_footprint( vtr_max * slot_max )        );
      34          27 :   FD_TEST( FD_SCRATCH_ALLOC_FINI( l, fd_tower_stakes_align() )==(ulong)shmem + footprint );
      35             : 
      36          27 :   tower_stakes->vtr_map          = fd_tower_stakes_vtr_map_new ( voter_stake_map,  vtr_stake_chain_cnt, seed );
      37          27 :   tower_stakes->vtr_pool         = fd_tower_stakes_vtr_pool_new( voter_stake_pool, vtr_max * slot_max        );
      38          27 :   tower_stakes->slot_map         = fd_tower_stakes_slot_new    ( tower_stakes_slot, lg_slot_cnt,         seed );
      39          27 :   tower_stakes->used_acc_scratch = fd_used_acc_scratch_new     ( used_acc_scratch, vtr_max * slot_max        );
      40          27 :   return shmem;
      41          27 : }
      42             : 
      43             : fd_tower_stakes_t *
      44          27 : fd_tower_stakes_join( void * shstakes ) {
      45             : 
      46          27 :   fd_tower_stakes_t * stakes = (fd_tower_stakes_t *)shstakes;
      47             : 
      48          27 :   if( FD_UNLIKELY( !stakes ) ) {
      49           0 :     FD_LOG_WARNING(( "NULL tower_stakes" ));
      50           0 :     return NULL;
      51           0 :   }
      52             : 
      53          27 :   if( FD_UNLIKELY( !fd_ulong_is_aligned((ulong)stakes, fd_tower_stakes_align() ) ) ) {
      54           0 :     FD_LOG_WARNING(( "misaligned tower_stakes" ));
      55           0 :     return NULL;
      56           0 :   }
      57             : 
      58          27 :   stakes->vtr_map          = fd_tower_stakes_vtr_map_join( stakes->vtr_map );
      59          27 :   stakes->vtr_pool         = fd_tower_stakes_vtr_pool_join( stakes->vtr_pool );
      60          27 :   stakes->slot_map         = fd_tower_stakes_slot_join( stakes->slot_map );
      61          27 :   stakes->used_acc_scratch = fd_used_acc_scratch_join( stakes->used_acc_scratch );
      62             : 
      63          27 :   FD_TEST( stakes->vtr_map );
      64          27 :   FD_TEST( stakes->vtr_pool );
      65          27 :   FD_TEST( stakes->slot_map );
      66          27 :   FD_TEST( stakes->used_acc_scratch );
      67             : 
      68          27 :   return stakes;
      69          27 : }
      70             : 
      71             : void *
      72          15 : fd_tower_stakes_leave( fd_tower_stakes_t const * stakes ) {
      73             : 
      74          15 :   if( FD_UNLIKELY( !stakes ) ) {
      75           0 :     FD_LOG_WARNING(( "NULL stakes" ));
      76           0 :     return NULL;
      77           0 :   }
      78             : 
      79          15 :   return (void *)stakes;
      80          15 : }
      81             : 
      82             : void *
      83          15 : fd_tower_stakes_delete( void * stakes ) {
      84             : 
      85          15 :   if( FD_UNLIKELY( !stakes ) ) {
      86           0 :     FD_LOG_WARNING(( "NULL stakes" ));
      87           0 :     return NULL;
      88           0 :   }
      89             : 
      90          15 :   if( FD_UNLIKELY( !fd_ulong_is_aligned((ulong)stakes, fd_tower_stakes_align() ) ) ) {
      91           0 :     FD_LOG_WARNING(( "misaligned stakes" ));
      92           0 :     return NULL;
      93           0 :   }
      94             : 
      95          15 :   return stakes;
      96          15 : }
      97             : 
      98             : ulong
      99             : fd_tower_stakes_insert( fd_tower_stakes_t * tower_stakes,
     100             :                         ulong               slot,
     101             :                         fd_hash_t const *   vote_account,
     102             :                         ulong               stake,
     103          84 :                         ulong               prev_voter_idx ) {
     104             : 
     105          84 :   fd_tower_stakes_vtr_t * pool = tower_stakes->vtr_pool;
     106          84 :   if( FD_UNLIKELY( !fd_tower_stakes_vtr_pool_free( pool ) ) ) FD_LOG_CRIT(( "no free voter stakes in pool" ));
     107          84 :   fd_tower_stakes_vtr_t * new_voter_stake = fd_tower_stakes_vtr_pool_ele_acquire( pool );
     108          84 :   new_voter_stake->key   = (fd_tower_stakes_vtr_xid_t){ .addr = *vote_account, .slot = slot };
     109          84 :   new_voter_stake->stake = stake;
     110          84 :   new_voter_stake->prev  = prev_voter_idx;
     111          84 :   fd_tower_stakes_vtr_map_ele_insert( tower_stakes->vtr_map, new_voter_stake, pool );
     112             : 
     113             :   /* Point to first vtr (head of list). */
     114             : 
     115          84 :   fd_tower_stakes_slot_t * blk = fd_tower_stakes_slot_query( tower_stakes->slot_map, slot, NULL );
     116          84 :   if( FD_UNLIKELY( !blk ) ) blk = fd_tower_stakes_slot_insert( tower_stakes->slot_map, slot );
     117          84 :   blk->head = fd_tower_stakes_vtr_pool_idx( pool, new_voter_stake );
     118          84 :   return blk->head;
     119          84 : }
     120             : 
     121             : void
     122             : fd_tower_stakes_remove( fd_tower_stakes_t * tower_stakes,
     123          15 :                         ulong               slot ) {
     124             : 
     125          15 :   fd_tower_stakes_slot_t * blk = fd_tower_stakes_slot_query( tower_stakes->slot_map, slot, NULL );
     126          15 :   if( FD_UNLIKELY( !blk ) ) return;
     127          15 :   ulong voter_idx = blk->head;
     128             : 
     129             :   /* Remove the linked list of voters. */
     130             : 
     131          45 :   while( FD_UNLIKELY( voter_idx!=ULONG_MAX ) ) {
     132          30 :     fd_tower_stakes_vtr_t * voter_stake = fd_tower_stakes_vtr_pool_ele( tower_stakes->vtr_pool, voter_idx );
     133          30 :     voter_idx = voter_stake->prev;
     134          30 :     fd_tower_stakes_vtr_t * remove = fd_tower_stakes_vtr_map_ele_remove( tower_stakes->vtr_map, &voter_stake->key, NULL, tower_stakes->vtr_pool );
     135          30 :     if( FD_UNLIKELY( !remove ) ) FD_LOG_CRIT(( "invariant violation: voter stake does not exist in map" ));
     136          30 :     fd_tower_stakes_vtr_pool_ele_release( tower_stakes->vtr_pool, voter_stake );
     137          30 :   }
     138          15 :   fd_tower_stakes_slot_remove( tower_stakes->slot_map, blk );
     139          15 : }

Generated by: LCOV version 1.14