Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_stakes_fd_vote_stakes_h
2 : #define HEADER_fd_src_flamenco_stakes_fd_vote_stakes_h
3 :
4 : #include "../../util/fd_util_base.h"
5 : #include "../fd_flamenco_base.h"
6 : #include "../accdb/fd_accdb_base.h"
7 :
8 3657 : #define FD_VOTE_STAKES_ALIGN (128UL)
9 :
10 : /* fd_vote_stakes is the Firedancer equivalent of the Agave epoch stakes
11 : data structure. It is a fork aware data structure that maintains the
12 : vote account state that is used for clock and VM syscall calculations
13 : during execution.
14 :
15 : The underlying data structure is a tiered set of caches:
16 : - t-2/t-3: these are caches used for the vote account states at the
17 : end of the t-2 epoch and the t-3 epoch assuming you are currently
18 : in the t epoch. These caches are shared across all forks.
19 : - t-1: these are sized to max_fork_width and are computed at the
20 : most recent epoch boundary. These caches are ref-cnt'd and fork
21 : specific. After the epoch boundary slot is rooted, then there will
22 : only be 1 active t-1 cache.
23 : - state: each bank has its own view of the t-2 state of vote
24 : accounts. This is what is actually used for clock calculations
25 : which is a stake weighted median of the last vote slot and
26 : timestamp.
27 :
28 : fd_vote_stakes also handles the creation of new vote stakes caches.
29 : The creation of new vote stakes caches happens at the epoch boundary
30 : and follows the rules defined in the validator_admission_ticket
31 : feature where every vote account must be in the top 2000 by stake.
32 : Under the hood, this is managed by a stake-sorted heap that is shared
33 : across all forks.
34 :
35 : NOTE:
36 : This system assumes that multiple forks can cross an epoch boundary
37 : but only one epoch boundary can be crossed at a time. This means
38 : that there can be multiple t-1 forks after an epoch boundary, but
39 : only one will be active when the first fork crosses into an epoch
40 : boundary. Similarly, this means that there will be 2 t-2 sets active
41 : during an epoch boundary crossing and 1 most of the time. */
42 :
43 : struct fd_vote_stakes;
44 : typedef struct fd_vote_stakes fd_vote_stakes_t;
45 :
46 : FD_PROTOTYPES_BEGIN
47 :
48 : ulong
49 : fd_vote_stakes_align( void );
50 :
51 : ulong
52 : fd_vote_stakes_footprint( ulong max_live_slots,
53 : ulong max_fork_width );
54 :
55 : void *
56 : fd_vote_stakes_new( void * mem,
57 : ulong max_live_slots,
58 : ulong max_fork_width,
59 : ulong seed );
60 :
61 : fd_vote_stakes_t *
62 : fd_vote_stakes_join( void * mem );
63 :
64 : /* fd_vote_stakes_fork_epoch returns the epoch of the fork. */
65 :
66 : ulong
67 : fd_vote_stakes_fork_epoch( ulong fork_id );
68 :
69 : /* fd_vote_stakes_init initializes the vote stakes data structure for a
70 : given epoch. */
71 :
72 : ulong
73 : fd_vote_stakes_init( fd_vote_stakes_t * vote_stakes,
74 : ulong epoch );
75 :
76 : /* fd_vote_stakes_reset resets the vote stakes data structure. */
77 :
78 : void
79 : fd_vote_stakes_reset( fd_vote_stakes_t * vote_stakes );
80 :
81 : /* fd_vote_stakes_snap_insert_t_1 inserts a new vote account into the
82 : t-1 set. This skips over any vote account validation and should
83 : only be used when loading in vote accounts from a snapshot. */
84 :
85 : void
86 : fd_vote_stakes_snap_insert_t_1( fd_vote_stakes_t * vote_stakes,
87 : ulong fork_id,
88 : fd_pubkey_t const * pubkey,
89 : fd_pubkey_t const * node_account,
90 : ulong stake,
91 : ushort commission );
92 :
93 : /* fd_vote_stakes_snap_insert_t_2 inserts a new vote account into the
94 : t-2 set. This skips over any vote account validation and should
95 : only be used when loading in vote accounts from a snapshot. */
96 :
97 : void
98 : fd_vote_stakes_snap_insert_t_2( fd_vote_stakes_t * vote_stakes,
99 : ulong fork_id,
100 : fd_pubkey_t const * pubkey,
101 : fd_pubkey_t const * node_account,
102 : ulong stake,
103 : ushort commission );
104 :
105 : /* fd_vote_stakes_insert inserts a new vote account into the t-1 set.
106 : This can be called repeatedly after a boundary-crossing
107 : fd_vote_stakes_new_fork. An account will only be inserted if it
108 : matches the semantics of the validator_admission_ticket feature.
109 : The top 2000 vote accounts by stake are inserted into the t-1 set. */
110 :
111 : void
112 : fd_vote_stakes_insert( fd_vote_stakes_t * vote_stakes,
113 : ulong fork_id,
114 : fd_pubkey_t const * pubkey,
115 : fd_pubkey_t const * node_account,
116 : ulong stake,
117 : ushort commission );
118 :
119 : /* fd_vote_stakes_purge_fork removes a t-1 set. This should be called
120 : when the banks are evicting a bank or during root advancement. */
121 :
122 : void
123 : fd_vote_stakes_purge_fork( fd_vote_stakes_t * vote_stakes,
124 : ulong fork_id );
125 :
126 : /* fd_vote_stakes_new_fork creates a child of the given parent fork.
127 : Within an epoch, the child shares the parent's t-1 set and receives a
128 : copy of its t-2 state. At an epoch boundary, it rotates t-1 into
129 : t-2 and acquires fresh t-1 and t-2 state. */
130 :
131 : ulong
132 : fd_vote_stakes_new_fork( fd_vote_stakes_t * vote_stakes,
133 : ulong parent_fork_id,
134 : ulong epoch );
135 :
136 : /* fd_vote_stakes_update updates the vote account state for a given
137 : fork id. It is a no-op if the pubkey corresponds to an account not
138 : in the t-2 set. If is_valid==0, the last vote arguments will be
139 : ignored. */
140 :
141 : void
142 : fd_vote_stakes_update_state( fd_vote_stakes_t * vote_stakes,
143 : ulong fork_id,
144 : fd_pubkey_t const * pubkey,
145 : ulong last_vote_slot,
146 : long last_vote_ts,
147 : uchar is_valid );
148 :
149 : void
150 : fd_vote_stakes_refresh( fd_vote_stakes_t * vote_stakes,
151 : ulong fork_id,
152 : fd_accdb_t * accdb,
153 : fd_accdb_fork_id_t accdb_fork_id );
154 :
155 : /* fd_vote_stakes_query_t_1 queries the fork's t-1 vote account.
156 : Returns 1 if the account exists in t-1 and 0 otherwise. */
157 :
158 : int
159 : fd_vote_stakes_query_t_1( fd_vote_stakes_t const * vote_stakes,
160 : ulong fork_id,
161 : fd_pubkey_t const * pubkey,
162 : fd_pubkey_t * node_account_out_opt,
163 : ulong * stake_out_opt,
164 : ushort * commission_out_opt );
165 :
166 : /* fd_vote_stakes_query_t_2 queries the t-2 vote account and fork-local
167 : vote state. Returns 1 if the account exists in t-2 and 0 otherwise. */
168 :
169 : int
170 : fd_vote_stakes_query_t_2( fd_vote_stakes_t const * vote_stakes,
171 : ulong fork_id,
172 : fd_pubkey_t const * pubkey,
173 : fd_pubkey_t * node_account_out_opt,
174 : ulong * stake_out_opt,
175 : ulong * last_vote_slot_out_opt,
176 : long * last_vote_ts_out_opt,
177 : ushort * commission_out_opt,
178 : uchar * is_valid_out_opt );
179 :
180 : /* fd_vote_stakes_query_t_3 queries the fork's t-3 vote account.
181 : Returns 1 if the account exists in t-3 and 0 otherwise. */
182 :
183 : int
184 : fd_vote_stakes_query_t_3( fd_vote_stakes_t const * vote_stakes,
185 : ulong fork_id,
186 : fd_pubkey_t const * pubkey,
187 : fd_pubkey_t * node_account_out_opt,
188 : ulong * stake_out_opt,
189 : ushort * commission_out_opt );
190 :
191 : /* fd_vote_stakes_cnt_t_{1,2} returns the number of vote accounts in the
192 : t-1 and t-2 sets respectively. */
193 :
194 : ulong
195 : fd_vote_stakes_cnt_t_1( fd_vote_stakes_t const * vote_stakes,
196 : ulong fork_id );
197 :
198 : ulong
199 : fd_vote_stakes_cnt_t_2( fd_vote_stakes_t const * vote_stakes,
200 : ulong fork_id );
201 :
202 : /* Defined below are the iterators for the t-1 and t-2 sets. These
203 : iterators will NOT skip over invalid vote accounts intentionally.
204 : The reason being is that invalid vote accounts are still considered
205 : for stake and leader calculations: the caller is expected to handle
206 : the state of each account correctly. */
207 :
208 : #define FD_VOTE_STAKES_ITER_FOOTPRINT (16UL)
209 : #define FD_VOTE_STAKES_ITER_ALIGN (8UL)
210 : #define FD_VOTE_STAKES_T_1_ITER_FOOTPRINT FD_VOTE_STAKES_ITER_FOOTPRINT
211 : #define FD_VOTE_STAKES_T_1_ITER_ALIGN FD_VOTE_STAKES_ITER_ALIGN
212 : #define FD_VOTE_STAKES_T_2_ITER_FOOTPRINT FD_VOTE_STAKES_ITER_FOOTPRINT
213 : #define FD_VOTE_STAKES_T_2_ITER_ALIGN FD_VOTE_STAKES_ITER_ALIGN
214 :
215 : struct vacc_map_iter;
216 : typedef struct vacc_map_iter fd_vote_stakes_iter_t;
217 : typedef fd_vote_stakes_iter_t fd_vote_stakes_t_1_iter_t;
218 : typedef fd_vote_stakes_iter_t fd_vote_stakes_t_2_iter_t;
219 :
220 : fd_vote_stakes_t_1_iter_t *
221 : fd_vote_stakes_t_1_iter_init( fd_vote_stakes_t const * vote_stakes,
222 : ulong fork_id,
223 : uchar iter_mem[ static FD_VOTE_STAKES_T_1_ITER_FOOTPRINT ] );
224 :
225 : int
226 : fd_vote_stakes_t_1_iter_done( fd_vote_stakes_t const * vote_stakes,
227 : ulong fork_id,
228 : fd_vote_stakes_t_1_iter_t * iter );
229 :
230 : void
231 : fd_vote_stakes_t_1_iter_next( fd_vote_stakes_t const * vote_stakes,
232 : ulong fork_id,
233 : fd_vote_stakes_t_1_iter_t * iter );
234 :
235 : void
236 : fd_vote_stakes_t_1_iter_ele( fd_vote_stakes_t const * vote_stakes,
237 : ulong fork_id,
238 : fd_vote_stakes_t_1_iter_t * iter,
239 : fd_pubkey_t * pubkey_out,
240 : fd_pubkey_t * node_account_out_opt,
241 : ulong * stake_out_opt,
242 : ushort * commission_out_opt );
243 :
244 : fd_vote_stakes_t_2_iter_t *
245 : fd_vote_stakes_t_2_iter_init( fd_vote_stakes_t const * vote_stakes,
246 : ulong fork_id,
247 : uchar iter_mem[ static FD_VOTE_STAKES_T_2_ITER_FOOTPRINT ] );
248 :
249 : int
250 : fd_vote_stakes_t_2_iter_done( fd_vote_stakes_t const * vote_stakes,
251 : ulong fork_id,
252 : fd_vote_stakes_t_2_iter_t * iter );
253 :
254 : void
255 : fd_vote_stakes_t_2_iter_next( fd_vote_stakes_t const * vote_stakes,
256 : ulong fork_id,
257 : fd_vote_stakes_t_2_iter_t * iter );
258 :
259 : void
260 : fd_vote_stakes_t_2_iter_ele( fd_vote_stakes_t const * vote_stakes,
261 : ulong fork_id,
262 : fd_vote_stakes_t_2_iter_t * iter,
263 : fd_pubkey_t * pubkey_out,
264 : fd_pubkey_t * node_account_out_opt,
265 : ulong * stake_out_opt,
266 : ulong * last_vote_slot_out_opt,
267 : long * last_vote_ts_out_opt,
268 : ushort * commission_out_opt,
269 : uchar * is_valid_out_opt );
270 :
271 : FD_PROTOTYPES_END
272 :
273 : #endif /* HEADER_fd_src_flamenco_stakes_fd_vote_stakes_h */
|