Line data Source code
1 : #include "fd_stake_delegations.h"
2 : #include "../accdb/fd_accdb_pipe.h"
3 : #include "fd_stakes.h"
4 :
5 : #define POOL_NAME root_pool
6 24 : #define POOL_T fd_stake_delegation_t
7 631590 : #define POOL_NEXT next_
8 : #define POOL_IDX_T uint
9 : #include "../../util/tmpl/fd_pool.c"
10 :
11 : #define MAP_NAME root_map
12 : #define MAP_KEY_T fd_pubkey_t
13 : #define MAP_ELE_T fd_stake_delegation_t
14 299 : #define MAP_KEY stake_account
15 0 : #define MAP_KEY_EQ(k0,k1) (fd_pubkey_eq( k0, k1 ))
16 598 : #define MAP_KEY_HASH(key,seed) (fd_funk_rec_key_hash1( key->uc, seed ))
17 313 : #define MAP_NEXT next_
18 1236 : #define MAP_IDX_T uint
19 : #include "../../util/tmpl/fd_map_chain.c"
20 :
21 : #define POOL_NAME delta_pool
22 24 : #define POOL_T fd_stake_delegation_t
23 24580 : #define POOL_NEXT next_
24 : #define POOL_IDX_T uint
25 : #include "../../util/tmpl/fd_pool.c"
26 :
27 : #define DLIST_NAME fork_dlist
28 : #define DLIST_ELE_T fd_stake_delegation_t
29 2 : #define DLIST_PREV prev_
30 4 : #define DLIST_NEXT next_
31 : #define DLIST_IDX_T uint
32 : #include "../../util/tmpl/fd_dlist.c"
33 :
34 : struct fork_pool_ele { ushort next; };
35 : typedef struct fork_pool_ele fork_pool_ele_t;
36 :
37 : #define POOL_NAME fork_pool
38 24 : #define POOL_T fork_pool_ele_t
39 : #define POOL_IDX_T ushort
40 : #include "../../util/tmpl/fd_pool.c"
41 :
42 : /* Internal getters for base map + pool */
43 :
44 : static inline fd_stake_delegation_t *
45 620 : get_root_pool( fd_stake_delegations_t const * stake_delegations ) {
46 620 : return fd_type_pun( (uchar *)stake_delegations + stake_delegations->pool_offset_ );
47 620 : }
48 :
49 : static inline root_map_t *
50 620 : get_root_map( fd_stake_delegations_t const * stake_delegations ) {
51 620 : return fd_type_pun( (uchar *)stake_delegations + stake_delegations->map_offset_ );
52 620 : }
53 :
54 : /* Internal getters for delta pool + fork structures */
55 :
56 : static inline fd_stake_delegation_t *
57 323 : get_delta_pool( fd_stake_delegations_t const * stake_delegations ) {
58 323 : return fd_type_pun( (uchar *)stake_delegations + stake_delegations->delta_pool_offset_ );
59 323 : }
60 :
61 : static inline fork_pool_ele_t *
62 609 : get_fork_pool( fd_stake_delegations_t const * stake_delegations ) {
63 609 : return fd_type_pun( (uchar *)stake_delegations + stake_delegations->fork_pool_offset_ );
64 609 : }
65 :
66 : static inline fork_dlist_t *
67 : get_fork_dlist( fd_stake_delegations_t const * stake_delegations,
68 309 : ushort fork_idx ) {
69 309 : return fd_type_pun( (uchar *)stake_delegations + stake_delegations->dlist_offsets_[ fork_idx ] );
70 309 : }
71 :
72 : ulong
73 671 : fd_stake_delegations_align( void ) {
74 671 : return FD_STAKE_DELEGATIONS_ALIGN;
75 671 : }
76 :
77 : ulong
78 : fd_stake_delegations_footprint( ulong max_stake_accounts,
79 : ulong expected_stake_accounts,
80 60 : ulong max_live_slots ) {
81 :
82 60 : ulong map_chain_cnt = root_map_chain_cnt_est( expected_stake_accounts );
83 :
84 60 : ulong l = FD_LAYOUT_INIT;
85 60 : l = FD_LAYOUT_APPEND( l, fd_stake_delegations_align(), sizeof(fd_stake_delegations_t) );
86 60 : l = FD_LAYOUT_APPEND( l, root_pool_align(), root_pool_footprint( max_stake_accounts ) );
87 60 : l = FD_LAYOUT_APPEND( l, root_map_align(), root_map_footprint( map_chain_cnt ) );
88 60 : l = FD_LAYOUT_APPEND( l, delta_pool_align(), delta_pool_footprint( max_stake_accounts ) );
89 60 : l = FD_LAYOUT_APPEND( l, fork_pool_align(), fork_pool_footprint( max_live_slots ) );
90 180 : for( ulong i=0UL; i<max_live_slots; i++ ) {
91 120 : l = FD_LAYOUT_APPEND( l, fork_dlist_align(), fork_dlist_footprint() );
92 120 : }
93 :
94 60 : return FD_LAYOUT_FINI( l, fd_stake_delegations_align() );
95 60 : }
96 :
97 : void *
98 : fd_stake_delegations_new( void * mem,
99 : ulong seed,
100 : ulong max_stake_accounts,
101 : ulong expected_stake_accounts,
102 12 : ulong max_live_slots ) {
103 12 : if( FD_UNLIKELY( !mem ) ) {
104 0 : FD_LOG_WARNING(( "NULL mem" ));
105 0 : return NULL;
106 0 : }
107 :
108 12 : if( FD_UNLIKELY( !max_stake_accounts ) ) {
109 0 : FD_LOG_WARNING(( "max_stake_accounts is 0" ));
110 0 : return NULL;
111 0 : }
112 :
113 12 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, fd_stake_delegations_align() ) ) ) {
114 0 : FD_LOG_WARNING(( "misaligned mem" ));
115 0 : return NULL;
116 0 : }
117 :
118 12 : if( FD_UNLIKELY( max_live_slots>FD_STAKE_DELEGATIONS_FORK_MAX ) ) {
119 0 : FD_LOG_WARNING(( "max_live_slots is too large" ));
120 0 : return NULL;
121 0 : }
122 :
123 12 : ulong map_chain_cnt = root_map_chain_cnt_est( expected_stake_accounts );
124 :
125 12 : FD_SCRATCH_ALLOC_INIT( l, mem );
126 12 : fd_stake_delegations_t * stake_delegations = FD_SCRATCH_ALLOC_APPEND( l, fd_stake_delegations_align(), sizeof(fd_stake_delegations_t) );
127 12 : void * pool_mem = FD_SCRATCH_ALLOC_APPEND( l, root_pool_align(), root_pool_footprint( max_stake_accounts ) );
128 12 : void * map_mem = FD_SCRATCH_ALLOC_APPEND( l, root_map_align(), root_map_footprint( map_chain_cnt ) );
129 12 : void * delta_pool_mem = FD_SCRATCH_ALLOC_APPEND( l, delta_pool_align(), delta_pool_footprint( max_stake_accounts ) );
130 12 : void * fork_pool_mem = FD_SCRATCH_ALLOC_APPEND( l, fork_pool_align(), fork_pool_footprint( max_live_slots ) );
131 36 : for( ushort i=0; i<(ushort)max_live_slots; i++ ) {
132 24 : void * fork_dlist_mem = FD_SCRATCH_ALLOC_APPEND( l, fork_dlist_align(), fork_dlist_footprint() );
133 0 : fork_dlist_t * dlist = fork_dlist_join( fork_dlist_new( fork_dlist_mem ) );
134 24 : if( FD_UNLIKELY( !dlist ) ) {
135 0 : FD_LOG_WARNING(( "Failed to create fork dlist" ));
136 0 : return NULL;
137 0 : }
138 24 : stake_delegations->dlist_offsets_[ i ] = (ulong)dlist - (ulong)mem;
139 24 : }
140 :
141 12 : if( FD_UNLIKELY( FD_SCRATCH_ALLOC_FINI( l, fd_stake_delegations_align() )!=(ulong)mem+fd_stake_delegations_footprint( max_stake_accounts, expected_stake_accounts, max_live_slots ) ) ) {
142 0 : FD_LOG_WARNING(( "fd_stake_delegations_new: bad layout" ));
143 0 : return NULL;
144 0 : }
145 :
146 12 : fd_stake_delegation_t * root_pool = root_pool_join( root_pool_new( pool_mem, max_stake_accounts ) );
147 12 : if( FD_UNLIKELY( !root_pool ) ) {
148 0 : FD_LOG_WARNING(( "Failed to create stake delegations pool" ));
149 0 : return NULL;
150 0 : }
151 :
152 12 : root_map_t * root_map = root_map_join( root_map_new( map_mem, map_chain_cnt, seed ) );
153 12 : if( FD_UNLIKELY( !root_map ) ) {
154 0 : FD_LOG_WARNING(( "Failed to create stake delegations map" ));
155 0 : return NULL;
156 0 : }
157 :
158 12 : fd_stake_delegation_t * delta_pool = delta_pool_join( delta_pool_new( delta_pool_mem, max_stake_accounts ) );
159 12 : if( FD_UNLIKELY( !delta_pool ) ) {
160 0 : FD_LOG_WARNING(( "Failed to create stake delegation delta pool" ));
161 0 : return NULL;
162 0 : }
163 :
164 12 : fork_pool_ele_t * fork_pool = fork_pool_join( fork_pool_new( fork_pool_mem, max_live_slots ) );
165 12 : if( FD_UNLIKELY( !fork_pool ) ) {
166 0 : FD_LOG_WARNING(( "Failed to create fork pool" ));
167 0 : return NULL;
168 0 : }
169 :
170 12 : stake_delegations->max_stake_accounts_ = max_stake_accounts;
171 12 : stake_delegations->expected_stake_accounts_ = expected_stake_accounts;
172 12 : stake_delegations->pool_offset_ = (ulong)root_pool - (ulong)mem;
173 12 : stake_delegations->map_offset_ = (ulong)root_map - (ulong)mem;
174 12 : stake_delegations->delta_pool_offset_ = (ulong)delta_pool - (ulong)mem;
175 12 : stake_delegations->fork_pool_offset_ = (ulong)fork_pool - (ulong)mem;
176 :
177 12 : fd_rwlock_new( &stake_delegations->delta_lock );
178 :
179 12 : FD_COMPILER_MFENCE();
180 12 : FD_VOLATILE( stake_delegations->magic ) = FD_STAKE_DELEGATIONS_MAGIC;
181 12 : FD_COMPILER_MFENCE();
182 :
183 12 : return mem;
184 12 : }
185 :
186 : fd_stake_delegations_t *
187 311 : fd_stake_delegations_join( void * mem ) {
188 311 : if( FD_UNLIKELY( !mem ) ) {
189 0 : FD_LOG_WARNING(( "NULL mem" ));
190 0 : return NULL;
191 0 : }
192 :
193 311 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, fd_stake_delegations_align() ) ) ) {
194 0 : FD_LOG_WARNING(( "misaligned mem" ));
195 0 : return NULL;
196 0 : }
197 :
198 311 : fd_stake_delegations_t * stake_delegations = (fd_stake_delegations_t *)mem;
199 :
200 311 : if( FD_UNLIKELY( stake_delegations->magic!=FD_STAKE_DELEGATIONS_MAGIC ) ) {
201 0 : FD_LOG_WARNING(( "Invalid stake delegations magic" ));
202 0 : return NULL;
203 0 : }
204 :
205 311 : return stake_delegations;
206 311 : }
207 :
208 : void
209 299 : fd_stake_delegations_init( fd_stake_delegations_t * stake_delegations ) {
210 299 : root_map_t * map = get_root_map( stake_delegations );
211 299 : fd_stake_delegation_t * pool = get_root_pool( stake_delegations );
212 299 : root_pool_reset( pool );
213 299 : root_map_reset( map );
214 299 : }
215 :
216 : void
217 : fd_stake_delegations_root_update( fd_stake_delegations_t * stake_delegations,
218 : fd_pubkey_t const * stake_account,
219 : fd_pubkey_t const * vote_account,
220 : ulong stake,
221 : ulong activation_epoch,
222 : ulong deactivation_epoch,
223 : ulong credits_observed,
224 299 : double warmup_cooldown_rate ) {
225 299 : fd_stake_delegation_t * pool = get_root_pool( stake_delegations );
226 299 : root_map_t * map = get_root_map( stake_delegations );
227 :
228 299 : fd_stake_delegation_t * stake_delegation = root_map_ele_query( map, stake_account, NULL, pool );
229 299 : if( !stake_delegation ) {
230 299 : FD_CRIT( root_pool_free( pool ), "no free stake delegations in pool" );
231 299 : stake_delegation = root_pool_ele_acquire( pool );
232 299 : stake_delegation->stake_account = *stake_account;
233 299 : FD_CRIT( root_map_ele_insert( map, stake_delegation, pool ), "unable to insert stake delegation into map" );
234 299 : }
235 :
236 299 : stake_delegation->vote_account = *vote_account;
237 299 : stake_delegation->stake = stake;
238 299 : stake_delegation->activation_epoch = (ushort)fd_ulong_min( activation_epoch, USHORT_MAX );
239 299 : stake_delegation->deactivation_epoch = (ushort)fd_ulong_min( deactivation_epoch, USHORT_MAX );
240 299 : stake_delegation->credits_observed = credits_observed;
241 299 : stake_delegation->warmup_cooldown_rate = fd_stake_delegations_warmup_cooldown_rate_enum( warmup_cooldown_rate );
242 299 : stake_delegation->dne_in_root = 0;
243 299 : stake_delegation->delta_idx = UINT_MAX;
244 299 : }
245 :
246 : static inline void
247 : fd_stake_delegations_remove( fd_stake_delegations_t * stake_delegations,
248 0 : fd_pubkey_t const * stake_account ) {
249 0 : fd_stake_delegation_t * pool = get_root_pool( stake_delegations );
250 0 : root_map_t * map = get_root_map( stake_delegations );
251 :
252 0 : ulong delegation_idx = root_map_idx_query( map, stake_account, UINT_MAX, pool );
253 0 : if( FD_UNLIKELY( delegation_idx==UINT_MAX ) ) return;
254 :
255 0 : root_map_idx_remove( map, stake_account, delegation_idx, pool );
256 0 : root_pool_idx_release( pool, delegation_idx );
257 0 : }
258 :
259 : void
260 : fd_stake_delegations_refresh( fd_stake_delegations_t * stake_delegations,
261 : fd_accdb_user_t * accdb,
262 0 : fd_funk_txn_xid_t const * xid ) {
263 :
264 0 : root_map_t * map = get_root_map( stake_delegations );
265 0 : fd_stake_delegation_t * pool = get_root_pool( stake_delegations );
266 :
267 0 : fd_accdb_ro_pipe_t ro_pipe[1];
268 0 : fd_accdb_ro_pipe_init( ro_pipe, accdb, xid );
269 0 : ulong const job_cnt = fd_stake_delegations_cnt( stake_delegations );
270 0 : for( ulong i=0UL; i<job_cnt; i++ ) {
271 :
272 : /* stream out read requests */
273 0 : fd_accdb_ro_pipe_enqueue( ro_pipe, &pool[ i ].stake_account );
274 0 : if( FD_UNLIKELY( i+1UL==job_cnt ) ) {
275 0 : fd_accdb_ro_pipe_flush( ro_pipe );
276 0 : }
277 :
278 : /* handle a batch of completions */
279 0 : fd_accdb_ro_t * ro;
280 0 : while( (ro = fd_accdb_ro_pipe_poll( ro_pipe )) ) {
281 0 : fd_pubkey_t const * address = fd_accdb_ref_address( ro );
282 0 : fd_stake_delegation_t * delegation = root_map_ele_query( map, address, NULL, pool );
283 0 : if( FD_UNLIKELY( !delegation ) ) continue;
284 :
285 0 : if( FD_UNLIKELY( fd_accdb_ref_lamports( ro )==0UL ) ) goto remove;
286 :
287 0 : fd_stake_state_v2_t stake;
288 0 : int err = fd_stakes_get_state( ro->meta, &stake );
289 0 : if( FD_UNLIKELY( err ) ) goto remove;
290 0 : if( FD_UNLIKELY( !fd_stake_state_v2_is_stake( &stake ) ) ) goto remove;
291 :
292 0 : fd_stake_delegations_root_update(
293 0 : stake_delegations,
294 0 : address,
295 0 : &stake.inner.stake.stake.delegation.voter_pubkey,
296 0 : stake.inner.stake.stake.delegation.stake,
297 0 : stake.inner.stake.stake.delegation.activation_epoch,
298 0 : stake.inner.stake.stake.delegation.deactivation_epoch,
299 0 : stake.inner.stake.stake.credits_observed,
300 0 : stake.inner.stake.stake.delegation.warmup_cooldown_rate );
301 0 : continue; /* ok */
302 :
303 0 : remove:
304 0 : root_map_idx_remove( map, address, UINT_MAX, pool );
305 0 : root_pool_ele_release( pool, delegation );
306 0 : }
307 0 : }
308 0 : fd_accdb_ro_pipe_fini( ro_pipe );
309 0 : }
310 :
311 : ulong
312 0 : fd_stake_delegations_cnt( fd_stake_delegations_t const * stake_delegations ) {
313 0 : return root_pool_used( get_root_pool( stake_delegations ) );
314 0 : }
315 :
316 : /* Fork-aware delta operations */
317 :
318 : ushort
319 311 : fd_stake_delegations_new_fork( fd_stake_delegations_t * stake_delegations ) {
320 311 : fork_pool_ele_t * fork_pool = get_fork_pool( stake_delegations );
321 311 : FD_CRIT( fork_pool_free( fork_pool ), "no free forks in pool" );
322 311 : ushort fork_idx = (ushort)fork_pool_idx_acquire( fork_pool );
323 :
324 311 : return fork_idx;
325 311 : }
326 :
327 : void
328 : fd_stake_delegations_fork_update( fd_stake_delegations_t * stake_delegations,
329 : ushort fork_idx,
330 : fd_pubkey_t const * stake_account,
331 : fd_pubkey_t const * vote_account,
332 : ulong stake,
333 : ulong activation_epoch,
334 : ulong deactivation_epoch,
335 : ulong credits_observed,
336 2 : double warmup_cooldown_rate ) {
337 2 : fd_rwlock_write( &stake_delegations->delta_lock );
338 :
339 2 : fd_stake_delegation_t * delta_pool = get_delta_pool( stake_delegations );
340 2 : FD_CRIT( delta_pool_free( delta_pool ), "no free stake delegations in pool" );
341 :
342 2 : fork_dlist_t * dlist = get_fork_dlist( stake_delegations, fork_idx );
343 :
344 2 : fd_stake_delegation_t * stake_delegation = delta_pool_ele_acquire( delta_pool );
345 :
346 2 : fork_dlist_ele_push_tail( dlist, stake_delegation, delta_pool );
347 :
348 2 : stake_delegation->stake_account = *stake_account;
349 2 : stake_delegation->vote_account = *vote_account;
350 2 : stake_delegation->stake = stake;
351 2 : stake_delegation->activation_epoch = (ushort)fd_ulong_min( activation_epoch, USHORT_MAX );
352 2 : stake_delegation->deactivation_epoch = (ushort)fd_ulong_min( deactivation_epoch, USHORT_MAX );
353 2 : stake_delegation->credits_observed = credits_observed;
354 2 : stake_delegation->warmup_cooldown_rate = fd_stake_delegations_warmup_cooldown_rate_enum( warmup_cooldown_rate );
355 2 : stake_delegation->is_tombstone = 0;
356 :
357 2 : fd_rwlock_unwrite( &stake_delegations->delta_lock );
358 2 : }
359 :
360 : void
361 : fd_stake_delegations_fork_remove( fd_stake_delegations_t * stake_delegations,
362 : ushort fork_idx,
363 0 : fd_pubkey_t const * stake_account ) {
364 0 : fd_rwlock_write( &stake_delegations->delta_lock );
365 :
366 0 : fd_stake_delegation_t * delta_pool = get_delta_pool( stake_delegations );
367 0 : FD_CRIT( delta_pool_free( delta_pool ), "no free stake delegations in pool" );
368 :
369 0 : fd_stake_delegation_t * stake_delegation = delta_pool_ele_acquire( delta_pool );
370 :
371 0 : fork_dlist_t * dlist = get_fork_dlist( stake_delegations, fork_idx );
372 0 : fork_dlist_ele_push_tail( dlist, stake_delegation, delta_pool );
373 :
374 0 : stake_delegation->stake_account = *stake_account;
375 0 : stake_delegation->is_tombstone = 1;
376 :
377 0 : fd_rwlock_unwrite( &stake_delegations->delta_lock );
378 0 : }
379 :
380 : void
381 : fd_stake_delegations_evict_fork( fd_stake_delegations_t * stake_delegations,
382 299 : ushort fork_idx ) {
383 299 : if( fork_idx==USHORT_MAX ) return;
384 :
385 299 : fd_rwlock_write( &stake_delegations->delta_lock );
386 :
387 299 : fd_stake_delegation_t * delta_pool = get_delta_pool( stake_delegations );
388 :
389 299 : fork_dlist_t * dlist = get_fork_dlist( stake_delegations, fork_idx );
390 301 : while( !fork_dlist_is_empty( dlist, delta_pool ) ) {
391 2 : fd_stake_delegation_t * ele = fork_dlist_ele_pop_head( dlist, delta_pool );
392 2 : delta_pool_ele_release( delta_pool, ele );
393 2 : }
394 :
395 299 : fork_pool_idx_release( get_fork_pool( stake_delegations ), fork_idx );
396 :
397 299 : fd_rwlock_unwrite( &stake_delegations->delta_lock );
398 299 : }
399 :
400 : void
401 : fd_stake_delegations_apply_fork_delta( fd_stake_delegations_t * stake_delegations,
402 0 : ushort fork_idx ) {
403 :
404 0 : fork_dlist_t * dlist = get_fork_dlist( stake_delegations, fork_idx );
405 0 : fd_stake_delegation_t * delta_pool = get_delta_pool( stake_delegations );
406 :
407 0 : for( fork_dlist_iter_t iter = fork_dlist_iter_fwd_init( dlist, delta_pool );
408 0 : !fork_dlist_iter_done( iter, dlist, delta_pool );
409 0 : iter = fork_dlist_iter_fwd_next( iter, dlist, delta_pool ) ) {
410 0 : fd_stake_delegation_t * stake_delegation = fork_dlist_iter_ele( iter, dlist, delta_pool );
411 0 : if( FD_LIKELY( !stake_delegation->is_tombstone ) ) {
412 0 : fd_stake_delegations_root_update(
413 0 : stake_delegations,
414 0 : &stake_delegation->stake_account,
415 0 : &stake_delegation->vote_account,
416 0 : stake_delegation->stake,
417 0 : stake_delegation->activation_epoch,
418 0 : stake_delegation->deactivation_epoch,
419 0 : stake_delegation->credits_observed,
420 0 : fd_stake_delegations_warmup_cooldown_rate_to_double( stake_delegation->warmup_cooldown_rate ) );
421 0 : } else {
422 0 : fd_stake_delegations_remove( stake_delegations, &stake_delegation->stake_account );
423 0 : }
424 0 : }
425 0 : }
426 :
427 : /* Combined base+delta iterator */
428 :
429 : fd_stake_delegation_t const *
430 14 : fd_stake_delegations_iter_ele( fd_stake_delegations_iter_t * iter ) {
431 14 : ulong idx = root_map_iter_idx( iter->iter, iter->root_map, iter->root_pool );
432 14 : fd_stake_delegation_t * stake_delegation = root_pool_ele( iter->root_pool, idx );
433 14 : if( FD_UNLIKELY( stake_delegation->delta_idx!=UINT_MAX ) ) {
434 0 : return (fd_stake_delegation_t *)delta_pool_ele( iter->delta_pool, stake_delegation->delta_idx );
435 0 : }
436 14 : return stake_delegation;
437 14 : }
438 :
439 : ulong
440 10 : fd_stake_delegations_iter_idx( fd_stake_delegations_iter_t * iter ) {
441 10 : return root_map_iter_idx( iter->iter, iter->root_map, iter->root_pool );
442 10 : }
443 :
444 : static void
445 28 : skip_tombstones( fd_stake_delegations_iter_t * iter ) {
446 28 : while( !root_map_iter_done( iter->iter, iter->root_map, iter->root_pool ) ) {
447 14 : fd_stake_delegation_t * root_delegation = root_map_iter_ele( iter->iter, iter->root_map, iter->root_pool );
448 14 : fd_stake_delegation_t const * ele = (root_delegation->delta_idx != UINT_MAX)
449 14 : ? (fd_stake_delegation_t const *)delta_pool_ele( iter->delta_pool, root_delegation->delta_idx )
450 14 : : (fd_stake_delegation_t const *)root_delegation;
451 14 : if( FD_LIKELY( !ele->is_tombstone ) ) return;
452 0 : iter->iter = root_map_iter_next( iter->iter, iter->root_map, iter->root_pool );
453 0 : }
454 28 : }
455 :
456 : fd_stake_delegations_iter_t *
457 : fd_stake_delegations_iter_init( fd_stake_delegations_iter_t * iter,
458 14 : fd_stake_delegations_t const * stake_delegations ) {
459 14 : if( FD_UNLIKELY( !stake_delegations ) ) {
460 0 : FD_LOG_CRIT(( "NULL stake_delegations" ));
461 0 : }
462 :
463 14 : iter->root_map = get_root_map( stake_delegations );
464 14 : iter->root_pool = get_root_pool( stake_delegations );
465 14 : iter->iter = root_map_iter_init( iter->root_map, iter->root_pool );
466 14 : iter->delta_pool = get_delta_pool( stake_delegations );
467 :
468 14 : skip_tombstones( iter );
469 :
470 14 : return iter;
471 14 : }
472 :
473 : void
474 14 : fd_stake_delegations_iter_next( fd_stake_delegations_iter_t * iter ) {
475 14 : iter->iter = root_map_iter_next( iter->iter, iter->root_map, iter->root_pool );
476 14 : skip_tombstones( iter );
477 14 : }
478 :
479 : int
480 28 : fd_stake_delegations_iter_done( fd_stake_delegations_iter_t * iter ) {
481 28 : return root_map_iter_done( iter->iter, iter->root_map, iter->root_pool );
482 28 : }
483 :
484 : void
485 : fd_stake_delegations_mark_delta( fd_stake_delegations_t * stake_delegations,
486 4 : ushort fork_idx ) {
487 :
488 4 : root_map_t * root_map = get_root_map( stake_delegations );
489 4 : fd_stake_delegation_t * root_pool = get_root_pool( stake_delegations );
490 4 : fd_stake_delegation_t * delta_pool = get_delta_pool( stake_delegations );
491 4 : fork_dlist_t * fork_dlist = get_fork_dlist( stake_delegations, fork_idx );
492 :
493 4 : for( fork_dlist_iter_t iter = fork_dlist_iter_fwd_init( fork_dlist, delta_pool );
494 4 : !fork_dlist_iter_done( iter, fork_dlist, delta_pool );
495 4 : iter = fork_dlist_iter_fwd_next( iter, fork_dlist, delta_pool ) ) {
496 0 : fd_stake_delegation_t * delta_delegation = fork_dlist_iter_ele( iter, fork_dlist, delta_pool );
497 :
498 0 : fd_stake_delegation_t * base_delegation = root_map_ele_query( root_map, &delta_delegation->stake_account, NULL, root_pool);
499 0 : if( FD_UNLIKELY( !base_delegation ) ) {
500 0 : base_delegation = root_pool_ele_acquire( root_pool );
501 0 : base_delegation->stake_account = delta_delegation->stake_account;
502 0 : root_map_ele_insert( root_map, base_delegation, root_pool );
503 :
504 0 : base_delegation->dne_in_root = 1;
505 0 : base_delegation->delta_idx = (uint)delta_pool_idx( delta_pool, delta_delegation );
506 0 : } else {
507 0 : base_delegation->delta_idx = (uint)delta_pool_idx( delta_pool, delta_delegation );
508 0 : }
509 0 : }
510 4 : }
511 :
512 : void
513 : fd_stake_delegations_unmark_delta( fd_stake_delegations_t * stake_delegations,
514 4 : ushort fork_idx ) {
515 :
516 4 : root_map_t * root_map = get_root_map( stake_delegations );
517 4 : fd_stake_delegation_t * root_pool = get_root_pool( stake_delegations );
518 4 : fork_dlist_t * fork_dlist = get_fork_dlist( stake_delegations, fork_idx );
519 4 : fd_stake_delegation_t * delta_pool = get_delta_pool( stake_delegations );
520 :
521 4 : for( fork_dlist_iter_t iter = fork_dlist_iter_fwd_init( fork_dlist, delta_pool );
522 4 : !fork_dlist_iter_done( iter, fork_dlist, delta_pool );
523 4 : iter = fork_dlist_iter_fwd_next( iter, fork_dlist, delta_pool ) ) {
524 0 : fd_stake_delegation_t * delta_delegation = fork_dlist_iter_ele( iter, fork_dlist, delta_pool );
525 :
526 0 : fd_stake_delegation_t * base_delegation = root_map_ele_query( root_map, &delta_delegation->stake_account, NULL, root_pool );
527 0 : if( FD_UNLIKELY( !base_delegation ) ) {
528 0 : continue;
529 0 : }
530 :
531 0 : if( FD_UNLIKELY( base_delegation->dne_in_root )) {
532 0 : base_delegation->dne_in_root = 0;
533 0 : base_delegation->delta_idx = UINT_MAX;
534 0 : root_map_ele_remove( root_map, &delta_delegation->stake_account, NULL, root_pool );
535 0 : root_pool_ele_release( root_pool, base_delegation );
536 0 : } else {
537 0 : base_delegation->delta_idx = UINT_MAX;
538 0 : }
539 0 : }
540 4 : }
|