LCOV - code coverage report
Current view: top level - flamenco/stakes - fd_stakes.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 257 0.0 %
Date: 2024-11-13 11:58:15 Functions: 0 8 0.0 %

          Line data    Source code
       1             : #include "fd_stakes.h"
       2             : #include "../runtime/fd_system_ids.h"
       3             : #include "../runtime/context/fd_exec_epoch_ctx.h"
       4             : #include "../runtime/context/fd_exec_slot_ctx.h"
       5             : #include "../runtime/program/fd_stake_program.h"
       6             : #include "../runtime/sysvar/fd_sysvar_stake_history.h"
       7             : 
       8             : /* fd_stakes_accum_by_node converts Stakes (unordered list of (vote acc,
       9             :    active stake) tuples) to StakedNodes (rbtree mapping (node identity)
      10             :    => (active stake) ordered by node identity).  Returns the tree root. */
      11             : 
      12             : static fd_stake_weight_t_mapnode_t *
      13             : fd_stakes_accum_by_node( fd_vote_accounts_t const * in,
      14           0 :                          fd_stake_weight_t_mapnode_t *    out_pool ) {
      15             : 
      16             :   /* Stakes::staked_nodes(&self: Stakes) -> HashMap<Pubkey, u64> */
      17             : 
      18           0 :   fd_vote_accounts_pair_t_mapnode_t * in_pool = in->vote_accounts_pool;
      19           0 :   fd_vote_accounts_pair_t_mapnode_t * in_root = in->vote_accounts_root;
      20             : 
      21             :   /* VoteAccounts::staked_nodes(&self: VoteAccounts) -> HashMap<Pubkey, u64> */
      22             : 
      23             :   /* For each active vote account, accumulate (node_identity, stake) by
      24             :      summing stake. */
      25             : 
      26           0 :   fd_stake_weight_t_mapnode_t * out_root = NULL;
      27             : 
      28           0 :   for( fd_vote_accounts_pair_t_mapnode_t * n = fd_vote_accounts_pair_t_map_minimum( in_pool, in_root );
      29           0 :                                            n;
      30           0 :                                            n = fd_vote_accounts_pair_t_map_successor( in_pool, n ) ) {
      31             : 
      32             :     /* ... filter(|(stake, _)| *stake != 0u64) */
      33           0 :     if( n->elem.stake == 0UL ) continue;
      34             : 
      35             :     /* Extract node pubkey */
      36           0 :     fd_pubkey_t const * node_pubkey = &n->elem.value.node_pubkey;
      37             : 
      38           0 :     fd_pubkey_t null_key = {0};
      39           0 :     if( memcmp( node_pubkey, null_key.uc, sizeof(fd_pubkey_t) ) == 0 ) {
      40           0 :       FD_LOG_WARNING(( "vote account %s skipped", FD_BASE58_ENC_32_ALLOCA( n->elem.key.key ) ));
      41           0 :       continue;
      42           0 :     }
      43             :     /* Check if node identity was previously visited */
      44           0 :     fd_stake_weight_t_mapnode_t * query = fd_stake_weight_t_map_acquire( out_pool );
      45           0 :     FD_TEST( query );
      46           0 :     query->elem.key = *node_pubkey;
      47           0 :     fd_stake_weight_t_mapnode_t * node = fd_stake_weight_t_map_find( out_pool, out_root, query );
      48             : 
      49           0 :     if( FD_UNLIKELY( node ) ) {
      50             :       /* Accumulate to previously created entry */
      51           0 :       fd_stake_weight_t_map_release( out_pool, query );
      52           0 :       node->elem.stake += n->elem.stake;
      53           0 :     } else {
      54             :       /* Create new entry */
      55           0 :       node = query;
      56           0 :       node->elem.stake = n->elem.stake;
      57           0 :       fd_stake_weight_t_map_insert( out_pool, &out_root, node );
      58           0 :     }
      59           0 :   }
      60             : 
      61           0 :   return out_root;
      62           0 : }
      63             : 
      64             : /* fd_stake_weight_sort sorts the given array of stake weights with
      65             :    length stakes_cnt by tuple (stake, pubkey) in descending order. */
      66             : 
      67             : FD_FN_CONST static int
      68             : fd_stakes_sort_before( fd_stake_weight_t a,
      69           0 :                        fd_stake_weight_t b ) {
      70             : 
      71           0 :   if( a.stake > b.stake ) return 1;
      72           0 :   if( a.stake < b.stake ) return 0;
      73           0 :   if( memcmp( &a.key, &b.key, 32UL )>0 ) return 1;
      74           0 :   return 0;
      75           0 : }
      76             : 
      77             : #define SORT_NAME        fd_stakes_sort
      78           0 : #define SORT_KEY_T       fd_stake_weight_t
      79           0 : #define SORT_BEFORE(a,b) fd_stakes_sort_before( (a), (b) )
      80             : #include "../../util/tmpl/fd_sort.c"
      81             : 
      82             : void
      83             : fd_stake_weight_sort( fd_stake_weight_t * stakes,
      84           0 :                       ulong               stakes_cnt ) {
      85           0 :   fd_stakes_sort_inplace( stakes, stakes_cnt );
      86           0 : }
      87             : 
      88             : /* fd_stakes_export_sorted converts StakedNodes (rbtree mapping
      89             :    (node identity) => (active stake) from fd_stakes_accum_by_node) to
      90             :    a list of fd_stake_weights_t. */
      91             : 
      92             : static ulong
      93             : fd_stakes_export( fd_stake_weight_t_mapnode_t const * const in_pool,
      94             :                   fd_stake_weight_t_mapnode_t const * const root,
      95           0 :                   fd_stake_weight_t *           const out ) {
      96             : 
      97           0 :   fd_stake_weight_t * out_end = out;
      98             : 
      99           0 :   for( fd_stake_weight_t_mapnode_t const * ele = fd_stake_weight_t_map_minimum( (fd_stake_weight_t_mapnode_t *)in_pool, (fd_stake_weight_t_mapnode_t *)root ); ele; ele = (fd_stake_weight_t_mapnode_t *)fd_stake_weight_t_map_successor( (fd_stake_weight_t_mapnode_t *)in_pool, (fd_stake_weight_t_mapnode_t *)ele ) ) {
     100           0 :     *out_end++ = ele->elem;
     101           0 :   }
     102             : 
     103           0 :   return (ulong)( out_end - out );
     104           0 : }
     105             : 
     106             : ulong
     107             : fd_stake_weights_by_node( fd_vote_accounts_t const * accs,
     108           0 :                           fd_stake_weight_t *        weights ) {
     109             : 
     110             :   /* Enter scratch frame for duration for function */
     111             : 
     112           0 :   if( FD_UNLIKELY( !fd_scratch_push_is_safe() ) ) {
     113           0 :     FD_LOG_WARNING(( "fd_scratch_push() failed" ));
     114           0 :     return ULONG_MAX;
     115           0 :   }
     116             : 
     117           0 :   FD_SCRATCH_SCOPE_BEGIN {
     118             : 
     119             :     /* Estimate size required to store temporary data structures */
     120             : 
     121             :     /* TODO size is the wrong method name for this */
     122           0 :     ulong vote_acc_cnt = fd_vote_accounts_pair_t_map_size( accs->vote_accounts_pool, accs->vote_accounts_root );
     123             : 
     124           0 :     ulong rb_align     = fd_stake_weight_t_map_align();
     125           0 :     ulong rb_footprint = fd_stake_weight_t_map_footprint( vote_acc_cnt );
     126             : 
     127           0 :     if( FD_UNLIKELY( !fd_scratch_alloc_is_safe( rb_align, rb_footprint ) ) ) {
     128           0 :       FD_LOG_WARNING(( "insufficient scratch space: need %lu align %lu footprint",
     129           0 :           rb_align, rb_footprint ));
     130           0 :       return ULONG_MAX;
     131           0 :     }
     132             : 
     133             :     /* Create rb tree */
     134             : 
     135           0 :     void * pool_mem = fd_scratch_alloc( rb_align, rb_footprint );
     136           0 :     pool_mem = fd_stake_weight_t_map_new( pool_mem, vote_acc_cnt );
     137           0 :     fd_stake_weight_t_mapnode_t * pool = fd_stake_weight_t_map_join( pool_mem );
     138           0 :     if( FD_UNLIKELY( !pool_mem ) ) FD_LOG_CRIT(( "fd_stake_weights_new() failed" ));
     139             : 
     140             :     /* Accumulate stakes to rb tree */
     141             : 
     142           0 :     fd_stake_weight_t_mapnode_t const * root = fd_stakes_accum_by_node( accs, pool );
     143             : 
     144             :     /* Export to sorted list */
     145             : 
     146           0 :     ulong weights_cnt = fd_stakes_export( pool, root, weights );
     147           0 :     fd_stake_weight_sort( weights, weights_cnt );
     148             : 
     149           0 :     return weights_cnt;
     150           0 :   } FD_SCRATCH_SCOPE_END;
     151           0 : }
     152             : 
     153             : /*
     154             : Refresh vote accounts.
     155             : 
     156             : This updates the epoch bank stakes vote_accounts cache - that is, the total amount
     157             : of delegated stake each vote account has, using the current delegation values from inside each
     158             : stake account.
     159             : 
     160             : https://github.com/solana-labs/solana/blob/c091fd3da8014c0ef83b626318018f238f506435/runtime/src/stakes.rs#L562 */
     161             : void
     162             : refresh_vote_accounts( fd_exec_slot_ctx_t *       slot_ctx,
     163           0 :                        fd_stake_history_t const * history ) {
     164           0 :   fd_epoch_bank_t * epoch_bank = fd_exec_epoch_ctx_epoch_bank( slot_ctx->epoch_ctx );
     165           0 :   fd_stakes_t * stakes = &epoch_bank->stakes;
     166             : 
     167           0 :   FD_SCRATCH_SCOPE_BEGIN {
     168             : 
     169             :     // Create a map of <pubkey, stake> to store the total stake of each vote account.
     170           0 :     static const ulong maplen = 10000;
     171           0 :     void * mem = fd_scratch_alloc( fd_stake_weight_t_map_align(), fd_stake_weight_t_map_footprint(maplen));
     172           0 :     fd_stake_weight_t_mapnode_t * pool = fd_stake_weight_t_map_join(fd_stake_weight_t_map_new(mem, maplen));
     173           0 :     fd_stake_weight_t_mapnode_t * root = NULL;
     174           0 :     ulong * new_rate_activation_epoch = NULL;
     175             : 
     176             :     // Iterate over each stake delegation and accumulate the stake amount associated with the given vote account.
     177           0 :     for (
     178           0 :       fd_delegation_pair_t_mapnode_t * n = fd_delegation_pair_t_map_minimum(stakes->stake_delegations_pool, stakes->stake_delegations_root);
     179           0 :       n;
     180           0 :       n = fd_delegation_pair_t_map_successor(stakes->stake_delegations_pool, n) ) {
     181             : 
     182             :         // Get the stake account
     183           0 :         FD_BORROWED_ACCOUNT_DECL(stake_acc);
     184           0 :         int rc = fd_acc_mgr_view(slot_ctx->acc_mgr, slot_ctx->funk_txn, &n->elem.account, stake_acc);
     185           0 :         if ( FD_UNLIKELY( rc != FD_ACC_MGR_SUCCESS || stake_acc->const_meta->info.lamports == 0 ) ) {
     186           0 :           continue;
     187           0 :         }
     188             : 
     189           0 :         fd_stake_state_v2_t stake_state;
     190           0 :         rc = fd_stake_get_state( stake_acc, &slot_ctx->valloc, &stake_state );
     191           0 :         if ( FD_UNLIKELY( rc != 0) ) {
     192           0 :           continue;
     193           0 :         }
     194             : 
     195             :         // Fetch the delegation associated with this stake account
     196           0 :         fd_delegation_t * delegation = &stake_state.inner.stake.stake.delegation;
     197           0 :         fd_stake_history_entry_t new_entry = fd_stake_activating_and_deactivating(
     198           0 :           delegation, stakes->epoch, history, new_rate_activation_epoch );
     199             : 
     200             :         // Add this delegation amount to the total stake of the vote account
     201           0 :         ulong delegation_stake = new_entry.effective;
     202           0 :         fd_stake_weight_t_mapnode_t temp;
     203           0 :         fd_memcpy(&temp.elem.key, &delegation->voter_pubkey, sizeof(fd_pubkey_t));
     204           0 :         fd_stake_weight_t_mapnode_t * entry  = fd_stake_weight_t_map_find(pool, root, &temp);
     205           0 :         if (entry != NULL) {
     206           0 :           entry->elem.stake += delegation_stake;
     207           0 :         } else {
     208           0 :           entry = fd_stake_weight_t_map_acquire( pool );
     209           0 :           fd_memcpy( &entry->elem.key, &delegation->voter_pubkey, sizeof(fd_pubkey_t));
     210           0 :           entry->elem.stake = delegation_stake;
     211           0 :           fd_stake_weight_t_map_insert( pool, &root, entry );
     212           0 :         }
     213           0 :     }
     214             : 
     215             :     // Also include delegations from the stake accounts in the current slot context's
     216             :     // slot_ctx->slot_bank.stake_account_keys (a set of the stake accounts which we have
     217             :     // from this epoch).
     218           0 :     for ( fd_stake_accounts_pair_t_mapnode_t * n = fd_stake_accounts_pair_t_map_minimum(
     219           0 :       slot_ctx->slot_bank.stake_account_keys.stake_accounts_pool,
     220           0 :       slot_ctx->slot_bank.stake_account_keys.stake_accounts_root);
     221           0 :           n;
     222           0 :           n = fd_stake_accounts_pair_t_map_successor( slot_ctx->slot_bank.stake_account_keys.stake_accounts_pool, n ) ) {
     223           0 :       FD_BORROWED_ACCOUNT_DECL(stake_acc);
     224           0 :       int rc = fd_acc_mgr_view(slot_ctx->acc_mgr, slot_ctx->funk_txn, &n->elem.key, stake_acc);
     225           0 :       if ( FD_UNLIKELY( rc != FD_ACC_MGR_SUCCESS || stake_acc->const_meta->info.lamports == 0 ) ) {
     226           0 :         continue;
     227           0 :       }
     228             : 
     229           0 :       fd_stake_state_v2_t stake_state;
     230           0 :       rc = fd_stake_get_state( stake_acc, &slot_ctx->valloc, &stake_state );
     231           0 :       if ( FD_UNLIKELY( rc != 0) ) {
     232           0 :         continue;
     233           0 :       }
     234             : 
     235           0 :       fd_delegation_t * delegation = &stake_state.inner.stake.stake.delegation;
     236           0 :       fd_stake_history_entry_t new_entry = fd_stake_activating_and_deactivating( delegation, stakes->epoch, history, new_rate_activation_epoch );
     237             : 
     238           0 :       ulong delegation_stake = new_entry.effective;
     239           0 :       fd_stake_weight_t_mapnode_t temp;
     240           0 :       fd_memcpy(&temp.elem.key, &delegation->voter_pubkey, sizeof(fd_pubkey_t));
     241           0 :       fd_stake_weight_t_mapnode_t * entry  = fd_stake_weight_t_map_find(pool, root, &temp);
     242           0 :       if (entry != NULL) {
     243           0 :         entry->elem.stake += delegation_stake;
     244           0 :       } else {
     245           0 :         entry = fd_stake_weight_t_map_acquire( pool );
     246           0 :         fd_memcpy( &entry->elem.key, &delegation->voter_pubkey, sizeof(fd_pubkey_t));
     247           0 :         entry->elem.stake = delegation_stake;
     248           0 :         fd_stake_weight_t_map_insert( pool, &root, entry );
     249           0 :       }
     250           0 :     }
     251             : 
     252             :     // Copy the delegated stake values calculated above to the epoch bank stakes vote_accounts
     253           0 :     for ( fd_vote_accounts_pair_t_mapnode_t * n =
     254           0 :         fd_vote_accounts_pair_t_map_minimum(
     255           0 :           stakes->vote_accounts.vote_accounts_pool, stakes->vote_accounts.vote_accounts_root);
     256           0 :           n;
     257           0 :           n = fd_vote_accounts_pair_t_map_successor(stakes->vote_accounts.vote_accounts_pool, n) ) {
     258           0 :       fd_stake_weight_t_mapnode_t temp;
     259           0 :       memcpy(&temp.elem.key, &n->elem.key, sizeof(fd_pubkey_t));
     260           0 :       fd_stake_weight_t_mapnode_t * entry = fd_stake_weight_t_map_find(pool, root, &temp);
     261           0 :       n->elem.stake = (entry == NULL) ? 0 : entry->elem.stake;
     262           0 :     }
     263             : 
     264             :     // Copy the delegated stake values calculated above to the slot bank stakes vote_accounts
     265           0 :     for ( fd_vote_accounts_pair_t_mapnode_t * n = fd_vote_accounts_pair_t_map_minimum( slot_ctx->slot_bank.vote_account_keys.vote_accounts_pool, slot_ctx->slot_bank.vote_account_keys.vote_accounts_root );
     266           0 :           n;
     267           0 :           n = fd_vote_accounts_pair_t_map_successor( slot_ctx->slot_bank.vote_account_keys.vote_accounts_pool, n )) {
     268           0 :       fd_stake_weight_t_mapnode_t temp;
     269           0 :       memcpy(&temp.elem.key, &n->elem.key, sizeof(fd_pubkey_t));
     270           0 :       fd_stake_weight_t_mapnode_t * entry = fd_stake_weight_t_map_find(pool, root, &temp);
     271           0 :       n->elem.stake = (entry == NULL) ? 0 : entry->elem.stake;
     272           0 :     }
     273             : 
     274           0 :   } FD_SCRATCH_SCOPE_END;
     275           0 : }
     276             : 
     277             : /* https://github.com/solana-labs/solana/blob/88aeaa82a856fc807234e7da0b31b89f2dc0e091/runtime/src/stakes.rs#L169 */
     278             : void
     279           0 : fd_stakes_activate_epoch( fd_exec_slot_ctx_t *  slot_ctx) {
     280             :   
     281           0 :   fd_epoch_bank_t * epoch_bank = fd_exec_epoch_ctx_epoch_bank( slot_ctx->epoch_ctx );
     282           0 :   fd_stakes_t * stakes = &epoch_bank->stakes;
     283             : 
     284             :   /* Current stake delegations: list of all current delegations in stake_delegations
     285             :      https://github.com/solana-labs/solana/blob/88aeaa82a856fc807234e7da0b31b89f2dc0e091/runtime/src/stakes.rs#L180 */
     286             :   /* Add a new entry to the Stake History sysvar for the previous epoch
     287             :      https://github.com/solana-labs/solana/blob/88aeaa82a856fc807234e7da0b31b89f2dc0e091/runtime/src/stakes.rs#L181-L192 */
     288             : 
     289           0 :   fd_stake_history_t const * history = fd_sysvar_cache_stake_history( slot_ctx->sysvar_cache );
     290           0 :    if( FD_UNLIKELY( !history ) ) FD_LOG_ERR(( "StakeHistory sysvar is missing from sysvar cache" ));
     291             : 
     292           0 :   fd_stake_history_entry_t accumulator = {
     293           0 :     .effective = 0,
     294           0 :     .activating = 0,
     295           0 :     .deactivating = 0
     296           0 :   };
     297             : 
     298           0 :   fd_stake_weight_t_mapnode_t * pool = fd_stake_weight_t_map_alloc(slot_ctx->valloc, 10000);
     299           0 :   fd_stake_weight_t_mapnode_t * root = NULL;
     300             : 
     301           0 :   ulong * new_rate_activation_epoch = NULL;
     302           0 :   for ( fd_delegation_pair_t_mapnode_t * n = fd_delegation_pair_t_map_minimum(stakes->stake_delegations_pool, stakes->stake_delegations_root); n; n = fd_delegation_pair_t_map_successor(stakes->stake_delegations_pool, n) ) {
     303           0 :     FD_BORROWED_ACCOUNT_DECL(acc);
     304           0 :     int rc = fd_acc_mgr_view(slot_ctx->acc_mgr, slot_ctx->funk_txn, &n->elem.account, acc);
     305           0 :     if ( FD_UNLIKELY( rc != FD_ACC_MGR_SUCCESS || acc->const_meta->info.lamports == 0 ) ) {
     306           0 :       continue;
     307           0 :     }
     308             : 
     309           0 :     fd_stake_state_v2_t stake_state;
     310           0 :     rc = fd_stake_get_state( acc, &slot_ctx->valloc, &stake_state );
     311           0 :     if ( FD_UNLIKELY( rc != 0) ) {
     312           0 :       continue;
     313           0 :     }
     314             : 
     315           0 :     fd_delegation_t * delegation = &stake_state.inner.stake.stake.delegation;
     316           0 :     fd_stake_history_entry_t new_entry = fd_stake_activating_and_deactivating( delegation, stakes->epoch, history, new_rate_activation_epoch );
     317           0 :     accumulator.effective += new_entry.effective;
     318           0 :     accumulator.activating += new_entry.activating;
     319           0 :     accumulator.deactivating += new_entry.deactivating;
     320             : 
     321           0 :     ulong delegation_stake = new_entry.effective;
     322           0 :     fd_stake_weight_t_mapnode_t temp;
     323           0 :     fd_memcpy(&temp.elem.key, &delegation->voter_pubkey, sizeof(fd_pubkey_t));
     324           0 :     fd_stake_weight_t_mapnode_t * entry  = fd_stake_weight_t_map_find(pool, root, &temp);
     325           0 :     if (entry != NULL) {
     326           0 :       entry->elem.stake += delegation_stake;
     327           0 :     } else {
     328           0 :       entry = fd_stake_weight_t_map_acquire( pool );
     329           0 :       fd_memcpy( &entry->elem.key, &delegation->voter_pubkey, sizeof(fd_pubkey_t));
     330           0 :       entry->elem.stake = delegation_stake;
     331           0 :       fd_stake_weight_t_map_insert( pool, &root, entry );
     332           0 :     }
     333           0 :   }
     334             : 
     335           0 :   for ( fd_stake_accounts_pair_t_mapnode_t * n = fd_stake_accounts_pair_t_map_minimum( slot_ctx->slot_bank.stake_account_keys.stake_accounts_pool, slot_ctx->slot_bank.stake_account_keys.stake_accounts_root);
     336           0 :         n;
     337           0 :         n = fd_stake_accounts_pair_t_map_successor( slot_ctx->slot_bank.stake_account_keys.stake_accounts_pool, n ) ) {
     338           0 :     FD_BORROWED_ACCOUNT_DECL(acc);
     339           0 :     int rc = fd_acc_mgr_view(slot_ctx->acc_mgr, slot_ctx->funk_txn, &n->elem.key, acc);
     340           0 :     if ( FD_UNLIKELY( rc != FD_ACC_MGR_SUCCESS || acc->const_meta->info.lamports == 0 ) ) {
     341           0 :       continue;
     342           0 :     }
     343             : 
     344           0 :     fd_stake_state_v2_t stake_state;
     345           0 :     rc = fd_stake_get_state( acc, &slot_ctx->valloc, &stake_state );
     346           0 :     if ( FD_UNLIKELY( rc != 0) ) {
     347           0 :       continue;
     348           0 :     }
     349             : 
     350           0 :     fd_delegation_t * delegation = &stake_state.inner.stake.stake.delegation;
     351           0 :     fd_stake_history_entry_t new_entry = fd_stake_activating_and_deactivating( delegation, stakes->epoch, history, new_rate_activation_epoch );
     352           0 :     accumulator.effective += new_entry.effective;
     353           0 :     accumulator.activating += new_entry.activating;
     354           0 :     accumulator.deactivating += new_entry.deactivating;
     355             : 
     356           0 :     ulong delegation_stake = new_entry.effective;
     357           0 :     fd_stake_weight_t_mapnode_t temp;
     358           0 :     fd_memcpy(&temp.elem.key, &delegation->voter_pubkey, sizeof(fd_pubkey_t));
     359           0 :     fd_stake_weight_t_mapnode_t * entry  = fd_stake_weight_t_map_find(pool, root, &temp);
     360           0 :     if (entry != NULL) {
     361           0 :       entry->elem.stake += delegation_stake;
     362           0 :     } else {
     363           0 :       entry = fd_stake_weight_t_map_acquire( pool );
     364           0 :       fd_memcpy( &entry->elem.key, &delegation->voter_pubkey, sizeof(fd_pubkey_t));
     365           0 :       entry->elem.stake = delegation_stake;
     366           0 :       fd_stake_weight_t_map_insert( pool, &root, entry );
     367           0 :     }
     368           0 :   }
     369             : 
     370           0 :   fd_stake_history_entry_t new_elem = {
     371           0 :     .epoch = stakes->epoch,
     372           0 :     .effective = accumulator.effective,
     373           0 :     .activating = accumulator.activating,
     374           0 :     .deactivating = accumulator.deactivating
     375           0 :   };
     376             : 
     377           0 :   fd_sysvar_stake_history_update( slot_ctx, &new_elem);
     378             : 
     379           0 :   fd_valloc_free( slot_ctx->valloc,
     380           0 :     fd_stake_weight_t_map_delete( fd_stake_weight_t_map_leave ( pool ) ) );
     381             : 
     382             :   /* Refresh the sysvar cache stake history entry after updating the sysvar.
     383             :       We need to do this here because it is used in subsequent places in the epoch boundary. */
     384           0 :   fd_bincode_destroy_ctx_t sysvar_cache_destroy_ctx = { .valloc = slot_ctx->sysvar_cache->valloc };
     385           0 :   fd_stake_history_destroy( slot_ctx->sysvar_cache->val_stake_history, &sysvar_cache_destroy_ctx );
     386           0 :   fd_sysvar_cache_restore_stake_history( slot_ctx->sysvar_cache, slot_ctx->acc_mgr, slot_ctx->funk_txn );
     387           0 : }
     388             : 
     389             : int
     390             : write_stake_state( fd_borrowed_account_t *  stake_acc_rec,
     391           0 :                    fd_stake_state_v2_t *    stake_state ) {
     392             : 
     393           0 :   ulong encoded_stake_state_size = fd_stake_state_v2_size(stake_state);
     394             : 
     395           0 :   fd_bincode_encode_ctx_t ctx = {
     396           0 :     .data = stake_acc_rec->data,
     397           0 :     .dataend = stake_acc_rec->data + encoded_stake_state_size,
     398           0 :   };
     399           0 :   if( FD_UNLIKELY( fd_stake_state_v2_encode( stake_state, &ctx ) != FD_BINCODE_SUCCESS ) ) {
     400           0 :     FD_LOG_ERR(( "fd_stake_state_encode failed" ));
     401           0 :   }
     402             : 
     403           0 :   return 0;
     404           0 : }

Generated by: LCOV version 1.14