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 648 : validate( fd_sysvar_epoch_rewards_t const * epoch_rewards ) {
10 648 : return epoch_rewards->active!=0 && epoch_rewards->active!=1;
11 :
12 648 : }
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 111 : fd_sysvar_epoch_rewards_t * epoch_rewards ) {
19 111 : fd_sysvar_account_update( bank, accdb, capture_ctx, &fd_sysvar_epoch_rewards_id, epoch_rewards, FD_SYSVAR_EPOCH_REWARDS_BINCODE_SZ );
20 111 : }
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 694 : fd_sysvar_epoch_rewards_t * out ) {
45 694 : fd_acc_t acc = fd_accdb_read_one( accdb, fork_id, fd_sysvar_epoch_rewards_id.uc );
46 694 : if( FD_UNLIKELY( !acc.lamports ) ) {
47 46 : fd_accdb_unread_one( accdb, &acc );
48 46 : return NULL;
49 46 : }
50 648 : 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 648 : fd_memcpy( out, acc.data, FD_SYSVAR_EPOCH_REWARDS_BINCODE_SZ );
56 :
57 648 : fd_accdb_unread_one( accdb, &acc );
58 648 : if( FD_UNLIKELY( validate( out ) ) ) return NULL;
59 648 : return out;
60 648 : }
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 41 : ulong debit_block_reward_lamports ) {
68 41 : fd_sysvar_epoch_rewards_t epoch_rewards[1];
69 41 : FD_TEST( fd_sysvar_epoch_rewards_read( accdb, bank->accdb_fork_id, epoch_rewards ) );
70 41 : FD_TEST( epoch_rewards->active );
71 :
72 41 : ulong new_distributed = fd_ulong_sat_add( epoch_rewards->distributed_rewards, distributed );
73 41 : FD_TEST( new_distributed<=epoch_rewards->total_rewards );
74 41 : epoch_rewards->distributed_rewards += distributed;
75 :
76 41 : write_epoch_rewards( bank, accdb, capture_ctx, epoch_rewards );
77 :
78 41 : if( FD_UNLIKELY( !debit_block_reward_lamports ) ) return;
79 :
80 0 : fd_accdb_svm_update_t update[1];
81 0 : 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 0 : FD_TEST( acc.lamports>=debit_block_reward_lamports );
84 0 : 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 0 : FD_TEST( acc.lamports>=fd_rent_exempt_minimum_balance( &bank->f.rent, acc.data_len ) );
87 0 : fd_accdb_svm_close_rw( bank, accdb, capture_ctx, &acc, update );
88 0 : }
89 :
90 : void
91 : fd_sysvar_epoch_rewards_set_inactive( fd_bank_t * bank,
92 : fd_accdb_t * accdb,
93 42 : fd_capture_ctx_t * capture_ctx ) {
94 42 : fd_sysvar_epoch_rewards_t epoch_rewards[1];
95 42 : FD_TEST( fd_sysvar_epoch_rewards_read( accdb, bank->accdb_fork_id, epoch_rewards ) );
96 42 : FD_TEST( epoch_rewards->total_rewards>=epoch_rewards->distributed_rewards );
97 :
98 42 : epoch_rewards->active = 0;
99 :
100 42 : 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 0 : write_epoch_rewards_reset_balance( bank, accdb, capture_ctx, epoch_rewards );
106 42 : } else {
107 42 : write_epoch_rewards( bank, accdb, capture_ctx, epoch_rewards );
108 42 : }
109 42 : }
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 28 : ulong block_rewards ) {
125 28 : fd_sysvar_epoch_rewards_t epoch_rewards = {
126 28 : .distribution_starting_block_height = distribution_starting_block_height,
127 28 : .num_partitions = num_partitions,
128 28 : .total_points = { .ud=total_points },
129 28 : .total_rewards = total_rewards,
130 28 : .distributed_rewards = distributed_rewards,
131 28 : .active = 1,
132 28 : .parent_blockhash = *last_blockhash
133 28 : };
134 :
135 28 : FD_TEST( epoch_rewards.total_rewards>=epoch_rewards.distributed_rewards );
136 28 : if( FD_UNLIKELY( fd_bank_report_runtime_diffs( bank ) ) ) fd_event_runtime_epoch_rewards( &epoch_rewards );
137 28 : 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 28 : if( block_rewards ) {
141 0 : fd_accdb_svm_credit( bank, accdb, capture_ctx, &fd_sysvar_epoch_rewards_id, block_rewards, 0 );
142 0 : }
143 28 : }
|