LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_runtime_stack.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 53 59 89.8 %
Date: 2026-03-19 18:19:27 Functions: 5 80 6.2 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_runtime_fd_runtime_stack_h
       2             : #define HEADER_fd_src_flamenco_runtime_fd_runtime_stack_h
       3             : 
       4             : #include "../types/fd_types_custom.h"
       5             : #include "sysvar/fd_sysvar_clock.h"
       6             : #include "program/fd_builtin_programs.h"
       7             : #include "fd_runtime_const.h"
       8             : 
       9             : /* https://github.com/anza-xyz/agave/blob/cbc8320d35358da14d79ebcada4dfb6756ffac79/programs/stake/src/points.rs#L27 */
      10             : struct fd_calculated_stake_points {
      11             :   fd_w_u128_t points;
      12             :   ulong       new_credits_observed;
      13             :   uchar       force_credits_update_with_skipped_reward;
      14             : };
      15             : typedef struct fd_calculated_stake_points fd_calculated_stake_points_t;
      16             : 
      17             : /* https://github.com/anza-xyz/agave/blob/cbc8320d35358da14d79ebcada4dfb6756ffac79/programs/stake/src/rewards.rs#L24 */
      18             : struct fd_calculated_stake_rewards {
      19             :   ulong staker_rewards;
      20             :   ulong voter_rewards;
      21             :   ulong new_credits_observed;
      22             :   uchar success;
      23             : };
      24             : typedef struct fd_calculated_stake_rewards fd_calculated_stake_rewards_t;
      25             : 
      26             : /* fd_vote_ele and fd_vote_ele_map are used to temporarily cache
      27             :    computed fields for vote accounts during epoch boundary stake
      28             :    and rewards calculations. */
      29             : 
      30             : struct fd_epoch_credits {
      31             :   ulong  cnt;
      32             :   ushort epoch       [ FD_EPOCH_CREDITS_MAX ];
      33             :   ulong  credits     [ FD_EPOCH_CREDITS_MAX ];
      34             :   ulong  prev_credits[ FD_EPOCH_CREDITS_MAX ];
      35             : };
      36             : typedef struct fd_epoch_credits fd_epoch_credits_t;
      37             : 
      38             : struct fd_vote_rewards {
      39             :   fd_pubkey_t        pubkey;
      40             :   ulong              vote_rewards;
      41             :   uint               next;
      42             :   uchar              commission;
      43             : };
      44             : typedef struct fd_vote_rewards fd_vote_rewards_t;
      45             : 
      46             : #define MAP_NAME               fd_vote_rewards_map
      47             : #define MAP_KEY_T              fd_pubkey_t
      48             : #define MAP_ELE_T              fd_vote_rewards_t
      49         301 : #define MAP_KEY                pubkey
      50           6 : #define MAP_KEY_EQ(k0,k1)      (!memcmp( k0, k1, sizeof(fd_pubkey_t) ))
      51         307 : #define MAP_KEY_HASH(key,seed) (fd_hash( seed, key, sizeof(fd_pubkey_t) ))
      52         303 : #define MAP_NEXT               next
      53         630 : #define MAP_IDX_T              uint
      54             : #include "../../util/tmpl/fd_map_chain.c"
      55             : 
      56             : #define FD_VOTE_ELE_MAP_ALIGN     (128UL)
      57             : 
      58             : FD_FN_PURE static inline ulong
      59          36 : fd_vote_ele_map_footprint( ulong max_vote_accounts ) {
      60          36 :   return sizeof(fd_vote_rewards_map_t) + max_vote_accounts * sizeof(uint);
      61          36 : }
      62             : 
      63             : /* fd_runtime_stack_t serves as stack memory to store temporary data
      64             :    for the runtime.  This object should only be used and owned by the
      65             :    replay tile and is used for short-lived allocations for the runtime,
      66             :    more specifically, for slot level calculations. */
      67             : struct fd_runtime_stack {
      68             : 
      69             :   ulong max_vote_accounts;
      70             :   ulong expected_vote_accounts;
      71             :   ulong expected_stake_accounts;
      72             : 
      73             :   struct {
      74             :     /* Staging memory to sort vote accounts by last vote timestamp for
      75             :        clock sysvar calculation. */
      76             :     ts_est_ele_t * staked_ts;
      77             :   } clock_ts;
      78             : 
      79             :   struct {
      80             :     /* Staging memory for bpf migration.  This is used to store and
      81             :        stage various accounts which is required for deploying a new BPF
      82             :        program at the epoch boundary. */
      83             :     fd_tmp_account_t source;
      84             :     fd_tmp_account_t program_account;
      85             :     fd_tmp_account_t new_target_program;
      86             :     fd_tmp_account_t new_target_program_data;
      87             :     fd_tmp_account_t empty;
      88             :   } bpf_migration;
      89             : 
      90             :   struct {
      91             :     fd_calculated_stake_points_t *  stake_points_result;
      92             : 
      93             :     fd_calculated_stake_rewards_t * stake_rewards_result;
      94             : 
      95             :     ulong       total_rewards;
      96             :     ulong       distributed_rewards;
      97             :     fd_w_u128_t total_points;
      98             : 
      99             :     ulong stake_rewards_cnt;
     100             : 
     101             :     /* Staging memory used for calculating and sorting vote account
     102             :        stake weights for the leader schedule calculation. */
     103             :     fd_vote_stake_weight_t * stake_weights;
     104             : 
     105             :     fd_vote_rewards_t * vote_ele;
     106             :     void *              vote_map_mem;
     107             : 
     108             :     fd_epoch_credits_t * epoch_credits;
     109             : 
     110             :   } stakes;
     111             : };
     112             : typedef struct fd_runtime_stack fd_runtime_stack_t;
     113             : 
     114             : FD_FN_CONST static inline ulong
     115          84 : fd_runtime_stack_align( void ) {
     116          84 :   return 128UL;
     117          84 : }
     118             : 
     119             : FD_FN_PURE static inline ulong
     120             : fd_runtime_stack_footprint( ulong max_vote_accounts,
     121             :                             ulong expected_vote_accounts,
     122          24 :                             ulong expected_stake_accounts ) {
     123          24 :   ulong chain_cnt = fd_vote_rewards_map_chain_cnt_est( expected_vote_accounts );
     124          24 :   ulong l = FD_LAYOUT_INIT;
     125          24 :   l = FD_LAYOUT_APPEND( l, alignof(fd_runtime_stack_t),           sizeof(fd_runtime_stack_t) );
     126          24 :   l = FD_LAYOUT_APPEND( l, alignof(ts_est_ele_t),                 sizeof(ts_est_ele_t) * max_vote_accounts );
     127          24 :   l = FD_LAYOUT_APPEND( l, alignof(fd_vote_stake_weight_t),       sizeof(fd_vote_stake_weight_t) * max_vote_accounts );
     128          24 :   l = FD_LAYOUT_APPEND( l, 128UL,                                 sizeof(fd_vote_rewards_t) * max_vote_accounts );
     129          24 :   l = FD_LAYOUT_APPEND( l, FD_VOTE_ELE_MAP_ALIGN,                 fd_vote_ele_map_footprint( chain_cnt ) );
     130          24 :   l = FD_LAYOUT_APPEND( l, alignof(fd_epoch_credits_t),           sizeof(fd_epoch_credits_t) * expected_vote_accounts );
     131          24 :   l = FD_LAYOUT_APPEND( l, alignof(fd_calculated_stake_points_t), sizeof(fd_calculated_stake_points_t) * expected_stake_accounts );
     132          24 :   l = FD_LAYOUT_APPEND( l, alignof(fd_calculated_stake_rewards_t),sizeof(fd_calculated_stake_rewards_t) * expected_stake_accounts );
     133          24 :   return FD_LAYOUT_FINI( l, fd_runtime_stack_align() );
     134          24 : }
     135             : 
     136             : static inline void *
     137             : fd_runtime_stack_new( void * shmem,
     138             :                       ulong  max_vote_accounts,
     139             :                       ulong  expected_vote_accounts,
     140             :                       ulong  expected_stake_accounts,
     141          12 :                       ulong  seed ) {
     142          12 :   if( FD_UNLIKELY( !shmem ) ) return NULL;
     143          12 :   ulong chain_cnt = fd_vote_rewards_map_chain_cnt_est( expected_vote_accounts );
     144          12 :   FD_SCRATCH_ALLOC_INIT( l, shmem );
     145          12 :   fd_runtime_stack_t *            runtime_stack        = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_runtime_stack_t),            sizeof(fd_runtime_stack_t) );
     146          12 :   ts_est_ele_t *                  staked_ts            = FD_SCRATCH_ALLOC_APPEND( l, alignof(ts_est_ele_t),                  sizeof(ts_est_ele_t) * max_vote_accounts );
     147          12 :   fd_vote_stake_weight_t *        stake_weights        = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_vote_stake_weight_t),        sizeof(fd_vote_stake_weight_t) * max_vote_accounts );
     148          12 :   fd_vote_rewards_t *             vote_ele             = FD_SCRATCH_ALLOC_APPEND( l, 128UL,                                  sizeof(fd_vote_rewards_t) * max_vote_accounts );
     149          12 :   void *                          vote_map_mem         = FD_SCRATCH_ALLOC_APPEND( l, FD_VOTE_ELE_MAP_ALIGN,                  fd_vote_ele_map_footprint( chain_cnt ) );
     150          12 :   fd_epoch_credits_t *            epoch_credits        = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_epoch_credits_t),            sizeof(fd_epoch_credits_t) * expected_vote_accounts );
     151          12 :   fd_calculated_stake_points_t *  stake_points_result  = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_calculated_stake_points_t),  sizeof(fd_calculated_stake_points_t) * expected_stake_accounts );
     152          12 :   fd_calculated_stake_rewards_t * stake_rewards_result = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_calculated_stake_rewards_t), sizeof(fd_calculated_stake_rewards_t) * expected_stake_accounts );
     153          12 :   if( FD_UNLIKELY( FD_SCRATCH_ALLOC_FINI( l, fd_runtime_stack_align() )!=(ulong)shmem + fd_runtime_stack_footprint( max_vote_accounts, expected_vote_accounts, expected_stake_accounts ) ) ) {
     154           0 :     FD_LOG_WARNING(( "fd_runtime_stack_new: bad layout" ));
     155           0 :     return NULL;
     156           0 :   }
     157             : 
     158          12 :   runtime_stack->max_vote_accounts           = max_vote_accounts;
     159          12 :   runtime_stack->expected_vote_accounts      = expected_vote_accounts;
     160          12 :   runtime_stack->expected_stake_accounts     = expected_stake_accounts;
     161          12 :   runtime_stack->clock_ts.staked_ts          = staked_ts;
     162          12 :   runtime_stack->stakes.stake_weights        = stake_weights;
     163          12 :   runtime_stack->stakes.vote_ele             = vote_ele;
     164          12 :   runtime_stack->stakes.vote_map_mem         = vote_map_mem;
     165          12 :   runtime_stack->stakes.epoch_credits        = epoch_credits;
     166          12 :   runtime_stack->stakes.stake_points_result  = stake_points_result;
     167          12 :   runtime_stack->stakes.stake_rewards_result = stake_rewards_result;
     168             : 
     169          12 :   if( FD_UNLIKELY( !fd_vote_rewards_map_join( fd_vote_rewards_map_new( runtime_stack->stakes.vote_map_mem, chain_cnt, seed ) ) ) ) {
     170           0 :     FD_LOG_WARNING(( "fd_runtime_stack_new: bad map" ));
     171           0 :     return NULL;
     172           0 :   }
     173          12 :   return shmem;
     174          12 : }
     175             : 
     176             : FD_FN_CONST static inline fd_runtime_stack_t *
     177          12 : fd_runtime_stack_join( void * shruntime_stack ) {
     178          12 :   return (fd_runtime_stack_t *)shruntime_stack;
     179          12 : }
     180             : 
     181             : #endif /* HEADER_fd_src_flamenco_runtime_fd_runtime_stack_h */

Generated by: LCOV version 1.14