Line data Source code
1 : #include "fd_stake_delegations.h"
2 : #include "../accdb/fd_accdb_pipe.h"
3 : #include "../runtime/program/fd_stake_program.h"
4 :
5 : #define POOL_NAME fd_stake_delegation_pool
6 1659 : #define POOL_T fd_stake_delegation_t
7 872063319 : #define POOL_NEXT next_
8 : #include "../../util/tmpl/fd_pool.c"
9 :
10 : #define MAP_NAME fd_stake_delegation_map
11 : #define MAP_KEY_T fd_pubkey_t
12 : #define MAP_ELE_T fd_stake_delegation_t
13 99 : #define MAP_KEY stake_account
14 165 : #define MAP_KEY_EQ(k0,k1) (fd_pubkey_eq( k0, k1 ))
15 348 : #define MAP_KEY_HASH(key,seed) (fd_funk_rec_key_hash1( key->uc, seed ))
16 225 : #define MAP_NEXT next_
17 : #include "../../util/tmpl/fd_map_chain.c"
18 :
19 : static inline fd_stake_delegation_t *
20 429 : fd_stake_delegations_get_pool( fd_stake_delegations_t const * stake_delegations ) {
21 429 : return fd_stake_delegation_pool_join( (uchar *)stake_delegations + stake_delegations->pool_offset_ );
22 429 : }
23 :
24 : static inline fd_stake_delegation_map_t *
25 354 : fd_stake_delegations_get_map( fd_stake_delegations_t const * stake_delegations ) {
26 354 : return fd_stake_delegation_map_join( (uchar *)stake_delegations + stake_delegations->map_offset_ );
27 354 : }
28 :
29 : ulong
30 9903 : fd_stake_delegations_align( void ) {
31 : /* The align of the struct should be the max of the align of the data
32 : structures that it contains. In this case, this is the map, the
33 : pool, and the struct itself. */
34 9903 : return fd_ulong_max( fd_ulong_max( fd_stake_delegation_map_align(),
35 9903 : fd_stake_delegation_pool_align() ), alignof(fd_stake_delegations_t) );
36 9903 : }
37 :
38 : ulong
39 1239 : fd_stake_delegations_footprint( ulong max_stake_accounts ) {
40 :
41 1239 : ulong map_chain_cnt = fd_stake_delegation_map_chain_cnt_est( max_stake_accounts );
42 :
43 1239 : ulong l = FD_LAYOUT_INIT;
44 1239 : l = FD_LAYOUT_APPEND( l, fd_stake_delegations_align(), sizeof(fd_stake_delegations_t) );
45 1239 : l = FD_LAYOUT_APPEND( l, fd_stake_delegation_pool_align(), fd_stake_delegation_pool_footprint( max_stake_accounts ) );
46 1239 : l = FD_LAYOUT_APPEND( l, fd_stake_delegation_map_align(), fd_stake_delegation_map_footprint( map_chain_cnt ) );
47 1239 : return FD_LAYOUT_FINI( l, fd_stake_delegations_align() );
48 1239 : }
49 :
50 : void *
51 : fd_stake_delegations_new( void * mem,
52 : ulong seed,
53 : ulong max_stake_accounts,
54 690 : int leave_tombstones ) {
55 690 : if( FD_UNLIKELY( !mem ) ) {
56 3 : FD_LOG_WARNING(( "NULL mem" ));
57 3 : return NULL;
58 3 : }
59 :
60 687 : if( FD_UNLIKELY( !max_stake_accounts ) ) {
61 3 : FD_LOG_WARNING(( "max_stake_accounts is 0" ));
62 3 : return NULL;
63 3 : }
64 :
65 684 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, fd_stake_delegations_align() ) ) ) {
66 0 : FD_LOG_WARNING(( "misaligned mem" ));
67 0 : return NULL;
68 0 : }
69 :
70 684 : ulong map_chain_cnt = fd_stake_delegation_map_chain_cnt_est( max_stake_accounts );
71 :
72 684 : FD_SCRATCH_ALLOC_INIT( l, mem );
73 684 : fd_stake_delegations_t * stake_delegations = FD_SCRATCH_ALLOC_APPEND( l, fd_stake_delegations_align(), sizeof(fd_stake_delegations_t) );
74 684 : void * pool_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_stake_delegation_pool_align(), fd_stake_delegation_pool_footprint( max_stake_accounts ) );
75 684 : void * map_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_stake_delegation_map_align(), fd_stake_delegation_map_footprint( map_chain_cnt ) );
76 :
77 684 : if( FD_UNLIKELY( FD_SCRATCH_ALLOC_FINI( l, fd_stake_delegations_align() )!=(ulong)mem+fd_stake_delegations_footprint( max_stake_accounts ) ) ) {
78 0 : FD_LOG_WARNING(( "fd_stake_delegations_new: bad layout" ));
79 0 : return NULL;
80 0 : }
81 :
82 684 : if( FD_UNLIKELY( !fd_stake_delegation_pool_new( pool_mem, max_stake_accounts ) ) ) {
83 0 : FD_LOG_WARNING(( "Failed to create stake delegations pool" ));
84 0 : return NULL;
85 0 : }
86 :
87 684 : if( FD_UNLIKELY( !fd_stake_delegation_map_new( map_mem, map_chain_cnt, seed ) ) ) {
88 0 : FD_LOG_WARNING(( "Failed to create stake delegations map" ));
89 0 : return NULL;
90 0 : }
91 :
92 684 : stake_delegations->pool_offset_ = (ulong)pool_mem - (ulong)mem;
93 684 : stake_delegations->map_offset_ = (ulong)map_mem - (ulong)mem;
94 684 : stake_delegations->max_stake_accounts_ = max_stake_accounts;
95 684 : stake_delegations->leave_tombstones_ = leave_tombstones;
96 :
97 684 : FD_COMPILER_MFENCE();
98 684 : FD_VOLATILE( stake_delegations->magic ) = FD_STAKE_DELEGATIONS_MAGIC;
99 684 : FD_COMPILER_MFENCE();
100 :
101 684 : return mem;
102 684 : }
103 :
104 : fd_stake_delegations_t *
105 555 : fd_stake_delegations_join( void * mem ) {
106 555 : if( FD_UNLIKELY( !mem ) ) {
107 3 : FD_LOG_WARNING(( "NULL mem" ));
108 3 : return NULL;
109 3 : }
110 :
111 552 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, fd_stake_delegations_align() ) ) ) {
112 0 : FD_LOG_WARNING(( "misaligned mem" ));
113 0 : return NULL;
114 0 : }
115 :
116 552 : fd_stake_delegations_t * stake_delegations = (fd_stake_delegations_t *)mem;
117 :
118 552 : if( FD_UNLIKELY( stake_delegations->magic != FD_STAKE_DELEGATIONS_MAGIC ) ) {
119 6 : FD_LOG_WARNING(( "Invalid stake delegations magic" ));
120 6 : return NULL;
121 6 : }
122 :
123 546 : ulong map_chain_cnt = fd_stake_delegation_map_chain_cnt_est( stake_delegations->max_stake_accounts_ );
124 :
125 546 : FD_SCRATCH_ALLOC_INIT( l, stake_delegations );
126 546 : stake_delegations = FD_SCRATCH_ALLOC_APPEND( l, fd_stake_delegations_align(), sizeof(fd_stake_delegations_t) );
127 546 : void * pool_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_stake_delegation_pool_align(), fd_stake_delegation_pool_footprint( stake_delegations->max_stake_accounts_ ) );
128 546 : void * map_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_stake_delegation_map_align(), fd_stake_delegation_map_footprint( map_chain_cnt ) );
129 :
130 546 : if( FD_UNLIKELY( FD_SCRATCH_ALLOC_FINI( l, fd_stake_delegations_align() )!=(ulong)mem+fd_stake_delegations_footprint( stake_delegations->max_stake_accounts_ ) ) ) {
131 0 : FD_LOG_WARNING(( "fd_stake_delegations_join: bad layout" ));
132 0 : return NULL;
133 0 : }
134 :
135 546 : if( FD_UNLIKELY( !fd_stake_delegation_pool_join( pool_mem ) ) ) {
136 0 : FD_LOG_WARNING(( "Failed to join stake delegations pool" ));
137 0 : return NULL;
138 0 : }
139 :
140 546 : if( FD_UNLIKELY( !fd_stake_delegation_map_join( map_mem ) ) ) {
141 0 : FD_LOG_WARNING(( "Failed to join stake delegations map" ));
142 0 : return NULL;
143 0 : }
144 :
145 546 : return stake_delegations;
146 546 : }
147 :
148 : void *
149 12 : fd_stake_delegations_leave( fd_stake_delegations_t * self ) {
150 12 : if( FD_UNLIKELY( !self ) ) {
151 3 : FD_LOG_WARNING(( "NULL self" ));
152 3 : return NULL;
153 3 : }
154 :
155 9 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)self, fd_stake_delegations_align() ) ) ) {
156 0 : FD_LOG_WARNING(( "misaligned self" ));
157 0 : return NULL;
158 0 : }
159 :
160 9 : fd_stake_delegations_t * stake_delegations = (fd_stake_delegations_t *)self;
161 :
162 9 : if( FD_UNLIKELY( stake_delegations->magic!=FD_STAKE_DELEGATIONS_MAGIC ) ) {
163 0 : FD_LOG_WARNING(( "Invalid stake delegations magic" ));
164 0 : return NULL;
165 0 : }
166 :
167 9 : return (void *)self;
168 9 : }
169 :
170 : void *
171 6 : fd_stake_delegations_delete( void * mem ) {
172 6 : if( FD_UNLIKELY( !mem ) ) {
173 3 : FD_LOG_WARNING(( "NULL mem" ));
174 3 : return NULL;
175 3 : }
176 :
177 3 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, fd_stake_delegations_align() ) ) ) {
178 0 : FD_LOG_WARNING(( "misaligned mem" ));
179 0 : return NULL;
180 0 : }
181 :
182 3 : fd_stake_delegations_t * stake_delegations = (fd_stake_delegations_t *)mem;
183 :
184 3 : if( FD_UNLIKELY( stake_delegations->magic!=FD_STAKE_DELEGATIONS_MAGIC ) ) {
185 0 : FD_LOG_WARNING(( "Invalid stake delegations magic" ));
186 0 : return NULL;
187 0 : }
188 :
189 3 : stake_delegations->magic = 0UL;
190 :
191 3 : return mem;
192 3 : }
193 :
194 : void
195 15 : fd_stake_delegations_init( fd_stake_delegations_t * stake_delegations ) {
196 15 : fd_stake_delegation_map_t * stake_delegation_map = fd_stake_delegations_get_map( stake_delegations );
197 15 : fd_stake_delegation_map_reset( stake_delegation_map );
198 15 : fd_stake_delegation_t * stake_delegation_pool = fd_stake_delegations_get_pool( stake_delegations );
199 15 : fd_stake_delegation_pool_reset( stake_delegation_pool );
200 15 : }
201 :
202 : void
203 : fd_stake_delegations_update( fd_stake_delegations_t * stake_delegations,
204 : fd_pubkey_t const * stake_account,
205 : fd_pubkey_t const * vote_account,
206 : ulong stake,
207 : ulong activation_epoch,
208 : ulong deactivation_epoch,
209 : ulong credits_observed,
210 114 : double warmup_cooldown_rate ) {
211 114 : fd_stake_delegation_t * stake_delegation_pool = fd_stake_delegations_get_pool( stake_delegations );
212 114 : if( FD_UNLIKELY( !stake_delegation_pool ) ) {
213 0 : FD_LOG_CRIT(( "unable to retrieve join to stake delegation pool" ));
214 0 : }
215 114 : fd_stake_delegation_map_t * stake_delegation_map = fd_stake_delegations_get_map( stake_delegations );
216 114 : if( FD_UNLIKELY( !stake_delegation_map ) ) {
217 0 : FD_LOG_CRIT(( "unable to retrieve join to stake delegation map" ));
218 0 : }
219 :
220 : /* First, handle the case where the stake delegation already exists
221 : and we just need to update the entry. The reason we do a const idx
222 : query is to allow fd_stake_delegations_update to be called while
223 : iterating over the map. It is unsafe to call
224 : fd_stake_delegation_map_ele_query() during iteration, but we only
225 : need to change fields which are not used for pool/map management. */
226 :
227 114 : ulong idx = fd_stake_delegation_map_idx_query_const(
228 114 : stake_delegation_map,
229 114 : stake_account,
230 114 : ULONG_MAX,
231 114 : stake_delegation_pool );
232 :
233 114 : if( idx!=ULONG_MAX ) {
234 :
235 21 : fd_stake_delegation_t * stake_delegation = fd_stake_delegation_pool_ele( stake_delegation_pool, idx );
236 21 : if( FD_UNLIKELY( !stake_delegation ) ) {
237 0 : FD_LOG_CRIT(( "unable to retrieve stake delegation" ));
238 0 : }
239 :
240 21 : stake_delegation->vote_account = *vote_account;
241 21 : stake_delegation->stake = stake;
242 21 : stake_delegation->activation_epoch = activation_epoch;
243 21 : stake_delegation->deactivation_epoch = deactivation_epoch;
244 21 : stake_delegation->credits_observed = credits_observed;
245 21 : stake_delegation->warmup_cooldown_rate = warmup_cooldown_rate;
246 21 : stake_delegation->is_tombstone = 0;
247 21 : return;
248 21 : }
249 :
250 : /* Otherwise, try to acquire a new node and populate it. */
251 93 : if( FD_UNLIKELY( !fd_stake_delegation_pool_free( stake_delegation_pool ) ) ) {
252 0 : FD_LOG_CRIT(( "no free stake delegations in pool" ));
253 0 : }
254 :
255 93 : fd_stake_delegation_t * stake_delegation = fd_stake_delegation_pool_ele_acquire( stake_delegation_pool );
256 :
257 93 : stake_delegation->stake_account = *stake_account;
258 93 : stake_delegation->vote_account = *vote_account;
259 93 : stake_delegation->stake = stake;
260 93 : stake_delegation->activation_epoch = activation_epoch;
261 93 : stake_delegation->deactivation_epoch = deactivation_epoch;
262 93 : stake_delegation->credits_observed = credits_observed;
263 93 : stake_delegation->warmup_cooldown_rate = warmup_cooldown_rate;
264 93 : stake_delegation->is_tombstone = 0;
265 :
266 93 : if( FD_UNLIKELY( !fd_stake_delegation_map_ele_insert(
267 93 : stake_delegation_map,
268 93 : stake_delegation,
269 93 : stake_delegation_pool ) ) ) {
270 0 : FD_LOG_CRIT(( "unable to insert stake delegation into map" ));
271 0 : }
272 :
273 93 : }
274 :
275 : void
276 : fd_stake_delegations_remove( fd_stake_delegations_t * stake_delegations,
277 24 : fd_pubkey_t const * stake_account ) {
278 24 : fd_stake_delegation_t * stake_delegation_pool = fd_stake_delegations_get_pool( stake_delegations );
279 24 : if( FD_UNLIKELY( !stake_delegation_pool ) ) {
280 0 : FD_LOG_CRIT(( "unable to retrieve join to stake delegation pool" ));
281 0 : }
282 24 : fd_stake_delegation_map_t * stake_delegation_map = fd_stake_delegations_get_map( stake_delegations );
283 24 : if( FD_UNLIKELY( !stake_delegation_map ) ) {
284 0 : FD_LOG_CRIT(( "unable to retrieve join to stake delegation map" ));
285 0 : }
286 :
287 24 : ulong delegation_idx = fd_stake_delegation_map_idx_query(
288 24 : stake_delegation_map,
289 24 : stake_account,
290 24 : ULONG_MAX,
291 24 : stake_delegation_pool );
292 :
293 24 : if( stake_delegations->leave_tombstones_==1 ) {
294 : /* If we are configured to leave tombstones, we need to either
295 : update the entry's is_tombstone flag or insert a new entry. */
296 :
297 9 : fd_stake_delegation_t * stake_delegation = NULL;
298 9 : if( delegation_idx!=ULONG_MAX ) {
299 : /* The delegation was found, update the is_tombstone flag. */
300 3 : stake_delegation = fd_stake_delegation_pool_ele( stake_delegation_pool, delegation_idx );
301 6 : } else {
302 : /* Otherwise, acquire an element from the pool and add it into the
303 : map. */
304 6 : stake_delegation = fd_stake_delegation_pool_ele_acquire( stake_delegation_pool );
305 6 : stake_delegation->stake_account = *stake_account;
306 6 : fd_stake_delegation_map_ele_insert( stake_delegation_map, stake_delegation, stake_delegation_pool );
307 6 : }
308 9 : stake_delegation->is_tombstone = 1;
309 :
310 15 : } else {
311 : /* If we are not configured to leave tombstones, we need to remove
312 : the entry from the map and release it from the pool. */
313 15 : if( FD_UNLIKELY( delegation_idx == ULONG_MAX ) ) {
314 : /* The delegation was not found, nothing to do. */
315 0 : return;
316 0 : }
317 :
318 : /* To be safe, we should set the next_ pointer to the null idx. */
319 :
320 15 : fd_stake_delegation_t * stake_delegation = fd_stake_delegation_pool_ele( stake_delegation_pool, delegation_idx );
321 15 : if( FD_UNLIKELY( !stake_delegation ) ) {
322 0 : FD_LOG_CRIT(( "unable to retrieve stake delegation" ));
323 0 : }
324 :
325 15 : ulong idx = fd_stake_delegation_map_idx_remove( stake_delegation_map, stake_account, ULONG_MAX, stake_delegation_pool );
326 15 : if( FD_UNLIKELY( idx==ULONG_MAX ) ) {
327 0 : FD_LOG_CRIT(( "unable to remove stake delegation" ));
328 0 : }
329 :
330 15 : stake_delegation->next_ = fd_stake_delegation_pool_idx_null( stake_delegation_pool );
331 :
332 15 : fd_stake_delegation_pool_idx_release( stake_delegation_pool, delegation_idx );
333 15 : }
334 24 : }
335 :
336 : void
337 : fd_stake_delegations_refresh( fd_stake_delegations_t * stake_delegations,
338 : fd_accdb_user_t * accdb,
339 0 : fd_funk_txn_xid_t const * xid ) {
340 :
341 0 : fd_stake_delegation_map_t * map = fd_stake_delegations_get_map( stake_delegations );
342 0 : if( FD_UNLIKELY( !map ) ) {
343 0 : FD_LOG_CRIT(( "unable to retrieve join to stake delegation map" ));
344 0 : }
345 0 : fd_stake_delegation_t * pool = fd_stake_delegations_get_pool( stake_delegations );
346 0 : if( FD_UNLIKELY( !pool ) ) {
347 0 : FD_LOG_CRIT(( "unable to retrieve join to stake delegation pool" ));
348 0 : }
349 :
350 0 : fd_accdb_ro_pipe_t ro_pipe[1];
351 0 : fd_accdb_ro_pipe_init( ro_pipe, accdb, xid );
352 0 : ulong const job_cnt = stake_delegations->max_stake_accounts_;
353 0 : for( ulong i=0UL; i<job_cnt; i++ ) {
354 :
355 : /* stream out read requests */
356 0 : fd_accdb_ro_pipe_enqueue( ro_pipe, &pool[ i ].stake_account );
357 0 : if( FD_UNLIKELY( i+1UL==job_cnt ) ) {
358 0 : fd_accdb_ro_pipe_flush( ro_pipe );
359 0 : }
360 :
361 : /* handle a batch of completions */
362 0 : fd_accdb_ro_t * ro;
363 0 : while( (ro = fd_accdb_ro_pipe_poll( ro_pipe )) ) {
364 0 : fd_pubkey_t const * address = fd_accdb_ref_address( ro );
365 0 : fd_stake_delegation_t * delegation =
366 0 : fd_stake_delegation_map_ele_query( map, address, NULL, pool );
367 0 : if( FD_UNLIKELY( !delegation ) ) continue;
368 :
369 0 : if( FD_UNLIKELY( fd_accdb_ref_lamports( ro )==0UL ) ) goto remove;
370 :
371 0 : fd_stake_state_v2_t stake;
372 0 : int err = fd_stake_get_state( ro->meta, &stake );
373 0 : if( FD_UNLIKELY( err ) ) goto remove;
374 0 : if( FD_UNLIKELY( !fd_stake_state_v2_is_stake( &stake ) ) ) goto remove;
375 :
376 0 : fd_stake_delegations_update(
377 0 : stake_delegations,
378 0 : address,
379 0 : &stake.inner.stake.stake.delegation.voter_pubkey,
380 0 : stake.inner.stake.stake.delegation.stake,
381 0 : stake.inner.stake.stake.delegation.activation_epoch,
382 0 : stake.inner.stake.stake.delegation.deactivation_epoch,
383 0 : stake.inner.stake.stake.credits_observed,
384 0 : stake.inner.stake.stake.delegation.warmup_cooldown_rate );
385 0 : continue; /* ok */
386 :
387 0 : remove:
388 0 : fd_stake_delegation_map_idx_remove( map, address, ULONG_MAX, pool );
389 0 : fd_stake_delegation_pool_ele_release( pool, delegation );
390 0 : }
391 0 : }
392 0 : fd_accdb_ro_pipe_fini( ro_pipe );
393 0 : }
394 :
395 : fd_stake_delegation_t const *
396 : fd_stake_delegations_query( fd_stake_delegations_t const * stake_delegations,
397 96 : fd_pubkey_t const * stake_account ) {
398 :
399 96 : if( FD_UNLIKELY( !stake_delegations ) ) {
400 0 : FD_LOG_CRIT(( "NULL stake_delegations" ));
401 0 : return NULL;
402 0 : }
403 :
404 96 : if( FD_UNLIKELY( !stake_account ) ) {
405 0 : FD_LOG_CRIT(( "NULL stake_account" ));
406 0 : return NULL;
407 0 : }
408 :
409 96 : fd_stake_delegation_t const * stake_delegation_pool = fd_stake_delegations_get_pool( stake_delegations );
410 96 : if( FD_UNLIKELY( !stake_delegation_pool ) ) {
411 0 : FD_LOG_CRIT(( "unable to retrieve join to stake delegation pool" ));
412 0 : }
413 :
414 96 : fd_stake_delegation_map_t const * stake_delegation_map = fd_stake_delegations_get_map( stake_delegations );
415 96 : if( FD_UNLIKELY( !stake_delegation_map ) ) {
416 0 : FD_LOG_CRIT(( "unable to retrieve join to stake delegation map" ));
417 0 : }
418 :
419 96 : return fd_stake_delegation_map_ele_query_const(
420 96 : stake_delegation_map,
421 96 : stake_account,
422 96 : NULL,
423 96 : stake_delegation_pool );
424 96 : }
425 :
426 : ulong
427 75 : fd_stake_delegations_cnt( fd_stake_delegations_t const * stake_delegations ) {
428 75 : if( FD_UNLIKELY( !stake_delegations ) ) {
429 0 : FD_LOG_CRIT(( "NULL stake_delegations" ));
430 0 : }
431 :
432 75 : fd_stake_delegation_t const * stake_delegation_pool = fd_stake_delegations_get_pool( stake_delegations );
433 75 : if( FD_UNLIKELY( !stake_delegation_pool ) ) {
434 0 : FD_LOG_CRIT(( "unable to retrieve join to stake delegation map" ));
435 0 : }
436 :
437 75 : return fd_stake_delegation_pool_used( stake_delegation_pool );
438 75 : }
439 :
440 : fd_stake_delegation_t *
441 84 : fd_stake_delegations_iter_ele( fd_stake_delegations_iter_t * iter ) {
442 84 : ulong idx = fd_stake_delegation_map_iter_idx( iter->iter, iter->map, iter->pool );
443 84 : return fd_stake_delegation_pool_ele( iter->pool, idx );
444 84 : }
445 :
446 : fd_stake_delegations_iter_t *
447 : fd_stake_delegations_iter_init( fd_stake_delegations_iter_t * iter,
448 105 : fd_stake_delegations_t const * stake_delegations ) {
449 105 : if( FD_UNLIKELY( !stake_delegations ) ) {
450 0 : FD_LOG_CRIT(( "NULL stake_delegations" ));
451 0 : }
452 :
453 105 : iter->map = fd_stake_delegations_get_map( stake_delegations );
454 105 : iter->pool = fd_stake_delegations_get_pool( stake_delegations );
455 105 : iter->iter = fd_stake_delegation_map_iter_init( iter->map, iter->pool );
456 :
457 105 : return iter;
458 105 : }
459 :
460 : void
461 84 : fd_stake_delegations_iter_next( fd_stake_delegations_iter_t * iter ) {
462 84 : iter->iter = fd_stake_delegation_map_iter_next( iter->iter, iter->map, iter->pool );
463 84 : }
464 :
465 : int
466 189 : fd_stake_delegations_iter_done( fd_stake_delegations_iter_t * iter ) {
467 189 : return fd_stake_delegation_map_iter_done( iter->iter, iter->map, iter->pool );
468 189 : }
|