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