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 534 : #define POOL_T fd_stake_delegation_t
8 18298812 : #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 102 : #define MAP_KEY stake_account
15 144 : #define MAP_KEY_EQ(k0,k1) (fd_pubkey_eq( k0, k1 ))
16 354 : #define MAP_KEY_HASH(key,seed) (fd_funk_rec_key_hash1( (uchar *)key, 0, seed ))
17 204 : #define MAP_NEXT next_
18 : #include "../../util/tmpl/fd_map_chain.c"
19 :
20 : static inline fd_stake_delegation_t *
21 372 : fd_stake_delegations_get_pool( fd_stake_delegations_t const * stake_delegations ) {
22 372 : return fd_stake_delegation_pool_join( (uchar *)stake_delegations + stake_delegations->pool_offset_ );
23 372 : }
24 :
25 : static inline fd_stake_delegation_map_t *
26 297 : fd_stake_delegations_get_map( fd_stake_delegations_t const * stake_delegations ) {
27 297 : return fd_stake_delegation_map_join( (uchar *)stake_delegations + stake_delegations->map_offset_ );
28 297 : }
29 :
30 : ulong
31 1521 : 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 1521 : return fd_ulong_max( fd_ulong_max( fd_stake_delegation_map_align(),
36 1521 : fd_stake_delegation_pool_align() ), alignof(fd_stake_delegations_t) );
37 1521 : }
38 :
39 : ulong
40 171 : fd_stake_delegations_footprint( ulong max_stake_accounts ) {
41 :
42 171 : ulong map_chain_cnt = fd_stake_delegation_map_chain_cnt_est( max_stake_accounts );
43 :
44 171 : ulong l = FD_LAYOUT_INIT;
45 171 : l = FD_LAYOUT_APPEND( l, fd_stake_delegations_align(), sizeof(fd_stake_delegations_t) );
46 171 : l = FD_LAYOUT_APPEND( l, fd_stake_delegation_pool_align(), fd_stake_delegation_pool_footprint( max_stake_accounts ) );
47 171 : l = FD_LAYOUT_APPEND( l, fd_stake_delegation_map_align(), fd_stake_delegation_map_footprint( map_chain_cnt ) );
48 171 : return FD_LAYOUT_FINI( l, fd_stake_delegations_align() );
49 171 : }
50 :
51 : void *
52 : fd_stake_delegations_new( void * mem,
53 : ulong max_stake_accounts,
54 33 : int leave_tombstones ) {
55 33 : if( FD_UNLIKELY( !mem ) ) {
56 3 : FD_LOG_WARNING(( "NULL mem" ));
57 3 : return NULL;
58 3 : }
59 :
60 30 : if( FD_UNLIKELY( !max_stake_accounts ) ) {
61 3 : FD_LOG_WARNING(( "max_stake_accounts is 0" ));
62 3 : return NULL;
63 3 : }
64 :
65 27 : 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 27 : ulong map_chain_cnt = fd_stake_delegation_map_chain_cnt_est( max_stake_accounts );
71 :
72 27 : FD_SCRATCH_ALLOC_INIT( l, mem );
73 27 : fd_stake_delegations_t * stake_delegations = FD_SCRATCH_ALLOC_APPEND( l, fd_stake_delegations_align(), sizeof(fd_stake_delegations_t) );
74 27 : void * pool_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_stake_delegation_pool_align(), fd_stake_delegation_pool_footprint( max_stake_accounts ) );
75 27 : void * map_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_stake_delegation_map_align(), fd_stake_delegation_map_footprint( map_chain_cnt ) );
76 :
77 27 : 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 27 : 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 27 : 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 27 : stake_delegations->pool_offset_ = (ulong)pool_mem - (ulong)mem;
94 27 : stake_delegations->map_offset_ = (ulong)map_mem - (ulong)mem;
95 27 : stake_delegations->max_stake_accounts_ = max_stake_accounts;
96 27 : stake_delegations->leave_tombstones_ = leave_tombstones;
97 :
98 27 : FD_COMPILER_MFENCE();
99 27 : FD_VOLATILE( stake_delegations->magic ) = FD_STAKE_DELEGATIONS_MAGIC;
100 27 : FD_COMPILER_MFENCE();
101 :
102 27 : return mem;
103 27 : }
104 :
105 : fd_stake_delegations_t *
106 144 : fd_stake_delegations_join( void * mem ) {
107 144 : if( FD_UNLIKELY( !mem ) ) {
108 3 : FD_LOG_WARNING(( "NULL mem" ));
109 3 : return NULL;
110 3 : }
111 :
112 141 : 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 141 : fd_stake_delegations_t * stake_delegations = (fd_stake_delegations_t *)mem;
118 :
119 141 : 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 135 : ulong map_chain_cnt = fd_stake_delegation_map_chain_cnt_est( stake_delegations->max_stake_accounts_ );
125 :
126 135 : FD_SCRATCH_ALLOC_INIT( l, stake_delegations );
127 135 : stake_delegations = FD_SCRATCH_ALLOC_APPEND( l, fd_stake_delegations_align(), sizeof(fd_stake_delegations_t) );
128 135 : void * pool_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_stake_delegation_pool_align(), fd_stake_delegation_pool_footprint( stake_delegations->max_stake_accounts_ ) );
129 135 : void * map_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_stake_delegation_map_align(), fd_stake_delegation_map_footprint( map_chain_cnt ) );
130 :
131 135 : 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 135 : 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 135 : 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 135 : return stake_delegations;
147 135 : }
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 117 : double warmup_cooldown_rate ) {
204 117 : fd_stake_delegation_t * stake_delegation_pool = fd_stake_delegations_get_pool( stake_delegations );
205 117 : if( FD_UNLIKELY( !stake_delegation_pool ) ) {
206 0 : FD_LOG_CRIT(( "unable to retrieve join to stake delegation pool" ));
207 0 : }
208 117 : fd_stake_delegation_map_t * stake_delegation_map = fd_stake_delegations_get_map( stake_delegations );
209 117 : if( FD_UNLIKELY( !stake_delegation_map ) ) {
210 0 : FD_LOG_CRIT(( "unable to retrieve join to stake delegation map" ));
211 0 : }
212 :
213 : /* First, handle the case where the stake delegation already exists
214 : and we just need to update the entry. The reason we do a const idx
215 : query is to allow fd_stake_delegations_update to be called while
216 : iterating over the map. It is unsafe to call
217 : fd_stake_delegation_map_ele_query() during iteration, but we only
218 : need to change fields which are not used for pool/map management. */
219 :
220 117 : ulong idx = fd_stake_delegation_map_idx_query_const(
221 117 : stake_delegation_map,
222 117 : stake_account,
223 117 : ULONG_MAX,
224 117 : stake_delegation_pool );
225 :
226 117 : if( idx!=ULONG_MAX ) {
227 :
228 21 : fd_stake_delegation_t * stake_delegation = fd_stake_delegation_pool_ele( stake_delegation_pool, idx );
229 21 : if( FD_UNLIKELY( !stake_delegation ) ) {
230 0 : FD_LOG_CRIT(( "unable to retrieve stake delegation" ));
231 0 : }
232 :
233 21 : stake_delegation->vote_account = *vote_account;
234 21 : stake_delegation->stake = stake;
235 21 : stake_delegation->activation_epoch = activation_epoch;
236 21 : stake_delegation->deactivation_epoch = deactivation_epoch;
237 21 : stake_delegation->credits_observed = credits_observed;
238 21 : stake_delegation->warmup_cooldown_rate = warmup_cooldown_rate;
239 21 : stake_delegation->is_tombstone = 0;
240 21 : return;
241 21 : }
242 :
243 : /* Otherwise, try to acquire a new node and populate it. */
244 96 : if( FD_UNLIKELY( !fd_stake_delegation_pool_free( stake_delegation_pool ) ) ) {
245 0 : FD_LOG_CRIT(( "no free stake delegations in pool" ));
246 0 : }
247 :
248 96 : fd_stake_delegation_t * stake_delegation = fd_stake_delegation_pool_ele_acquire( stake_delegation_pool );
249 96 : if( FD_UNLIKELY( !stake_delegation ) ) {
250 0 : FD_LOG_CRIT(( "unable to acquire stake delegation" ));
251 0 : }
252 :
253 96 : stake_delegation->stake_account = *stake_account;
254 96 : stake_delegation->vote_account = *vote_account;
255 96 : stake_delegation->stake = stake;
256 96 : stake_delegation->activation_epoch = activation_epoch;
257 96 : stake_delegation->deactivation_epoch = deactivation_epoch;
258 96 : stake_delegation->credits_observed = credits_observed;
259 96 : stake_delegation->warmup_cooldown_rate = warmup_cooldown_rate;
260 96 : stake_delegation->is_tombstone = 0;
261 :
262 96 : if( FD_UNLIKELY( !fd_stake_delegation_map_ele_insert(
263 96 : stake_delegation_map,
264 96 : stake_delegation,
265 96 : stake_delegation_pool ) ) ) {
266 0 : FD_LOG_CRIT(( "unable to insert stake delegation into map" ));
267 0 : }
268 :
269 96 : }
270 :
271 : void
272 : fd_stake_delegations_remove( fd_stake_delegations_t * stake_delegations,
273 24 : fd_pubkey_t const * stake_account ) {
274 24 : fd_stake_delegation_t * stake_delegation_pool = fd_stake_delegations_get_pool( stake_delegations );
275 24 : if( FD_UNLIKELY( !stake_delegation_pool ) ) {
276 0 : FD_LOG_CRIT(( "unable to retrieve join to stake delegation pool" ));
277 0 : }
278 24 : fd_stake_delegation_map_t * stake_delegation_map = fd_stake_delegations_get_map( stake_delegations );
279 24 : if( FD_UNLIKELY( !stake_delegation_map ) ) {
280 0 : FD_LOG_CRIT(( "unable to retrieve join to stake delegation map" ));
281 0 : }
282 :
283 24 : ulong delegation_idx = fd_stake_delegation_map_idx_query(
284 24 : stake_delegation_map,
285 24 : stake_account,
286 24 : ULONG_MAX,
287 24 : stake_delegation_pool );
288 :
289 24 : if( stake_delegations->leave_tombstones_==1 ) {
290 : /* If we are configured to leave tombstones, we need to either
291 : update the entry's is_tombstone flag or insert a new entry. */
292 :
293 9 : fd_stake_delegation_t * stake_delegation = NULL;
294 9 : if( delegation_idx!=ULONG_MAX ) {
295 : /* The delegation was found, update the is_tombstone flag. */
296 3 : stake_delegation = fd_stake_delegation_pool_ele( stake_delegation_pool, delegation_idx );
297 6 : } else {
298 : /* Otherwise, acquire an element from the pool and add it into the
299 : map. */
300 6 : stake_delegation = fd_stake_delegation_pool_ele_acquire( stake_delegation_pool );
301 6 : stake_delegation->stake_account = *stake_account;
302 6 : fd_stake_delegation_map_ele_insert( stake_delegation_map, stake_delegation, stake_delegation_pool );
303 6 : }
304 9 : stake_delegation->is_tombstone = 1;
305 :
306 15 : } else {
307 : /* If we are not configured to leave tombstones, we need to remove
308 : the entry from the map and release it from the pool. */
309 15 : if( FD_UNLIKELY( delegation_idx == ULONG_MAX ) ) {
310 : /* The delegation was not found, nothing to do. */
311 0 : return;
312 0 : }
313 :
314 : /* To be safe, we should set the next_ pointer to the null idx. */
315 :
316 15 : fd_stake_delegation_t * stake_delegation = fd_stake_delegation_pool_ele( stake_delegation_pool, delegation_idx );
317 15 : if( FD_UNLIKELY( !stake_delegation ) ) {
318 0 : FD_LOG_CRIT(( "unable to retrieve stake delegation" ));
319 0 : }
320 :
321 15 : ulong idx = fd_stake_delegation_map_idx_remove( stake_delegation_map, stake_account, ULONG_MAX, stake_delegation_pool );
322 15 : if( FD_UNLIKELY( idx==ULONG_MAX ) ) {
323 0 : FD_LOG_CRIT(( "unable to remove stake delegation" ));
324 0 : }
325 :
326 15 : stake_delegation->next_ = fd_stake_delegation_pool_idx_null( stake_delegation_pool );
327 :
328 15 : fd_stake_delegation_pool_idx_release( stake_delegation_pool, delegation_idx );
329 15 : }
330 24 : }
331 :
332 : void
333 : fd_stake_delegations_refresh( fd_stake_delegations_t * stake_delegations,
334 : fd_funk_t * funk,
335 0 : fd_funk_txn_xid_t const * xid ) {
336 :
337 0 : fd_stake_delegation_map_t * stake_delegation_map = fd_stake_delegations_get_map( stake_delegations );
338 0 : if( FD_UNLIKELY( !stake_delegation_map ) ) {
339 0 : FD_LOG_CRIT(( "unable to retrieve join to stake delegation map" ));
340 0 : }
341 :
342 0 : fd_stake_delegation_t * stake_delegation_pool = fd_stake_delegations_get_pool( stake_delegations );
343 0 : if( FD_UNLIKELY( !stake_delegation_pool ) ) {
344 0 : FD_LOG_CRIT(( "unable to retrieve join to stake delegation pool" ));
345 0 : }
346 :
347 0 : for( ulong i=0UL; i<stake_delegations->max_stake_accounts_; i++ ) {
348 :
349 0 : fd_stake_delegation_t * stake_delegation = fd_stake_delegation_pool_ele( fd_stake_delegations_get_pool( stake_delegations ), i );
350 :
351 0 : if( !fd_stake_delegation_map_ele_query_const(
352 0 : fd_stake_delegations_get_map( stake_delegations ),
353 0 : &stake_delegation->stake_account,
354 0 : NULL,
355 0 : fd_stake_delegations_get_pool( stake_delegations ) ) ) {
356 : /* This means that the stake delegation is not in the map, so we
357 : can skip it. */
358 0 : continue;
359 0 : }
360 :
361 0 : fd_txn_account_t acct_rec[1];
362 0 : int err = fd_txn_account_init_from_funk_readonly(
363 0 : acct_rec,
364 0 : &stake_delegation->stake_account,
365 0 : funk,
366 0 : xid );
367 :
368 0 : if( FD_UNLIKELY( err || fd_txn_account_get_lamports( acct_rec )==0UL ) ) {
369 0 : fd_stake_delegation_map_idx_remove( stake_delegation_map, &stake_delegation->stake_account, ULONG_MAX, stake_delegation_pool );
370 0 : fd_stake_delegation_pool_idx_release( stake_delegation_pool, i );
371 0 : continue;
372 0 : }
373 :
374 0 : fd_stake_state_v2_t stake_state;
375 0 : err = fd_stake_get_state( acct_rec, &stake_state );
376 0 : if( FD_UNLIKELY( err ) ) {
377 0 : fd_stake_delegation_map_idx_remove( stake_delegation_map, &stake_delegation->stake_account, ULONG_MAX, stake_delegation_pool );
378 0 : fd_stake_delegation_pool_idx_release( stake_delegation_pool, i );
379 0 : }
380 :
381 0 : if( FD_UNLIKELY( !fd_stake_state_v2_is_stake( &stake_state ) ) ) {
382 0 : fd_stake_delegation_map_idx_remove( stake_delegation_map, &stake_delegation->stake_account, ULONG_MAX, stake_delegation_pool );
383 0 : fd_stake_delegation_pool_idx_release( stake_delegation_pool, i );
384 0 : }
385 :
386 0 : fd_stake_delegations_update(
387 0 : stake_delegations,
388 0 : &stake_delegation->stake_account,
389 0 : &stake_state.inner.stake.stake.delegation.voter_pubkey,
390 0 : stake_state.inner.stake.stake.delegation.stake,
391 0 : stake_state.inner.stake.stake.delegation.activation_epoch,
392 0 : stake_state.inner.stake.stake.delegation.deactivation_epoch,
393 0 : stake_state.inner.stake.stake.credits_observed,
394 0 : stake_state.inner.stake.stake.delegation.warmup_cooldown_rate );
395 0 : }
396 0 : }
397 :
398 : fd_stake_delegation_t const *
399 : fd_stake_delegations_query( fd_stake_delegations_t const * stake_delegations,
400 96 : fd_pubkey_t const * stake_account ) {
401 :
402 96 : if( FD_UNLIKELY( !stake_delegations ) ) {
403 0 : FD_LOG_CRIT(( "NULL stake_delegations" ));
404 0 : return NULL;
405 0 : }
406 :
407 96 : if( FD_UNLIKELY( !stake_account ) ) {
408 0 : FD_LOG_CRIT(( "NULL stake_account" ));
409 0 : return NULL;
410 0 : }
411 :
412 96 : fd_stake_delegation_t const * stake_delegation_pool = fd_stake_delegations_get_pool( stake_delegations );
413 96 : if( FD_UNLIKELY( !stake_delegation_pool ) ) {
414 0 : FD_LOG_CRIT(( "unable to retrieve join to stake delegation pool" ));
415 0 : }
416 :
417 96 : fd_stake_delegation_map_t const * stake_delegation_map = fd_stake_delegations_get_map( stake_delegations );
418 96 : if( FD_UNLIKELY( !stake_delegation_map ) ) {
419 0 : FD_LOG_CRIT(( "unable to retrieve join to stake delegation map" ));
420 0 : }
421 :
422 96 : return fd_stake_delegation_map_ele_query_const(
423 96 : stake_delegation_map,
424 96 : stake_account,
425 96 : NULL,
426 96 : stake_delegation_pool );
427 96 : }
428 :
429 : ulong
430 75 : fd_stake_delegations_cnt( fd_stake_delegations_t const * stake_delegations ) {
431 75 : if( FD_UNLIKELY( !stake_delegations ) ) {
432 0 : FD_LOG_CRIT(( "NULL stake_delegations" ));
433 0 : }
434 :
435 75 : fd_stake_delegation_t const * stake_delegation_pool = fd_stake_delegations_get_pool( stake_delegations );
436 75 : if( FD_UNLIKELY( !stake_delegation_pool ) ) {
437 0 : FD_LOG_CRIT(( "unable to retrieve join to stake delegation map" ));
438 0 : }
439 :
440 75 : return fd_stake_delegation_pool_used( stake_delegation_pool );
441 75 : }
442 :
443 : fd_stake_delegation_t *
444 87 : fd_stake_delegations_iter_ele( fd_stake_delegations_iter_t * iter ) {
445 87 : ulong idx = fd_stake_delegation_map_iter_idx( iter->iter, iter->map, iter->pool );
446 87 : return fd_stake_delegation_pool_ele( iter->pool, idx );
447 87 : }
448 :
449 : fd_stake_delegations_iter_t *
450 : fd_stake_delegations_iter_init( fd_stake_delegations_iter_t * iter,
451 60 : fd_stake_delegations_t const * stake_delegations ) {
452 60 : if( FD_UNLIKELY( !stake_delegations ) ) {
453 0 : FD_LOG_CRIT(( "NULL stake_delegations" ));
454 0 : }
455 :
456 60 : iter->map = fd_stake_delegations_get_map( stake_delegations );
457 60 : iter->pool = fd_stake_delegations_get_pool( stake_delegations );
458 60 : iter->iter = fd_stake_delegation_map_iter_init( iter->map, iter->pool );
459 :
460 60 : return iter;
461 60 : }
462 :
463 : void
464 87 : fd_stake_delegations_iter_next( fd_stake_delegations_iter_t * iter ) {
465 87 : iter->iter = fd_stake_delegation_map_iter_next( iter->iter, iter->map, iter->pool );
466 87 : }
467 :
468 : int
469 147 : fd_stake_delegations_iter_done( fd_stake_delegations_iter_t * iter ) {
470 147 : return fd_stake_delegation_map_iter_done( iter->iter, iter->map, iter->pool );
471 147 : }
|