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 411 : validate( fd_sysvar_epoch_rewards_t const * epoch_rewards ) {
10 411 : return epoch_rewards->active!=0 && epoch_rewards->active!=1;
11 :
12 411 : }
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 669 : fd_sysvar_epoch_rewards_t * epoch_rewards ) {
19 669 : fd_sysvar_account_update( bank, accdb, capture_ctx, &fd_sysvar_epoch_rewards_id, epoch_rewards, FD_SYSVAR_EPOCH_REWARDS_BINCODE_SZ );
20 669 : }
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 12 : fd_sysvar_epoch_rewards_t * epoch_rewards ) {
31 12 : fd_accdb_svm_update_t update[1];
32 12 : fd_acc_t acc = fd_accdb_svm_open_rw( bank, accdb, update, &fd_sysvar_epoch_rewards_id, 1 );
33 12 : fd_memcpy( acc.owner, &fd_sysvar_owner_id, 32UL );
34 12 : acc.executable = 0;
35 12 : fd_memcpy( acc.data, epoch_rewards, FD_SYSVAR_EPOCH_REWARDS_BINCODE_SZ );
36 12 : acc.data_len = FD_SYSVAR_EPOCH_REWARDS_BINCODE_SZ;
37 12 : acc.lamports = fd_ulong_max( fd_rent_exempt_minimum_balance( &bank->f.rent, acc.data_len ), FD_SYSVAR_RENT_UNADJUSTED_INITIAL_BALANCE );
38 12 : fd_accdb_svm_close_rw( bank, accdb, capture_ctx, &acc, update );
39 12 : }
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 411 : fd_sysvar_epoch_rewards_t * out ) {
45 411 : fd_acc_t acc = fd_accdb_read_one( accdb, fork_id, fd_sysvar_epoch_rewards_id.uc );
46 411 : if( FD_UNLIKELY( !acc.lamports ) ) {
47 0 : fd_accdb_unread_one( accdb, &acc );
48 0 : return NULL;
49 0 : }
50 411 : 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 411 : fd_memcpy( out, acc.data, FD_SYSVAR_EPOCH_REWARDS_BINCODE_SZ );
56 :
57 411 : fd_accdb_unread_one( accdb, &acc );
58 411 : if( FD_UNLIKELY( validate( out ) ) ) return NULL;
59 411 : return out;
60 411 : }
61 :
62 : void
63 : fd_sysvar_epoch_rewards_distribute( fd_bank_t * bank,
64 : fd_accdb_t * accdb,
65 : fd_capture_ctx_t * capture_ctx,
66 : ulong distributed,
67 174 : ulong debit_block_reward_lamports ) {
68 174 : fd_sysvar_epoch_rewards_t epoch_rewards[1];
69 174 : FD_TEST( fd_sysvar_epoch_rewards_read( accdb, bank->accdb_fork_id, epoch_rewards ) );
70 174 : FD_TEST( epoch_rewards->active );
71 :
72 174 : ulong new_distributed = fd_ulong_sat_add( epoch_rewards->distributed_rewards, distributed );
73 174 : FD_TEST( new_distributed<=epoch_rewards->total_rewards );
74 174 : epoch_rewards->distributed_rewards += distributed;
75 :
76 174 : write_epoch_rewards( bank, accdb, capture_ctx, epoch_rewards );
77 :
78 174 : if( FD_UNLIKELY( !debit_block_reward_lamports ) ) return;
79 :
80 9 : fd_accdb_svm_update_t update[1];
81 9 : fd_acc_t acc = fd_accdb_svm_open_rw( bank, accdb, update, &fd_sysvar_epoch_rewards_id, 0 );
82 : /* https://github.com/anza-xyz/agave/blob/v4.4.0-alpha.5/runtime/src/bank/partitioned_epoch_rewards/sysvar.rs#L101 */
83 9 : FD_TEST( acc.lamports>=debit_block_reward_lamports );
84 9 : acc.lamports -= debit_block_reward_lamports;
85 : /* https://github.com/anza-xyz/agave/blob/v4.4.0-alpha.5/runtime/src/bank/partitioned_epoch_rewards/sysvar.rs#L102-L105 */
86 9 : FD_TEST( acc.lamports>=fd_rent_exempt_minimum_balance( &bank->f.rent, acc.data_len ) );
87 9 : fd_accdb_svm_close_rw( bank, accdb, capture_ctx, &acc, update );
88 9 : }
89 :
90 : void
91 : fd_sysvar_epoch_rewards_set_inactive( fd_bank_t * bank,
92 : fd_accdb_t * accdb,
93 165 : fd_capture_ctx_t * capture_ctx ) {
94 165 : fd_sysvar_epoch_rewards_t epoch_rewards[1];
95 165 : FD_TEST( fd_sysvar_epoch_rewards_read( accdb, bank->accdb_fork_id, epoch_rewards ) );
96 165 : FD_TEST( epoch_rewards->total_rewards>=epoch_rewards->distributed_rewards );
97 :
98 165 : epoch_rewards->active = 0;
99 :
100 165 : if( FD_FEATURE_ACTIVE_BANK( bank, block_revenue_sharing ) ) {
101 : /* Don't inherit the balance to ensure that any remaining lamports
102 : get burned: the balance is reset to the rent-exempt minimum and
103 : capitalization is updated.
104 : https://github.com/anza-xyz/agave/blob/v4.4.0-alpha.5/runtime/src/bank/partitioned_epoch_rewards/sysvar.rs#L120-L135 */
105 12 : write_epoch_rewards_reset_balance( bank, accdb, capture_ctx, epoch_rewards );
106 153 : } else {
107 153 : write_epoch_rewards( bank, accdb, capture_ctx, epoch_rewards );
108 153 : }
109 165 : }
110 :
111 : /* Create EpochRewards sysvar with calculated rewards
112 :
113 : https://github.com/anza-xyz/agave/blob/cbc8320d35358da14d79ebcada4dfb6756ffac79/runtime/src/bank/partitioned_epoch_rewards/sysvar.rs#L25 */
114 : void
115 : fd_sysvar_epoch_rewards_init( fd_bank_t * bank,
116 : fd_accdb_t * accdb,
117 : fd_capture_ctx_t * capture_ctx,
118 : ulong distributed_rewards,
119 : ulong distribution_starting_block_height,
120 : ulong num_partitions,
121 : ulong total_rewards,
122 : uint128 total_points,
123 : fd_hash_t const * last_blockhash,
124 342 : ulong block_rewards ) {
125 342 : fd_sysvar_epoch_rewards_t epoch_rewards = {
126 342 : .distribution_starting_block_height = distribution_starting_block_height,
127 342 : .num_partitions = num_partitions,
128 342 : .total_points = { .ud=total_points },
129 342 : .total_rewards = total_rewards,
130 342 : .distributed_rewards = distributed_rewards,
131 342 : .active = 1,
132 342 : .parent_blockhash = *last_blockhash
133 342 : };
134 :
135 342 : FD_TEST( epoch_rewards.total_rewards>=epoch_rewards.distributed_rewards );
136 342 : if( FD_UNLIKELY( fd_bank_report_runtime_diffs( bank ) ) ) fd_event_runtime_epoch_rewards( &epoch_rewards );
137 342 : write_epoch_rewards( bank, accdb, capture_ctx, &epoch_rewards );
138 :
139 : /* https://github.com/anza-xyz/agave/blob/v4.4.0-alpha.5/runtime/src/bank/partitioned_epoch_rewards/sysvar.rs#L58-L69 */
140 342 : if( block_rewards ) {
141 12 : fd_accdb_svm_credit( bank, accdb, capture_ctx, &fd_sysvar_epoch_rewards_id, block_rewards, 0 );
142 12 : }
143 342 : }
|