Line data Source code
1 : #include "fd_sysvar_epoch_rewards.h"
2 : #include "fd_sysvar.h"
3 : #include "../fd_system_ids.h"
4 :
5 : static int
6 315 : validate( fd_sysvar_epoch_rewards_t const * epoch_rewards ) {
7 315 : return epoch_rewards->active!=0 && epoch_rewards->active!=1;
8 :
9 315 : }
10 :
11 : static void
12 : write_epoch_rewards( fd_bank_t * bank,
13 : fd_accdb_t * accdb,
14 : fd_capture_ctx_t * capture_ctx,
15 558 : fd_sysvar_epoch_rewards_t * epoch_rewards ) {
16 558 : fd_sysvar_account_update( bank, accdb, capture_ctx, &fd_sysvar_epoch_rewards_id, epoch_rewards, FD_SYSVAR_EPOCH_REWARDS_BINCODE_SZ );
17 558 : }
18 :
19 : fd_sysvar_epoch_rewards_t *
20 : fd_sysvar_epoch_rewards_read( fd_accdb_t * accdb,
21 : fd_accdb_fork_id_t fork_id,
22 315 : fd_sysvar_epoch_rewards_t * out ) {
23 315 : fd_acc_t acc = fd_accdb_read_one( accdb, fork_id, fd_sysvar_epoch_rewards_id.uc );
24 315 : if( FD_UNLIKELY( !acc.lamports ) ) {
25 0 : fd_accdb_unread_one( accdb, &acc );
26 0 : return NULL;
27 0 : }
28 315 : if( FD_UNLIKELY( acc.data_len!=FD_SYSVAR_EPOCH_REWARDS_BINCODE_SZ ) ) {
29 0 : fd_accdb_unread_one( accdb, &acc );
30 0 : return NULL;
31 0 : }
32 :
33 315 : fd_memcpy( out, acc.data, FD_SYSVAR_EPOCH_REWARDS_BINCODE_SZ );
34 :
35 315 : fd_accdb_unread_one( accdb, &acc );
36 315 : if( FD_UNLIKELY( validate( out ) ) ) return NULL;
37 315 : return out;
38 315 : }
39 :
40 : /* Since there are multiple sysvar epoch rewards updates within a single slot,
41 : we need to ensure that the cache stays updated after each change (versus with other
42 : sysvars which only get updated once per slot and then synced up after) */
43 : void
44 : fd_sysvar_epoch_rewards_distribute( fd_bank_t * bank,
45 : fd_accdb_t * accdb,
46 : fd_capture_ctx_t * capture_ctx,
47 141 : ulong distributed ) {
48 141 : fd_sysvar_epoch_rewards_t epoch_rewards[1];
49 141 : FD_TEST( fd_sysvar_epoch_rewards_read( accdb, bank->accdb_fork_id, epoch_rewards ) );
50 141 : FD_TEST( epoch_rewards->active );
51 :
52 141 : ulong new_distributed = fd_ulong_sat_add( epoch_rewards->distributed_rewards, distributed );
53 141 : FD_TEST( new_distributed<=epoch_rewards->total_rewards );
54 141 : epoch_rewards->distributed_rewards += distributed;
55 :
56 141 : write_epoch_rewards( bank, accdb, capture_ctx, epoch_rewards );
57 141 : }
58 :
59 : void
60 : fd_sysvar_epoch_rewards_set_inactive( fd_bank_t * bank,
61 : fd_accdb_t * accdb,
62 132 : fd_capture_ctx_t * capture_ctx ) {
63 132 : fd_sysvar_epoch_rewards_t epoch_rewards[1];
64 132 : FD_TEST( fd_sysvar_epoch_rewards_read( accdb, bank->accdb_fork_id, epoch_rewards ) );
65 132 : FD_TEST( epoch_rewards->total_rewards>=epoch_rewards->distributed_rewards );
66 :
67 132 : epoch_rewards->active = 0;
68 132 : write_epoch_rewards( bank, accdb, capture_ctx, epoch_rewards );
69 132 : }
70 :
71 : /* Create EpochRewards sysvar with calculated rewards
72 :
73 : https://github.com/anza-xyz/agave/blob/cbc8320d35358da14d79ebcada4dfb6756ffac79/runtime/src/bank/partitioned_epoch_rewards/sysvar.rs#L25 */
74 : void
75 : fd_sysvar_epoch_rewards_init( fd_bank_t * bank,
76 : fd_accdb_t * accdb,
77 : fd_capture_ctx_t * capture_ctx,
78 : ulong distributed_rewards,
79 : ulong distribution_starting_block_height,
80 : ulong num_partitions,
81 : ulong total_rewards,
82 : uint128 total_points,
83 285 : fd_hash_t const * last_blockhash ) {
84 285 : fd_sysvar_epoch_rewards_t epoch_rewards = {
85 285 : .distribution_starting_block_height = distribution_starting_block_height,
86 285 : .num_partitions = num_partitions,
87 285 : .total_points = { .ud=total_points },
88 285 : .total_rewards = total_rewards,
89 285 : .distributed_rewards = distributed_rewards,
90 285 : .active = 1,
91 285 : .parent_blockhash = *last_blockhash
92 285 : };
93 :
94 285 : FD_TEST( epoch_rewards.total_rewards>=epoch_rewards.distributed_rewards );
95 285 : write_epoch_rewards( bank, accdb, capture_ctx, &epoch_rewards );
96 285 : }
|