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: 43 63 68.3 %
Date: 2026-05-25 08:51:51 Functions: 6 6 100.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 int
       7         159 : validate( fd_sysvar_epoch_rewards_t const * epoch_rewards ) {
       8         159 :   return epoch_rewards->active!=0 && epoch_rewards->active!=1;
       9             : 
      10         159 : }
      11             : 
      12             : static void
      13             : write_epoch_rewards( fd_bank_t *                 bank,
      14             :                      fd_accdb_user_t *           accdb,
      15             :                      fd_funk_txn_xid_t const *   xid,
      16             :                      fd_capture_ctx_t *          capture_ctx,
      17         279 :                      fd_sysvar_epoch_rewards_t * epoch_rewards ) {
      18         279 :   fd_sysvar_account_update( bank, accdb, xid, capture_ctx, &fd_sysvar_epoch_rewards_id, epoch_rewards, FD_SYSVAR_EPOCH_REWARDS_BINCODE_SZ );
      19         279 : }
      20             : 
      21             : fd_sysvar_epoch_rewards_t *
      22             : fd_sysvar_epoch_rewards_read( fd_accdb_user_t *           accdb,
      23             :                               fd_funk_txn_xid_t const *   xid,
      24         159 :                               fd_sysvar_epoch_rewards_t * out ) {
      25         159 :   fd_accdb_ro_t ro[1];
      26         159 :   if( FD_UNLIKELY( !fd_accdb_open_ro( accdb, ro, xid, &fd_sysvar_epoch_rewards_id ) ) ) {
      27           0 :     return NULL;
      28           0 :   }
      29             : 
      30         159 :   if( FD_UNLIKELY( fd_accdb_ref_data_sz( ro )!=FD_SYSVAR_EPOCH_REWARDS_BINCODE_SZ ) ) {
      31           0 :     fd_accdb_close_ro( accdb, ro );
      32           0 :     return NULL;
      33           0 :   }
      34             : 
      35         159 :   memcpy( out, fd_accdb_ref_data_const( ro ), FD_SYSVAR_EPOCH_REWARDS_BINCODE_SZ );
      36             : 
      37         159 :   if( FD_UNLIKELY( validate( out ) ) ) {
      38           0 :     fd_accdb_close_ro( accdb, ro );
      39           0 :     return NULL;
      40           0 :   }
      41         159 :   fd_accdb_close_ro( accdb, ro );
      42         159 :   return out;
      43         159 : }
      44             : 
      45             : /* Since there are multiple sysvar epoch rewards updates within a single slot,
      46             :    we need to ensure that the cache stays updated after each change (versus with other
      47             :    sysvars which only get updated once per slot and then synced up after) */
      48             : void
      49             : fd_sysvar_epoch_rewards_distribute( fd_bank_t *               bank,
      50             :                                     fd_accdb_user_t *         accdb,
      51             :                                     fd_funk_txn_xid_t const * xid,
      52             :                                     fd_capture_ctx_t *        capture_ctx,
      53          69 :                                     ulong                     distributed ) {
      54          69 :   fd_sysvar_epoch_rewards_t epoch_rewards[1];
      55          69 :   if( FD_UNLIKELY( !fd_sysvar_epoch_rewards_read( accdb, xid, epoch_rewards ) ) ) {
      56           0 :     FD_LOG_ERR(( "failed to read sysvar epoch rewards" ));
      57           0 :   }
      58             : 
      59          69 :   if( FD_UNLIKELY( !epoch_rewards->active ) ) {
      60           0 :     FD_LOG_ERR(( "sysvar epoch rewards is not active" ));
      61           0 :   }
      62             : 
      63          69 :   if( FD_UNLIKELY( fd_ulong_sat_add( epoch_rewards->distributed_rewards, distributed )>epoch_rewards->total_rewards ) ) {
      64           0 :     FD_LOG_ERR(( "distributed rewards overflow" ));
      65           0 :   }
      66             : 
      67          69 :   epoch_rewards->distributed_rewards += distributed;
      68             : 
      69          69 :   write_epoch_rewards( bank, accdb, xid, capture_ctx, epoch_rewards );
      70          69 : }
      71             : 
      72             : void
      73             : fd_sysvar_epoch_rewards_set_inactive( fd_bank_t *               bank,
      74             :                                       fd_accdb_user_t *         accdb,
      75             :                                       fd_funk_txn_xid_t const * xid,
      76          60 :                                       fd_capture_ctx_t *        capture_ctx ) {
      77          60 :   fd_sysvar_epoch_rewards_t epoch_rewards[1];
      78          60 :   if( FD_UNLIKELY( !fd_sysvar_epoch_rewards_read( accdb, xid, epoch_rewards ) ) ) {
      79           0 :     FD_LOG_ERR(( "failed to read sysvar epoch rewards" ));
      80           0 :   }
      81             : 
      82          60 :   if( FD_UNLIKELY( epoch_rewards->total_rewards < epoch_rewards->distributed_rewards ) ) {
      83           0 :     FD_LOG_ERR(( "distributed rewards overflow" ));
      84           0 :   }
      85             : 
      86          60 :   epoch_rewards->active = 0;
      87             : 
      88          60 :   write_epoch_rewards( bank, accdb, xid, capture_ctx, epoch_rewards );
      89          60 : }
      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_bank_t *               bank,
      96             :                               fd_accdb_user_t *         accdb,
      97             :                               fd_funk_txn_xid_t const * xid,
      98             :                               fd_capture_ctx_t *        capture_ctx,
      99             :                               ulong                     distributed_rewards,
     100             :                               ulong                     distribution_starting_block_height,
     101             :                               ulong                     num_partitions,
     102             :                               ulong                     total_rewards,
     103             :                               uint128                   total_points,
     104         150 :                               fd_hash_t const *         last_blockhash ) {
     105         150 :   fd_sysvar_epoch_rewards_t epoch_rewards = {
     106         150 :     .distribution_starting_block_height = distribution_starting_block_height,
     107         150 :     .num_partitions                     = num_partitions,
     108         150 :     .total_points                       = { .ud=total_points },
     109         150 :     .total_rewards                      = total_rewards,
     110         150 :     .distributed_rewards                = distributed_rewards,
     111         150 :     .active                             = 1,
     112         150 :     .parent_blockhash                   = *last_blockhash
     113         150 :   };
     114             : 
     115         150 :   if( FD_UNLIKELY( epoch_rewards.total_rewards<distributed_rewards ) ) {
     116           0 :     FD_LOG_ERR(( "total rewards overflow" ));
     117           0 :   }
     118             : 
     119         150 :   write_epoch_rewards( bank, accdb, xid, capture_ctx, &epoch_rewards );
     120         150 : }

Generated by: LCOV version 1.14