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 68 0.0 %
Date: 2025-09-18 04:41:32 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 "../context/fd_exec_slot_ctx.h"
       7             : 
       8             : static void
       9           0 : write_epoch_rewards( fd_exec_slot_ctx_t * slot_ctx, fd_sysvar_epoch_rewards_t * epoch_rewards ) {
      10           0 :   ulong sz = fd_sysvar_epoch_rewards_size( epoch_rewards );
      11           0 :   uchar enc[sz];
      12           0 :   fd_memset( enc, 0, sz );
      13           0 :   fd_bincode_encode_ctx_t ctx = {
      14           0 :     .data    = enc,
      15           0 :     .dataend = enc + sz
      16           0 :   };
      17           0 :   if( FD_UNLIKELY( fd_sysvar_epoch_rewards_encode( epoch_rewards, &ctx ) ) ) {
      18           0 :     FD_LOG_ERR(( "fd_sysvar_epoch_rewards_encode failed" ));
      19           0 :   }
      20             : 
      21           0 :   fd_sysvar_account_update( slot_ctx, &fd_sysvar_epoch_rewards_id, enc, sz );
      22           0 : }
      23             : 
      24             : fd_sysvar_epoch_rewards_t *
      25             : fd_sysvar_epoch_rewards_read( fd_funk_t *                 funk,
      26             :                               fd_funk_txn_t *             funk_txn,
      27           0 :                               fd_sysvar_epoch_rewards_t * out ) {
      28           0 :   FD_TXN_ACCOUNT_DECL( acc );
      29           0 :   int err = fd_txn_account_init_from_funk_readonly( acc, &fd_sysvar_epoch_rewards_id, funk, funk_txn );
      30           0 :   if( FD_UNLIKELY( err != FD_ACC_MGR_SUCCESS ) ) {
      31           0 :     return NULL;
      32           0 :   }
      33             : 
      34             :   /* This check is needed as a quirk of the fuzzer. If a sysvar account
      35             :      exists in the accounts database, but doesn't have any lamports,
      36             :      this means that the account does not exist. This wouldn't happen
      37             :      in a real execution environment. */
      38           0 :   if( FD_UNLIKELY( fd_txn_account_get_lamports( acc )==0UL ) ) {
      39           0 :     return NULL;
      40           0 :   }
      41             : 
      42           0 :   return fd_bincode_decode_static(
      43           0 :       sysvar_epoch_rewards, out,
      44           0 :       fd_txn_account_get_data( acc ),
      45           0 :       fd_txn_account_get_data_len( acc ),
      46           0 :       &err );
      47           0 : }
      48             : 
      49             : /* Since there are multiple sysvar epoch rewards updates within a single slot,
      50             :    we need to ensure that the cache stays updated after each change (versus with other
      51             :    sysvars which only get updated once per slot and then synced up after) */
      52             : void
      53             : fd_sysvar_epoch_rewards_distribute( fd_exec_slot_ctx_t * slot_ctx,
      54           0 :                                     ulong                distributed ) {
      55           0 :   fd_sysvar_epoch_rewards_t epoch_rewards[1];
      56           0 :   if( FD_UNLIKELY( !fd_sysvar_epoch_rewards_read( slot_ctx->funk, slot_ctx->funk_txn, epoch_rewards ) ) ) {
      57           0 :     FD_LOG_ERR(( "failed to read sysvar epoch rewards" ));
      58           0 :   }
      59             : 
      60           0 :   if( FD_UNLIKELY( !epoch_rewards->active ) ) {
      61           0 :     FD_LOG_ERR(( "sysvar epoch rewards is not active" ));
      62           0 :   }
      63             : 
      64           0 :   if( FD_UNLIKELY( fd_ulong_sat_add( epoch_rewards->distributed_rewards, distributed ) > epoch_rewards->total_rewards ) ) {
      65           0 :     FD_LOG_ERR(( "distributed rewards overflow" ));
      66           0 :   }
      67             : 
      68           0 :   epoch_rewards->distributed_rewards += distributed;
      69             : 
      70           0 :   write_epoch_rewards( slot_ctx, epoch_rewards );
      71           0 : }
      72             : 
      73             : void
      74           0 : fd_sysvar_epoch_rewards_set_inactive( fd_exec_slot_ctx_t * slot_ctx ) {
      75           0 :   fd_sysvar_epoch_rewards_t epoch_rewards[1];
      76           0 :   if( FD_UNLIKELY( !fd_sysvar_epoch_rewards_read( slot_ctx->funk, slot_ctx->funk_txn, epoch_rewards ) ) ) {
      77           0 :     FD_LOG_ERR(( "failed to read sysvar epoch rewards" ));
      78           0 :   }
      79             : 
      80           0 :   if( FD_UNLIKELY( epoch_rewards->total_rewards < epoch_rewards->distributed_rewards ) ) {
      81           0 :     FD_LOG_ERR(( "distributed rewards overflow" ));
      82           0 :   }
      83             : 
      84           0 :   epoch_rewards->active = 0;
      85             : 
      86           0 :   write_epoch_rewards( slot_ctx, epoch_rewards );
      87           0 : }
      88             : 
      89             : /* Create EpochRewards sysvar with calculated rewards
      90             : 
      91             :    https://github.com/anza-xyz/agave/blob/cbc8320d35358da14d79ebcada4dfb6756ffac79/runtime/src/bank/partitioned_epoch_rewards/sysvar.rs#L25 */
      92             : void
      93             : fd_sysvar_epoch_rewards_init( fd_exec_slot_ctx_t * slot_ctx,
      94             :                               ulong                distributed_rewards,
      95             :                               ulong                distribution_starting_block_height,
      96             :                               ulong                num_partitions,
      97             :                               ulong                total_rewards,
      98             :                               uint128              total_points,
      99           0 :                               fd_hash_t const *    last_blockhash ) {
     100           0 :   fd_sysvar_epoch_rewards_t epoch_rewards = {
     101           0 :     .distribution_starting_block_height = distribution_starting_block_height,
     102           0 :     .num_partitions                     = num_partitions,
     103           0 :     .total_points                       = total_points,
     104           0 :     .total_rewards                      = total_rewards,
     105           0 :     .distributed_rewards                = distributed_rewards,
     106           0 :     .active                             = 1,
     107           0 :     .parent_blockhash                   = *last_blockhash
     108           0 :   };
     109             : 
     110           0 :   if( FD_UNLIKELY( epoch_rewards.total_rewards<distributed_rewards ) ) {
     111           0 :     FD_LOG_ERR(( "total rewards overflow" ));
     112           0 :   }
     113             : 
     114           0 :   write_epoch_rewards( slot_ctx, &epoch_rewards );
     115           0 : }

Generated by: LCOV version 1.14