Line data Source code
1 : #include "fd_sysvar_epoch_rewards.h"
2 : #include "fd_sysvar.h"
3 : #include "../fd_system_ids.h"
4 : #include "../../accdb/fd_accdb_sync.h"
5 :
6 : static int
7 159 : validate( fd_sysvar_epoch_rewards_t const * epoch_rewards ) {
8 159 : return epoch_rewards->active!=0 && epoch_rewards->active!=1;
9 :
10 159 : }
11 :
12 : static void
13 : write_epoch_rewards( fd_bank_t * bank,
14 : fd_accdb_user_t * accdb,
15 : fd_funk_txn_xid_t const * xid,
16 : fd_capture_ctx_t * capture_ctx,
17 279 : fd_sysvar_epoch_rewards_t * epoch_rewards ) {
18 279 : fd_sysvar_account_update( bank, accdb, xid, capture_ctx, &fd_sysvar_epoch_rewards_id, epoch_rewards, FD_SYSVAR_EPOCH_REWARDS_BINCODE_SZ );
19 279 : }
20 :
21 : fd_sysvar_epoch_rewards_t *
22 : fd_sysvar_epoch_rewards_read( fd_accdb_user_t * accdb,
23 : fd_funk_txn_xid_t const * xid,
24 159 : fd_sysvar_epoch_rewards_t * out ) {
25 159 : fd_accdb_ro_t ro[1];
26 159 : if( FD_UNLIKELY( !fd_accdb_open_ro( accdb, ro, xid, &fd_sysvar_epoch_rewards_id ) ) ) {
27 0 : return NULL;
28 0 : }
29 :
30 159 : if( FD_UNLIKELY( fd_accdb_ref_data_sz( ro )!=FD_SYSVAR_EPOCH_REWARDS_BINCODE_SZ ) ) {
31 0 : fd_accdb_close_ro( accdb, ro );
32 0 : return NULL;
33 0 : }
34 :
35 159 : memcpy( out, fd_accdb_ref_data_const( ro ), FD_SYSVAR_EPOCH_REWARDS_BINCODE_SZ );
36 :
37 159 : if( FD_UNLIKELY( validate( out ) ) ) {
38 0 : fd_accdb_close_ro( accdb, ro );
39 0 : return NULL;
40 0 : }
41 159 : fd_accdb_close_ro( accdb, ro );
42 159 : return out;
43 159 : }
44 :
45 : /* Since there are multiple sysvar epoch rewards updates within a single slot,
46 : we need to ensure that the cache stays updated after each change (versus with other
47 : sysvars which only get updated once per slot and then synced up after) */
48 : void
49 : fd_sysvar_epoch_rewards_distribute( fd_bank_t * bank,
50 : fd_accdb_user_t * accdb,
51 : fd_funk_txn_xid_t const * xid,
52 : fd_capture_ctx_t * capture_ctx,
53 69 : ulong distributed ) {
54 69 : fd_sysvar_epoch_rewards_t epoch_rewards[1];
55 69 : if( FD_UNLIKELY( !fd_sysvar_epoch_rewards_read( accdb, xid, epoch_rewards ) ) ) {
56 0 : FD_LOG_ERR(( "failed to read sysvar epoch rewards" ));
57 0 : }
58 :
59 69 : if( FD_UNLIKELY( !epoch_rewards->active ) ) {
60 0 : FD_LOG_ERR(( "sysvar epoch rewards is not active" ));
61 0 : }
62 :
63 69 : if( FD_UNLIKELY( fd_ulong_sat_add( epoch_rewards->distributed_rewards, distributed )>epoch_rewards->total_rewards ) ) {
64 0 : FD_LOG_ERR(( "distributed rewards overflow" ));
65 0 : }
66 :
67 69 : epoch_rewards->distributed_rewards += distributed;
68 :
69 69 : write_epoch_rewards( bank, accdb, xid, capture_ctx, epoch_rewards );
70 69 : }
71 :
72 : void
73 : fd_sysvar_epoch_rewards_set_inactive( fd_bank_t * bank,
74 : fd_accdb_user_t * accdb,
75 : fd_funk_txn_xid_t const * xid,
76 60 : fd_capture_ctx_t * capture_ctx ) {
77 60 : fd_sysvar_epoch_rewards_t epoch_rewards[1];
78 60 : if( FD_UNLIKELY( !fd_sysvar_epoch_rewards_read( accdb, xid, epoch_rewards ) ) ) {
79 0 : FD_LOG_ERR(( "failed to read sysvar epoch rewards" ));
80 0 : }
81 :
82 60 : if( FD_UNLIKELY( epoch_rewards->total_rewards < epoch_rewards->distributed_rewards ) ) {
83 0 : FD_LOG_ERR(( "distributed rewards overflow" ));
84 0 : }
85 :
86 60 : epoch_rewards->active = 0;
87 :
88 60 : write_epoch_rewards( bank, accdb, xid, capture_ctx, epoch_rewards );
89 60 : }
90 :
91 : /* Create EpochRewards sysvar 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( fd_bank_t * bank,
96 : fd_accdb_user_t * accdb,
97 : fd_funk_txn_xid_t const * xid,
98 : fd_capture_ctx_t * capture_ctx,
99 : ulong distributed_rewards,
100 : ulong distribution_starting_block_height,
101 : ulong num_partitions,
102 : ulong total_rewards,
103 : uint128 total_points,
104 150 : fd_hash_t const * last_blockhash ) {
105 150 : fd_sysvar_epoch_rewards_t epoch_rewards = {
106 150 : .distribution_starting_block_height = distribution_starting_block_height,
107 150 : .num_partitions = num_partitions,
108 150 : .total_points = { .ud=total_points },
109 150 : .total_rewards = total_rewards,
110 150 : .distributed_rewards = distributed_rewards,
111 150 : .active = 1,
112 150 : .parent_blockhash = *last_blockhash
113 150 : };
114 :
115 150 : if( FD_UNLIKELY( epoch_rewards.total_rewards<distributed_rewards ) ) {
116 0 : FD_LOG_ERR(( "total rewards overflow" ));
117 0 : }
118 :
119 150 : write_epoch_rewards( bank, accdb, xid, capture_ctx, &epoch_rewards );
120 150 : }
|