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: 54 75 72.0 %
Date: 2026-10-22 18:10:43 Functions: 6 7 85.7 %

          Line data    Source code
       1             : #include "fd_sysvar_epoch_rewards.h"
       2             : #include "../../events/fd_event_runtime.h"
       3             : #include "fd_sysvar.h"
       4             : #include "../fd_system_ids.h"
       5             : #include "../fd_accdb_svm.h"
       6             : #include "fd_sysvar_rent.h"
       7             : 
       8             : static int
       9         652 : validate( fd_sysvar_epoch_rewards_t const * epoch_rewards ) {
      10         652 :   return epoch_rewards->active!=0 && epoch_rewards->active!=1;
      11             : 
      12         652 : }
      13             : 
      14             : static void
      15             : write_epoch_rewards( fd_bank_t *                 bank,
      16             :                      fd_accdb_t *                accdb,
      17             :                      fd_capture_ctx_t *          capture_ctx,
      18         115 :                      fd_sysvar_epoch_rewards_t * epoch_rewards ) {
      19         115 :   fd_sysvar_account_update( bank, accdb, capture_ctx, &fd_sysvar_epoch_rewards_id, epoch_rewards, FD_SYSVAR_EPOCH_REWARDS_BINCODE_SZ );
      20         115 : }
      21             : 
      22             : /* write_epoch_rewards with the balance set to the rent exempt minimum,
      23             :    burning any surplus.
      24             :    Agave: create_account with RENT_UNADJUSTED_INITIAL_BALANCE followed by
      25             :    adjust_sysvar_balance_for_rent. */
      26             : static void
      27             : write_epoch_rewards_reset_balance( fd_bank_t *                 bank,
      28             :                                    fd_accdb_t *                accdb,
      29             :                                    fd_capture_ctx_t *          capture_ctx,
      30           0 :                                    fd_sysvar_epoch_rewards_t * epoch_rewards ) {
      31           0 :   fd_accdb_svm_update_t update[1];
      32           0 :   fd_acc_t              acc = fd_accdb_svm_open_rw( bank, accdb, update, &fd_sysvar_epoch_rewards_id, 1 );
      33           0 :   fd_memcpy( acc.owner, &fd_sysvar_owner_id, 32UL );
      34           0 :   acc.executable = 0;
      35           0 :   fd_memcpy( acc.data, epoch_rewards, FD_SYSVAR_EPOCH_REWARDS_BINCODE_SZ );
      36           0 :   acc.data_len = FD_SYSVAR_EPOCH_REWARDS_BINCODE_SZ;
      37           0 :   acc.lamports = fd_ulong_max( fd_rent_exempt_minimum_balance( &bank->f.rent, acc.data_len ), FD_SYSVAR_RENT_UNADJUSTED_INITIAL_BALANCE );
      38           0 :   fd_accdb_svm_close_rw( bank, accdb, capture_ctx, &acc, update );
      39           0 : }
      40             : 
      41             : fd_sysvar_epoch_rewards_t *
      42             : fd_sysvar_epoch_rewards_read( fd_accdb_t *                accdb,
      43             :                               fd_accdb_fork_id_t          fork_id,
      44         698 :                               fd_sysvar_epoch_rewards_t * out ) {
      45         698 :   fd_acc_t acc = fd_accdb_read_one( accdb, fork_id, fd_sysvar_epoch_rewards_id.uc );
      46         698 :   if( FD_UNLIKELY( !acc.lamports ) ) {
      47          46 :     fd_accdb_unread_one( accdb, &acc );
      48          46 :     return NULL;
      49          46 :   }
      50         652 :   if( FD_UNLIKELY( acc.data_len!=FD_SYSVAR_EPOCH_REWARDS_BINCODE_SZ ) ) {
      51           0 :     fd_accdb_unread_one( accdb, &acc );
      52           0 :     return NULL;
      53           0 :   }
      54             : 
      55         652 :   fd_memcpy( out, acc.data, FD_SYSVAR_EPOCH_REWARDS_BINCODE_SZ );
      56             : 
      57         652 :   fd_accdb_unread_one( accdb, &acc );
      58         652 :   if( FD_UNLIKELY( validate( out ) ) ) return NULL;
      59         652 :   return out;
      60         652 : }
      61             : 
      62             : /* Since there are multiple sysvar epoch rewards updates within a single slot,
      63             :    we need to ensure that the cache stays updated after each change (versus with other
      64             :    sysvars which only get updated once per slot and then synced up after) */
      65             : void
      66             : fd_sysvar_epoch_rewards_distribute( fd_bank_t *        bank,
      67             :                                     fd_accdb_t *       accdb,
      68             :                                     fd_capture_ctx_t * capture_ctx,
      69             :                                     ulong              distributed,
      70          41 :                                     ulong              debit_block_reward_lamports ) {
      71          41 :   fd_sysvar_epoch_rewards_t epoch_rewards[1];
      72          41 :   FD_TEST( fd_sysvar_epoch_rewards_read( accdb, bank->accdb_fork_id, epoch_rewards ) );
      73          41 :   FD_TEST( epoch_rewards->active );
      74             : 
      75          41 :   ulong new_distributed = fd_ulong_sat_add( epoch_rewards->distributed_rewards, distributed );
      76          41 :   FD_TEST( new_distributed<=epoch_rewards->total_rewards );
      77          41 :   epoch_rewards->distributed_rewards += distributed;
      78             : 
      79          41 :   write_epoch_rewards( bank, accdb, capture_ctx, epoch_rewards );
      80             : 
      81          41 :   if( FD_UNLIKELY( !debit_block_reward_lamports ) ) return;
      82             : 
      83           0 :   fd_accdb_svm_update_t update[1];
      84           0 :   fd_acc_t              acc = fd_accdb_svm_open_rw( bank, accdb, update, &fd_sysvar_epoch_rewards_id, 0 );
      85             :   /* https://github.com/anza-xyz/agave/blob/v4.4.0-alpha.5/runtime/src/bank/partitioned_epoch_rewards/sysvar.rs#L101 */
      86           0 :   FD_TEST( acc.lamports>=debit_block_reward_lamports );
      87           0 :   acc.lamports -= debit_block_reward_lamports;
      88             :   /* https://github.com/anza-xyz/agave/blob/v4.4.0-alpha.5/runtime/src/bank/partitioned_epoch_rewards/sysvar.rs#L102-L105 */
      89           0 :   FD_TEST( acc.lamports>=fd_rent_exempt_minimum_balance( &bank->f.rent, acc.data_len ) );
      90           0 :   fd_accdb_svm_close_rw( bank, accdb, capture_ctx, &acc, update );
      91           0 : }
      92             : 
      93             : void
      94             : fd_sysvar_epoch_rewards_set_inactive( fd_bank_t *        bank,
      95             :                                       fd_accdb_t *       accdb,
      96          42 :                                       fd_capture_ctx_t * capture_ctx ) {
      97          42 :   fd_sysvar_epoch_rewards_t epoch_rewards[1];
      98          42 :   FD_TEST( fd_sysvar_epoch_rewards_read( accdb, bank->accdb_fork_id, epoch_rewards ) );
      99          42 :   FD_TEST( epoch_rewards->total_rewards>=epoch_rewards->distributed_rewards );
     100             : 
     101          42 :   epoch_rewards->active = 0;
     102             : 
     103          42 :   if( FD_FEATURE_ACTIVE_BANK( bank, block_revenue_sharing ) ) {
     104             :     /* Don't inherit the balance to ensure that any remaining lamports
     105             :        get burned: the balance is reset to the rent-exempt minimum and
     106             :        capitalization is updated.
     107             :        https://github.com/anza-xyz/agave/blob/v4.4.0-alpha.5/runtime/src/bank/partitioned_epoch_rewards/sysvar.rs#L120-L135 */
     108           0 :     write_epoch_rewards_reset_balance( bank, accdb, capture_ctx, epoch_rewards );
     109          42 :   } else {
     110          42 :     write_epoch_rewards( bank, accdb, capture_ctx, epoch_rewards );
     111          42 :   }
     112          42 : }
     113             : 
     114             : /* Create EpochRewards sysvar with calculated rewards
     115             : 
     116             :    https://github.com/anza-xyz/agave/blob/cbc8320d35358da14d79ebcada4dfb6756ffac79/runtime/src/bank/partitioned_epoch_rewards/sysvar.rs#L25 */
     117             : void
     118             : fd_sysvar_epoch_rewards_init( fd_bank_t *        bank,
     119             :                               fd_accdb_t *       accdb,
     120             :                               fd_capture_ctx_t * capture_ctx,
     121             :                               ulong              distributed_rewards,
     122             :                               ulong              distribution_starting_block_height,
     123             :                               ulong              num_partitions,
     124             :                               ulong              total_rewards,
     125             :                               uint128            total_points,
     126             :                               fd_hash_t const *  last_blockhash,
     127          32 :                               ulong              block_rewards ) {
     128          32 :   fd_sysvar_epoch_rewards_t epoch_rewards = {
     129          32 :     .distribution_starting_block_height = distribution_starting_block_height,
     130          32 :     .num_partitions                     = num_partitions,
     131          32 :     .total_points                       = { .ud=total_points },
     132          32 :     .total_rewards                      = total_rewards,
     133          32 :     .distributed_rewards                = distributed_rewards,
     134          32 :     .active                             = 1,
     135          32 :     .parent_blockhash                   = *last_blockhash
     136          32 :   };
     137             : 
     138          32 :   FD_TEST( epoch_rewards.total_rewards>=epoch_rewards.distributed_rewards );
     139          32 :   if( FD_UNLIKELY( fd_bank_report_runtime_diffs( bank ) ) ) fd_event_runtime_epoch_rewards( &epoch_rewards );
     140          32 :   write_epoch_rewards( bank, accdb, capture_ctx, &epoch_rewards );
     141             : 
     142             :   /* https://github.com/anza-xyz/agave/blob/v4.4.0-alpha.5/runtime/src/bank/partitioned_epoch_rewards/sysvar.rs#L58-L69 */
     143          32 :   if( block_rewards ) {
     144           4 :     fd_accdb_svm_credit( bank, accdb, capture_ctx, &fd_sysvar_epoch_rewards_id, block_rewards, 0 );
     145           4 :   }
     146          32 : }

Generated by: LCOV version 1.14