LCOV - code coverage report
Current view: top level - flamenco/rewards - fd_epoch_inflation_account.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 79 93 84.9 %
Date: 2026-10-25 04:27:46 Functions: 12 35 34.3 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_rewards_fd_epoch_inflation_account_h
       2             : #define HEADER_fd_src_flamenco_rewards_fd_epoch_inflation_account_h
       3             : 
       4             : #include "../features/fd_features.h"
       5             : #include "../runtime/fd_accdb_svm.h"
       6             : #include "../runtime/fd_bank.h"
       7             : #include "../runtime/fd_pubkey_utils.h"
       8             : #include "../runtime/fd_system_ids.h"
       9             : #include "../runtime/sysvar/fd_sysvar_rent.h"
      10             : 
      11             : /* https://github.com/anza-xyz/agave/blob/v4.3.0-beta.0/runtime/src/block_component_processor/vote_reward/epoch_inflation_account_state.rs#L14-L175 */
      12        3129 : #define FD_EPOCH_INFLATION_STATE_SZ     (24UL)
      13          27 : #define FD_EPOCH_INFLATION_ACCOUNT_NONE (25UL)
      14          24 : #define FD_EPOCH_INFLATION_ACCOUNT_SOME (49UL)
      15             : 
      16             : struct fd_epoch_inflation_state {
      17             :   ulong max_possible_validator_reward;
      18             :   ulong slots_per_epoch;
      19             :   ulong epoch;
      20             : };
      21             : typedef struct fd_epoch_inflation_state fd_epoch_inflation_state_t;
      22             : 
      23             : struct fd_epoch_inflation_account_state {
      24             :   fd_epoch_inflation_state_t current;
      25             :   int                        has_prev;
      26             :   fd_epoch_inflation_state_t prev;
      27             : };
      28             : typedef struct fd_epoch_inflation_account_state fd_epoch_inflation_account_state_t;
      29             : 
      30             : static inline fd_pubkey_t
      31        3129 : fd_epoch_inflation_account_address( void ) {
      32        3129 :   fd_feature_id_t const * feature_id  = &ids[ offsetof( fd_features_t, alpenglow )>>3 ];
      33        3129 :   fd_pubkey_t const *     program_id  = &feature_id->id;
      34        3129 :   uchar const             seed[]      = "vote_reward_account";
      35        3129 :   uchar const *           seeds[1]    = { seed };
      36        3129 :   ulong                   seed_szs[1] = { sizeof(seed)-1UL };
      37        3129 :   fd_pubkey_t             address[1];
      38        3129 :   uchar                   bump_seed;
      39        3129 :   uint                    custom_err  = 0U;
      40        3129 :   FD_TEST( !fd_pubkey_find_program_address( program_id, 1UL, seeds, seed_szs, address, &bump_seed, &custom_err ) );
      41        3129 :   return *address;
      42        3129 : }
      43             : 
      44             : static inline fd_epoch_inflation_state_t
      45        3084 : fd_epoch_inflation_state_decode( uchar const * data ) {
      46        3084 :   return (fd_epoch_inflation_state_t) {
      47        3084 :     .max_possible_validator_reward = FD_LOAD( ulong, data      ),
      48        3084 :     .slots_per_epoch               = FD_LOAD( ulong, data+8UL  ),
      49        3084 :     .epoch                         = FD_LOAD( ulong, data+16UL ),
      50        3084 :   };
      51        3084 : }
      52             : 
      53             : static inline int
      54             : fd_epoch_inflation_account_read( fd_bank_t const *                    bank,
      55             :                                  fd_accdb_t *                         accdb,
      56        3081 :                                  fd_epoch_inflation_account_state_t * state ) {
      57        3081 :   fd_pubkey_t address = fd_epoch_inflation_account_address();
      58        3081 :   fd_acc_t    acc     = fd_accdb_read_one( accdb, bank->accdb_fork_id, address.uc );
      59        3081 :   if( FD_UNLIKELY( !acc.lamports ||
      60        3081 :                    memcmp( acc.owner, fd_solana_system_program_id.uc, sizeof(fd_pubkey_t) ) ||
      61        3081 :                    (acc.data_len!=FD_EPOCH_INFLATION_ACCOUNT_NONE &&
      62        3081 :                     acc.data_len!=FD_EPOCH_INFLATION_ACCOUNT_SOME) ) ) {
      63           0 :     fd_accdb_unread_one( accdb, &acc );
      64           0 :     return 0;
      65           0 :   }
      66             : 
      67        3081 :   state->current = fd_epoch_inflation_state_decode( acc.data );
      68        3081 :   if( FD_UNLIKELY( acc.data[ FD_EPOCH_INFLATION_STATE_SZ ]>1U ) ) {
      69           0 :     fd_accdb_unread_one( accdb, &acc );
      70           0 :     return 0;
      71           0 :   }
      72        3081 :   state->has_prev = !!acc.data[ FD_EPOCH_INFLATION_STATE_SZ ];
      73        3081 :   if( FD_UNLIKELY( state->has_prev!=(acc.data_len==FD_EPOCH_INFLATION_ACCOUNT_SOME) ) ) {
      74           0 :     fd_accdb_unread_one( accdb, &acc );
      75           0 :     return 0;
      76           0 :   }
      77        3081 :   if( state->has_prev ) state->prev = fd_epoch_inflation_state_decode( acc.data+FD_EPOCH_INFLATION_ACCOUNT_NONE );
      78        3081 :   fd_accdb_unread_one( accdb, &acc );
      79        3081 :   return 1;
      80        3081 : }
      81             : 
      82             : static inline ulong
      83             : fd_epoch_inflation_rewards_for_epoch( fd_bank_t const * bank,
      84             :                                       fd_accdb_t *      accdb,
      85          24 :                                       ulong             epoch ) {
      86          24 :   fd_epoch_inflation_account_state_t state[1];
      87          24 :   if( FD_UNLIKELY( !fd_epoch_inflation_account_read( bank, accdb, state ) ) ) {
      88           0 :     FD_LOG_CRIT(( "missing epoch inflation account state for Alpenglow reward epoch %lu", epoch ));
      89           0 :   }
      90          24 :   if( state->current.epoch==epoch ) return state->current.max_possible_validator_reward;
      91           0 :   if( state->has_prev && state->prev.epoch==epoch ) return state->prev.max_possible_validator_reward;
      92           0 :   FD_LOG_CRIT(( "missing epoch inflation state for Alpenglow reward epoch %lu", epoch ));
      93           0 : }
      94             : 
      95             : /* fd_epoch_inflation_account_encode writes the account data of state
      96             :    to data, which has room for FD_EPOCH_INFLATION_ACCOUNT_SOME bytes.
      97             :    Returns the data size. */
      98             : 
      99             : static inline ulong
     100             : fd_epoch_inflation_account_encode( uchar                                      data[ static FD_EPOCH_INFLATION_ACCOUNT_SOME ],
     101          48 :                                    fd_epoch_inflation_account_state_t const * state ) {
     102          48 :   FD_STORE( ulong, data,      state->current.max_possible_validator_reward );
     103          48 :   FD_STORE( ulong, data+8UL,  state->current.slots_per_epoch               );
     104          48 :   FD_STORE( ulong, data+16UL, state->current.epoch                         );
     105          48 :   data[ FD_EPOCH_INFLATION_STATE_SZ ] = (uchar)!!state->has_prev;
     106          48 :   if( !state->has_prev ) return FD_EPOCH_INFLATION_ACCOUNT_NONE;
     107          24 :   FD_STORE( ulong, data+25UL, state->prev.max_possible_validator_reward );
     108          24 :   FD_STORE( ulong, data+33UL, state->prev.slots_per_epoch               );
     109          24 :   FD_STORE( ulong, data+41UL, state->prev.epoch                         );
     110          24 :   return FD_EPOCH_INFLATION_ACCOUNT_SOME;
     111          48 : }
     112             : 
     113             : static inline void
     114             : fd_epoch_inflation_account_write( fd_bank_t *                                bank,
     115             :                                   fd_accdb_t *                               accdb,
     116             :                                   fd_capture_ctx_t *                         capture_ctx,
     117          24 :                                   fd_epoch_inflation_account_state_t const * state ) {
     118          24 :   uchar data[ FD_EPOCH_INFLATION_ACCOUNT_SOME ];
     119          24 :   ulong data_sz = fd_epoch_inflation_account_encode( data, state );
     120             : 
     121          24 :   fd_pubkey_t           address = fd_epoch_inflation_account_address();
     122          24 :   fd_accdb_svm_update_t update[1];
     123          24 :   fd_acc_t              acc     = fd_accdb_svm_open_rw( bank, accdb, update, &address, 1 );
     124          24 :   acc.lamports = fd_ulong_max( fd_rent_exempt_minimum_balance( &bank->f.rent, data_sz ), 1UL );
     125          24 :   fd_memcpy( acc.owner, fd_solana_system_program_id.uc, sizeof(fd_pubkey_t) );
     126          24 :   acc.executable = 0;
     127          24 :   acc.data_len   = data_sz;
     128          24 :   fd_memcpy( acc.data, data, data_sz );
     129          24 :   fd_accdb_svm_close_rw( bank, accdb, capture_ctx, &acc, update );
     130          24 : }
     131             : 
     132             : /* https://github.com/anza-xyz/agave/blob/v4.3.0-beta.0/runtime/src/block_component_processor/vote_reward/epoch_inflation_account_state.rs#L147-L160 */
     133             : static inline void
     134             : fd_epoch_inflation_account_update( fd_bank_t *        bank,
     135             :                                    fd_accdb_t *       accdb,
     136             :                                    fd_capture_ctx_t * capture_ctx,
     137          24 :                                    ulong              max_possible_validator_reward ) {
     138          24 :   fd_epoch_inflation_account_state_t old_state[1];
     139          24 :   int                                has_old_state = fd_epoch_inflation_account_read( bank, accdb, old_state );
     140             : 
     141          24 :   fd_epoch_inflation_account_state_t new_state = {
     142          24 :     .current  = {
     143          24 :       .max_possible_validator_reward = max_possible_validator_reward,
     144          24 :       .slots_per_epoch               = bank->f.epoch_schedule.slots_per_epoch,
     145          24 :       .epoch                         = bank->f.epoch,
     146          24 :     },
     147          24 :     .has_prev = has_old_state,
     148          24 :   };
     149          24 :   if( has_old_state ) new_state.prev = old_state->current;
     150          24 :   fd_epoch_inflation_account_write( bank, accdb, capture_ctx, &new_state );
     151          24 : }
     152             : 
     153             : #endif /* HEADER_fd_src_flamenco_rewards_fd_epoch_inflation_account_h */

Generated by: LCOV version 1.14