Line data Source code
1 : #include "fd_vote_stakes.h"
2 : #include "fd_vote_stakes_private.h"
3 :
4 : ulong
5 9387 : fd_vote_stakes_align( void ) {
6 9387 : return FD_VOTE_STAKES_ALIGN;
7 9387 : }
8 :
9 : ulong
10 : fd_vote_stakes_footprint( ulong max_vote_accounts,
11 : ulong expected_vote_accounts,
12 1563 : ulong max_fork_width ) {
13 1563 : ulong map_chain_cnt = index_map_chain_cnt_est( expected_vote_accounts );
14 :
15 1563 : ulong l = FD_LAYOUT_INIT;
16 1563 : l = FD_LAYOUT_APPEND( l, fd_vote_stakes_align(), sizeof(fd_vote_stakes_t) );
17 1563 : l = FD_LAYOUT_APPEND( l, index_pool_align(), index_pool_footprint( max_vote_accounts * 2UL ) );
18 1563 : l = FD_LAYOUT_APPEND( l, index_map_align(), index_map_footprint( map_chain_cnt ) );
19 1563 : l = FD_LAYOUT_APPEND( l, index_map_multi_align(), index_map_multi_footprint( map_chain_cnt ) );
20 1563 : l = FD_LAYOUT_APPEND( l, fork_pool_align(), fork_pool_footprint( max_fork_width ) );
21 1563 : l = FD_LAYOUT_APPEND( l, fork_dlist_align(), fork_dlist_footprint() );
22 3807 : for( ulong i=0; i<max_fork_width; i++ ) {
23 2244 : l = FD_LAYOUT_APPEND( l, stakes_pool_align(), stakes_pool_footprint( max_vote_accounts ) );
24 2244 : l = FD_LAYOUT_APPEND( l, stakes_map_align(), stakes_map_footprint( map_chain_cnt ) );
25 2244 : }
26 1563 : return FD_LAYOUT_FINI( l, fd_vote_stakes_align() );
27 1563 : }
28 :
29 : void *
30 : fd_vote_stakes_new( void * shmem,
31 : ulong max_vote_accounts,
32 : ulong expected_vote_accounts,
33 : ulong max_fork_width,
34 399 : ulong seed ) {
35 399 : if( FD_UNLIKELY( !shmem ) ) {
36 0 : FD_LOG_WARNING(( "NULL mem" ));
37 0 : return NULL;
38 0 : }
39 :
40 399 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_vote_stakes_align() ) ) ) {
41 0 : FD_LOG_WARNING(( "misaligned mem" ));
42 0 : return NULL;
43 0 : }
44 :
45 399 : if( FD_UNLIKELY( max_fork_width>MAX_FORK_WIDTH ) ) {
46 0 : FD_LOG_WARNING(( "max_fork_width is too large" ));
47 0 : return NULL;
48 0 : }
49 :
50 399 : ulong map_chain_cnt = index_map_chain_cnt_est( expected_vote_accounts );
51 :
52 399 : FD_SCRATCH_ALLOC_INIT( l, shmem );
53 399 : fd_vote_stakes_t * vote_stakes = FD_SCRATCH_ALLOC_APPEND( l, fd_vote_stakes_align(), sizeof(fd_vote_stakes_t) );
54 399 : void * index_pool_mem = FD_SCRATCH_ALLOC_APPEND( l, index_pool_align(), index_pool_footprint( max_vote_accounts * 2UL ) );
55 399 : void * index_map_mem = FD_SCRATCH_ALLOC_APPEND( l, index_map_align(), index_map_footprint( map_chain_cnt ) );
56 399 : void * index_map_multi_mem = FD_SCRATCH_ALLOC_APPEND( l, index_map_multi_align(), index_map_multi_footprint( map_chain_cnt ) );
57 399 : void * fork_pool_mem = FD_SCRATCH_ALLOC_APPEND( l, fork_pool_align(), fork_pool_footprint( max_fork_width ) );
58 399 : void * fork_dlist_mem = FD_SCRATCH_ALLOC_APPEND( l, fork_dlist_align(), fork_dlist_footprint() );
59 1023 : for( ulong i=0; i<max_fork_width; i++ ) {
60 624 : void * stakes_pool_mem = FD_SCRATCH_ALLOC_APPEND( l, stakes_pool_align(), stakes_pool_footprint( max_vote_accounts ) );
61 0 : stake_t * stakes_pool = stakes_pool_join( stakes_pool_new( stakes_pool_mem, max_vote_accounts ) );
62 624 : if( FD_UNLIKELY( !stakes_pool ) ) {
63 0 : FD_LOG_WARNING(( "Failed to create vote stakes ele pool" ));
64 0 : return NULL;
65 0 : }
66 624 : vote_stakes->stakes_pool_off[ i ] = (ulong)stakes_pool - (ulong)shmem;
67 :
68 624 : void * stakes_map_mem = FD_SCRATCH_ALLOC_APPEND( l, stakes_map_align(), stakes_map_footprint( map_chain_cnt ) );
69 0 : stakes_map_t * stakes_map = stakes_map_join( stakes_map_new( stakes_map_mem, map_chain_cnt, seed ) );
70 624 : if( FD_UNLIKELY( !stakes_map ) ) {
71 0 : FD_LOG_WARNING(( "Failed to create vote stakes ele map" ));
72 0 : return NULL;
73 0 : }
74 624 : vote_stakes->stakes_map_off[ i ] = (ulong)stakes_map - (ulong)shmem;
75 624 : }
76 :
77 399 : index_ele_t * index_pool = index_pool_join( index_pool_new( index_pool_mem, max_vote_accounts * 2UL ) );
78 399 : if( FD_UNLIKELY( !index_pool ) ) {
79 0 : FD_LOG_WARNING(( "Failed to create vote stakes index pool" ));
80 0 : return NULL;
81 0 : }
82 :
83 399 : index_map_t * index_map = index_map_join( index_map_new( index_map_mem, map_chain_cnt, seed ) );
84 399 : if( FD_UNLIKELY( !index_map ) ) {
85 0 : FD_LOG_WARNING(( "Failed to create vote stakes index map" ));
86 0 : return NULL;
87 0 : }
88 :
89 399 : index_map_multi_t * index_map_multi = index_map_multi_join( index_map_multi_new( index_map_multi_mem, map_chain_cnt, seed ) );
90 399 : if( FD_UNLIKELY( !index_map_multi ) ) {
91 0 : FD_LOG_WARNING(( "Failed to create vote stakes index map multi" ));
92 0 : return NULL;
93 0 : }
94 :
95 399 : fork_t * fork_pool = fork_pool_join( fork_pool_new( fork_pool_mem, max_fork_width ) );
96 399 : if( FD_UNLIKELY( !fork_pool ) ) {
97 0 : FD_LOG_WARNING(( "Failed to create vote stakes fork pool" ));
98 0 : return NULL;
99 0 : }
100 :
101 399 : fork_dlist_t * fork_dlist = fork_dlist_join( fork_dlist_new( fork_dlist_mem ) );
102 399 : if( FD_UNLIKELY( !fork_dlist ) ) {
103 0 : FD_LOG_WARNING(( "Failed to create vote stakes fork dlist" ));
104 0 : return NULL;
105 0 : }
106 :
107 399 : if( FD_UNLIKELY( max_fork_width>USHORT_MAX ) ) {
108 0 : FD_LOG_WARNING(( "max_fork_width is too large" ));
109 0 : return NULL;
110 0 : }
111 :
112 399 : vote_stakes->max_fork_width = (ushort)max_fork_width;
113 399 : vote_stakes->index_pool_off = (ulong)index_pool - (ulong)shmem;
114 399 : vote_stakes->index_map_off = (ulong)index_map - (ulong)shmem;
115 399 : vote_stakes->index_map_multi_off = (ulong)index_map_multi - (ulong)shmem;
116 399 : vote_stakes->fork_pool_off = (ulong)fork_pool - (ulong)shmem;
117 399 : vote_stakes->fork_dlist_off = (ulong)fork_dlist - (ulong)shmem;
118 399 : vote_stakes->root_idx = (ushort)fork_pool_idx_acquire( fork_pool );
119 399 : fork_dlist_idx_push_tail( fork_dlist, vote_stakes->root_idx, fork_pool );
120 :
121 399 : fd_rwlock_new( &vote_stakes->lock );
122 :
123 399 : FD_COMPILER_MFENCE();
124 399 : FD_VOLATILE( vote_stakes->magic ) = FD_VOTE_STAKES_MAGIC;
125 399 : FD_COMPILER_MFENCE();
126 :
127 399 : return vote_stakes;
128 399 : }
129 :
130 : fd_vote_stakes_t *
131 789 : fd_vote_stakes_join( void * shmem ) {
132 789 : fd_vote_stakes_t * vote_stakes = (fd_vote_stakes_t *)shmem;
133 :
134 789 : if( FD_UNLIKELY( !vote_stakes ) ) {
135 0 : FD_LOG_WARNING(( "NULL vote stakes" ));
136 0 : return NULL;
137 0 : }
138 :
139 789 : if( FD_UNLIKELY( vote_stakes->magic != FD_VOTE_STAKES_MAGIC ) ) {
140 0 : FD_LOG_WARNING(( "Invalid vote stakes magic" ));
141 0 : return NULL;
142 0 : }
143 :
144 789 : return vote_stakes;
145 789 : }
146 :
147 : void
148 : fd_vote_stakes_root_insert_key( fd_vote_stakes_t * vote_stakes,
149 : fd_pubkey_t const * pubkey,
150 : fd_pubkey_t const * node_account_t_1,
151 : ulong stake_t_1,
152 : uchar commission_t_1,
153 21 : ulong epoch ) {
154 21 : fd_rwlock_write( &vote_stakes->lock );
155 :
156 21 : index_ele_t * index_pool = get_index_pool( vote_stakes );
157 21 : index_map_t * index_map = get_index_map( vote_stakes );
158 21 : index_map_multi_t * index_map_multi = get_index_map_multi( vote_stakes );
159 :
160 21 : index_ele_t * ele = index_pool_ele_acquire( index_pool );
161 21 : ele->pubkey = *pubkey;
162 21 : ele->refcnt = 1;
163 21 : ele->stake_t_1 = (stake_t_1 & 0x7FFFFFFFFFFFFFFFUL);
164 21 : ele->commission_t_1 = commission_t_1;
165 21 : ele->node_account_t_1 = *node_account_t_1;
166 21 : ele->stake_t_2 = 0UL;
167 21 : ele->node_account_t_2 = (fd_pubkey_t){0};
168 21 : ele->commission_t_2 = 0U;
169 21 : ele->epoch = epoch % 2;
170 21 : ele->exists_t_1 = 1;
171 : /* It is fine to leave node account t_2 uninitalized because it will
172 : only be used if stake_t_2 is non-zero. */
173 :
174 21 : FD_TEST( index_map_ele_insert( index_map, ele, index_pool ) );
175 21 : FD_TEST( index_map_multi_ele_insert( index_map_multi, ele, index_pool ) );
176 :
177 21 : stake_t * stakes_pool = get_stakes_pool( vote_stakes, vote_stakes->root_idx );
178 21 : stakes_map_t * stakes_map = get_stakes_map( vote_stakes, vote_stakes->root_idx );
179 :
180 21 : uint pubkey_idx = (uint)index_pool_idx( index_pool, ele );
181 21 : stake_t * new_stake = stakes_pool_ele_acquire( stakes_pool );
182 21 : new_stake->idx = pubkey_idx;
183 21 : FD_TEST( stakes_map_ele_insert( stakes_map, new_stake, stakes_pool ) );
184 :
185 21 : fd_rwlock_unwrite( &vote_stakes->lock );
186 21 : }
187 :
188 : void
189 : fd_vote_stakes_root_update_meta( fd_vote_stakes_t * vote_stakes,
190 : fd_pubkey_t const * pubkey,
191 : fd_pubkey_t const * node_account_t_2,
192 : ulong stake_t_2,
193 : uchar commission_t_2,
194 21 : ulong epoch ) {
195 21 : fd_rwlock_write( &vote_stakes->lock );
196 :
197 21 : index_ele_t * index_pool = get_index_pool( vote_stakes );
198 21 : index_map_t * index_map = get_index_map( vote_stakes );
199 21 : index_map_multi_t * index_map_multi = get_index_map_multi( vote_stakes );
200 21 : index_ele_t * ele = index_map_multi_ele_query( index_map_multi, pubkey, NULL, index_pool );
201 21 : if( FD_UNLIKELY( !ele ) ) {
202 0 : ele = index_pool_ele_acquire( index_pool );
203 0 : ele->pubkey = *pubkey;
204 0 : ele->refcnt = 1;
205 0 : ele->stake_t_1 = 0UL;
206 0 : ele->node_account_t_1 = (fd_pubkey_t){0};
207 0 : ele->epoch = epoch % 2;
208 0 : ele->commission_t_1 = 0U;
209 0 : ele->exists_t_1 = 0;
210 :
211 0 : FD_TEST( index_map_ele_insert( index_map, ele, index_pool ) );
212 0 : FD_TEST( index_map_multi_ele_insert( index_map_multi, ele, index_pool ) );
213 :
214 0 : stake_t * stakes_pool = get_stakes_pool( vote_stakes, vote_stakes->root_idx );
215 0 : stakes_map_t * stakes_map = get_stakes_map( vote_stakes, vote_stakes->root_idx );
216 :
217 0 : uint pubkey_idx = (uint)index_pool_idx( index_pool, ele );
218 0 : stake_t * new_stake = stakes_pool_ele_acquire( stakes_pool );
219 0 : new_stake->idx = pubkey_idx;
220 0 : FD_TEST( stakes_map_ele_insert( stakes_map, new_stake, stakes_pool ) );
221 0 : }
222 :
223 21 : ele->commission_t_2 = commission_t_2;
224 21 : ele->node_account_t_2 = *node_account_t_2;
225 21 : ele->stake_t_2 = stake_t_2;
226 :
227 21 : fd_rwlock_unwrite( &vote_stakes->lock );
228 21 : }
229 :
230 : void
231 : fd_vote_stakes_root_purge_key( fd_vote_stakes_t * vote_stakes,
232 0 : fd_pubkey_t const * pubkey ) {
233 0 : fd_rwlock_write( &vote_stakes->lock );
234 :
235 0 : index_ele_t * index_pool = get_index_pool( vote_stakes );
236 0 : index_map_t * index_map = get_index_map( vote_stakes );
237 0 : index_map_multi_t * index_map_multi = get_index_map_multi( vote_stakes );
238 :
239 0 : uint ele_idx = (uint)index_map_multi_idx_query( index_map_multi, pubkey, UINT_MAX, index_pool );
240 0 : FD_TEST( ele_idx!=UINT_MAX );
241 :
242 0 : index_ele_t * ele = index_pool_ele( index_pool, ele_idx );
243 :
244 0 : FD_TEST( index_map_multi_ele_remove_fast( index_map_multi, ele, index_pool ) );
245 0 : FD_TEST( index_map_ele_remove( index_map, &ele->index_key, NULL, index_pool ) );
246 :
247 0 : stake_t * stakes_pool = get_stakes_pool( vote_stakes, vote_stakes->root_idx );
248 0 : stakes_map_t * stakes_map = get_stakes_map( vote_stakes, vote_stakes->root_idx );
249 :
250 0 : stake_t * stake_ele = stakes_map_ele_remove( stakes_map, &ele_idx, NULL, stakes_pool );
251 0 : stakes_pool_ele_release( stakes_pool, stake_ele );
252 :
253 0 : index_pool_ele_release( index_pool, ele );
254 :
255 0 : fd_rwlock_unwrite( &vote_stakes->lock );
256 0 : }
257 :
258 : void
259 : fd_vote_stakes_insert( fd_vote_stakes_t * vote_stakes,
260 : ushort fork_idx,
261 : fd_pubkey_t const * pubkey,
262 : fd_pubkey_t const * node_account_t_1,
263 : fd_pubkey_t const * node_account_t_2,
264 : ulong stake_t_1,
265 : ulong stake_t_2,
266 : uchar commission_t_1,
267 : uchar commission_t_2,
268 63 : ulong epoch ) {
269 63 : fd_rwlock_write( &vote_stakes->lock );
270 :
271 63 : index_ele_t * index_pool = get_index_pool( vote_stakes );
272 63 : index_map_t * index_map = get_index_map( vote_stakes );
273 63 : index_map_multi_t * index_map_multi = get_index_map_multi( vote_stakes );
274 63 : stake_t * stakes_pool = get_stakes_pool( vote_stakes, fork_idx );
275 63 : stakes_map_t * stakes_map = get_stakes_map( vote_stakes, fork_idx );
276 :
277 63 : index_key_t index_key = {
278 63 : .pubkey = *pubkey,
279 63 : .node_account_t_1 = *node_account_t_1,
280 63 : .stake_t_1 = stake_t_1 & 0x7FFFFFFFFFFFFFFFUL,
281 63 : .epoch = epoch % 2,
282 63 : .commission_t_1 = commission_t_1,
283 63 : };
284 63 : index_ele_t * index_ele = index_map_ele_query( index_map, &index_key, NULL, index_pool );
285 63 : if( FD_LIKELY( !index_ele ) ) {
286 60 : index_ele = index_pool_ele_acquire( index_pool );
287 60 : index_ele->pubkey = *pubkey;
288 60 : index_ele->node_account_t_1 = *node_account_t_1;
289 60 : index_ele->node_account_t_2 = *node_account_t_2;
290 60 : index_ele->commission_t_1 = commission_t_1;
291 60 : index_ele->commission_t_2 = commission_t_2;
292 60 : index_ele->stake_t_1 = stake_t_1 & 0x7FFFFFFFFFFFFFFFUL;
293 60 : index_ele->stake_t_2 = stake_t_2;
294 60 : index_ele->epoch = epoch % 2;
295 60 : index_ele->refcnt = 1;
296 60 : FD_TEST( index_map_multi_ele_insert( index_map_multi, index_ele, index_pool ) );
297 60 : FD_TEST( index_map_ele_insert( index_map, index_ele, index_pool ) );
298 60 : } else {
299 3 : index_ele->refcnt++;
300 3 : }
301 :
302 63 : stake_t * stake = stakes_pool_ele_acquire( stakes_pool );
303 63 : stake->idx = (uint)index_pool_idx( index_pool, index_ele );
304 63 : FD_TEST( stakes_map_ele_insert( stakes_map, stake, stakes_pool ) );
305 :
306 63 : fd_rwlock_unwrite( &vote_stakes->lock );
307 63 : }
308 :
309 : void
310 0 : fd_vote_stakes_genesis_fini( fd_vote_stakes_t * vote_stakes ) {
311 0 : fd_rwlock_write( &vote_stakes->lock );
312 :
313 0 : index_ele_t * index_pool = get_index_pool( vote_stakes );
314 0 : index_map_multi_t * index_map_multi = get_index_map_multi( vote_stakes );
315 :
316 0 : for( index_map_multi_iter_t iter = index_map_multi_iter_init( index_map_multi, index_pool );
317 0 : !index_map_multi_iter_done( iter, index_map_multi, index_pool );
318 0 : iter = index_map_multi_iter_next( iter, index_map_multi, index_pool ) ) {
319 0 : index_ele_t * ele = index_map_multi_iter_ele( iter, index_map_multi, index_pool );
320 0 : ele->node_account_t_2 = ele->node_account_t_1;
321 0 : ele->stake_t_2 = ele->stake_t_1;
322 0 : }
323 :
324 0 : fd_rwlock_unwrite( &vote_stakes->lock );
325 0 : }
326 :
327 : ushort
328 24 : fd_vote_stakes_new_child( fd_vote_stakes_t * vote_stakes ) {
329 24 : fd_rwlock_write( &vote_stakes->lock );
330 :
331 24 : fork_t * fork_pool = get_fork_pool( vote_stakes );
332 24 : fork_dlist_t * fork_dlist = get_fork_dlist( vote_stakes );
333 :
334 24 : if( FD_UNLIKELY( !fork_pool_free( fork_pool ) ) ) {
335 0 : FD_LOG_CRIT(( "no free forks in pool" ));
336 0 : }
337 :
338 24 : ushort idx = (ushort)fork_pool_idx_acquire( fork_pool );
339 :
340 24 : fork_dlist_idx_push_tail( fork_dlist, idx, fork_pool );
341 :
342 24 : fd_rwlock_unwrite( &vote_stakes->lock );
343 24 : return idx;
344 24 : }
345 :
346 : void
347 : fd_vote_stakes_advance_root( fd_vote_stakes_t * vote_stakes,
348 60 : ushort root_idx ) {
349 60 : fd_rwlock_write( &vote_stakes->lock );
350 :
351 : /* Only expect the vote stakes to update once an epoch. */
352 60 : if( FD_LIKELY( root_idx==vote_stakes->root_idx ) ) {
353 48 : fd_rwlock_unwrite( &vote_stakes->lock );
354 48 : return;
355 48 : }
356 :
357 12 : fork_t * fork_pool = get_fork_pool( vote_stakes );
358 12 : fork_dlist_t * fork_dlist = get_fork_dlist( vote_stakes );
359 :
360 12 : index_ele_t * index_pool = get_index_pool( vote_stakes );
361 12 : index_map_t * index_map = get_index_map( vote_stakes );
362 12 : index_map_multi_t * index_map_multi = get_index_map_multi( vote_stakes );
363 : /* For every outstanding fork that is not the new candidate root,
364 : remove all stakes refcnts from the index. If the index has no
365 : outstanding references, remove the index entry. */
366 42 : while( !fork_dlist_is_empty( fork_dlist, fork_pool ) ) {
367 30 : ushort fork_idx = (ushort)fork_dlist_idx_pop_head( fork_dlist, fork_pool );
368 30 : if( fork_idx==root_idx ) continue;
369 :
370 18 : stake_t * stakes_pool = get_stakes_pool( vote_stakes, fork_idx );
371 18 : stakes_map_t * stakes_map = get_stakes_map( vote_stakes, fork_idx );
372 18 : for( stakes_map_iter_t iter = stakes_map_iter_init( stakes_map, stakes_pool );
373 75 : !stakes_map_iter_done( iter, stakes_map, stakes_pool );
374 57 : iter = stakes_map_iter_next( iter, stakes_map, stakes_pool ) ) {
375 57 : stake_t * stake = stakes_map_iter_ele( iter, stakes_map, stakes_pool );
376 57 : index_ele_t * ele = index_pool_ele( index_pool, stake->idx );
377 57 : ele->refcnt--;
378 :
379 57 : if( FD_UNLIKELY( ele->refcnt==0U ) ) {
380 57 : FD_TEST( index_map_ele_remove( index_map, &ele->index_key, NULL, index_pool ) );
381 57 : FD_TEST( index_map_multi_ele_remove_fast( index_map_multi, ele, index_pool ) );
382 57 : index_pool_ele_release( index_pool, ele );
383 57 : }
384 57 : }
385 18 : fork_pool_idx_release( fork_pool, fork_idx );
386 18 : stakes_map_reset( get_stakes_map( vote_stakes, fork_idx ) );
387 18 : stakes_pool_reset( get_stakes_pool( vote_stakes, fork_idx ) );
388 18 : }
389 : /* TODO: There's probably a way to do a more efficient reset here. */
390 :
391 12 : fork_dlist_idx_push_head( fork_dlist, root_idx, fork_pool );
392 12 : vote_stakes->root_idx = root_idx;
393 :
394 12 : fd_rwlock_unwrite( &vote_stakes->lock );
395 12 : }
396 :
397 : static int
398 : fd_vote_stakes_query_private( fd_vote_stakes_t * vote_stakes,
399 : ushort fork_idx,
400 : fd_pubkey_t const * pubkey,
401 : ulong * stake_t_1_out_opt,
402 : ulong * stake_t_2_out_opt,
403 : fd_pubkey_t * node_account_t_1_out_opt,
404 : fd_pubkey_t * node_account_t_2_out_opt,
405 : uchar * commission_t_1_out_opt,
406 72 : uchar * commission_t_2_out_opt ) {
407 :
408 72 : index_ele_t * index_pool = get_index_pool( vote_stakes );
409 72 : index_map_multi_t * index_map_multi = get_index_map_multi( vote_stakes );
410 :
411 72 : stake_t * stakes_pool = get_stakes_pool( vote_stakes, fork_idx );
412 72 : stakes_map_t * stakes_map = get_stakes_map( vote_stakes, fork_idx );
413 :
414 : /* The index may have multiple entries for the same pubkey, so every
415 : single matching index entry must be checked to see if the index
416 : exists in the given fork's stakes map. If it does, return the
417 : t_2 stake value.*/
418 72 : uint ele_idx = (uint)index_map_multi_idx_query_const( index_map_multi, pubkey, UINT_MAX, index_pool );
419 72 : if( FD_UNLIKELY( ele_idx==UINT_MAX ) ) {
420 0 : return 0;
421 0 : }
422 :
423 72 : while( !stakes_map_ele_query_const( stakes_map, &ele_idx, NULL, stakes_pool ) ) {
424 0 : ele_idx = (uint)index_map_multi_idx_next_const( ele_idx, UINT_MAX, index_pool );
425 0 : if( FD_UNLIKELY( ele_idx==UINT_MAX ) ) {
426 0 : return 0;
427 0 : }
428 0 : }
429 :
430 72 : index_ele_t * index_ele = index_pool_ele( index_pool, ele_idx );
431 72 : if( stake_t_1_out_opt ) *stake_t_1_out_opt = index_ele->stake_t_1;
432 72 : if( stake_t_2_out_opt ) *stake_t_2_out_opt = index_ele->stake_t_2;
433 72 : if( node_account_t_1_out_opt ) *node_account_t_1_out_opt = index_ele->node_account_t_1;
434 72 : if( node_account_t_2_out_opt ) *node_account_t_2_out_opt = index_ele->node_account_t_2;
435 72 : if( commission_t_1_out_opt ) *commission_t_1_out_opt = (uchar)index_ele->commission_t_1;
436 72 : if( commission_t_2_out_opt ) *commission_t_2_out_opt = (uchar)index_ele->commission_t_2;
437 72 : return 1;
438 72 : }
439 :
440 : int
441 : fd_vote_stakes_query( fd_vote_stakes_t * vote_stakes,
442 : ushort fork_idx,
443 : fd_pubkey_t const * pubkey,
444 : ulong * stake_t_1_out_opt,
445 : ulong * stake_t_2_out_opt,
446 : fd_pubkey_t * node_account_t_1_out_opt,
447 : fd_pubkey_t * node_account_t_2_out_opt,
448 : uchar * commission_t_1_out_opt,
449 63 : uchar * commission_t_2_out_opt ) {
450 63 : fd_rwlock_read( &vote_stakes->lock );
451 63 : int result = fd_vote_stakes_query_private( vote_stakes, fork_idx, pubkey, stake_t_1_out_opt, stake_t_2_out_opt, node_account_t_1_out_opt, node_account_t_2_out_opt, commission_t_1_out_opt, commission_t_2_out_opt );
452 63 : fd_rwlock_unread( &vote_stakes->lock );
453 63 : return result;
454 63 : }
455 :
456 : int
457 : fd_vote_stakes_query_pubkey( fd_vote_stakes_t * vote_stakes,
458 : ushort fork_idx,
459 0 : fd_pubkey_t const * pubkey ) {
460 0 : fd_rwlock_read( &vote_stakes->lock );
461 0 : int result = fd_vote_stakes_query_private( vote_stakes, fork_idx, pubkey, NULL, NULL, NULL, NULL, NULL, NULL );
462 0 : fd_rwlock_unread( &vote_stakes->lock );
463 0 : return result;
464 0 : }
465 :
466 : int
467 : fd_vote_stakes_query_t_1( fd_vote_stakes_t * vote_stakes,
468 : ushort fork_idx,
469 : fd_pubkey_t const * pubkey,
470 : ulong * stake_out,
471 : fd_pubkey_t * node_account_out,
472 9 : uchar * commission_out ) {
473 9 : fd_rwlock_read( &vote_stakes->lock );
474 9 : int found = fd_vote_stakes_query_private( vote_stakes, fork_idx, pubkey, stake_out, NULL, node_account_out, NULL, commission_out, NULL );
475 9 : fd_rwlock_unread( &vote_stakes->lock );
476 9 : return found && *stake_out>0UL;
477 9 : }
478 :
479 : int
480 : fd_vote_stakes_query_t_2( fd_vote_stakes_t * vote_stakes,
481 : ushort fork_idx,
482 : fd_pubkey_t const * pubkey,
483 : ulong * stake_out,
484 : fd_pubkey_t * node_account_out,
485 0 : uchar * commission_out ) {
486 0 : fd_rwlock_read( &vote_stakes->lock );
487 0 : int found = fd_vote_stakes_query_private( vote_stakes, fork_idx, pubkey, NULL, stake_out, NULL, node_account_out, NULL, commission_out );
488 0 : fd_rwlock_unread( &vote_stakes->lock );
489 0 : return found && *stake_out>0UL;
490 0 : }
491 :
492 : void
493 6 : fd_vote_stakes_reset( fd_vote_stakes_t * vote_stakes ) {
494 6 : fd_rwlock_write( &vote_stakes->lock );
495 :
496 : /* Pop the fork dlist */
497 6 : fork_t * fork_pool = get_fork_pool( vote_stakes );
498 6 : fork_dlist_t * fork_dlist = get_fork_dlist( vote_stakes );
499 6 : fork_dlist_remove_all( fork_dlist, fork_pool );
500 :
501 6 : fork_pool_reset( fork_pool );
502 :
503 : /* For each fork, reset the stakes map and pool */
504 66 : for( ushort i=0; i<vote_stakes->max_fork_width; i++ ) {
505 60 : stakes_map_reset( get_stakes_map( vote_stakes, i ) );
506 60 : stakes_pool_reset( get_stakes_pool( vote_stakes, i ) );
507 60 : }
508 :
509 : /* Reset the index map and multi map */
510 6 : index_map_reset( get_index_map( vote_stakes ) );
511 6 : index_map_multi_reset( get_index_map_multi( vote_stakes ) );
512 :
513 : /* Reset the index pool */
514 6 : index_pool_reset( get_index_pool( vote_stakes ) );
515 :
516 : /* Setup the pool again */
517 6 : vote_stakes->root_idx = (ushort)fork_pool_idx_acquire( fork_pool );
518 6 : fork_dlist_idx_push_tail( fork_dlist, vote_stakes->root_idx, fork_pool );
519 :
520 6 : fd_rwlock_unwrite( &vote_stakes->lock );
521 6 : }
522 :
523 : uint
524 : fd_vote_stakes_ele_cnt( fd_vote_stakes_t * vote_stakes,
525 21 : ushort fork_idx ) {
526 21 : fd_rwlock_read( &vote_stakes->lock );
527 21 : stake_t * stakes_pool = get_stakes_pool( vote_stakes, fork_idx );
528 21 : uint cnt = (uint)stakes_pool_used( stakes_pool );
529 21 : fd_rwlock_unread( &vote_stakes->lock );
530 21 : return cnt;
531 21 : }
532 :
533 : ushort
534 405 : fd_vote_stakes_get_root_idx( fd_vote_stakes_t * vote_stakes ) {
535 405 : fd_rwlock_read( &vote_stakes->lock );
536 405 : ushort idx = vote_stakes->root_idx;
537 405 : fd_rwlock_unread( &vote_stakes->lock );
538 405 : return idx;
539 405 : }
540 :
541 : fd_vote_stakes_iter_t *
542 : fd_vote_stakes_fork_iter_init( fd_vote_stakes_t * vote_stakes,
543 : ushort fork_idx,
544 54 : uchar iter_mem[ static FD_VOTE_STAKES_ITER_FOOTPRINT ] ) {
545 54 : fd_rwlock_write( &vote_stakes->lock );
546 :
547 54 : stakes_map_iter_t iter = stakes_map_iter_init( get_stakes_map( vote_stakes, fork_idx ), get_stakes_pool( vote_stakes, fork_idx ) );
548 54 : memcpy( iter_mem, &iter, sizeof(stakes_map_iter_t) );
549 54 : return (fd_vote_stakes_iter_t *)iter_mem;
550 54 : }
551 :
552 : void
553 54 : fd_vote_stakes_fork_iter_fini( fd_vote_stakes_t * vote_stakes ) {
554 54 : fd_rwlock_unwrite( &vote_stakes->lock );
555 54 : }
556 :
557 : int
558 : fd_vote_stakes_fork_iter_done( fd_vote_stakes_t * vote_stakes,
559 : ushort fork_idx,
560 114 : fd_vote_stakes_iter_t * iter ) {
561 114 : stakes_map_iter_t * stakes_map_iter = (stakes_map_iter_t *)iter;
562 114 : return stakes_map_iter_done( *stakes_map_iter, get_stakes_map( vote_stakes, fork_idx ), get_stakes_pool( vote_stakes, fork_idx ) );
563 114 : }
564 :
565 : void
566 : fd_vote_stakes_fork_iter_next( fd_vote_stakes_t * vote_stakes,
567 : ushort fork_idx,
568 60 : fd_vote_stakes_iter_t * iter ) {
569 60 : stakes_map_iter_t * stakes_map_iter = (stakes_map_iter_t *)iter;
570 60 : *stakes_map_iter = stakes_map_iter_next( *stakes_map_iter, get_stakes_map( vote_stakes, fork_idx ), get_stakes_pool( vote_stakes, fork_idx ) );
571 60 : }
572 :
573 : void
574 : fd_vote_stakes_fork_iter_ele( fd_vote_stakes_t * vote_stakes,
575 : ushort fork_idx,
576 : fd_vote_stakes_iter_t * iter,
577 : fd_pubkey_t * pubkey_out,
578 : ulong * stake_t_1_out_opt,
579 : ulong * stake_t_2_out_opt,
580 : fd_pubkey_t * node_account_t_1_out_opt,
581 : fd_pubkey_t * node_account_t_2_out_opt,
582 : uchar * commission_t_1_out_opt,
583 60 : uchar * commission_t_2_out_opt ) {
584 60 : stakes_map_iter_t * stakes_map_iter = (stakes_map_iter_t *)iter;
585 60 : stake_t * stake = stakes_map_iter_ele( *stakes_map_iter, get_stakes_map( vote_stakes, fork_idx ), get_stakes_pool( vote_stakes, fork_idx ) );
586 :
587 60 : index_ele_t * index_pool = get_index_pool( vote_stakes );
588 60 : index_ele_t * index_ele = index_pool_ele( index_pool, stake->idx );
589 :
590 60 : *pubkey_out = index_ele->index_key.pubkey;
591 :
592 60 : if( stake_t_1_out_opt ) *stake_t_1_out_opt = index_ele->index_key.stake_t_1;
593 60 : if( stake_t_2_out_opt ) *stake_t_2_out_opt = index_ele->stake_t_2;
594 60 : if( node_account_t_1_out_opt ) *node_account_t_1_out_opt = index_ele->node_account_t_1;
595 60 : if( node_account_t_2_out_opt ) *node_account_t_2_out_opt = index_ele->node_account_t_2;
596 60 : if( commission_t_1_out_opt ) *commission_t_1_out_opt = (uchar)index_ele->commission_t_1;
597 60 : if( commission_t_2_out_opt ) *commission_t_2_out_opt = (uchar)index_ele->commission_t_2;
598 60 : }
|