Line data Source code
1 : #include "fd_vote_stakes.h"
2 : #include "../accdb/fd_accdb.h"
3 : #include "../fd_flamenco_base.h"
4 : #include "../runtime/fd_runtime_const.h"
5 : #include "../runtime/program/vote/fd_vote_state_versioned.h"
6 : #include "../runtime/program/vote/fd_vote_codec.h"
7 : #include "../../util/bits/fd_bits.h"
8 : #include "../../util/log/fd_log.h"
9 :
10 117 : #define FD_VOTE_STAKES_MAGIC (0xF17EDA2CE7601E70UL) /* FIREDANCER VOTE STAKES V0 */
11 : #define FD_VOTE_STAKES_MAX_FORK_WIDTH (128UL)
12 :
13 : struct vacc {
14 : fd_pubkey_t pubkey;
15 : fd_pubkey_t node_account;
16 : ulong stake;
17 : ushort commission;
18 : uint left;
19 : uint right;
20 : uint next;
21 : };
22 : typedef struct vacc vacc_t;
23 :
24 : #define HEAP_NAME vacc_heap
25 6333 : #define HEAP_IDX_T uint
26 : #define HEAP_T vacc_t
27 54906 : #define HEAP_LT(e0,e1) ( ((e0)->stake < (e1)->stake) | \
28 54906 : (((e0)->stake==(e1)->stake) & \
29 54906 : (memcmp( &(e0)->pubkey, &(e1)->pubkey, sizeof(fd_pubkey_t) )<0 ) ) )
30 : #include "../../util/tmpl/fd_heap.c"
31 :
32 : #define POOL_NAME vacc_pool
33 2334 : #define POOL_T vacc_t
34 : #define POOL_IDX_T uint
35 : #define POOL_LAZY 1
36 : #include "../../util/tmpl/fd_pool.c"
37 :
38 : #define MAP_NAME vacc_map
39 : #define MAP_KEY_T fd_pubkey_t
40 : #define MAP_ELE_T vacc_t
41 14565 : #define MAP_KEY pubkey
42 4869 : #define MAP_KEY_EQ(k0,k1) (!memcmp( k0, k1, sizeof(fd_pubkey_t) ))
43 19473 : #define MAP_KEY_HASH(key,seed) (fd_hash( seed, key, sizeof(fd_pubkey_t) ))
44 89376 : #define MAP_IDX_T uint
45 : #include "../../util/tmpl/fd_map_chain.c"
46 :
47 : struct vacc_fork {
48 : uint ref_cnt;
49 : uint next;
50 : };
51 : typedef struct vacc_fork vacc_fork_t;
52 :
53 : #define POOL_NAME vacc_fork_pool
54 234 : #define POOL_T vacc_fork_t
55 : #define POOL_IDX_T uint
56 : #define POOL_LAZY 1
57 : #include "../../util/tmpl/fd_pool.c"
58 :
59 : struct vacc_states {
60 : struct {
61 : ulong last_vote_slot;
62 : long last_vote_ts;
63 : uchar is_valid;
64 : } states[ FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS ];
65 : uint next;
66 : };
67 : typedef struct vacc_states vacc_states_t;
68 :
69 : #define POOL_NAME vacc_state_pool
70 234 : #define POOL_T vacc_states_t
71 : #define POOL_IDX_T uint
72 : #define POOL_LAZY 1
73 : #include "../../util/tmpl/fd_pool.c"
74 :
75 : struct fd_vote_stakes {
76 : ulong magic;
77 : ulong max_fork_width;
78 : ulong max_live_slots;
79 : ulong min_stake_wmark;
80 :
81 : /* (pubkey, stake) pairs for the t-2 epoch. These are shared across
82 : forks/banks. */
83 : ulong t_2_epoch[ 2UL ];
84 : uint t_2_vacc_pool_off[ 2UL ];
85 : uint t_2_vacc_map_off [ 2UL ];
86 :
87 : /* (pubkey, stake) pairs for the t-1 epoch. These can be different
88 : for every fork across the epoch boundary. These must be sized to
89 : the max fork width of the running system. These are keyed by fork
90 : idx. */
91 : uint vacc_fork_pool_off;
92 : uint t_1_vacc_pools_off;
93 : uint t_1_vacc_maps_off;
94 : uint vacc_heap_off;
95 :
96 : /* Per-bank state about the t-2 vote state. Each per-bank state will
97 : be an array sized to length max_live_slots which is a system-wide
98 : bound. Keyed by bank idx. */
99 : uint vacc_states_pool_off;
100 : };
101 : typedef struct fd_vote_stakes fd_vote_stakes_t;
102 :
103 : FD_FN_UNUSED static inline vacc_t *
104 : t_2_vacc_pool( fd_vote_stakes_t const * vote_stakes,
105 52104 : ulong idx ) {
106 52104 : return fd_type_pun( (uchar *)vote_stakes + vote_stakes->t_2_vacc_pool_off[ idx ] );
107 52104 : }
108 :
109 : FD_FN_UNUSED static inline vacc_map_t *
110 : t_2_vacc_map( fd_vote_stakes_t const * vote_stakes,
111 52095 : ulong idx ) {
112 52095 : return fd_type_pun( (uchar *)vote_stakes + vote_stakes->t_2_vacc_map_off[ idx ] );
113 52095 : }
114 :
115 : FD_FN_UNUSED static inline vacc_fork_t *
116 17850 : vacc_fork_pool( fd_vote_stakes_t const * vote_stakes ) {
117 17850 : return fd_type_pun( (uchar *)vote_stakes + vote_stakes->vacc_fork_pool_off );
118 17850 : }
119 :
120 : FD_FN_UNUSED static inline vacc_t *
121 : t_1_vacc_pool( fd_vote_stakes_t const * vote_stakes,
122 53676 : ulong width_idx ) {
123 53676 : ulong off = vote_stakes->t_1_vacc_pools_off + width_idx*vacc_pool_footprint( FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS );
124 53676 : return fd_type_pun( (uchar *)vote_stakes + off );
125 53676 : }
126 :
127 : FD_FN_UNUSED static inline vacc_map_t *
128 : t_1_vacc_map( fd_vote_stakes_t const * vote_stakes,
129 53652 : ulong width_idx ) {
130 53652 : ulong chain_cnt = vacc_map_chain_cnt_est( FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS );
131 53652 : ulong off = vote_stakes->t_1_vacc_maps_off + width_idx*vacc_map_footprint( chain_cnt );
132 53652 : return fd_type_pun( (uchar *)vote_stakes + off );
133 53652 : }
134 :
135 : FD_FN_UNUSED static inline vacc_heap_t *
136 14598 : vacc_heap( fd_vote_stakes_t const * vote_stakes ) {
137 14598 : return fd_type_pun( (uchar *)vote_stakes + vote_stakes->vacc_heap_off );
138 14598 : }
139 :
140 : FD_FN_UNUSED static inline vacc_states_t *
141 28176 : vacc_states_pool( fd_vote_stakes_t const * vote_stakes ) {
142 28176 : return fd_type_pun( (uchar *)vote_stakes + vote_stakes->vacc_states_pool_off );
143 28176 : }
144 :
145 : /* The fork id is a compound of the epoch, width idx, and bank idx. */
146 :
147 : FD_FN_UNUSED static inline ushort
148 16335 : fork_id_bank_id( ulong fork_id ) {
149 16335 : return (ushort)(fork_id & (ulong)USHORT_MAX);
150 16335 : }
151 :
152 : FD_FN_UNUSED static inline ushort
153 23274 : fork_id_width_id( ulong fork_id ) {
154 23274 : return (ushort)((fork_id>>16UL) & (ulong)USHORT_MAX);
155 23274 : }
156 :
157 : FD_FN_UNUSED static inline ushort
158 45588 : fork_id_epoch( ulong fork_id ) {
159 45588 : return (ushort)((fork_id>>32UL) & (ulong)USHORT_MAX);
160 45588 : }
161 :
162 : FD_FN_UNUSED static inline void
163 : fork_id_set_bank_id( ulong * fork_id,
164 8985 : ushort bank_id ) {
165 8985 : *fork_id = (*fork_id & ~(ulong)USHORT_MAX) | (ulong)bank_id;
166 8985 : }
167 :
168 : FD_FN_UNUSED static inline void
169 : fork_id_set_width_id( ulong * fork_id,
170 8985 : ushort width_id ) {
171 8985 : *fork_id = (*fork_id & ~((ulong)USHORT_MAX<<16UL)) | ((ulong)width_id<<16UL);
172 8985 : }
173 :
174 : FD_FN_UNUSED static inline void
175 : fork_id_set_epoch( ulong * fork_id,
176 8985 : ushort epoch ) {
177 8985 : *fork_id = (*fork_id & ~((ulong)USHORT_MAX<<32UL)) | ((ulong)epoch<<32UL);
178 8985 : }
179 :
180 : ulong
181 3657 : fd_vote_stakes_align( void ) {
182 3657 : return FD_VOTE_STAKES_ALIGN;
183 3657 : }
184 :
185 : ulong
186 : fd_vote_stakes_footprint( ulong max_live_slots,
187 609 : ulong max_fork_width ) {
188 609 : if( FD_UNLIKELY( !max_live_slots || max_live_slots>USHORT_MAX ) ) return 0UL;
189 609 : if( FD_UNLIKELY( !max_fork_width || max_fork_width>FD_VOTE_STAKES_MAX_FORK_WIDTH ) ) return 0UL;
190 :
191 609 : ulong map_chain_cnt = vacc_map_chain_cnt_est( FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS );
192 609 : ulong pool_footprint = vacc_pool_footprint( FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS );
193 609 : ulong map_footprint = vacc_map_footprint( map_chain_cnt );
194 609 : ulong width_cnt = max_fork_width + 1UL;
195 :
196 609 : ulong l = FD_LAYOUT_INIT;
197 609 : l = FD_LAYOUT_APPEND( l, fd_vote_stakes_align(), sizeof(fd_vote_stakes_t) );
198 1827 : for( ulong i=0UL; i<2UL; i++ ) {
199 1218 : l = FD_LAYOUT_APPEND( l, vacc_pool_align(), pool_footprint );
200 1218 : l = FD_LAYOUT_APPEND( l, vacc_map_align(), map_footprint );
201 1218 : }
202 609 : l = FD_LAYOUT_APPEND( l, vacc_fork_pool_align(), vacc_fork_pool_footprint( width_cnt ) );
203 609 : l = FD_LAYOUT_APPEND( l, vacc_pool_align(), width_cnt*pool_footprint );
204 609 : l = FD_LAYOUT_APPEND( l, vacc_map_align(), width_cnt*map_footprint );
205 609 : l = FD_LAYOUT_APPEND( l, vacc_heap_align(), vacc_heap_footprint( FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS ) );
206 609 : l = FD_LAYOUT_APPEND( l, vacc_state_pool_align(), vacc_state_pool_footprint( max_live_slots ) );
207 609 : return FD_LAYOUT_FINI( l, fd_vote_stakes_align() );
208 609 : }
209 :
210 : void *
211 : fd_vote_stakes_new( void * mem,
212 : ulong max_live_slots,
213 : ulong max_fork_width,
214 117 : ulong seed ) {
215 117 : if( FD_UNLIKELY( !mem ) ) {
216 0 : FD_LOG_WARNING(( "NULL mem" ));
217 0 : return NULL;
218 0 : }
219 :
220 117 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, fd_vote_stakes_align() ) ) ) {
221 0 : FD_LOG_WARNING(( "misaligned mem" ));
222 0 : return NULL;
223 0 : }
224 :
225 117 : if( FD_UNLIKELY( !max_live_slots || max_live_slots>USHORT_MAX ) ) {
226 0 : FD_LOG_WARNING(( "invalid max_live_slots" ));
227 0 : return NULL;
228 0 : }
229 :
230 117 : if( FD_UNLIKELY( !max_fork_width || max_fork_width>FD_VOTE_STAKES_MAX_FORK_WIDTH ) ) {
231 0 : FD_LOG_WARNING(( "invalid max_fork_width" ));
232 0 : return NULL;
233 0 : }
234 :
235 117 : ulong map_chain_cnt = vacc_map_chain_cnt_est( FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS );
236 117 : ulong pool_footprint = vacc_pool_footprint( FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS );
237 117 : ulong map_footprint = vacc_map_footprint( map_chain_cnt );
238 117 : ulong width_cnt = max_fork_width + 1UL;
239 :
240 117 : FD_SCRATCH_ALLOC_INIT( l, mem );
241 117 : fd_vote_stakes_t * vote_stakes = FD_SCRATCH_ALLOC_APPEND( l, fd_vote_stakes_align(), sizeof(fd_vote_stakes_t) );
242 117 : void * t_2_pool_mem[ 2UL ];
243 117 : void * t_2_map_mem [ 2UL ];
244 351 : for( ulong i=0UL; i<2UL; i++ ) {
245 234 : t_2_pool_mem[ i ] = FD_SCRATCH_ALLOC_APPEND( l, vacc_pool_align(), pool_footprint );
246 234 : t_2_map_mem [ i ] = FD_SCRATCH_ALLOC_APPEND( l, vacc_map_align(), map_footprint );
247 234 : }
248 117 : void * vacc_fork_pool_mem = FD_SCRATCH_ALLOC_APPEND( l, vacc_fork_pool_align(), vacc_fork_pool_footprint( width_cnt ) );
249 117 : void * t_1_vacc_pools_mem = FD_SCRATCH_ALLOC_APPEND( l, vacc_pool_align(), width_cnt*pool_footprint );
250 117 : void * t_1_vacc_maps_mem = FD_SCRATCH_ALLOC_APPEND( l, vacc_map_align(), width_cnt*map_footprint );
251 117 : void * vacc_heap_mem = FD_SCRATCH_ALLOC_APPEND( l, vacc_heap_align(), vacc_heap_footprint( FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS ) );
252 117 : void * vacc_states_pool_mem = FD_SCRATCH_ALLOC_APPEND( l, vacc_state_pool_align(), vacc_state_pool_footprint( max_live_slots ) );
253 :
254 117 : if( FD_UNLIKELY( FD_SCRATCH_ALLOC_FINI( l, fd_vote_stakes_align() )!=(ulong)mem+fd_vote_stakes_footprint( max_live_slots, max_fork_width ) ) ) {
255 0 : FD_LOG_WARNING(( "fd_vote_stakes_new: bad layout" ));
256 0 : return NULL;
257 0 : }
258 :
259 351 : for( ulong i=0UL; i<2UL; i++ ) {
260 234 : vacc_t * t_2_pool = vacc_pool_join( vacc_pool_new( t_2_pool_mem[ i ], FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS ) );
261 234 : if( FD_UNLIKELY( !t_2_pool ) ) {
262 0 : FD_LOG_WARNING(( "Failed to create t-2 vote account pool" ));
263 0 : return NULL;
264 0 : }
265 :
266 234 : vacc_map_t * t_2_map = vacc_map_join( vacc_map_new( t_2_map_mem[ i ], map_chain_cnt, seed ) );
267 234 : if( FD_UNLIKELY( !t_2_map ) ) {
268 0 : FD_LOG_WARNING(( "Failed to create t-2 vote account map" ));
269 0 : return NULL;
270 0 : }
271 :
272 234 : vote_stakes->t_2_vacc_pool_off[ i ] = (uint)((ulong)t_2_pool - (ulong)mem);
273 234 : vote_stakes->t_2_vacc_map_off [ i ] = (uint)((ulong)t_2_map - (ulong)mem);
274 234 : }
275 :
276 117 : vacc_fork_t * fork_pool = vacc_fork_pool_join( vacc_fork_pool_new( vacc_fork_pool_mem, width_cnt ) );
277 117 : if( FD_UNLIKELY( !fork_pool ) ) {
278 0 : FD_LOG_WARNING(( "Failed to create vote account fork pool" ));
279 0 : return NULL;
280 0 : }
281 117 : vote_stakes->vacc_fork_pool_off = (uint)((ulong)fork_pool - (ulong)mem);
282 :
283 1050 : for( ulong i=0UL; i<width_cnt; i++ ) {
284 933 : void * pool_mem = (uchar *)t_1_vacc_pools_mem + i*pool_footprint;
285 933 : vacc_t * pool = vacc_pool_join( vacc_pool_new( pool_mem, FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS ) );
286 933 : if( FD_UNLIKELY( !pool ) ) {
287 0 : FD_LOG_WARNING(( "Failed to create t-1 vote account pool" ));
288 0 : return NULL;
289 0 : }
290 933 : if( FD_UNLIKELY( !i ) ) vote_stakes->t_1_vacc_pools_off = (uint)((ulong)pool - (ulong)mem);
291 :
292 933 : void * map_mem = (uchar *)t_1_vacc_maps_mem + i*map_footprint;
293 933 : vacc_map_t * map = vacc_map_join( vacc_map_new( map_mem, map_chain_cnt, seed ) );
294 933 : if( FD_UNLIKELY( !map ) ) {
295 0 : FD_LOG_WARNING(( "Failed to create t-1 vote account map" ));
296 0 : return NULL;
297 0 : }
298 933 : }
299 117 : vote_stakes->t_1_vacc_maps_off = (uint)((ulong)t_1_vacc_maps_mem - (ulong)mem);
300 :
301 117 : vacc_heap_t * heap = vacc_heap_join( vacc_heap_new( vacc_heap_mem, FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS ) );
302 117 : if( FD_UNLIKELY( !heap ) ) {
303 0 : FD_LOG_WARNING(( "Failed to create vote account heap" ));
304 0 : return NULL;
305 0 : }
306 :
307 117 : vacc_states_t * vacc_states_pool = vacc_state_pool_join( vacc_state_pool_new( vacc_states_pool_mem, max_live_slots ) );
308 117 : if( FD_UNLIKELY( !vacc_states_pool ) ) {
309 0 : FD_LOG_WARNING(( "Failed to create vote account state pool" ));
310 0 : return NULL;
311 0 : }
312 :
313 117 : vote_stakes->max_live_slots = max_live_slots;
314 117 : vote_stakes->max_fork_width = max_fork_width;
315 117 : vote_stakes->min_stake_wmark = 0UL;
316 117 : vote_stakes->vacc_heap_off = (uint)((ulong)heap - (ulong)mem);
317 117 : vote_stakes->vacc_states_pool_off = (uint)((ulong)vacc_states_pool - (ulong)mem);
318 117 : vote_stakes->t_2_epoch[ 0 ] = ULONG_MAX;
319 117 : vote_stakes->t_2_epoch[ 1 ] = ULONG_MAX;
320 :
321 117 : FD_COMPILER_MFENCE();
322 117 : FD_VOLATILE( vote_stakes->magic ) = FD_VOTE_STAKES_MAGIC;
323 117 : FD_COMPILER_MFENCE();
324 :
325 117 : return vote_stakes;
326 117 : }
327 :
328 : fd_vote_stakes_t *
329 231 : fd_vote_stakes_join( void * mem ) {
330 231 : fd_vote_stakes_t * vote_stakes = (fd_vote_stakes_t *)mem;
331 :
332 231 : if( FD_UNLIKELY( !vote_stakes ) ) {
333 0 : FD_LOG_WARNING(( "NULL vote stakes" ));
334 0 : return NULL;
335 0 : }
336 :
337 231 : if( FD_UNLIKELY( vote_stakes->magic!=FD_VOTE_STAKES_MAGIC ) ) {
338 0 : FD_LOG_WARNING(( "Invalid vote stakes magic" ));
339 0 : return NULL;
340 0 : }
341 :
342 231 : return vote_stakes;
343 231 : }
344 :
345 : ulong
346 4458 : fd_vote_stakes_fork_epoch( ulong fork_id ) {
347 4458 : return (ulong)fork_id_epoch( fork_id );
348 4458 : }
349 :
350 : ulong
351 : fd_vote_stakes_init( fd_vote_stakes_t * vote_stakes,
352 3969 : ulong epoch ) {
353 : /* Acquire t-1 key set width idx */
354 3969 : vacc_fork_t * fork_pool = vacc_fork_pool( vote_stakes );
355 3969 : FD_CHECK_CRIT( vacc_fork_pool_free( fork_pool ), "vote stakes width pool exhausted" );
356 3969 : ushort width_idx = (ushort)vacc_fork_pool_idx_acquire( fork_pool );
357 3969 : vacc_fork_pool_ele( fork_pool, width_idx )->ref_cnt = 1U;
358 :
359 : /* Acquire t-2 state bank idx */
360 3969 : vacc_states_t * states_pool = vacc_states_pool( vote_stakes );
361 3969 : FD_CHECK_CRIT( vacc_state_pool_free( states_pool ), "vote stakes state pool exhausted" );
362 3969 : ushort bank_idx = (ushort)vacc_state_pool_idx_acquire( states_pool );
363 3969 : vacc_states_t * states = vacc_state_pool_ele( states_pool, bank_idx );
364 3969 : memset( states->states, 0, sizeof(states->states) );
365 3969 : vote_stakes->t_2_epoch[ epoch & 1UL ] = epoch;
366 :
367 : /* Construct the fork id */
368 3969 : ulong fork_id = 0UL;
369 3969 : fork_id_set_bank_id( &fork_id, bank_idx );
370 3969 : fork_id_set_width_id( &fork_id, width_idx );
371 3969 : fork_id_set_epoch( &fork_id, (ushort)epoch );
372 3969 : return fork_id;
373 3969 : }
374 :
375 : void
376 7872 : fd_vote_stakes_reset( fd_vote_stakes_t * vote_stakes ) {
377 23616 : for( ulong i=0UL; i<2UL; i++ ) {
378 15744 : vacc_map_reset( t_2_vacc_map( vote_stakes, i ) );
379 15744 : vacc_pool_reset( t_2_vacc_pool( vote_stakes, i ) );
380 15744 : vote_stakes->t_2_epoch[ i ] = ULONG_MAX;
381 15744 : }
382 :
383 7872 : ulong width_cnt = vote_stakes->max_fork_width + 1UL;
384 47211 : for( ulong i=0UL; i<width_cnt; i++ ) {
385 39339 : vacc_map_reset( t_1_vacc_map( vote_stakes, i ) );
386 39339 : vacc_pool_reset( t_1_vacc_pool( vote_stakes, i ) );
387 39339 : }
388 :
389 7872 : vacc_fork_pool_reset( vacc_fork_pool( vote_stakes ) );
390 7872 : vacc_state_pool_reset( vacc_states_pool( vote_stakes ) );
391 7872 : FD_TEST( vacc_heap_new( vacc_heap( vote_stakes ), FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS ) );
392 7872 : vote_stakes->min_stake_wmark = 0UL;
393 7872 : }
394 :
395 : void
396 : fd_vote_stakes_snap_insert_t_1( fd_vote_stakes_t * vote_stakes,
397 : ulong fork_id,
398 : fd_pubkey_t const * pubkey,
399 : fd_pubkey_t const * node_account,
400 : ulong stake,
401 3918 : ushort commission ) {
402 3918 : if( FD_UNLIKELY( !stake ) ) return;
403 :
404 3918 : vacc_t * pool = t_1_vacc_pool( vote_stakes, fork_id_width_id( fork_id ) );
405 3918 : vacc_map_t * map = t_1_vacc_map ( vote_stakes, fork_id_width_id( fork_id ) );
406 :
407 3918 : vacc_t * vacc = vacc_pool_ele_acquire( pool );
408 3918 : vacc->pubkey = *pubkey;
409 3918 : vacc->node_account = *node_account;
410 3918 : vacc->stake = stake;
411 3918 : vacc->commission = commission;
412 3918 : FD_TEST( vacc_map_ele_insert( map, vacc, pool ) );
413 3918 : }
414 :
415 : void
416 : fd_vote_stakes_snap_insert_t_2( fd_vote_stakes_t * vote_stakes,
417 : ulong fork_id,
418 : fd_pubkey_t const * pubkey,
419 : fd_pubkey_t const * node_account,
420 : ulong stake,
421 3912 : ushort commission ) {
422 3912 : if( FD_UNLIKELY( !stake ) ) return;
423 :
424 3912 : ulong epoch_idx = (ulong)fork_id_epoch( fork_id ) & 1UL;
425 3912 : vacc_t * pool = t_2_vacc_pool( vote_stakes, epoch_idx );
426 3912 : vacc_map_t * map = t_2_vacc_map ( vote_stakes, epoch_idx );
427 :
428 3912 : vacc_t * vacc = vacc_pool_ele_acquire( pool );
429 3912 : vacc->pubkey = *pubkey;
430 3912 : vacc->node_account = *node_account;
431 3912 : vacc->stake = stake;
432 3912 : vacc->commission = commission;
433 3912 : FD_TEST( vacc_map_ele_insert( map, vacc, pool ) );
434 3912 : }
435 :
436 : void
437 : fd_vote_stakes_insert( fd_vote_stakes_t * vote_stakes,
438 : ulong fork_id,
439 : fd_pubkey_t const * pubkey,
440 : fd_pubkey_t const * node_account,
441 : ulong stake,
442 6330 : ushort commission ) {
443 6330 : ulong width_idx = (ulong)fork_id_width_id( fork_id );
444 6330 : vacc_t * pool = t_1_vacc_pool( vote_stakes, width_idx );
445 6330 : vacc_map_t * map = t_1_vacc_map ( vote_stakes, width_idx );
446 6330 : vacc_heap_t * heap = vacc_heap( vote_stakes );
447 :
448 6330 : if( FD_UNLIKELY( stake==0UL || stake<=vote_stakes->min_stake_wmark ) ) return;
449 :
450 6330 : if( FD_UNLIKELY( vacc_heap_ele_cnt( heap )==vacc_heap_ele_max( heap ) ) ) {
451 3 : vacc_t * ele = vacc_heap_ele_peek_min( heap, pool );
452 3 : ulong min_stake = ele->stake;
453 3 : if( stake<min_stake ) return;
454 :
455 3 : vote_stakes->min_stake_wmark = min_stake;
456 9 : while( (ele=vacc_heap_ele_peek_min( heap, pool )) && min_stake==ele->stake ) {
457 6 : vacc_heap_ele_remove_min( heap, pool );
458 6 : vacc_map_ele_remove( map, &ele->pubkey, NULL, pool );
459 6 : vacc_pool_ele_release( pool, ele );
460 6 : }
461 3 : if( FD_UNLIKELY( stake==min_stake ) ) return;
462 3 : }
463 :
464 6327 : vacc_t * vacc = vacc_pool_ele_acquire( pool );
465 6327 : vacc->pubkey = *pubkey;
466 6327 : vacc->node_account = *node_account;
467 6327 : vacc->stake = stake;
468 6327 : vacc->commission = commission;
469 6327 : vacc_heap_ele_insert( heap, vacc, pool );
470 6327 : FD_TEST( vacc_map_ele_insert( map, vacc, pool ) );
471 6327 : }
472 :
473 : void
474 : fd_vote_stakes_purge_fork( fd_vote_stakes_t * vote_stakes,
475 993 : ulong fork_id ) {
476 993 : ushort bank_id = fork_id_bank_id( fork_id );
477 993 : ushort width_id = fork_id_width_id( fork_id );
478 :
479 993 : vacc_state_pool_idx_release( vacc_states_pool( vote_stakes ), bank_id );
480 :
481 993 : vacc_fork_t * fork_pool = vacc_fork_pool( vote_stakes );
482 993 : vacc_fork_t * fork = vacc_fork_pool_ele( fork_pool, width_id );
483 993 : FD_TEST( fork->ref_cnt );
484 993 : if( !--fork->ref_cnt ) {
485 198 : vacc_map_reset( t_1_vacc_map( vote_stakes, width_id ) );
486 198 : vacc_pool_reset( t_1_vacc_pool( vote_stakes, width_id ) );
487 198 : vacc_fork_pool_idx_release( fork_pool, width_id );
488 198 : }
489 993 : }
490 :
491 : ulong
492 : fd_vote_stakes_new_fork( fd_vote_stakes_t * vote_stakes,
493 : ulong parent_fork_id,
494 5016 : ulong epoch ) {
495 5016 : FD_TEST( epoch<=USHORT_MAX );
496 :
497 5016 : vacc_states_t * states_pool = vacc_states_pool( vote_stakes );
498 5016 : FD_CHECK_CRIT( vacc_state_pool_free( states_pool ), "vote stakes state pool exhausted" );
499 5016 : ushort parent_bank_id = fork_id_bank_id( parent_fork_id );
500 5016 : ushort bank_id = (ushort)vacc_state_pool_idx_acquire( states_pool );
501 5016 : ushort parent_epoch = fork_id_epoch( parent_fork_id );
502 5016 : ushort width_id;
503 :
504 5016 : vacc_states_t * child_state = vacc_state_pool_ele( states_pool, bank_id );
505 5016 : if( FD_LIKELY( epoch==(ulong)parent_epoch ) ) {
506 : /* Standard case: just inherit the parent's t-1 set (and increment
507 : the ref count) and copy over the t-2 state. */
508 4620 : width_id = fork_id_width_id( parent_fork_id );
509 4620 : vacc_fork_pool_ele( vacc_fork_pool( vote_stakes ), width_id )->ref_cnt++;
510 :
511 4620 : vacc_states_t const * parent_state = vacc_state_pool_ele_const( states_pool, parent_bank_id );
512 4620 : memcpy( child_state->states, parent_state->states, sizeof(child_state->states) );
513 4620 : } else {
514 : /* Epoch boundary: copy the parent's t-1 set into the t-2 set and
515 : acquire new t-1 and t-2 state. */
516 :
517 : /* Copy the t-1 set iff it's the first time crossing into a new
518 : epoch boundary. */
519 396 : ulong t_2_idx = epoch & 1UL;
520 396 : if( vote_stakes->t_2_epoch[ t_2_idx ]!=epoch ) {
521 351 : ulong parent_width_id = (ulong)fork_id_width_id( parent_fork_id );
522 351 : vacc_t * t_1_pool = t_1_vacc_pool( vote_stakes, parent_width_id );
523 351 : vacc_map_t * t_1_map = t_1_vacc_map ( vote_stakes, parent_width_id );
524 351 : vacc_t * t_2_pool = t_2_vacc_pool( vote_stakes, t_2_idx );
525 351 : vacc_map_t * t_2_map = t_2_vacc_map ( vote_stakes, t_2_idx );
526 :
527 351 : vacc_map_reset( t_2_map );
528 351 : vacc_pool_reset( t_2_pool );
529 351 : for( vacc_map_iter_t iter = vacc_map_iter_init( t_1_map, t_1_pool );
530 759 : !vacc_map_iter_done( iter, t_1_map, t_1_pool );
531 408 : iter = vacc_map_iter_next( iter, t_1_map, t_1_pool ) ) {
532 408 : vacc_t const * src = vacc_map_iter_ele_const( iter, t_1_map, t_1_pool );
533 408 : vacc_t * dst = vacc_pool_ele_acquire( t_2_pool );
534 408 : dst->pubkey = src->pubkey;
535 408 : dst->node_account = src->node_account;
536 408 : dst->stake = src->stake;
537 408 : dst->commission = src->commission;
538 408 : FD_TEST( vacc_map_ele_insert( t_2_map, dst, t_2_pool ) );
539 408 : }
540 351 : vote_stakes->t_2_epoch[ t_2_idx ] = epoch;
541 351 : }
542 :
543 : /* Reset the t-2 states for the new fork and prepare the heap for
544 : insertion into the new t-1 set. */
545 396 : vacc_fork_t * fork_pool = vacc_fork_pool( vote_stakes );
546 396 : FD_CHECK_CRIT( vacc_fork_pool_free( fork_pool ), "vote stakes width pool exhausted" );
547 396 : width_id = (ushort)vacc_fork_pool_idx_acquire( fork_pool );
548 396 : vacc_fork_pool_ele( fork_pool, width_id )->ref_cnt = 1U;
549 396 : vacc_map_reset( t_1_vacc_map( vote_stakes, width_id ) );
550 396 : vacc_pool_reset( t_1_vacc_pool( vote_stakes, width_id ) );
551 396 : memset( child_state->states, 0, sizeof(child_state->states) );
552 :
553 396 : FD_TEST( vacc_heap_new( vacc_heap( vote_stakes ), FD_RUNTIME_MAX_VAT_VOTE_ACCOUNTS ) );
554 396 : vote_stakes->min_stake_wmark = 0UL;
555 396 : }
556 :
557 5016 : ulong fork_id = 0UL;
558 5016 : fork_id_set_bank_id( &fork_id, bank_id );
559 5016 : fork_id_set_width_id( &fork_id, width_id );
560 5016 : fork_id_set_epoch( &fork_id, (ushort)epoch );
561 5016 : return fork_id;
562 5016 : }
563 :
564 : void
565 : fd_vote_stakes_update_state( fd_vote_stakes_t * vote_stakes,
566 : ulong fork_id,
567 : fd_pubkey_t const * pubkey,
568 : ulong last_vote_slot,
569 : long last_vote_ts,
570 4302 : uchar is_valid ) {
571 4302 : ulong epoch_idx = (ulong)fork_id_epoch( fork_id ) & 1UL;
572 4302 : vacc_t * pool = t_2_vacc_pool( vote_stakes, epoch_idx );
573 4302 : vacc_map_t * map = t_2_vacc_map ( vote_stakes, epoch_idx );
574 :
575 4302 : vacc_t const * vacc = vacc_map_ele_query_const( map, pubkey, NULL, pool );
576 4302 : if( FD_UNLIKELY( !vacc ) ) return;
577 :
578 4242 : ulong vacc_idx = vacc_pool_idx( pool, vacc );
579 4242 : vacc_states_t * states = vacc_state_pool_ele( vacc_states_pool( vote_stakes ), fork_id_bank_id( fork_id ) );
580 4242 : states->states[ vacc_idx ].is_valid = (uchar)!!is_valid;
581 4242 : if( is_valid ) {
582 4236 : states->states[ vacc_idx ].last_vote_slot = last_vote_slot;
583 4236 : states->states[ vacc_idx ].last_vote_ts = last_vote_ts;
584 4236 : }
585 4242 : }
586 :
587 : void
588 : fd_vote_stakes_refresh( fd_vote_stakes_t * vote_stakes,
589 : ulong fork_id,
590 : fd_accdb_t * accdb,
591 264 : fd_accdb_fork_id_t accdb_fork_id ) {
592 264 : uchar __attribute__((aligned(FD_VOTE_STAKES_T_2_ITER_ALIGN))) iter_mem[ FD_VOTE_STAKES_T_2_ITER_FOOTPRINT ];
593 :
594 264 : for( fd_vote_stakes_t_2_iter_t * iter = fd_vote_stakes_t_2_iter_init( vote_stakes, fork_id, iter_mem );
595 588 : !fd_vote_stakes_t_2_iter_done( vote_stakes, fork_id, iter );
596 324 : fd_vote_stakes_t_2_iter_next( vote_stakes, fork_id, iter ) ) {
597 324 : fd_pubkey_t pubkey;
598 324 : fd_vote_stakes_t_2_iter_ele( vote_stakes, fork_id, iter, &pubkey, NULL, NULL, NULL, NULL, NULL, NULL );
599 :
600 324 : fd_acc_t acc = fd_accdb_read_one( accdb, accdb_fork_id, pubkey.uc );
601 324 : if( FD_UNLIKELY( !acc.lamports || !fd_vsv_is_correct_size_owner_and_init( acc.owner, acc.data, acc.data_len ) ) ) {
602 3 : fd_accdb_unread_one( accdb, &acc );
603 3 : fd_vote_stakes_update_state( vote_stakes, fork_id, &pubkey, 0UL, 0L, 0 );
604 3 : continue;
605 3 : }
606 :
607 321 : fd_vote_block_timestamp_t last_vote;
608 321 : FD_TEST( !fd_vote_account_last_timestamp( acc.data, acc.data_len, &last_vote ) );
609 321 : fd_vote_stakes_update_state( vote_stakes, fork_id, &pubkey, last_vote.slot, last_vote.timestamp, 1 );
610 321 : fd_accdb_unread_one( accdb, &acc );
611 321 : }
612 264 : }
613 :
614 : int
615 : fd_vote_stakes_query_t_1( fd_vote_stakes_t const * vote_stakes,
616 : ulong fork_id,
617 : fd_pubkey_t const * pubkey,
618 : fd_pubkey_t * node_account_out_opt,
619 : ulong * stake_out_opt,
620 45 : ushort * commission_out_opt ) {
621 45 : ulong width_idx = (ulong)fork_id_width_id( fork_id );
622 45 : vacc_t * pool = t_1_vacc_pool( vote_stakes, width_idx );
623 45 : vacc_map_t * map = t_1_vacc_map ( vote_stakes, width_idx );
624 :
625 45 : vacc_t const * vacc = vacc_map_ele_query_const( map, pubkey, NULL, pool );
626 45 : if( FD_UNLIKELY( !vacc ) ) return 0;
627 :
628 30 : if( node_account_out_opt ) *node_account_out_opt = vacc->node_account;
629 30 : if( stake_out_opt ) *stake_out_opt = vacc->stake;
630 30 : if( commission_out_opt ) *commission_out_opt = vacc->commission;
631 30 : return 1;
632 45 : }
633 :
634 : int
635 : fd_vote_stakes_query_t_2( fd_vote_stakes_t const * vote_stakes,
636 : ulong fork_id,
637 : fd_pubkey_t const * pubkey,
638 : fd_pubkey_t * node_account_out_opt,
639 : ulong * stake_out_opt,
640 : ulong * last_vote_slot_out_opt,
641 : long * last_vote_ts_out_opt,
642 : ushort * commission_out_opt,
643 336 : uchar * is_valid_out_opt ) {
644 336 : ulong epoch_idx = (ulong)fork_id_epoch( fork_id ) & 1UL;
645 336 : vacc_t * pool = t_2_vacc_pool( vote_stakes, epoch_idx );
646 336 : vacc_map_t * map = t_2_vacc_map ( vote_stakes, epoch_idx );
647 :
648 336 : vacc_t const * vacc = vacc_map_ele_query_const( map, pubkey, NULL, pool );
649 336 : if( FD_UNLIKELY( !vacc ) ) return 0;
650 :
651 333 : ulong vacc_idx = vacc_pool_idx( pool, vacc );
652 333 : vacc_states_t const * states = vacc_state_pool_ele_const( vacc_states_pool( vote_stakes ), fork_id_bank_id( fork_id ) );
653 :
654 333 : if( node_account_out_opt ) *node_account_out_opt = vacc->node_account;
655 333 : if( stake_out_opt ) *stake_out_opt = vacc->stake;
656 333 : if( last_vote_slot_out_opt ) *last_vote_slot_out_opt = states->states[ vacc_idx ].last_vote_slot;
657 333 : if( last_vote_ts_out_opt ) *last_vote_ts_out_opt = states->states[ vacc_idx ].last_vote_ts;
658 333 : if( commission_out_opt ) *commission_out_opt = vacc->commission;
659 333 : if( is_valid_out_opt ) *is_valid_out_opt = states->states[ vacc_idx ].is_valid;
660 333 : return 1;
661 336 : }
662 :
663 : int
664 : fd_vote_stakes_query_t_3( fd_vote_stakes_t const * vote_stakes,
665 : ulong fork_id,
666 : fd_pubkey_t const * pubkey,
667 : fd_pubkey_t * node_account_out_opt,
668 : ulong * stake_out_opt,
669 324 : ushort * commission_out_opt ) {
670 324 : ulong epoch = (ulong)fork_id_epoch( fork_id );
671 324 : if( FD_UNLIKELY( !epoch ) ) return 0;
672 :
673 324 : ulong t_3_epoch = epoch - 1UL;
674 324 : ulong t_3_idx = t_3_epoch & 1UL;
675 324 : if( FD_UNLIKELY( vote_stakes->t_2_epoch[ t_3_idx ]!=t_3_epoch ) ) return 0;
676 :
677 219 : vacc_t * pool = t_2_vacc_pool( vote_stakes, t_3_idx );
678 219 : vacc_map_t * map = t_2_vacc_map ( vote_stakes, t_3_idx );
679 219 : vacc_t const * vacc = vacc_map_ele_query_const( map, pubkey, NULL, pool );
680 219 : if( FD_UNLIKELY( !vacc ) ) return 0;
681 :
682 216 : if( node_account_out_opt ) *node_account_out_opt = vacc->node_account;
683 216 : if( stake_out_opt ) *stake_out_opt = vacc->stake;
684 216 : if( commission_out_opt ) *commission_out_opt = vacc->commission;
685 216 : return 1;
686 219 : }
687 :
688 : ulong
689 : fd_vote_stakes_cnt_t_1( fd_vote_stakes_t const * vote_stakes,
690 24 : ulong fork_id ) {
691 24 : return vacc_pool_used( t_1_vacc_pool( vote_stakes, fork_id_width_id( fork_id ) ) );
692 24 : }
693 :
694 : ulong
695 : fd_vote_stakes_cnt_t_2( fd_vote_stakes_t const * vote_stakes,
696 9 : ulong fork_id ) {
697 9 : return vacc_pool_used( t_2_vacc_pool( vote_stakes, (ulong)fork_id_epoch( fork_id ) & 1UL ) );
698 9 : }
699 :
700 : FD_STATIC_ASSERT( FD_VOTE_STAKES_T_1_ITER_FOOTPRINT == sizeof(vacc_map_iter_t), t_1_iter_footprint );
701 : FD_STATIC_ASSERT( FD_VOTE_STAKES_T_1_ITER_ALIGN == alignof(vacc_map_iter_t), t_1_iter_align );
702 : FD_STATIC_ASSERT( FD_VOTE_STAKES_T_2_ITER_FOOTPRINT == sizeof(vacc_map_iter_t), t_2_iter_footprint );
703 : FD_STATIC_ASSERT( FD_VOTE_STAKES_T_2_ITER_ALIGN == alignof(vacc_map_iter_t), t_2_iter_align );
704 :
705 : fd_vote_stakes_t_1_iter_t *
706 : fd_vote_stakes_t_1_iter_init( fd_vote_stakes_t const * vote_stakes,
707 : ulong fork_id,
708 540 : uchar iter_mem[ static FD_VOTE_STAKES_T_1_ITER_FOOTPRINT ] ) {
709 540 : ulong width_idx = (ulong)fork_id_width_id( fork_id );
710 540 : vacc_t * pool = t_1_vacc_pool( vote_stakes, width_idx );
711 540 : vacc_map_t * map = t_1_vacc_map ( vote_stakes, width_idx );
712 540 : vacc_map_iter_t iter = vacc_map_iter_init( map, pool );
713 540 : memcpy( iter_mem, &iter, sizeof(iter) );
714 540 : return (fd_vote_stakes_t_1_iter_t *)iter_mem;
715 540 : }
716 :
717 : int
718 : fd_vote_stakes_t_1_iter_done( fd_vote_stakes_t const * vote_stakes,
719 : ulong fork_id,
720 1200 : fd_vote_stakes_t_1_iter_t * iter ) {
721 1200 : ulong width_idx = (ulong)fork_id_width_id( fork_id );
722 1200 : vacc_t * pool = t_1_vacc_pool( vote_stakes, width_idx );
723 1200 : vacc_map_t * map = t_1_vacc_map ( vote_stakes, width_idx );
724 1200 : return vacc_map_iter_done( *(vacc_map_iter_t *)iter, map, pool );
725 1200 : }
726 :
727 : void
728 : fd_vote_stakes_t_1_iter_next( fd_vote_stakes_t const * vote_stakes,
729 : ulong fork_id,
730 666 : fd_vote_stakes_t_1_iter_t * iter ) {
731 666 : ulong width_idx = (ulong)fork_id_width_id( fork_id );
732 666 : vacc_t * pool = t_1_vacc_pool( vote_stakes, width_idx );
733 666 : vacc_map_t * map = t_1_vacc_map ( vote_stakes, width_idx );
734 666 : vacc_map_iter_t * map_iter = (vacc_map_iter_t *)iter;
735 666 : *map_iter = vacc_map_iter_next( *map_iter, map, pool );
736 666 : }
737 :
738 : void
739 : fd_vote_stakes_t_1_iter_ele( fd_vote_stakes_t const * vote_stakes,
740 : ulong fork_id,
741 : fd_vote_stakes_t_1_iter_t * iter,
742 : fd_pubkey_t * pubkey_out,
743 : fd_pubkey_t * node_account_out_opt,
744 : ulong * stake_out_opt,
745 669 : ushort * commission_out_opt ) {
746 669 : ulong width_idx = (ulong)fork_id_width_id( fork_id );
747 669 : vacc_t * pool = t_1_vacc_pool( vote_stakes, width_idx );
748 669 : vacc_map_t * map = t_1_vacc_map ( vote_stakes, width_idx );
749 669 : vacc_t const * vacc = vacc_map_iter_ele_const( *(vacc_map_iter_t *)iter, map, pool );
750 :
751 669 : *pubkey_out = vacc->pubkey;
752 669 : if( node_account_out_opt ) *node_account_out_opt = vacc->node_account;
753 669 : if( stake_out_opt ) *stake_out_opt = vacc->stake;
754 669 : if( commission_out_opt ) *commission_out_opt = vacc->commission;
755 669 : }
756 :
757 : fd_vote_stakes_t_2_iter_t *
758 : fd_vote_stakes_t_2_iter_init( fd_vote_stakes_t const * vote_stakes,
759 : ulong fork_id,
760 4992 : uchar iter_mem[ static FD_VOTE_STAKES_T_2_ITER_FOOTPRINT ] ) {
761 4992 : ulong epoch_idx = (ulong)fork_id_epoch( fork_id ) & 1UL;
762 4992 : vacc_t * pool = t_2_vacc_pool( vote_stakes, epoch_idx );
763 4992 : vacc_map_t * map = t_2_vacc_map ( vote_stakes, epoch_idx );
764 4992 : vacc_map_iter_t iter = vacc_map_iter_init( map, pool );
765 4992 : memcpy( iter_mem, &iter, sizeof(iter) );
766 4992 : return (fd_vote_stakes_t_2_iter_t *)iter_mem;
767 4992 : }
768 :
769 : int
770 : fd_vote_stakes_t_2_iter_done( fd_vote_stakes_t const * vote_stakes,
771 : ulong fork_id,
772 10737 : fd_vote_stakes_t_2_iter_t * iter ) {
773 10737 : ulong epoch_idx = (ulong)fork_id_epoch( fork_id ) & 1UL;
774 10737 : vacc_t * pool = t_2_vacc_pool( vote_stakes, epoch_idx );
775 10737 : vacc_map_t * map = t_2_vacc_map ( vote_stakes, epoch_idx );
776 10737 : return vacc_map_iter_done( *(vacc_map_iter_t *)iter, map, pool );
777 10737 : }
778 :
779 : void
780 : fd_vote_stakes_t_2_iter_next( fd_vote_stakes_t const * vote_stakes,
781 : ulong fork_id,
782 5751 : fd_vote_stakes_t_2_iter_t * iter ) {
783 5751 : ulong epoch_idx = (ulong)fork_id_epoch( fork_id ) & 1UL;
784 5751 : vacc_t * pool = t_2_vacc_pool( vote_stakes, epoch_idx );
785 5751 : vacc_map_t * map = t_2_vacc_map ( vote_stakes, epoch_idx );
786 5751 : vacc_map_iter_t * map_iter = (vacc_map_iter_t *)iter;
787 5751 : *map_iter = vacc_map_iter_next( *map_iter, map, pool );
788 5751 : }
789 :
790 : void
791 : fd_vote_stakes_t_2_iter_ele( fd_vote_stakes_t const * vote_stakes,
792 : ulong fork_id,
793 : fd_vote_stakes_t_2_iter_t * iter,
794 : fd_pubkey_t * pubkey_out,
795 : fd_pubkey_t * node_account_out_opt,
796 : ulong * stake_out_opt,
797 : ulong * last_vote_slot_out_opt,
798 : long * last_vote_ts_out_opt,
799 : ushort * commission_out_opt,
800 5751 : uchar * is_valid_out_opt ) {
801 5751 : ulong epoch_idx = (ulong)fork_id_epoch( fork_id ) & 1UL;
802 5751 : vacc_t * pool = t_2_vacc_pool( vote_stakes, epoch_idx );
803 5751 : vacc_map_t * map = t_2_vacc_map ( vote_stakes, epoch_idx );
804 5751 : vacc_t const * vacc = vacc_map_iter_ele_const( *(vacc_map_iter_t *)iter, map, pool );
805 5751 : ulong vacc_idx = vacc_pool_idx( pool, vacc );
806 5751 : vacc_states_t const * states = vacc_state_pool_ele_const( vacc_states_pool( vote_stakes ), fork_id_bank_id( fork_id ) );
807 :
808 5751 : *pubkey_out = vacc->pubkey;
809 5751 : if( node_account_out_opt ) *node_account_out_opt = vacc->node_account;
810 5751 : if( stake_out_opt ) *stake_out_opt = vacc->stake;
811 5751 : if( last_vote_slot_out_opt ) *last_vote_slot_out_opt = states->states[ vacc_idx ].last_vote_slot;
812 5751 : if( last_vote_ts_out_opt ) *last_vote_ts_out_opt = states->states[ vacc_idx ].last_vote_ts;
813 5751 : if( commission_out_opt ) *commission_out_opt = vacc->commission;
814 5751 : if( is_valid_out_opt ) *is_valid_out_opt = states->states[ vacc_idx ].is_valid;
815 5751 : }
|