LCOV - code coverage report
Current view: top level - flamenco/stakes - fd_vote_stakes.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 219 363 60.3 %
Date: 2026-03-19 18:19:27 Functions: 18 24 75.0 %

          Line data    Source code
       1             : #include "fd_vote_stakes.h"
       2             : #include "fd_vote_stakes_private.h"
       3             : 
       4             : ulong
       5       60595 : fd_vote_stakes_align( void ) {
       6       60595 :   return FD_VOTE_STAKES_ALIGN;
       7       60595 : }
       8             : 
       9             : ulong
      10             : fd_vote_stakes_footprint( ulong max_vote_accounts,
      11             :                           ulong expected_vote_accounts,
      12          48 :                           ulong max_fork_width ) {
      13          48 :   ulong map_chain_cnt = index_map_chain_cnt_est( expected_vote_accounts );
      14             : 
      15          48 :   ulong l = FD_LAYOUT_INIT;
      16          48 :   l = FD_LAYOUT_APPEND( l, fd_vote_stakes_align(),  sizeof(fd_vote_stakes_t) );
      17          48 :   l = FD_LAYOUT_APPEND( l, index_pool_align(),      index_pool_footprint( max_vote_accounts ) );
      18          48 :   l = FD_LAYOUT_APPEND( l, index_map_align(),       index_map_footprint( map_chain_cnt ) );
      19          48 :   l = FD_LAYOUT_APPEND( l, index_map_multi_align(), index_map_multi_footprint( map_chain_cnt ) );
      20          48 :   l = FD_LAYOUT_APPEND( l, fork_pool_align(),       fork_pool_footprint( max_fork_width ) );
      21          48 :   l = FD_LAYOUT_APPEND( l, fork_dlist_align(),      fork_dlist_footprint() );
      22         144 :   for( ulong i=0; i<max_fork_width; i++ ) {
      23          96 :     l = FD_LAYOUT_APPEND( l, stakes_pool_align(), stakes_pool_footprint( max_vote_accounts ) );
      24          96 :     l = FD_LAYOUT_APPEND( l, stakes_map_align(),  stakes_map_footprint( map_chain_cnt ) );
      25          96 :   }
      26          48 :   return FD_LAYOUT_FINI( l, fd_vote_stakes_align() );
      27          48 : }
      28             : 
      29             : void *
      30             : fd_vote_stakes_new( void * shmem,
      31             :                     ulong  max_vote_accounts,
      32             :                     ulong  expected_vote_accounts,
      33             :                     ulong  max_fork_width,
      34       30172 :                     ulong  seed ) {
      35       30172 :   if( FD_UNLIKELY( !shmem ) ) {
      36           0 :     FD_LOG_WARNING(( "NULL mem" ));
      37           0 :     return NULL;
      38           0 :   }
      39             : 
      40       30172 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_vote_stakes_align() ) ) ) {
      41           0 :     FD_LOG_WARNING(( "misaligned mem" ));
      42           0 :     return NULL;
      43           0 :   }
      44             : 
      45       30172 :   if( FD_UNLIKELY( max_fork_width>MAX_FORK_WIDTH ) ) {
      46           0 :     FD_LOG_WARNING(( "max_fork_width is too large" ));
      47           0 :     return NULL;
      48           0 :   }
      49             : 
      50       30172 :   ulong map_chain_cnt = index_map_chain_cnt_est( expected_vote_accounts );
      51             : 
      52       30172 :   FD_SCRATCH_ALLOC_INIT( l, shmem );
      53       30172 :   fd_vote_stakes_t * vote_stakes         = FD_SCRATCH_ALLOC_APPEND( l, fd_vote_stakes_align(),  sizeof(fd_vote_stakes_t) );
      54       30172 :   void *             index_pool_mem      = FD_SCRATCH_ALLOC_APPEND( l, index_pool_align(),      index_pool_footprint( max_vote_accounts ) );
      55       30172 :   void *             index_map_mem       = FD_SCRATCH_ALLOC_APPEND( l, index_map_align(),       index_map_footprint( map_chain_cnt ) );
      56       30172 :   void *             index_map_multi_mem = FD_SCRATCH_ALLOC_APPEND( l, index_map_multi_align(), index_map_multi_footprint( map_chain_cnt ) );
      57       30172 :   void *             fork_pool_mem       = FD_SCRATCH_ALLOC_APPEND( l, fork_pool_align(),       fork_pool_footprint( max_fork_width ) );
      58       30172 :   void *             fork_dlist_mem      = FD_SCRATCH_ALLOC_APPEND( l, fork_dlist_align(),      fork_dlist_footprint() );
      59       90463 :   for( ulong i=0; i<max_fork_width; i++ ) {
      60       60291 :     void *    stakes_pool_mem = FD_SCRATCH_ALLOC_APPEND( l, stakes_pool_align(), stakes_pool_footprint( max_vote_accounts ) );
      61           0 :     stake_t * stakes_pool     = stakes_pool_join( stakes_pool_new( stakes_pool_mem, max_vote_accounts ) );
      62       60291 :     if( FD_UNLIKELY( !stakes_pool ) ) {
      63           0 :       FD_LOG_WARNING(( "Failed to create vote stakes ele pool" ));
      64           0 :       return NULL;
      65           0 :     }
      66       60291 :     vote_stakes->stakes_pool_off[ i ] = (ulong)stakes_pool - (ulong)shmem;
      67             : 
      68       60291 :     void * stakes_map_mem = FD_SCRATCH_ALLOC_APPEND( l, stakes_map_align(), stakes_map_footprint( map_chain_cnt ) );
      69           0 :     stakes_map_t * stakes_map = stakes_map_join( stakes_map_new( stakes_map_mem, map_chain_cnt, seed ) );
      70       60291 :     if( FD_UNLIKELY( !stakes_map ) ) {
      71           0 :       FD_LOG_WARNING(( "Failed to create vote stakes ele map" ));
      72           0 :       return NULL;
      73           0 :     }
      74       60291 :     vote_stakes->stakes_map_off[ i ] = (ulong)stakes_map - (ulong)shmem;
      75       60291 :   }
      76             : 
      77       30172 :   index_ele_t * index_pool = index_pool_join( index_pool_new( index_pool_mem, max_vote_accounts ) );
      78       30172 :   if( FD_UNLIKELY( !index_pool ) ) {
      79           0 :     FD_LOG_WARNING(( "Failed to create vote stakes index pool" ));
      80           0 :     return NULL;
      81           0 :   }
      82             : 
      83       30172 :   index_map_t * index_map = index_map_join( index_map_new( index_map_mem, map_chain_cnt, seed ) );
      84       30172 :   if( FD_UNLIKELY( !index_map ) ) {
      85           0 :     FD_LOG_WARNING(( "Failed to create vote stakes index map" ));
      86           0 :     return NULL;
      87           0 :   }
      88             : 
      89       30172 :   index_map_multi_t * index_map_multi = index_map_multi_join( index_map_multi_new( index_map_multi_mem, map_chain_cnt, seed ) );
      90       30172 :   if( FD_UNLIKELY( !index_map_multi ) ) {
      91           0 :     FD_LOG_WARNING(( "Failed to create vote stakes index map multi" ));
      92           0 :     return NULL;
      93           0 :   }
      94             : 
      95       30172 :   fork_t * fork_pool = fork_pool_join( fork_pool_new( fork_pool_mem, max_fork_width ) );
      96       30172 :   if( FD_UNLIKELY( !fork_pool ) ) {
      97           0 :     FD_LOG_WARNING(( "Failed to create vote stakes fork pool" ));
      98           0 :     return NULL;
      99           0 :   }
     100             : 
     101       30172 :   fork_dlist_t * fork_dlist = fork_dlist_join( fork_dlist_new( fork_dlist_mem ) );
     102       30172 :   if( FD_UNLIKELY( !fork_dlist ) ) {
     103           0 :     FD_LOG_WARNING(( "Failed to create vote stakes fork dlist" ));
     104           0 :     return NULL;
     105           0 :   }
     106             : 
     107       30172 :   if( FD_UNLIKELY( max_fork_width>USHORT_MAX ) ) {
     108           0 :     FD_LOG_WARNING(( "max_fork_width is too large" ));
     109           0 :     return NULL;
     110           0 :   }
     111             : 
     112       30172 :   vote_stakes->max_fork_width      = (ushort)max_fork_width;
     113       30172 :   vote_stakes->index_pool_off      = (ulong)index_pool - (ulong)shmem;
     114       30172 :   vote_stakes->index_map_off       = (ulong)index_map - (ulong)shmem;
     115       30172 :   vote_stakes->index_map_multi_off = (ulong)index_map_multi - (ulong)shmem;
     116       30172 :   vote_stakes->fork_pool_off       = (ulong)fork_pool - (ulong)shmem;
     117       30172 :   vote_stakes->fork_dlist_off      = (ulong)fork_dlist - (ulong)shmem;
     118       30172 :   vote_stakes->root_idx            = (ushort)fork_pool_idx_acquire( fork_pool );
     119       30172 :   fork_dlist_idx_push_tail( fork_dlist, vote_stakes->root_idx, fork_pool );
     120             : 
     121       30172 :   FD_COMPILER_MFENCE();
     122       30172 :   FD_VOLATILE( vote_stakes->magic ) = FD_VOTE_STAKES_MAGIC;
     123       30172 :   FD_COMPILER_MFENCE();
     124             : 
     125       30172 :   return vote_stakes;
     126       30172 : }
     127             : 
     128             : fd_vote_stakes_t *
     129          12 : fd_vote_stakes_join( void * shmem ) {
     130          12 :   fd_vote_stakes_t * vote_stakes = (fd_vote_stakes_t *)shmem;
     131             : 
     132          12 :   if( FD_UNLIKELY( !vote_stakes ) ) {
     133           0 :     FD_LOG_WARNING(( "NULL vote stakes" ));
     134           0 :     return NULL;
     135           0 :   }
     136             : 
     137          12 :   if( FD_UNLIKELY( vote_stakes->magic != FD_VOTE_STAKES_MAGIC ) ) {
     138           0 :     FD_LOG_WARNING(( "Invalid vote stakes magic" ));
     139           0 :     return NULL;
     140           0 :   }
     141             : 
     142          12 :   return vote_stakes;
     143          12 : }
     144             : 
     145             : void
     146             : fd_vote_stakes_root_insert_key( fd_vote_stakes_t *  vote_stakes,
     147             :                                 fd_pubkey_t const * pubkey,
     148             :                                 fd_pubkey_t const * node_account_t_1,
     149             :                                 ulong               stake_t_1,
     150         299 :                                 ulong               epoch ) {
     151         299 :   index_ele_t *       index_pool      = get_index_pool( vote_stakes );
     152         299 :   index_map_t *       index_map       = get_index_map( vote_stakes );
     153         299 :   index_map_multi_t * index_map_multi = get_index_map_multi( vote_stakes );
     154             : 
     155         299 :   index_ele_t * ele     = index_pool_ele_acquire( index_pool );
     156         299 :   ele->pubkey           = *pubkey;
     157         299 :   ele->refcnt           = 1;
     158         299 :   ele->stake_t_1        = stake_t_1 & 0x7FFFFFFFFFFFFFFFUL; /* mask to 63 bits */
     159         299 :   ele->node_account_t_1 = *node_account_t_1;
     160         299 :   ele->stake_t_2        = 0UL;
     161         299 :   ele->node_account_t_2 = (fd_pubkey_t){0};
     162         299 :   ele->epoch            = epoch % 2;
     163         299 :   ele->exists_t_1       = 1U;
     164             :   /* It is fine to leave node account t_2 uninitalized because it will
     165             :      only be used if stake_t_2 is non-zero. */
     166             : 
     167         299 :   FD_TEST( index_map_ele_insert( index_map, ele, index_pool ) );
     168         299 :   FD_TEST( index_map_multi_ele_insert( index_map_multi, ele, index_pool ) );
     169             : 
     170         299 :   stake_t *      stakes_pool = get_stakes_pool( vote_stakes, vote_stakes->root_idx );
     171         299 :   stakes_map_t * stakes_map  = get_stakes_map( vote_stakes, vote_stakes->root_idx );
     172             : 
     173         299 :   uint      pubkey_idx = (uint)index_pool_idx( index_pool, ele );
     174         299 :   stake_t * new_stake = stakes_pool_ele_acquire( stakes_pool );
     175         299 :   new_stake->idx = pubkey_idx;
     176         299 :   FD_TEST( stakes_map_ele_insert( stakes_map, new_stake, stakes_pool ) );
     177         299 : }
     178             : 
     179             : void
     180             : fd_vote_stakes_root_update_meta( fd_vote_stakes_t *  vote_stakes,
     181             :                                  fd_pubkey_t const * pubkey,
     182             :                                  fd_pubkey_t const * node_account_t_2,
     183             :                                  ulong               stake_t_2,
     184         299 :                                  ulong               epoch ) {
     185         299 :   index_ele_t *       index_pool      = get_index_pool( vote_stakes );
     186         299 :   index_map_t *       index_map       = get_index_map( vote_stakes );
     187         299 :   index_map_multi_t * index_map_multi = get_index_map_multi( vote_stakes );
     188         299 :   index_ele_t *       ele             = index_map_multi_ele_query( index_map_multi, pubkey, NULL, index_pool );
     189         299 :   if( FD_UNLIKELY( !ele ) ) {
     190           0 :     ele                   = index_pool_ele_acquire( index_pool );
     191           0 :     ele->pubkey           = *pubkey;
     192           0 :     ele->refcnt           = 1;
     193           0 :     ele->stake_t_1        = 0UL;
     194           0 :     ele->node_account_t_1 = (fd_pubkey_t){0};
     195           0 :     ele->epoch            = epoch % 2;
     196           0 :     ele->exists_t_1       = 0U;
     197             : 
     198           0 :     FD_TEST( index_map_ele_insert( index_map, ele, index_pool ) );
     199           0 :     FD_TEST( index_map_multi_ele_insert( index_map_multi, ele, index_pool ) );
     200             : 
     201           0 :     stake_t *      stakes_pool = get_stakes_pool( vote_stakes, vote_stakes->root_idx );
     202           0 :     stakes_map_t * stakes_map  = get_stakes_map( vote_stakes, vote_stakes->root_idx );
     203             : 
     204           0 :     uint      pubkey_idx = (uint)index_pool_idx( index_pool, ele );
     205           0 :     stake_t * new_stake = stakes_pool_ele_acquire( stakes_pool );
     206           0 :     new_stake->idx = pubkey_idx;
     207           0 :     FD_TEST( stakes_map_ele_insert( stakes_map, new_stake, stakes_pool ) );
     208           0 :   }
     209             : 
     210         299 :   ele->node_account_t_2 = *node_account_t_2;
     211         299 :   ele->stake_t_2        = stake_t_2;
     212         299 : }
     213             : 
     214             : void
     215             : fd_vote_stakes_root_purge_key( fd_vote_stakes_t *  vote_stakes,
     216           0 :                                fd_pubkey_t const * pubkey ) {
     217           0 :   index_ele_t *       index_pool      = get_index_pool( vote_stakes );
     218           0 :   index_map_t *       index_map       = get_index_map( vote_stakes );
     219           0 :   index_map_multi_t * index_map_multi = get_index_map_multi( vote_stakes );
     220             : 
     221           0 :   uint ele_idx = (uint)index_map_multi_idx_query( index_map_multi, pubkey, UINT_MAX, index_pool );
     222           0 :   FD_TEST( ele_idx!=UINT_MAX );
     223             : 
     224           0 :   index_ele_t * ele = index_pool_ele( index_pool, ele_idx );
     225             : 
     226           0 :   FD_TEST( index_map_multi_ele_remove_fast( index_map_multi, ele, index_pool ) );
     227           0 :   FD_TEST( index_map_ele_remove( index_map, &ele->index_key, NULL, index_pool ) );
     228             : 
     229           0 :   stake_t *      stakes_pool = get_stakes_pool( vote_stakes, vote_stakes->root_idx );
     230           0 :   stakes_map_t * stakes_map  = get_stakes_map( vote_stakes, vote_stakes->root_idx );
     231             : 
     232           0 :   stake_t * stake_ele = stakes_map_ele_remove( stakes_map, &ele_idx, NULL, stakes_pool );
     233           0 :   stakes_pool_ele_release( stakes_pool, stake_ele );
     234             : 
     235           0 :   index_pool_ele_release( index_pool, ele );
     236           0 : }
     237             : 
     238             : void
     239             : fd_vote_stakes_insert_key( fd_vote_stakes_t *  vote_stakes,
     240             :                            ushort              fork_idx,
     241             :                            fd_pubkey_t const * pubkey,
     242             :                            fd_pubkey_t const * node_account_t_1,
     243             :                            fd_pubkey_t const * node_account_t_2,
     244             :                            ulong               stake_t_2,
     245             :                            ulong               epoch,
     246           2 :                            uchar               exists_curr ) {
     247           2 :   index_ele_t *       index_pool      = get_index_pool( vote_stakes );
     248           2 :   index_map_multi_t * index_map_multi = get_index_map_multi( vote_stakes );
     249             : 
     250           2 :   stake_t *      stakes_pool = get_stakes_pool( vote_stakes, fork_idx );
     251           2 :   stakes_map_t * stakes_map  = get_stakes_map( vote_stakes, fork_idx );
     252             : 
     253           2 :   index_ele_t * index_ele = index_pool_ele_acquire( index_pool );
     254           2 :   index_ele->pubkey           = *pubkey;
     255           2 :   index_ele->node_account_t_1 = *node_account_t_1;
     256           2 :   index_ele->node_account_t_2 = *node_account_t_2;
     257           2 :   index_ele->exists_t_1       = exists_curr;
     258           2 :   index_ele->stake_t_1        = 0UL;
     259           2 :   index_ele->stake_t_2        = stake_t_2;
     260           2 :   index_ele->epoch            = epoch % 2;
     261           2 :   FD_TEST( index_map_multi_ele_insert( index_map_multi, index_ele, index_pool ) );
     262             : 
     263           2 :   stake_t * stake = stakes_pool_ele_acquire( stakes_pool );
     264           2 :   stake->idx = (uint)index_pool_idx( index_pool, index_ele );
     265           2 :   FD_TEST( stakes_map_ele_insert( stakes_map, stake, stakes_pool ) );
     266           2 : }
     267             : 
     268             : void
     269             : fd_vote_stakes_insert_update( fd_vote_stakes_t *  vote_stakes,
     270             :                               ushort              fork_idx,
     271             :                               fd_pubkey_t const * pubkey,
     272           2 :                               ulong               stake ) {
     273           2 :   index_ele_t *       index_pool      = get_index_pool( vote_stakes );
     274           2 :   index_map_multi_t * index_map_multi = get_index_map_multi( vote_stakes );
     275             : 
     276           2 :   stake_t *      stakes_pool = get_stakes_pool( vote_stakes, fork_idx );
     277           2 :   stakes_map_t * stakes_map  = get_stakes_map( vote_stakes, fork_idx );
     278             : 
     279           2 :   uint ele_idx = (uint)index_map_multi_idx_query_const( index_map_multi, pubkey, UINT_MAX, index_pool );
     280           2 :   FD_TEST( ele_idx!=UINT_MAX );
     281             : 
     282           2 :   while( !stakes_map_ele_query( stakes_map, &ele_idx, NULL, stakes_pool ) ) {
     283           0 :     ele_idx = (uint)index_map_multi_idx_next_const( ele_idx, UINT_MAX, index_pool );
     284           0 :     FD_TEST( ele_idx!=UINT_MAX );
     285           0 :   }
     286             : 
     287           2 :   index_ele_t * index_ele = index_pool_ele( index_pool, ele_idx );
     288             : 
     289           2 :   if( FD_UNLIKELY( index_ele->exists_t_1==0U ) ) return;
     290           2 :   index_ele->stake_t_1 += (stake & 0x7FFFFFFFFFFFFFFFUL); /* mask to 63 bits */
     291           2 : }
     292             : 
     293             : void
     294             : fd_vote_stakes_insert_fini( fd_vote_stakes_t * vote_stakes,
     295           2 :                             ushort             fork_idx ) {
     296           2 :   index_ele_t *       index_pool      = get_index_pool( vote_stakes );
     297           2 :   index_map_t *       index_map       = get_index_map( vote_stakes );
     298           2 :   index_map_multi_t * index_map_multi = get_index_map_multi( vote_stakes );
     299             : 
     300           2 :   stake_t *      stakes_pool = get_stakes_pool( vote_stakes, fork_idx );
     301           2 :   stakes_map_t * stakes_map  = get_stakes_map( vote_stakes, fork_idx );
     302             : 
     303           2 :   ulong stakes_pool_cnt = stakes_pool_used( stakes_pool );
     304           4 :   for( ulong i=0UL; i<stakes_pool_cnt; i++ ) {
     305           2 :     stake_t *     stake           = stakes_pool_ele( stakes_pool, i );
     306           2 :     index_ele_t * index_ele       = index_pool_ele( index_pool, stake->idx );
     307           2 :     index_ele_t * index_ele_query = index_map_ele_query( index_map, &index_ele->index_key, NULL, index_pool );
     308           2 :     if( FD_UNLIKELY( index_ele_query ) ) {
     309             :       /* The element that we inserted into the index matches up with an
     310             :          existing element.  It is safe to release it from the stakes map
     311             :          stakes index, index_pool, and index_map_multi.  Simply,
     312             :          increase the reference to the existing element and add it to
     313             :          the stakes map/pool.  The iteration we are doing is safe,
     314             :          because the pool freelist has a lifo policy. */
     315           1 :       index_ele_query->refcnt++;
     316           1 :       index_map_multi_ele_remove_fast( index_map_multi, index_ele, index_pool );
     317           1 :       index_pool_ele_release( index_pool, index_ele );
     318           1 :       stakes_map_ele_remove( stakes_map, &stake->idx, NULL, stakes_pool );
     319           1 :       stakes_pool_ele_release( stakes_pool, stake );
     320             : 
     321           1 :       stake = stakes_pool_ele_acquire( stakes_pool );
     322           1 :       stake->idx = (uint)index_pool_idx( index_pool, index_ele_query );
     323           1 :       FD_TEST( stakes_map_ele_insert( stakes_map, stake, stakes_pool ) );
     324           1 :     } else {
     325             :       /* If the element is new, add it to the index map. */
     326           1 :       index_ele->refcnt = 1;
     327           1 :       index_map_ele_insert( index_map, index_ele, index_pool );
     328           1 :     }
     329           2 :   }
     330           2 : }
     331             : 
     332             : void
     333           0 : fd_vote_stakes_genesis_fini( fd_vote_stakes_t * vote_stakes ) {
     334           0 :   index_ele_t *       index_pool      = get_index_pool( vote_stakes );
     335           0 :   index_map_multi_t * index_map_multi = get_index_map_multi( vote_stakes );
     336             : 
     337           0 :   for( index_map_multi_iter_t iter = index_map_multi_iter_init( index_map_multi, index_pool );
     338           0 :        !index_map_multi_iter_done( iter, index_map_multi, index_pool );
     339           0 :        iter = index_map_multi_iter_next( iter, index_map_multi, index_pool ) ) {
     340           0 :     index_ele_t * ele = index_map_multi_iter_ele( iter, index_map_multi, index_pool );
     341           0 :     ele->node_account_t_2 = ele->node_account_t_1;
     342           0 :     ele->stake_t_2        = ele->stake_t_1;
     343           0 :   }
     344           0 : }
     345             : 
     346             : ushort
     347           2 : fd_vote_stakes_new_child( fd_vote_stakes_t * vote_stakes ) {
     348             : 
     349           2 :   fork_t *       fork_pool  = get_fork_pool( vote_stakes );
     350           2 :   fork_dlist_t * fork_dlist = get_fork_dlist( vote_stakes );
     351             : 
     352           2 :   if( FD_UNLIKELY( !fork_pool_free( fork_pool ) ) ) {
     353           0 :     FD_LOG_CRIT(( "no free forks in pool" ));
     354           0 :   }
     355             : 
     356           2 :   ushort idx = (ushort)fork_pool_idx_acquire( fork_pool );
     357             : 
     358           2 :   fork_dlist_idx_push_tail( fork_dlist, idx, fork_pool );
     359             : 
     360           2 :   return idx;
     361           2 : }
     362             : 
     363             : void
     364             : fd_vote_stakes_advance_root( fd_vote_stakes_t * vote_stakes,
     365           0 :                              ushort             root_idx ) {
     366             : 
     367             :   /* Only expect the vote stakes to update once an epoch. */
     368           0 :   if( FD_LIKELY( root_idx==vote_stakes->root_idx ) ) {
     369           0 :     return;
     370           0 :   }
     371             : 
     372           0 :   fork_t *       fork_pool  = get_fork_pool( vote_stakes );
     373           0 :   fork_dlist_t * fork_dlist = get_fork_dlist( vote_stakes );
     374             : 
     375           0 :   index_ele_t *       index_pool      = get_index_pool( vote_stakes );
     376           0 :   index_map_t *       index_map       = get_index_map( vote_stakes );
     377           0 :   index_map_multi_t * index_map_multi = get_index_map_multi( vote_stakes );
     378             :   /* For every outstanding fork that is not the new candidate root,
     379             :      remove all stakes refcnts from the index.  If the index has no
     380             :      outstanding references, remove the index entry. */
     381           0 :   while( !fork_dlist_is_empty( fork_dlist, fork_pool ) ) {
     382           0 :     ushort fork_idx = (ushort)fork_dlist_idx_pop_head( fork_dlist, fork_pool );
     383           0 :     if( fork_idx==root_idx ) continue;
     384             : 
     385           0 :     stake_t *      stakes_pool = get_stakes_pool( vote_stakes, fork_idx );
     386           0 :     stakes_map_t * stakes_map  = get_stakes_map( vote_stakes, fork_idx );
     387           0 :     for( stakes_map_iter_t iter = stakes_map_iter_init( stakes_map, stakes_pool );
     388           0 :          !stakes_map_iter_done( iter, stakes_map, stakes_pool );
     389           0 :          iter = stakes_map_iter_next( iter, stakes_map, stakes_pool ) ) {
     390           0 :       stake_t *     stake = stakes_map_iter_ele( iter, stakes_map, stakes_pool );
     391           0 :       index_ele_t * ele   = index_pool_ele( index_pool, stake->idx );
     392           0 :       ele->refcnt--;
     393             : 
     394           0 :       if( FD_UNLIKELY( ele->refcnt==0U ) ) {
     395           0 :         FD_TEST( index_map_ele_remove( index_map, &ele->index_key, NULL, index_pool ) );
     396           0 :         FD_TEST( index_map_multi_ele_remove_fast( index_map_multi, ele, index_pool ) );
     397           0 :         index_pool_ele_release( index_pool, ele );
     398           0 :       }
     399           0 :     }
     400           0 :     fork_pool_idx_release( fork_pool, fork_idx );
     401           0 :     stakes_map_reset( get_stakes_map( vote_stakes, fork_idx ) );
     402           0 :     stakes_pool_reset( get_stakes_pool( vote_stakes, fork_idx ) );
     403           0 :   }
     404             :   /* TODO: There's probably a way to do a more efficient reset here. */
     405             : 
     406           0 :   fork_dlist_idx_push_head( fork_dlist, root_idx, fork_pool );
     407           0 :   vote_stakes->root_idx = root_idx;
     408           0 : }
     409             : 
     410             : int
     411             : fd_vote_stakes_query( fd_vote_stakes_t const * vote_stakes,
     412             :                       ushort                   fork_idx,
     413             :                       fd_pubkey_t const *      pubkey,
     414             :                       ulong *                  stake_t_1_out_opt,
     415             :                       ulong *                  stake_t_2_out_opt,
     416             :                       fd_pubkey_t *            node_account_t_1_out_opt,
     417          20 :                       fd_pubkey_t *            node_account_t_2_out_opt ) {
     418             : 
     419          20 :   index_ele_t *       index_pool      = get_index_pool( vote_stakes );
     420          20 :   index_map_multi_t * index_map_multi = get_index_map_multi( vote_stakes );
     421             : 
     422          20 :   stake_t *      stakes_pool = get_stakes_pool( vote_stakes, fork_idx );
     423          20 :   stakes_map_t * stakes_map  = get_stakes_map( vote_stakes, fork_idx );
     424             : 
     425             :   /* The index may have multiple entries for the same pubkey, so every
     426             :      single matching index entry must be checked to see if the index
     427             :      exists in the given fork's stakes map.  If it does, return the
     428             :      t_2 stake value.*/
     429          20 :   uint ele_idx = (uint)index_map_multi_idx_query_const( index_map_multi, pubkey, UINT_MAX, index_pool );
     430          20 :   if( FD_UNLIKELY( ele_idx==UINT_MAX ) ) {
     431          16 :     return 0;
     432          16 :   }
     433             : 
     434           4 :   while( !stakes_map_ele_query_const( stakes_map, &ele_idx, NULL, stakes_pool ) ) {
     435           2 :     ele_idx = (uint)index_map_multi_idx_next_const( ele_idx, UINT_MAX, index_pool );
     436           2 :     if( FD_UNLIKELY( ele_idx==UINT_MAX ) ) {
     437           2 :       return 0;
     438           2 :     }
     439           2 :   }
     440             : 
     441           2 :   index_ele_t * index_ele = index_pool_ele( index_pool, ele_idx );
     442           2 :   if( stake_t_1_out_opt )        *stake_t_1_out_opt        = index_ele->stake_t_1;
     443           2 :   if( stake_t_2_out_opt )        *stake_t_2_out_opt        = index_ele->stake_t_2;
     444           2 :   if( node_account_t_1_out_opt ) *node_account_t_1_out_opt = index_ele->node_account_t_1;
     445           2 :   if( node_account_t_2_out_opt ) *node_account_t_2_out_opt = index_ele->node_account_t_2;
     446           2 :   return 1;
     447           4 : }
     448             : 
     449             : int
     450             : fd_vote_stakes_query_pubkey( fd_vote_stakes_t const * vote_stakes,
     451             :                              ushort                   fork_idx,
     452           2 :                              fd_pubkey_t const *      pubkey ) {
     453           2 :   return fd_vote_stakes_query( vote_stakes, fork_idx, pubkey, NULL, NULL, NULL, NULL );
     454           2 : }
     455             : 
     456             : int
     457             : fd_vote_stakes_query_t_1( fd_vote_stakes_t const * vote_stakes,
     458             :                           ushort                   fork_idx,
     459             :                           fd_pubkey_t const *      pubkey,
     460             :                           ulong *                  stake_out,
     461          18 :                           fd_pubkey_t *            node_account_out ) {
     462          18 :   int found = fd_vote_stakes_query( vote_stakes, fork_idx, pubkey, stake_out, NULL, node_account_out, NULL );
     463          18 :   return found && *stake_out>0UL;
     464          18 : }
     465             : 
     466             : int
     467             : fd_vote_stakes_query_t_2( fd_vote_stakes_t const * vote_stakes,
     468             :                           ushort                   fork_idx,
     469             :                           fd_pubkey_t const *      pubkey,
     470             :                           ulong *                  stake_out,
     471           0 :                           fd_pubkey_t *            node_account_out ) {
     472           0 :   int found = fd_vote_stakes_query( vote_stakes, fork_idx, pubkey, NULL, stake_out, NULL, node_account_out );
     473           0 :   return found && *stake_out>0UL;
     474           0 : }
     475             : 
     476             : void
     477           0 : fd_vote_stakes_reset( fd_vote_stakes_t * vote_stakes ) {
     478             :   /* Pop the fork dlist */
     479           0 :   fork_t *       fork_pool  = get_fork_pool( vote_stakes );
     480           0 :   fork_dlist_t * fork_dlist = get_fork_dlist( vote_stakes );
     481           0 :   fork_dlist_remove_all( fork_dlist, fork_pool );
     482             : 
     483           0 :   fork_pool_reset( fork_pool );
     484             : 
     485             :   /* For each fork, reset the stakes map and pool */
     486           0 :   for( ushort i=0; i<vote_stakes->max_fork_width; i++ ) {
     487           0 :     stakes_map_reset( get_stakes_map( vote_stakes, i ) );
     488           0 :     stakes_pool_reset( get_stakes_pool( vote_stakes, i ) );
     489           0 :   }
     490             : 
     491             :   /* Reset the index map and multi map */
     492           0 :   index_map_reset( get_index_map( vote_stakes ) );
     493           0 :   index_map_multi_reset( get_index_map_multi( vote_stakes ) );
     494             : 
     495             :   /* Reset the index pool */
     496           0 :   index_pool_reset( get_index_pool( vote_stakes ) );
     497             : 
     498             :   /* Setup the pool again */
     499           0 :   vote_stakes->root_idx = (ushort)fork_pool_idx_acquire( fork_pool );
     500           0 :   fork_dlist_idx_push_tail( fork_dlist, vote_stakes->root_idx, fork_pool );
     501           0 : }
     502             : 
     503             : uint
     504             : fd_vote_stakes_ele_cnt( fd_vote_stakes_t * vote_stakes,
     505           0 :                         ushort             fork_idx ) {
     506           0 :   stake_t * stakes_pool = get_stakes_pool( vote_stakes, fork_idx );
     507           0 :   return (uint)stakes_pool_used( stakes_pool );
     508           0 : }
     509             : 
     510             : ushort
     511         311 : fd_vote_stakes_get_root_idx( fd_vote_stakes_t * vote_stakes ) {
     512         311 :   return vote_stakes->root_idx;
     513         311 : }
     514             : 
     515             : fd_vote_stakes_iter_t *
     516             : fd_vote_stakes_fork_iter_init( fd_vote_stakes_t * vote_stakes,
     517             :                                ushort             fork_idx,
     518         901 :                                uchar              iter_mem[ static FD_VOTE_STAKES_ITER_FOOTPRINT ] ) {
     519             : 
     520         901 :   stakes_map_iter_t iter = stakes_map_iter_init( get_stakes_map( vote_stakes, fork_idx ), get_stakes_pool( vote_stakes, fork_idx ) );
     521         901 :   memcpy( iter_mem, &iter, sizeof(stakes_map_iter_t) );
     522         901 :   return (fd_vote_stakes_iter_t *)iter_mem;
     523         901 : }
     524             : 
     525             : int
     526             : fd_vote_stakes_fork_iter_done( fd_vote_stakes_t *      vote_stakes,
     527             :                                ushort                  fork_idx,
     528        1801 :                                fd_vote_stakes_iter_t * iter ) {
     529        1801 :   stakes_map_iter_t * stakes_map_iter = (stakes_map_iter_t *)iter;
     530        1801 :   return stakes_map_iter_done( *stakes_map_iter, get_stakes_map( vote_stakes, fork_idx ), get_stakes_pool( vote_stakes, fork_idx ) );
     531        1801 : }
     532             : 
     533             : void
     534             : fd_vote_stakes_fork_iter_next( fd_vote_stakes_t *      vote_stakes,
     535             :                                ushort                  fork_idx,
     536         901 :                                fd_vote_stakes_iter_t * iter ) {
     537         901 :   stakes_map_iter_t * stakes_map_iter = (stakes_map_iter_t *)iter;
     538         901 :   *stakes_map_iter = stakes_map_iter_next( *stakes_map_iter, get_stakes_map( vote_stakes, fork_idx ), get_stakes_pool( vote_stakes, fork_idx ) );
     539         901 : }
     540             : 
     541             : void
     542             : fd_vote_stakes_fork_iter_ele( fd_vote_stakes_t *      vote_stakes,
     543             :                               ushort                  fork_idx,
     544             :                               fd_vote_stakes_iter_t * iter,
     545             :                               fd_pubkey_t *           pubkey_out,
     546             :                               ulong *                 stake_t_1_out_opt,
     547             :                               ulong *                 stake_t_2_out_opt,
     548             :                               fd_pubkey_t *           node_account_t_1_out_opt,
     549         901 :                               fd_pubkey_t *           node_account_t_2_out_opt ) {
     550         901 :   stakes_map_iter_t * stakes_map_iter = (stakes_map_iter_t *)iter;
     551         901 :   stake_t * stake = stakes_map_iter_ele( *stakes_map_iter, get_stakes_map( vote_stakes, fork_idx ), get_stakes_pool( vote_stakes, fork_idx ) );
     552             : 
     553         901 :   index_ele_t * index_pool = get_index_pool( vote_stakes );
     554         901 :   index_ele_t * index_ele  = index_pool_ele( index_pool, stake->idx );
     555             : 
     556         901 :   *pubkey_out = index_ele->index_key.pubkey;
     557             : 
     558         901 :   if( stake_t_1_out_opt )        *stake_t_1_out_opt        = index_ele->index_key.stake_t_1;
     559         901 :   if( stake_t_2_out_opt )        *stake_t_2_out_opt        = index_ele->stake_t_2;
     560         901 :   if( node_account_t_1_out_opt ) *node_account_t_1_out_opt = index_ele->node_account_t_1;
     561         901 :   if( node_account_t_2_out_opt ) *node_account_t_2_out_opt = index_ele->node_account_t_2;
     562         901 : }

Generated by: LCOV version 1.14