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: 0 70 0.0 %
Date: 2025-12-18 05:07:35 Functions: 0 5 0.0 %

          Line data    Source code
       1             : #include "fd_sysvar_epoch_rewards.h"
       2             : #include "fd_sysvar.h"
       3             : #include "../fd_acc_mgr.h"
       4             : #include "../fd_txn_account.h"
       5             : #include "../fd_system_ids.h"
       6             : #include "../../accdb/fd_accdb_impl_v1.h"
       7             : 
       8             : static void
       9             : write_epoch_rewards( fd_bank_t *                 bank,
      10             :                      fd_accdb_user_t *           accdb,
      11             :                      fd_funk_txn_xid_t const *   xid,
      12             :                      fd_capture_ctx_t *          capture_ctx,
      13           0 :                      fd_sysvar_epoch_rewards_t * epoch_rewards ) {
      14           0 :   ulong sz = fd_sysvar_epoch_rewards_size( epoch_rewards );
      15           0 :   uchar enc[sz];
      16           0 :   fd_memset( enc, 0, sz );
      17           0 :   fd_bincode_encode_ctx_t ctx = {
      18           0 :     .data    = enc,
      19           0 :     .dataend = enc + sz
      20           0 :   };
      21           0 :   if( FD_UNLIKELY( fd_sysvar_epoch_rewards_encode( epoch_rewards, &ctx ) ) ) {
      22           0 :     FD_LOG_ERR(( "fd_sysvar_epoch_rewards_encode failed" ));
      23           0 :   }
      24             : 
      25           0 :   fd_sysvar_account_update( bank, accdb, xid, capture_ctx, &fd_sysvar_epoch_rewards_id, enc, sz );
      26           0 : }
      27             : 
      28             : fd_sysvar_epoch_rewards_t *
      29             : fd_sysvar_epoch_rewards_read( fd_funk_t *                 funk,
      30             :                               fd_funk_txn_xid_t const *   xid,
      31           0 :                               fd_sysvar_epoch_rewards_t * out ) {
      32           0 :   fd_txn_account_t acc[1];
      33           0 :   int err = fd_txn_account_init_from_funk_readonly( acc, &fd_sysvar_epoch_rewards_id, funk, xid );
      34           0 :   if( FD_UNLIKELY( err != FD_ACC_MGR_SUCCESS ) ) {
      35           0 :     return NULL;
      36           0 :   }
      37             : 
      38             :   /* This check is needed as a quirk of the fuzzer. If a sysvar account
      39             :      exists in the accounts database, but doesn't have any lamports,
      40             :      this means that the account does not exist. This wouldn't happen
      41             :      in a real execution environment. */
      42           0 :   if( FD_UNLIKELY( fd_txn_account_get_lamports( acc )==0UL ) ) {
      43           0 :     return NULL;
      44           0 :   }
      45             : 
      46           0 :   return fd_bincode_decode_static(
      47           0 :       sysvar_epoch_rewards, out,
      48           0 :       fd_txn_account_get_data( acc ),
      49           0 :       fd_txn_account_get_data_len( acc ),
      50           0 :       &err );
      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_funk_t * funk = fd_accdb_user_v1_funk( accdb );
      63           0 :   fd_sysvar_epoch_rewards_t epoch_rewards[1];
      64           0 :   if( FD_UNLIKELY( !fd_sysvar_epoch_rewards_read( funk, xid, epoch_rewards ) ) ) {
      65           0 :     FD_LOG_ERR(( "failed to read sysvar epoch rewards" ));
      66           0 :   }
      67             : 
      68           0 :   if( FD_UNLIKELY( !epoch_rewards->active ) ) {
      69           0 :     FD_LOG_ERR(( "sysvar epoch rewards is not active" ));
      70           0 :   }
      71             : 
      72           0 :   if( FD_UNLIKELY( fd_ulong_sat_add( epoch_rewards->distributed_rewards, distributed ) > epoch_rewards->total_rewards ) ) {
      73           0 :     FD_LOG_ERR(( "distributed rewards overflow" ));
      74           0 :   }
      75             : 
      76           0 :   epoch_rewards->distributed_rewards += distributed;
      77             : 
      78           0 :   write_epoch_rewards( bank, accdb, xid, capture_ctx, epoch_rewards );
      79           0 : }
      80             : 
      81             : void
      82             : fd_sysvar_epoch_rewards_set_inactive( fd_bank_t *               bank,
      83             :                                       fd_accdb_user_t *         accdb,
      84             :                                       fd_funk_txn_xid_t const * xid,
      85           0 :                                       fd_capture_ctx_t *        capture_ctx ) {
      86           0 :   fd_funk_t * funk = fd_accdb_user_v1_funk( accdb );
      87           0 :   fd_sysvar_epoch_rewards_t epoch_rewards[1];
      88           0 :   if( FD_UNLIKELY( !fd_sysvar_epoch_rewards_read( funk, xid, epoch_rewards ) ) ) {
      89           0 :     FD_LOG_ERR(( "failed to read sysvar epoch rewards" ));
      90           0 :   }
      91             : 
      92           0 :   if( FD_UNLIKELY( epoch_rewards->total_rewards < epoch_rewards->distributed_rewards ) ) {
      93           0 :     FD_LOG_ERR(( "distributed rewards overflow" ));
      94           0 :   }
      95             : 
      96           0 :   epoch_rewards->active = 0;
      97             : 
      98           0 :   write_epoch_rewards( bank, accdb, xid, capture_ctx, epoch_rewards );
      99           0 : }
     100             : 
     101             : /* Create EpochRewards sysvar with calculated rewards
     102             : 
     103             :    https://github.com/anza-xyz/agave/blob/cbc8320d35358da14d79ebcada4dfb6756ffac79/runtime/src/bank/partitioned_epoch_rewards/sysvar.rs#L25 */
     104             : void
     105             : fd_sysvar_epoch_rewards_init( fd_bank_t *               bank,
     106             :                               fd_accdb_user_t *         accdb,
     107             :                               fd_funk_txn_xid_t const * xid,
     108             :                               fd_capture_ctx_t *        capture_ctx,
     109             :                               ulong                     distributed_rewards,
     110             :                               ulong                     distribution_starting_block_height,
     111             :                               ulong                     num_partitions,
     112             :                               ulong                     total_rewards,
     113             :                               uint128                   total_points,
     114           0 :                               fd_hash_t const *         last_blockhash ) {
     115           0 :   fd_sysvar_epoch_rewards_t epoch_rewards = {
     116           0 :     .distribution_starting_block_height = distribution_starting_block_height,
     117           0 :     .num_partitions                     = num_partitions,
     118           0 :     .total_points                       = { .ud=total_points },
     119           0 :     .total_rewards                      = total_rewards,
     120           0 :     .distributed_rewards                = distributed_rewards,
     121           0 :     .active                             = 1,
     122           0 :     .parent_blockhash                   = *last_blockhash
     123           0 :   };
     124             : 
     125           0 :   if( FD_UNLIKELY( epoch_rewards.total_rewards<distributed_rewards ) ) {
     126           0 :     FD_LOG_ERR(( "total rewards overflow" ));
     127           0 :   }
     128             : 
     129           0 :   write_epoch_rewards( bank, accdb, xid, capture_ctx, &epoch_rewards );
     130           0 : }

Generated by: LCOV version 1.14