LCOV - code coverage report
Current view: top level - flamenco/runtime/sysvar - fd_sysvar_epoch_rewards.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 24 70 34.3 %
Date: 2026-02-01 06:05:50 Functions: 2 5 40.0 %

          Line data    Source code
       1             : #include "fd_sysvar_epoch_rewards.h"
       2             : #include "fd_sysvar.h"
       3             : #include "../fd_system_ids.h"
       4             : #include "../../accdb/fd_accdb_sync.h"
       5             : 
       6             : static void
       7             : write_epoch_rewards( fd_bank_t *                 bank,
       8             :                      fd_accdb_user_t *           accdb,
       9             :                      fd_funk_txn_xid_t const *   xid,
      10             :                      fd_capture_ctx_t *          capture_ctx,
      11          30 :                      fd_sysvar_epoch_rewards_t * epoch_rewards ) {
      12          30 :   ulong sz = fd_sysvar_epoch_rewards_size( epoch_rewards );
      13          30 :   uchar enc[sz];
      14          30 :   fd_memset( enc, 0, sz );
      15          30 :   fd_bincode_encode_ctx_t ctx = {
      16          30 :     .data    = enc,
      17          30 :     .dataend = enc + sz
      18          30 :   };
      19          30 :   if( FD_UNLIKELY( fd_sysvar_epoch_rewards_encode( epoch_rewards, &ctx ) ) ) {
      20           0 :     FD_LOG_ERR(( "fd_sysvar_epoch_rewards_encode failed" ));
      21           0 :   }
      22             : 
      23          30 :   fd_sysvar_account_update( bank, accdb, xid, capture_ctx, &fd_sysvar_epoch_rewards_id, enc, sz );
      24          30 : }
      25             : 
      26             : fd_sysvar_epoch_rewards_t *
      27             : fd_sysvar_epoch_rewards_read( fd_accdb_user_t *           accdb,
      28             :                               fd_funk_txn_xid_t const *   xid,
      29           0 :                               fd_sysvar_epoch_rewards_t * out ) {
      30           0 :   fd_accdb_ro_t ro[1];
      31           0 :   if( FD_UNLIKELY( !fd_accdb_open_ro( accdb, ro, xid, &fd_sysvar_epoch_rewards_id ) ) ) {
      32           0 :     return NULL;
      33           0 :   }
      34             : 
      35             :   /* This check is needed as a quirk of the fuzzer. If a sysvar account
      36             :      exists in the accounts database, but doesn't have any lamports,
      37             :      this means that the account does not exist. This wouldn't happen
      38             :      in a real execution environment. */
      39           0 :   if( FD_UNLIKELY( fd_accdb_ref_lamports( ro )==0UL ) ) {
      40           0 :     fd_accdb_close_ro( accdb, ro );
      41           0 :     return NULL;
      42           0 :   }
      43             : 
      44           0 :   out = fd_bincode_decode_static(
      45           0 :       sysvar_epoch_rewards, out,
      46           0 :       fd_accdb_ref_data_const( ro ),
      47           0 :       fd_accdb_ref_data_sz   ( ro ),
      48           0 :       NULL );
      49           0 :   fd_accdb_close_ro( accdb, ro );
      50           0 :   return out;
      51           0 : }
      52             : 
      53             : /* Since there are multiple sysvar epoch rewards updates within a single slot,
      54             :    we need to ensure that the cache stays updated after each change (versus with other
      55             :    sysvars which only get updated once per slot and then synced up after) */
      56             : void
      57             : fd_sysvar_epoch_rewards_distribute( fd_bank_t *               bank,
      58             :                                     fd_accdb_user_t *         accdb,
      59             :                                     fd_funk_txn_xid_t const * xid,
      60             :                                     fd_capture_ctx_t *        capture_ctx,
      61           0 :                                     ulong                     distributed ) {
      62           0 :   fd_sysvar_epoch_rewards_t epoch_rewards[1];
      63           0 :   if( FD_UNLIKELY( !fd_sysvar_epoch_rewards_read( accdb, xid, epoch_rewards ) ) ) {
      64           0 :     FD_LOG_ERR(( "failed to read sysvar epoch rewards" ));
      65           0 :   }
      66             : 
      67           0 :   if( FD_UNLIKELY( !epoch_rewards->active ) ) {
      68           0 :     FD_LOG_ERR(( "sysvar epoch rewards is not active" ));
      69           0 :   }
      70             : 
      71           0 :   if( FD_UNLIKELY( fd_ulong_sat_add( epoch_rewards->distributed_rewards, distributed ) > epoch_rewards->total_rewards ) ) {
      72           0 :     FD_LOG_ERR(( "distributed rewards overflow" ));
      73           0 :   }
      74             : 
      75           0 :   epoch_rewards->distributed_rewards += distributed;
      76             : 
      77           0 :   write_epoch_rewards( bank, accdb, xid, capture_ctx, epoch_rewards );
      78           0 : }
      79             : 
      80             : void
      81             : fd_sysvar_epoch_rewards_set_inactive( fd_bank_t *               bank,
      82             :                                       fd_accdb_user_t *         accdb,
      83             :                                       fd_funk_txn_xid_t const * xid,
      84           0 :                                       fd_capture_ctx_t *        capture_ctx ) {
      85           0 :   fd_sysvar_epoch_rewards_t epoch_rewards[1];
      86           0 :   if( FD_UNLIKELY( !fd_sysvar_epoch_rewards_read( accdb, xid, epoch_rewards ) ) ) {
      87           0 :     FD_LOG_ERR(( "failed to read sysvar epoch rewards" ));
      88           0 :   }
      89             : 
      90           0 :   if( FD_UNLIKELY( epoch_rewards->total_rewards < epoch_rewards->distributed_rewards ) ) {
      91           0 :     FD_LOG_ERR(( "distributed rewards overflow" ));
      92           0 :   }
      93             : 
      94           0 :   epoch_rewards->active = 0;
      95             : 
      96           0 :   write_epoch_rewards( bank, accdb, xid, capture_ctx, epoch_rewards );
      97           0 : }
      98             : 
      99             : /* Create EpochRewards sysvar with calculated rewards
     100             : 
     101             :    https://github.com/anza-xyz/agave/blob/cbc8320d35358da14d79ebcada4dfb6756ffac79/runtime/src/bank/partitioned_epoch_rewards/sysvar.rs#L25 */
     102             : void
     103             : fd_sysvar_epoch_rewards_init( fd_bank_t *               bank,
     104             :                               fd_accdb_user_t *         accdb,
     105             :                               fd_funk_txn_xid_t const * xid,
     106             :                               fd_capture_ctx_t *        capture_ctx,
     107             :                               ulong                     distributed_rewards,
     108             :                               ulong                     distribution_starting_block_height,
     109             :                               ulong                     num_partitions,
     110             :                               ulong                     total_rewards,
     111             :                               uint128                   total_points,
     112          30 :                               fd_hash_t const *         last_blockhash ) {
     113          30 :   fd_sysvar_epoch_rewards_t epoch_rewards = {
     114          30 :     .distribution_starting_block_height = distribution_starting_block_height,
     115          30 :     .num_partitions                     = num_partitions,
     116          30 :     .total_points                       = { .ud=total_points },
     117          30 :     .total_rewards                      = total_rewards,
     118          30 :     .distributed_rewards                = distributed_rewards,
     119          30 :     .active                             = 1,
     120          30 :     .parent_blockhash                   = *last_blockhash
     121          30 :   };
     122             : 
     123          30 :   if( FD_UNLIKELY( epoch_rewards.total_rewards<distributed_rewards ) ) {
     124           0 :     FD_LOG_ERR(( "total rewards overflow" ));
     125           0 :   }
     126             : 
     127          30 :   write_epoch_rewards( bank, accdb, xid, capture_ctx, &epoch_rewards );
     128          30 : }

Generated by: LCOV version 1.14