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_borrowed_account.h" 5 : #include "../fd_system_ids.h" 6 : #include "../context/fd_exec_slot_ctx.h" 7 : #include "../context/fd_exec_epoch_ctx.h" 8 : 9 : static void 10 1800 : write_epoch_rewards( fd_exec_slot_ctx_t * slot_ctx, fd_sysvar_epoch_rewards_t * epoch_rewards ) { 11 1800 : ulong sz = fd_sysvar_epoch_rewards_size( epoch_rewards ); 12 1800 : uchar enc[sz]; 13 1800 : fd_memset( enc, 0, sz ); 14 1800 : fd_bincode_encode_ctx_t ctx; 15 1800 : ctx.data = enc; 16 1800 : ctx.dataend = enc + sz; 17 1800 : if ( fd_sysvar_epoch_rewards_encode( epoch_rewards, &ctx ) ) { 18 0 : FD_LOG_ERR(("fd_sysvar_epoch_rewards_encode failed")); 19 0 : } 20 : 21 1800 : fd_sysvar_set( slot_ctx, fd_sysvar_owner_id.key, &fd_sysvar_epoch_rewards_id, enc, sz, slot_ctx->slot_bank.slot ); 22 1800 : } 23 : 24 : fd_sysvar_epoch_rewards_t * 25 : fd_sysvar_epoch_rewards_read( 26 : fd_sysvar_epoch_rewards_t * result, 27 : fd_exec_slot_ctx_t * slot_ctx 28 0 : ) { 29 0 : fd_sysvar_epoch_rewards_t const * ret = fd_sysvar_cache_epoch_rewards( slot_ctx->sysvar_cache ); 30 0 : if( FD_UNLIKELY( NULL != ret ) ) { 31 0 : fd_memcpy(result, ret, sizeof(fd_sysvar_epoch_rewards_t)); 32 0 : return result; 33 0 : } 34 : 35 0 : FD_BORROWED_ACCOUNT_DECL(acc); 36 0 : int err = fd_acc_mgr_view( slot_ctx->acc_mgr, slot_ctx->funk_txn, &fd_sysvar_epoch_rewards_id, acc ); 37 0 : if( FD_UNLIKELY( err != FD_ACC_MGR_SUCCESS ) ) { 38 0 : return NULL; 39 0 : } 40 : 41 0 : fd_bincode_decode_ctx_t decode = 42 0 : { .data = acc->const_data, 43 0 : .dataend = acc->const_data + acc->const_meta->dlen, 44 0 : .valloc = {0} /* valloc not required */ }; 45 : 46 0 : if( FD_UNLIKELY( fd_sysvar_epoch_rewards_decode( result, &decode )!=FD_BINCODE_SUCCESS ) ) 47 0 : return NULL; 48 : 49 0 : return result; 50 0 : } 51 : 52 : void 53 : fd_sysvar_epoch_rewards_distribute( 54 : fd_exec_slot_ctx_t * slot_ctx, 55 : ulong distributed 56 0 : ) { 57 0 : fd_sysvar_epoch_rewards_t epoch_rewards[1]; 58 0 : if ( FD_UNLIKELY( fd_sysvar_epoch_rewards_read( epoch_rewards, slot_ctx ) == NULL ) ) { 59 0 : FD_LOG_ERR(( "failed to read sysvar epoch rewards" )); 60 0 : } 61 0 : FD_TEST( epoch_rewards->active ); 62 : 63 0 : FD_TEST( fd_ulong_sat_add( epoch_rewards->distributed_rewards, distributed ) <= epoch_rewards->total_rewards ); 64 : 65 0 : epoch_rewards->distributed_rewards += distributed; 66 : 67 0 : write_epoch_rewards( slot_ctx, epoch_rewards ); 68 0 : } 69 : 70 : void 71 : fd_sysvar_epoch_rewards_set_inactive( 72 : fd_exec_slot_ctx_t * slot_ctx 73 0 : ) { 74 0 : fd_sysvar_epoch_rewards_t epoch_rewards[1]; 75 0 : if ( FD_UNLIKELY( fd_sysvar_epoch_rewards_read( epoch_rewards, slot_ctx ) == NULL ) ) { 76 0 : FD_LOG_ERR(( "failed to read sysvar epoch rewards" )); 77 0 : } 78 : 79 0 : if ( FD_LIKELY( FD_FEATURE_ACTIVE( slot_ctx, partitioned_epoch_rewards_superfeature ) ) ) { 80 0 : FD_TEST( epoch_rewards->total_rewards >= epoch_rewards->distributed_rewards ); 81 0 : } else { 82 0 : FD_TEST( epoch_rewards->total_rewards == epoch_rewards->distributed_rewards ); 83 0 : } 84 : 85 : 86 0 : epoch_rewards->active = 0; 87 : 88 0 : write_epoch_rewards( slot_ctx, epoch_rewards ); 89 0 : } 90 : 91 : /* Create EpochRewards syavar 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( 96 : fd_exec_slot_ctx_t * slot_ctx, 97 : ulong total_rewards, 98 : ulong distributed_rewards, 99 : ulong distribution_starting_block_height, 100 : ulong num_partitions, 101 : fd_point_value_t point_value, 102 : const fd_hash_t * last_blockhash 103 1800 : ) { 104 1800 : FD_TEST( total_rewards >= distributed_rewards ); 105 : 106 1800 : fd_sysvar_epoch_rewards_t epoch_rewards = { 107 1800 : .distribution_starting_block_height = distribution_starting_block_height, 108 1800 : .num_partitions = num_partitions, 109 1800 : .total_points = point_value.points, 110 1800 : .total_rewards = total_rewards, 111 1800 : .distributed_rewards = distributed_rewards, 112 1800 : .active = 1 113 1800 : }; 114 : 115 : /* On clusters where partitioned_epoch_rewards_superfeature is enabled, we should use point_value.rewards. 116 : On other clusters, including those where enable_partitioned_epoch_reward is enabled, we should use total_rewards. 117 : 118 : https://github.com/anza-xyz/agave/blob/b9c9ecccbb05d9da774d600bdbef2cf210c57fa8/runtime/src/bank/partitioned_epoch_rewards/sysvar.rs#L36-L43 */ 119 1800 : if ( FD_LIKELY( FD_FEATURE_ACTIVE( slot_ctx, partitioned_epoch_rewards_superfeature ) ) ) { 120 0 : epoch_rewards.total_rewards = point_value.rewards; 121 0 : } 122 : 123 1800 : fd_memcpy( &epoch_rewards.parent_blockhash, last_blockhash, FD_HASH_FOOTPRINT ); 124 : 125 1800 : write_epoch_rewards( slot_ctx, &epoch_rewards ); 126 1800 : }