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-07-01 05:00:49 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_runtime.h"
       5             : #include "../fd_borrowed_account.h"
       6             : #include "../fd_system_ids.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_set( slot_ctx->bank, slot_ctx->funk, slot_ctx->funk_txn, &fd_sysvar_owner_id, &fd_sysvar_epoch_rewards_id, enc, sz, slot_ctx->slot );
      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_spad_t *     spad ) {
      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( acc->vt->get_lamports( acc ) == 0UL ) ) {
      39           0 :     return NULL;
      40           0 :   }
      41             : 
      42           0 :   return fd_bincode_decode_spad(
      43           0 :       sysvar_epoch_rewards, spad,
      44           0 :       acc->vt->get_data( acc ),
      45           0 :       acc->vt->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             :                                     ulong                distributed,
      55           0 :                                     fd_spad_t *          runtime_spad ) {
      56           0 :   fd_sysvar_epoch_rewards_t * epoch_rewards = fd_sysvar_epoch_rewards_read( slot_ctx->funk, slot_ctx->funk_txn, runtime_spad );
      57           0 :   if( FD_UNLIKELY( epoch_rewards == NULL ) ) {
      58           0 :     FD_LOG_ERR(( "failed to read sysvar epoch rewards" ));
      59           0 :   }
      60             : 
      61           0 :   if( FD_UNLIKELY( !epoch_rewards->active ) ) {
      62           0 :     FD_LOG_ERR(( "sysvar epoch rewards is not active" ));
      63           0 :   }
      64             : 
      65           0 :   if( FD_UNLIKELY( fd_ulong_sat_add( epoch_rewards->distributed_rewards, distributed ) > epoch_rewards->total_rewards ) ) {
      66           0 :     FD_LOG_ERR(( "distributed rewards overflow" ));
      67           0 :   }
      68             : 
      69           0 :   epoch_rewards->distributed_rewards += distributed;
      70             : 
      71           0 :   write_epoch_rewards( slot_ctx, epoch_rewards );
      72           0 : }
      73             : 
      74             : void
      75             : fd_sysvar_epoch_rewards_set_inactive( fd_exec_slot_ctx_t * slot_ctx,
      76           0 :                                       fd_spad_t *          runtime_spad ) {
      77           0 :   fd_sysvar_epoch_rewards_t * epoch_rewards = fd_sysvar_epoch_rewards_read( slot_ctx->funk, slot_ctx->funk_txn, runtime_spad );
      78           0 :   if( FD_UNLIKELY( epoch_rewards == NULL ) ) {
      79           0 :     FD_LOG_ERR(( "failed to read sysvar epoch rewards" ));
      80           0 :   }
      81             : 
      82           0 :   if( FD_UNLIKELY( epoch_rewards->total_rewards < epoch_rewards->distributed_rewards ) ) {
      83           0 :     FD_LOG_ERR(( "distributed rewards overflow" ));
      84           0 :   }
      85             : 
      86           0 :   epoch_rewards->active = 0;
      87             : 
      88           0 :   write_epoch_rewards( slot_ctx, epoch_rewards );
      89           0 : }
      90             : 
      91             : /* Create EpochRewards sysvar with calculated rewards
      92             : 
      93             :    https://github.com/anza-xyz/agave/blob/cbc8320d35358da14d79ebcada4dfb6756ffac79/runtime/src/bank/partitioned_epoch_rewards/sysvar.rs#L25 */
      94             : void
      95             : fd_sysvar_epoch_rewards_init( fd_exec_slot_ctx_t * slot_ctx,
      96             :                               ulong                distributed_rewards,
      97             :                               ulong                distribution_starting_block_height,
      98             :                               ulong                num_partitions,
      99             :                               fd_point_value_t     point_value,
     100           0 :                               fd_hash_t const *    last_blockhash ) {
     101           0 :   fd_sysvar_epoch_rewards_t epoch_rewards = {
     102           0 :     .distribution_starting_block_height = distribution_starting_block_height,
     103           0 :     .num_partitions                     = num_partitions,
     104           0 :     .total_points                       = point_value.points,
     105           0 :     .total_rewards                      = point_value.rewards,
     106           0 :     .distributed_rewards                = distributed_rewards,
     107           0 :     .active                             = 1
     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 :   fd_memcpy( &epoch_rewards.parent_blockhash, last_blockhash, FD_HASH_FOOTPRINT );
     115             : 
     116           0 :   write_epoch_rewards( slot_ctx, &epoch_rewards );
     117           0 : }

Generated by: LCOV version 1.14