Line data Source code
1 : #include "fd_bank.h"
2 : #include "fd_runtime_const.h"
3 : #include "../rewards/fd_stake_rewards.h"
4 : #include "sysvar/fd_sysvar_cache.h"
5 :
6 : fd_lthash_value_t const *
7 81 : fd_bank_lthash_locking_query( fd_bank_t * bank ) {
8 81 : fd_rwlock_read( &bank->lthash_lock );
9 81 : return &bank->f.lthash;
10 81 : }
11 :
12 : void
13 81 : fd_bank_lthash_end_locking_query( fd_bank_t * bank ) {
14 81 : fd_rwlock_unread( &bank->lthash_lock );
15 81 : }
16 :
17 : fd_lthash_value_t *
18 17640 : fd_bank_lthash_locking_modify( fd_bank_t * bank ) {
19 17640 : fd_rwlock_write( &bank->lthash_lock );
20 17640 : return &bank->f.lthash;
21 17640 : }
22 :
23 : void
24 17640 : fd_bank_lthash_end_locking_modify( fd_bank_t * bank ) {
25 17640 : fd_rwlock_unwrite( &bank->lthash_lock );
26 17640 : }
27 :
28 : ulong
29 1833 : fd_banks_align( void ) {
30 1833 : return FD_BANKS_ALIGN;
31 1833 : }
32 :
33 : static fd_bank_t *
34 52440 : fd_banks_get_bank_pool( fd_banks_t * banks_data ) {
35 52440 : return fd_type_pun( (uchar *)banks_data + banks_data->pool_offset );
36 52440 : }
37 :
38 : static fd_bank_idx_seq_t *
39 3726 : fd_banks_get_dead_banks_deque( fd_banks_t * banks_data ) {
40 3726 : return fd_type_pun( (uchar *)banks_data + banks_data->dead_banks_deque_offset );
41 3726 : }
42 :
43 : static fd_epoch_leaders_t *
44 3933 : fd_banks_get_epoch_leaders( fd_banks_t * banks_data ) {
45 3933 : return fd_type_pun( (uchar *)banks_data + banks_data->epoch_leaders_offset );
46 3933 : }
47 :
48 : static fd_stake_delegations_t *
49 13569 : fd_banks_get_stake_delegations( fd_banks_t * banks_data ) {
50 13569 : return fd_type_pun( (uchar *)banks_data + banks_data->stake_delegations_offset );
51 13569 : }
52 :
53 : static fd_bank_cost_tracker_t *
54 17445 : fd_banks_get_cost_tracker_pool( fd_banks_t * banks_data ) {
55 17445 : return fd_type_pun( (uchar *)banks_data + banks_data->cost_tracker_pool_offset );
56 17445 : }
57 :
58 : static fd_stake_rewards_t *
59 4509 : fd_banks_get_stake_rewards( fd_banks_t * banks_data ) {
60 4509 : return fd_type_pun( (uchar *)banks_data + banks_data->stake_rewards_offset );
61 4509 : }
62 :
63 : static fd_vote_stakes_t *
64 15993 : fd_banks_get_vote_stakes( fd_banks_t * banks_data ) {
65 15993 : return fd_type_pun( (uchar *)banks_data + banks_data->vote_stakes_pool_offset );
66 15993 : }
67 :
68 : static fd_new_votes_t *
69 9306 : fd_banks_get_new_votes( fd_banks_t * banks_data ) {
70 9306 : return fd_type_pun( (uchar *)banks_data + banks_data->new_votes_offset );
71 9306 : }
72 :
73 : static fd_epoch_credits_t *
74 510 : fd_banks_get_epoch_credits( fd_banks_t * banks_data ) {
75 510 : return fd_type_pun( (uchar *)banks_data + banks_data->epoch_credits_offset );
76 510 : }
77 :
78 : static fd_stashed_commission_t *
79 0 : fd_banks_get_snapshot_commission_t_3( fd_banks_t * banks_data ) {
80 0 : return fd_type_pun( (uchar *)banks_data + banks_data->snapshot_commission_t_3_offset );
81 0 : }
82 :
83 : fd_epoch_credits_t *
84 510 : fd_bank_epoch_credits( fd_bank_t * bank ) {
85 510 : fd_banks_t * banks_data = fd_type_pun( (uchar *)bank - bank->banks_data_offset );
86 510 : return fd_banks_get_epoch_credits( banks_data );
87 510 : }
88 :
89 : ulong *
90 192 : fd_bank_epoch_credits_len( fd_bank_t * bank ) {
91 192 : fd_banks_t * banks_data = fd_type_pun( (uchar *)bank - bank->banks_data_offset );
92 192 : return &banks_data->epoch_credits_len;
93 192 : }
94 :
95 : fd_stashed_commission_t *
96 0 : fd_bank_snapshot_commission_t_3( fd_bank_t * bank ) {
97 0 : fd_banks_t * banks_data = fd_type_pun( (uchar *)bank - bank->banks_data_offset );
98 0 : return fd_banks_get_snapshot_commission_t_3( banks_data );
99 0 : }
100 :
101 : ulong *
102 6 : fd_bank_snapshot_commission_t_3_len( fd_bank_t * bank ) {
103 6 : fd_banks_t * banks_data = fd_type_pun( (uchar *)bank - bank->banks_data_offset );
104 6 : return &banks_data->snapshot_commission_t_3_len;
105 6 : }
106 :
107 : fd_vote_stakes_t *
108 8139 : fd_bank_vote_stakes( fd_bank_t const * bank ) {
109 8139 : fd_banks_t * banks_data = fd_type_pun( (uchar *)bank - bank->banks_data_offset );
110 8139 : return fd_banks_get_vote_stakes( banks_data );
111 8139 : }
112 :
113 : fd_new_votes_t *
114 207 : fd_bank_new_votes( fd_bank_t const * bank ) {
115 207 : fd_banks_t * banks_data = fd_type_pun( (uchar *)bank - bank->banks_data_offset );
116 207 : return fd_banks_get_new_votes( banks_data );
117 207 : }
118 :
119 : fd_stake_delegations_t *
120 279 : fd_bank_stake_delegations_modify( fd_bank_t * bank ) {
121 279 : fd_banks_t * banks_data = fd_type_pun( (uchar *)bank - bank->banks_data_offset );
122 279 : return fd_banks_get_stake_delegations( banks_data );
123 279 : }
124 :
125 : fd_stake_rewards_t const *
126 186 : fd_bank_stake_rewards_query( fd_bank_t * bank ) {
127 186 : fd_banks_t * banks_data = fd_type_pun( (uchar *)bank - bank->banks_data_offset );
128 186 : return fd_type_pun_const( fd_banks_get_stake_rewards( banks_data ) );
129 186 : }
130 :
131 : fd_stake_rewards_t *
132 687 : fd_bank_stake_rewards_modify( fd_bank_t * bank ) {
133 687 : fd_banks_t * banks_data = fd_type_pun( (uchar *)bank - bank->banks_data_offset );
134 687 : return fd_banks_get_stake_rewards( banks_data );
135 687 : }
136 :
137 : fd_epoch_leaders_t const *
138 : fd_bank_epoch_leaders_query( fd_bank_t const * bank,
139 18 : ulong epoch ) {
140 18 : FD_TEST( bank->f.epoch==epoch || bank->f.epoch==epoch-1UL );
141 18 : fd_banks_t * banks_data = fd_type_pun( (uchar *)bank - bank->banks_data_offset );
142 18 : return (fd_epoch_leaders_t const *)fd_type_pun( (uchar *)fd_banks_get_epoch_leaders( banks_data ) + (epoch % 2UL) * banks_data->epoch_leaders_footprint );
143 18 : }
144 :
145 : fd_epoch_leaders_t *
146 : fd_bank_epoch_leaders_modify( fd_bank_t * bank,
147 3816 : ulong epoch ) {
148 3816 : FD_TEST( bank->f.epoch==epoch || bank->f.epoch==epoch-1UL );
149 3816 : fd_banks_t * banks_data = fd_type_pun( (uchar *)bank - bank->banks_data_offset );
150 3816 : return (fd_epoch_leaders_t *)fd_type_pun( (uchar *)fd_banks_get_epoch_leaders( banks_data ) + (epoch % 2UL) * banks_data->epoch_leaders_footprint );
151 3816 : }
152 :
153 : fd_top_votes_t const *
154 63 : fd_bank_top_votes_t_1_query( fd_bank_t const * bank ) {
155 63 : return fd_type_pun_const( bank->top_votes_t_1_mem );
156 63 : }
157 :
158 : fd_top_votes_t *
159 3807 : fd_bank_top_votes_t_1_modify( fd_bank_t * bank ) {
160 3807 : return fd_type_pun( bank->top_votes_t_1_mem );
161 3807 : }
162 :
163 : fd_top_votes_t const *
164 4368 : fd_bank_top_votes_t_2_query( fd_bank_t const * bank ) {
165 4368 : return fd_type_pun_const( bank->top_votes_t_2_mem );
166 4368 : }
167 :
168 : fd_top_votes_t *
169 3909 : fd_bank_top_votes_t_2_modify( fd_bank_t * bank ) {
170 3909 : return fd_type_pun( bank->top_votes_t_2_mem );
171 3909 : }
172 :
173 : fd_cost_tracker_t *
174 4299 : fd_bank_cost_tracker_modify( fd_bank_t * bank ) {
175 4299 : fd_banks_t * banks_data = fd_type_pun( (uchar *)bank - bank->banks_data_offset );
176 4299 : fd_bank_cost_tracker_t * cost_tracker_pool = fd_banks_get_cost_tracker_pool( banks_data );
177 4299 : FD_TEST( bank->cost_tracker_pool_idx!=fd_bank_cost_tracker_pool_idx_null( cost_tracker_pool ) );
178 4299 : uchar * cost_tracker_mem = fd_bank_cost_tracker_pool_ele( cost_tracker_pool, bank->cost_tracker_pool_idx )->data;
179 4299 : return fd_type_pun( cost_tracker_mem );
180 4299 : }
181 :
182 : fd_cost_tracker_t const *
183 0 : fd_bank_cost_tracker_query( fd_bank_t * bank ) {
184 0 : fd_banks_t * banks_data = fd_type_pun( (uchar *)bank - bank->banks_data_offset );
185 0 : fd_bank_cost_tracker_t * cost_tracker_pool = fd_banks_get_cost_tracker_pool( banks_data );
186 0 : FD_TEST( bank->cost_tracker_pool_idx!=fd_bank_cost_tracker_pool_idx_null( cost_tracker_pool ) );
187 0 : uchar * cost_tracker_mem = fd_bank_cost_tracker_pool_ele( cost_tracker_pool, bank->cost_tracker_pool_idx )->data;
188 0 : return fd_type_pun_const( cost_tracker_mem );
189 0 : }
190 :
191 : fd_bank_t *
192 16014 : fd_banks_root( fd_banks_t * banks ) {
193 16014 : return fd_banks_pool_ele( fd_banks_get_bank_pool( banks ), banks->root_idx );
194 16014 : }
195 :
196 : fd_bank_t *
197 : fd_banks_bank_query( fd_banks_t * banks,
198 11385 : ulong bank_idx ) {
199 11385 : fd_bank_t * bank = fd_banks_pool_ele( fd_banks_get_bank_pool( banks ), bank_idx );
200 11385 : if( FD_UNLIKELY( bank->state==FD_BANK_STATE_INACTIVE ) ) return NULL;
201 11337 : return bank;
202 11385 : }
203 :
204 : fd_bank_t *
205 : fd_banks_get_parent( fd_banks_t * banks,
206 12 : fd_bank_t * bank ) {
207 12 : if( FD_UNLIKELY( bank->parent_idx==ULONG_MAX ) ) return NULL;
208 12 : return fd_banks_pool_ele( fd_banks_get_bank_pool( banks ), bank->parent_idx );
209 12 : }
210 :
211 : int
212 0 : fd_banks_is_full( fd_banks_t * banks ) {
213 0 : return fd_banks_pool_free( fd_banks_get_bank_pool( banks ) )==0UL ||
214 0 : fd_bank_cost_tracker_pool_free( fd_banks_get_cost_tracker_pool( banks ) )==0UL;
215 0 : }
216 :
217 : ulong
218 9 : fd_banks_pool_used_cnt( fd_banks_t * banks ) {
219 9 : return fd_banks_pool_used( fd_banks_get_bank_pool( banks ) );
220 9 : }
221 :
222 : ulong
223 7095 : fd_banks_pool_max_cnt( fd_banks_t * banks ) {
224 7095 : return fd_banks_pool_max( fd_banks_get_bank_pool( banks ) );
225 7095 : }
226 :
227 : void
228 : fd_banks_stake_delegations_evict_bank_fork( fd_banks_t * banks,
229 0 : fd_bank_t * bank ) {
230 0 : if( bank->stake_delegations_fork_id!=USHORT_MAX ) {
231 0 : fd_stake_delegations_t * sd = fd_banks_get_stake_delegations( banks );
232 0 : fd_stake_delegations_evict_fork( sd, bank->stake_delegations_fork_id );
233 0 : bank->stake_delegations_fork_id = USHORT_MAX;
234 0 : }
235 0 : }
236 :
237 : ulong
238 : fd_banks_footprint( ulong max_total_banks,
239 : ulong max_fork_width,
240 : ulong max_stake_accounts,
241 228 : ulong max_vote_accounts ) {
242 :
243 : /* max_fork_width is used in the macro below. */
244 :
245 228 : ulong epoch_leaders_footprint = FD_EPOCH_LEADERS_FOOTPRINT( max_vote_accounts, FD_RUNTIME_SLOTS_PER_EPOCH );
246 228 : ulong expected_stake_accounts = fd_ulong_min( max_stake_accounts, FD_RUNTIME_EXPECTED_STAKE_ACCOUNTS );
247 228 : ulong expected_vote_accounts = fd_ulong_min( max_vote_accounts, FD_RUNTIME_EXPECTED_VOTE_ACCOUNTS );
248 :
249 228 : ulong l = FD_LAYOUT_INIT;
250 228 : l = FD_LAYOUT_APPEND( l, fd_banks_align(), sizeof(fd_banks_t) );
251 228 : l = FD_LAYOUT_APPEND( l, fd_stake_delegations_align(), fd_stake_delegations_footprint( max_stake_accounts, expected_stake_accounts, max_total_banks ) );
252 228 : l = FD_LAYOUT_APPEND( l, FD_EPOCH_LEADERS_ALIGN, 2UL * epoch_leaders_footprint );
253 228 : l = FD_LAYOUT_APPEND( l, fd_banks_pool_align(), fd_banks_pool_footprint( max_total_banks ) );
254 228 : l = FD_LAYOUT_APPEND( l, fd_banks_dead_align(), fd_banks_dead_footprint() );
255 228 : l = FD_LAYOUT_APPEND( l, fd_bank_cost_tracker_pool_align(), fd_bank_cost_tracker_pool_footprint( max_fork_width ) );
256 228 : l = FD_LAYOUT_APPEND( l, fd_stake_rewards_align(), fd_stake_rewards_footprint( max_stake_accounts, max_fork_width ) );
257 228 : l = FD_LAYOUT_APPEND( l, fd_vote_stakes_align(), fd_vote_stakes_footprint( max_vote_accounts, fd_ulong_min( max_vote_accounts, expected_vote_accounts ), max_fork_width ) );
258 228 : l = FD_LAYOUT_APPEND( l, fd_new_votes_align(), fd_new_votes_footprint( max_vote_accounts, expected_vote_accounts, max_total_banks ) );
259 228 : l = FD_LAYOUT_APPEND( l, alignof(fd_epoch_credits_t), sizeof(fd_epoch_credits_t) * max_vote_accounts );
260 228 : l = FD_LAYOUT_APPEND( l, alignof(fd_stashed_commission_t), sizeof(fd_stashed_commission_t) * max_vote_accounts );
261 228 : return FD_LAYOUT_FINI( l, fd_banks_align() );
262 228 : }
263 :
264 : void *
265 : fd_banks_new( void * shmem,
266 : ulong max_total_banks,
267 : ulong max_fork_width,
268 : ulong max_stake_accounts,
269 : ulong max_vote_accounts,
270 : int larger_max_cost_per_block,
271 99 : ulong seed ) {
272 99 : if( FD_UNLIKELY( !shmem ) ) {
273 0 : FD_LOG_WARNING(( "NULL shmem" ));
274 0 : return NULL;
275 0 : }
276 :
277 99 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)shmem, fd_banks_align() ) ) ) {
278 0 : FD_LOG_WARNING(( "misaligned shmem" ));
279 0 : return NULL;
280 0 : }
281 :
282 99 : if( FD_UNLIKELY( max_total_banks>FD_BANKS_MAX_BANKS ) ) {
283 0 : FD_LOG_WARNING(( "max_total_banks is too large" ));
284 0 : return NULL;
285 0 : }
286 99 : if( FD_UNLIKELY( max_fork_width>FD_BANKS_MAX_BANKS ) ) {
287 0 : FD_LOG_WARNING(( "max_fork_width is too large" ));
288 0 : return NULL;
289 0 : }
290 :
291 99 : ulong epoch_leaders_footprint = FD_EPOCH_LEADERS_FOOTPRINT( max_vote_accounts, FD_RUNTIME_SLOTS_PER_EPOCH );
292 99 : ulong expected_stake_accounts = fd_ulong_min( max_stake_accounts, FD_RUNTIME_EXPECTED_STAKE_ACCOUNTS );
293 99 : ulong expected_vote_accounts = fd_ulong_min( max_vote_accounts, FD_RUNTIME_EXPECTED_VOTE_ACCOUNTS );
294 :
295 99 : FD_SCRATCH_ALLOC_INIT( l, shmem );
296 99 : fd_banks_t * banks_data = FD_SCRATCH_ALLOC_APPEND( l, fd_banks_align(), sizeof(fd_banks_t) );
297 99 : void * stake_delegations_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_stake_delegations_align(), fd_stake_delegations_footprint( max_stake_accounts, expected_stake_accounts, max_total_banks ) );
298 99 : void * epoch_leaders_mem = FD_SCRATCH_ALLOC_APPEND( l, FD_EPOCH_LEADERS_ALIGN, 2UL * epoch_leaders_footprint );
299 99 : void * pool_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_banks_pool_align(), fd_banks_pool_footprint( max_total_banks ) );
300 99 : void * dead_banks_deque_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_banks_dead_align(), fd_banks_dead_footprint() );
301 99 : void * cost_tracker_pool_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_bank_cost_tracker_pool_align(), fd_bank_cost_tracker_pool_footprint( max_fork_width ) );
302 99 : void * stake_rewards_pool_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_stake_rewards_align(), fd_stake_rewards_footprint( max_stake_accounts, max_fork_width ) );
303 99 : void * vote_stakes_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_vote_stakes_align(), fd_vote_stakes_footprint( max_vote_accounts, expected_vote_accounts, max_fork_width ) );
304 99 : void * new_votes_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_new_votes_align(), fd_new_votes_footprint( max_vote_accounts, expected_vote_accounts, max_total_banks ) );
305 99 : void * epoch_credits_mem = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_epoch_credits_t), sizeof(fd_epoch_credits_t) * max_vote_accounts );
306 99 : void * snapshot_commission_t_3 = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_stashed_commission_t), sizeof(fd_stashed_commission_t) * max_vote_accounts );
307 :
308 99 : if( FD_UNLIKELY( FD_SCRATCH_ALLOC_FINI( l, fd_banks_align() ) != (ulong)banks_data + fd_banks_footprint( max_total_banks, max_fork_width, max_stake_accounts, max_vote_accounts ) ) ) {
309 0 : FD_LOG_WARNING(( "fd_banks_new: bad layout" ));
310 0 : return NULL;
311 0 : }
312 :
313 99 : void * pool = fd_banks_pool_new( pool_mem, max_total_banks );
314 99 : if( FD_UNLIKELY( !pool ) ) {
315 0 : FD_LOG_WARNING(( "Failed to create bank pool" ));
316 0 : return NULL;
317 0 : }
318 :
319 99 : fd_bank_t * bank_pool = fd_banks_pool_join( pool );
320 99 : if( FD_UNLIKELY( !bank_pool ) ) {
321 0 : FD_LOG_WARNING(( "Failed to join bank pool" ));
322 0 : return NULL;
323 0 : }
324 :
325 99 : fd_bank_idx_seq_t * banks_dead_deque = fd_banks_dead_join( fd_banks_dead_new( dead_banks_deque_mem ) );
326 99 : if( FD_UNLIKELY( !banks_dead_deque ) ) {
327 0 : FD_LOG_WARNING(( "Failed to create banks dead deque" ));
328 0 : return NULL;
329 0 : }
330 99 : banks_data->dead_banks_deque_offset = (ulong)banks_dead_deque - (ulong)banks_data;
331 :
332 99 : banks_data->epoch_leaders_offset = (ulong)epoch_leaders_mem - (ulong)banks_data;
333 99 : banks_data->epoch_leaders_footprint = epoch_leaders_footprint;
334 99 : banks_data->pool_offset = (ulong)bank_pool - (ulong)banks_data;
335 99 : banks_data->epoch_credits_offset = (ulong)epoch_credits_mem - (ulong)banks_data;
336 99 : banks_data->snapshot_commission_t_3_offset = (ulong)snapshot_commission_t_3 - (ulong)banks_data;
337 :
338 : /* Create the pools for the non-inlined fields. Also new() and join()
339 : each of the elements in the pool as well as set up the lock for
340 : each of the pools. */
341 :
342 99 : fd_stake_delegations_t * stake_delegations = fd_stake_delegations_join( fd_stake_delegations_new( stake_delegations_mem, seed, max_stake_accounts, expected_stake_accounts, max_total_banks ) );
343 99 : if( FD_UNLIKELY( !stake_delegations ) ) {
344 0 : FD_LOG_WARNING(( "Unable to create stake delegations root" ));
345 0 : return NULL;
346 0 : }
347 99 : banks_data->stake_delegations_offset = (ulong)stake_delegations - (ulong)banks_data;
348 :
349 99 : fd_bank_cost_tracker_t * cost_tracker_pool = fd_bank_cost_tracker_pool_join( fd_bank_cost_tracker_pool_new( cost_tracker_pool_mem, max_fork_width ) );
350 99 : if( FD_UNLIKELY( !cost_tracker_pool ) ) {
351 0 : FD_LOG_WARNING(( "Failed to create cost tracker pool" ));
352 0 : return NULL;
353 0 : }
354 99 : banks_data->cost_tracker_pool_offset = (ulong)cost_tracker_pool - (ulong)banks_data;
355 :
356 480 : for( ulong i=0UL; i<max_fork_width; i++ ) {
357 381 : fd_bank_cost_tracker_t * cost_tracker = fd_bank_cost_tracker_pool_ele( cost_tracker_pool, i );
358 381 : if( FD_UNLIKELY( !fd_cost_tracker_join( fd_cost_tracker_new( cost_tracker->data, larger_max_cost_per_block, seed ) ) ) ) {
359 0 : FD_LOG_WARNING(( "Failed to create cost tracker" ));
360 0 : return NULL;
361 0 : }
362 381 : }
363 :
364 99 : fd_stake_rewards_t * stake_rewards = fd_stake_rewards_join( fd_stake_rewards_new( stake_rewards_pool_mem, max_stake_accounts, max_fork_width ) );
365 99 : if( FD_UNLIKELY( !stake_rewards ) ) {
366 0 : FD_LOG_WARNING(( "Failed to create stake rewards" ));
367 0 : return NULL;
368 0 : }
369 99 : banks_data->stake_rewards_offset = (ulong)stake_rewards - (ulong)banks_data;
370 :
371 :
372 99 : fd_vote_stakes_t * vote_stakes = fd_vote_stakes_join( fd_vote_stakes_new( vote_stakes_mem, max_vote_accounts, expected_vote_accounts, max_fork_width, seed ) );
373 99 : if( FD_UNLIKELY( !vote_stakes ) ) {
374 0 : FD_LOG_WARNING(( "Failed to create vote stakes" ));
375 0 : return NULL;
376 0 : }
377 99 : banks_data->vote_stakes_pool_offset = (ulong)vote_stakes - (ulong)banks_data;
378 :
379 99 : fd_new_votes_t * new_votes = fd_new_votes_join( fd_new_votes_new( new_votes_mem, seed, max_vote_accounts, expected_vote_accounts, max_total_banks ) );
380 99 : if( FD_UNLIKELY( !new_votes ) ) {
381 0 : FD_LOG_WARNING(( "Failed to create new votes" ));
382 0 : return NULL;
383 0 : }
384 99 : banks_data->new_votes_offset = (ulong)new_votes - (ulong)banks_data;
385 :
386 : /* For each bank, set the offset back to banks_data and initialize
387 : per-bank state. */
388 :
389 99 : fd_bank_cost_tracker_t * cost_tracker_pool_init = fd_banks_get_cost_tracker_pool( banks_data );
390 :
391 1644 : for( ulong i=0UL; i<max_total_banks; i++ ) {
392 :
393 1545 : fd_bank_t * bank = fd_banks_pool_ele( bank_pool, i );
394 :
395 1545 : fd_rwlock_new( &bank->lthash_lock );
396 :
397 1545 : bank->idx = i;
398 1545 : bank->state = FD_BANK_STATE_INACTIVE;
399 1545 : bank->banks_data_offset = (ulong)bank - (ulong)banks_data;
400 :
401 1545 : if( i==0UL ) {
402 99 : FD_TEST( fd_top_votes_join( fd_top_votes_new( bank->top_votes_t_1_mem, FD_RUNTIME_MAX_VOTE_ACCOUNTS_VAT, seed ) ) );
403 99 : FD_TEST( fd_top_votes_join( fd_top_votes_new( bank->top_votes_t_2_mem, FD_RUNTIME_MAX_VOTE_ACCOUNTS_VAT, seed ) ) );
404 99 : }
405 :
406 1545 : bank->cost_tracker_pool_idx = fd_bank_cost_tracker_pool_idx_null( cost_tracker_pool_init );
407 1545 : }
408 :
409 99 : banks_data->max_total_banks = max_total_banks;
410 99 : banks_data->max_fork_width = max_fork_width;
411 99 : banks_data->max_stake_accounts = max_stake_accounts;
412 99 : banks_data->max_vote_accounts = max_vote_accounts;
413 99 : banks_data->root_idx = ULONG_MAX;
414 99 : banks_data->bank_seq = 1UL;
415 :
416 99 : FD_COMPILER_MFENCE();
417 99 : FD_VOLATILE( banks_data->magic ) = FD_BANKS_MAGIC;
418 99 : FD_COMPILER_MFENCE();
419 :
420 99 : return shmem;
421 99 : }
422 :
423 : fd_banks_t *
424 99 : fd_banks_join( void * banks_data_mem ) {
425 99 : fd_banks_t * banks_data = (fd_banks_t *)banks_data_mem;
426 :
427 99 : if( FD_UNLIKELY( !banks_data ) ) {
428 0 : FD_LOG_WARNING(( "NULL banks data" ));
429 0 : return NULL;
430 0 : }
431 :
432 99 : if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)banks_data, fd_banks_align() ) ) ) {
433 0 : FD_LOG_WARNING(( "misaligned banks" ));
434 0 : return NULL;
435 0 : }
436 :
437 99 : if( FD_UNLIKELY( banks_data->magic!=FD_BANKS_MAGIC ) ) {
438 0 : FD_LOG_WARNING(( "Invalid banks magic" ));
439 0 : return NULL;
440 0 : }
441 :
442 99 : ulong expected_stake_accounts = fd_ulong_min( banks_data->max_stake_accounts, FD_RUNTIME_EXPECTED_STAKE_ACCOUNTS );
443 99 : ulong expected_vote_accounts = fd_ulong_min( banks_data->max_vote_accounts, FD_RUNTIME_EXPECTED_VOTE_ACCOUNTS );
444 :
445 99 : FD_SCRATCH_ALLOC_INIT( l, banks_data );
446 99 : banks_data = FD_SCRATCH_ALLOC_APPEND( l, fd_banks_align(), sizeof(fd_banks_t) );
447 99 : void * stake_delegations_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_stake_delegations_align(), fd_stake_delegations_footprint( banks_data->max_stake_accounts, expected_stake_accounts, banks_data->max_total_banks ) );
448 99 : void * epoch_leaders_mem = FD_SCRATCH_ALLOC_APPEND( l, FD_EPOCH_LEADERS_ALIGN, 2UL * banks_data->epoch_leaders_footprint );
449 99 : void * pool_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_banks_pool_align(), fd_banks_pool_footprint( banks_data->max_total_banks ) );
450 99 : void * dead_banks_deque_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_banks_dead_align(), fd_banks_dead_footprint() );
451 99 : void * cost_tracker_pool_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_bank_cost_tracker_pool_align(), fd_bank_cost_tracker_pool_footprint( banks_data->max_fork_width ) );
452 99 : void * stake_rewards_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_stake_rewards_align(), fd_stake_rewards_footprint( banks_data->max_stake_accounts, banks_data->max_fork_width ) );
453 99 : void * vote_stakes_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_vote_stakes_align(), fd_vote_stakes_footprint( banks_data->max_vote_accounts, expected_vote_accounts, banks_data->max_fork_width ) );
454 99 : void * new_votes_mem = FD_SCRATCH_ALLOC_APPEND( l, fd_new_votes_align(), fd_new_votes_footprint( banks_data->max_vote_accounts, expected_vote_accounts, banks_data->max_total_banks ) );
455 99 : void * epoch_credits_mem = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_epoch_credits_t), sizeof(fd_epoch_credits_t) * banks_data->max_vote_accounts );
456 99 : void * snapshot_commission = FD_SCRATCH_ALLOC_APPEND( l, alignof(fd_stashed_commission_t), sizeof(fd_stashed_commission_t) * banks_data->max_vote_accounts );
457 99 : (void)new_votes_mem;
458 99 : (void)epoch_credits_mem;
459 99 : (void)snapshot_commission;
460 :
461 99 : FD_SCRATCH_ALLOC_FINI( l, fd_banks_align() );
462 :
463 99 : fd_bank_t * banks_pool = fd_banks_get_bank_pool( banks_data );
464 99 : if( FD_UNLIKELY( !banks_pool ) ) {
465 0 : FD_LOG_WARNING(( "Failed to join bank pool" ));
466 0 : return NULL;
467 0 : }
468 :
469 99 : if( FD_UNLIKELY( banks_pool!=fd_banks_pool_join( pool_mem ) ) ) {
470 0 : FD_LOG_WARNING(( "Failed to join bank pool" ));
471 0 : return NULL;
472 0 : }
473 :
474 99 : fd_bank_idx_seq_t * banks_dead_deque = fd_banks_dead_join( dead_banks_deque_mem );
475 99 : if( FD_UNLIKELY( !banks_dead_deque ) ) {
476 0 : FD_LOG_WARNING(( "Failed to join banks dead deque" ));
477 0 : return NULL;
478 0 : }
479 :
480 99 : if( FD_UNLIKELY( epoch_leaders_mem!=fd_banks_get_epoch_leaders( banks_data ) ) ) {
481 0 : FD_LOG_WARNING(( "Failed to join epoch leaders mem" ));
482 0 : return NULL;
483 0 : }
484 :
485 99 : if( FD_UNLIKELY( stake_delegations_mem!=fd_banks_get_stake_delegations( banks_data ) ) ) {
486 0 : FD_LOG_WARNING(( "Failed to join stake delegations root mem" ));
487 0 : return NULL;
488 0 : }
489 :
490 99 : fd_bank_cost_tracker_t * cost_tracker_pool = fd_banks_get_cost_tracker_pool( banks_data );
491 99 : if( FD_UNLIKELY( !cost_tracker_pool ) ) {
492 0 : FD_LOG_WARNING(( "Failed to join cost tracker pool" ));
493 0 : return NULL;
494 0 : }
495 :
496 99 : if( FD_UNLIKELY( cost_tracker_pool!=fd_bank_cost_tracker_pool_join( cost_tracker_pool_mem ) ) ) {
497 0 : FD_LOG_WARNING(( "Failed to join cost tracker pool" ));
498 0 : return NULL;
499 0 : }
500 :
501 99 : if( FD_UNLIKELY( !fd_stake_rewards_join( stake_rewards_mem ) ) ) {
502 0 : FD_LOG_WARNING(( "Failed to join stake rewards" ));
503 0 : return NULL;
504 0 : }
505 :
506 99 : if( FD_UNLIKELY( !fd_vote_stakes_join( vote_stakes_mem ) ) ) {
507 0 : FD_LOG_WARNING(( "Failed to join vote stakes" ));
508 0 : return NULL;
509 0 : }
510 :
511 99 : return banks_data;
512 99 : }
513 :
514 : fd_bank_t *
515 3669 : fd_banks_init_bank( fd_banks_t * banks ) {
516 :
517 3669 : fd_bank_t * bank_pool = fd_banks_get_bank_pool( banks );
518 3669 : FD_CHECK_CRIT( fd_banks_pool_free( bank_pool )!=0UL, "invariant violation: no free bank pool elements" );
519 :
520 3669 : fd_bank_t * bank = fd_banks_pool_ele_acquire( bank_pool );
521 3669 : bank->bank_seq = FD_ATOMIC_FETCH_AND_ADD( &banks->bank_seq, 1UL );
522 :
523 3669 : ulong null_idx = fd_banks_pool_idx_null( bank_pool );
524 3669 : bank->idx = fd_banks_pool_idx( bank_pool, bank );
525 3669 : bank->next = null_idx;
526 3669 : bank->parent_idx = null_idx;
527 3669 : bank->child_idx = null_idx;
528 3669 : bank->sibling_idx = null_idx;
529 :
530 3669 : fd_memset( &bank->f, 0, sizeof(bank->f) );
531 3669 : bank->stake_rewards_fork_id = UCHAR_MAX;
532 3669 : bank->stake_delegations_fork_id = USHORT_MAX;
533 3669 : bank->new_votes_fork_id = USHORT_MAX;
534 3669 : bank->parent_accdb_fork_id.val = USHORT_MAX;
535 3669 : bank->cost_tracker_pool_idx = fd_bank_cost_tracker_pool_idx_null( fd_banks_get_cost_tracker_pool( banks ) );
536 3669 : bank->first_fec_set_received_nanos = fd_log_wallclock();
537 3669 : bank->preparation_begin_nanos = 0L;
538 3669 : bank->first_transaction_scheduled_nanos = 0L;
539 3669 : bank->last_transaction_finished_nanos = 0L;
540 3669 : bank->block_completed_nanos = 0L;
541 :
542 3669 : fd_vote_stakes_t * vote_stakes = fd_banks_get_vote_stakes( banks );
543 3669 : bank->vote_stakes_fork_id = fd_vote_stakes_get_root_idx( vote_stakes );
544 :
545 3669 : bank->state = FD_BANK_STATE_FROZEN;
546 3669 : bank->refcnt = 0UL;
547 3669 : bank->is_leader = 0;
548 :
549 3669 : banks->root_idx = bank->idx;
550 :
551 3669 : FD_LOG_DEBUG(( "init bank (idx=%lu, vote_stakes_idx=%u, stake_rewards_idx=%u, stake_delegations_idx=%u, new_votes_idx=%u)",
552 3669 : bank->idx,
553 3669 : bank->vote_stakes_fork_id,
554 3669 : bank->stake_rewards_fork_id,
555 3669 : bank->stake_delegations_fork_id,
556 3669 : bank->new_votes_fork_id ));
557 :
558 3669 : return bank;
559 3669 : }
560 :
561 : fd_bank_t *
562 : fd_banks_clone_from_parent( fd_banks_t * banks,
563 4338 : ulong child_bank_idx ) {
564 :
565 4338 : fd_bank_t * bank_pool = fd_banks_get_bank_pool( banks );
566 4338 : fd_bank_t * child_bank = fd_banks_pool_ele( bank_pool, child_bank_idx );
567 4338 : FD_CHECK_CRIT( child_bank->state==FD_BANK_STATE_INIT, "invariant violation: bank is not initialized" );
568 :
569 4338 : fd_bank_t * parent_bank = fd_banks_pool_ele( bank_pool, child_bank->parent_idx );
570 4338 : FD_CHECK_CRIT( parent_bank->state==FD_BANK_STATE_FROZEN, "invariant violation: parent bank is not frozen" );
571 :
572 4338 : fd_bank_cost_tracker_t * cost_tracker_pool = fd_banks_get_cost_tracker_pool( banks );
573 4338 : FD_CHECK_CRIT( fd_bank_cost_tracker_pool_free( cost_tracker_pool )!=0UL, "invariant violation: no free cost tracker pool elements" );
574 4338 : child_bank->cost_tracker_pool_idx = fd_bank_cost_tracker_pool_idx_acquire( cost_tracker_pool );
575 :
576 4338 : fd_memcpy( child_bank->top_votes_t_1_mem, parent_bank->top_votes_t_1_mem, FD_TOP_VOTES_MAX_FOOTPRINT );
577 4338 : fd_memcpy( child_bank->top_votes_t_2_mem, parent_bank->top_votes_t_2_mem, FD_TOP_VOTES_MAX_FOOTPRINT );
578 :
579 4338 : child_bank->f = parent_bank->f;
580 4338 : child_bank->vote_stakes_fork_id = parent_bank->vote_stakes_fork_id;
581 4338 : child_bank->stake_rewards_fork_id = parent_bank->stake_rewards_fork_id;
582 4338 : child_bank->stake_delegations_fork_id = fd_stake_delegations_new_fork( fd_banks_get_stake_delegations( banks ) );
583 4338 : child_bank->new_votes_fork_id = fd_new_votes_new_fork( fd_banks_get_new_votes( banks ) );
584 4338 : child_bank->f.block_height = parent_bank->f.block_height + 1UL;
585 4338 : child_bank->f.tick_height = parent_bank->f.max_tick_height;
586 4338 : child_bank->f.parent_slot = parent_bank->f.slot;
587 4338 : child_bank->f.parent_signature_cnt = parent_bank->f.signature_count;
588 4338 : child_bank->f.parent_txn_count = parent_bank->f.parent_txn_count + parent_bank->f.txn_count;
589 4338 : child_bank->f.prev_bank_hash = parent_bank->f.bank_hash;
590 4338 : child_bank->f.execution_fees = 0UL;
591 4338 : child_bank->f.priority_fees = 0UL;
592 4338 : child_bank->f.tips = 0UL;
593 4338 : child_bank->f.signature_count = 0UL;
594 4338 : child_bank->f.total_compute_units_used = 0UL;
595 4338 : child_bank->f.shred_cnt = 0UL;
596 4338 : child_bank->f.txn_count = 0UL;
597 4338 : child_bank->f.nonvote_txn_count = 0UL;
598 4338 : child_bank->f.failed_txn_count = 0UL;
599 4338 : child_bank->f.nonvote_failed_txn_count = 0UL;
600 4338 : child_bank->f.identity_vote_idx = ULONG_MAX;
601 :
602 4338 : child_bank->state = FD_BANK_STATE_REPLAYABLE;
603 :
604 4338 : FD_LOG_DEBUG(( "cloning bank (idx=%lu, parent_idx=%lu, vote_stakes_idx=%u, stake_rewards_idx=%u, stake_delegations_idx=%u, new_votes_idx=%u)",
605 4338 : child_bank_idx,
606 4338 : parent_bank->idx,
607 4338 : child_bank->vote_stakes_fork_id,
608 4338 : child_bank->stake_rewards_fork_id,
609 4338 : child_bank->stake_delegations_fork_id,
610 4338 : child_bank->new_votes_fork_id ));
611 :
612 4338 : return child_bank;
613 4338 : }
614 :
615 : /* fd_bank_stake_delegation_apply_deltas applies all of the stake
616 : delegations for the entire direct ancestry from the bank to the
617 : root into a full fd_stake_delegations_t object. */
618 :
619 : static inline void
620 : fd_bank_apply_deltas( fd_banks_t * banks,
621 546 : fd_bank_t * bank ) {
622 :
623 546 : fd_stake_delegations_t * stake_delegations = fd_banks_get_stake_delegations( banks );
624 546 : fd_new_votes_t * new_votes = fd_banks_get_new_votes( banks );
625 :
626 : /* The stake_delegations root has crossed an epoch boundary. The
627 : stake totals for the current root need to be updated. */
628 546 : fd_bank_t * old_root = fd_banks_root( banks );
629 546 : if( old_root->f.epoch!=bank->f.epoch ) {
630 42 : stake_delegations->effective_stake = bank->f.total_effective_stake;
631 42 : stake_delegations->activating_stake = bank->f.total_activating_stake;
632 42 : stake_delegations->deactivating_stake = bank->f.total_deactivating_stake;
633 42 : fd_new_votes_reset_root( new_votes );
634 42 : }
635 :
636 : /* Naively what we want to do is iterate from the old root to the new
637 : root and apply the delta to the full state iteratively. */
638 :
639 : /* First, gather all of the pool indicies that we want to apply deltas
640 : for in reverse order starting from the new root. We want to exclude
641 : the old root since its delta has been applied previously. */
642 546 : ushort sd_pool_indices[ banks->max_total_banks ];
643 546 : ushort nv_pool_indices[ banks->max_total_banks ];
644 546 : ulong pool_indices_len = 0UL;
645 :
646 546 : fd_bank_t * bank_pool = fd_banks_get_bank_pool( banks );
647 :
648 546 : fd_bank_t * curr_bank = fd_banks_pool_ele( bank_pool, bank->idx );
649 1638 : while( !!curr_bank ) {
650 1092 : FD_LOG_DEBUG(( "applying bank delta (bank_idx=%lu, sd_fork_idx=%u, nv_fork_idx=%u)", curr_bank->idx, curr_bank->stake_delegations_fork_id, curr_bank->new_votes_fork_id ));
651 1092 : if( curr_bank->stake_delegations_fork_id!=USHORT_MAX ) {
652 555 : sd_pool_indices[pool_indices_len] = curr_bank->stake_delegations_fork_id;
653 555 : nv_pool_indices[pool_indices_len] = curr_bank->new_votes_fork_id;
654 555 : pool_indices_len++;
655 555 : }
656 1092 : curr_bank = fd_banks_pool_ele( bank_pool, curr_bank->parent_idx );
657 1092 : }
658 :
659 : /* We have populated all of the indicies that we need to apply deltas
660 : from in reverse order. */
661 :
662 546 : fd_stake_history_t stake_history_[1];
663 546 : fd_stake_history_t const * stake_history = fd_sysvar_cache_stake_history_view( &bank->f.sysvar_cache, stake_history_ );
664 : /* stake_history may be NULL */
665 1101 : for( ulong i=pool_indices_len; i>0; i-- ) {
666 555 : ushort sd_idx = sd_pool_indices[i-1UL];
667 555 : ushort nv_idx = nv_pool_indices[i-1UL];
668 555 : fd_stake_delegations_apply_fork_delta( bank->f.epoch, stake_history, &bank->f.warmup_cooldown_rate_epoch, stake_delegations, sd_idx );
669 555 : fd_new_votes_apply_delta( new_votes, nv_idx );
670 555 : }
671 546 : }
672 :
673 : static inline void
674 : fd_bank_stake_delegation_mark_deltas( fd_banks_t * banks,
675 : fd_bank_t * bank,
676 225 : fd_stake_delegations_t * stake_delegations ) {
677 :
678 225 : ushort pool_indices[ banks->max_total_banks ];
679 225 : ulong pool_indices_len = 0UL;
680 :
681 225 : fd_bank_t * bank_pool = fd_banks_get_bank_pool( banks );
682 :
683 225 : fd_bank_t * curr_bank = fd_banks_pool_ele( bank_pool, bank->idx );
684 687 : while( !!curr_bank ) {
685 462 : if( curr_bank->stake_delegations_fork_id!=USHORT_MAX ) {
686 258 : pool_indices[pool_indices_len++] = curr_bank->stake_delegations_fork_id;
687 258 : }
688 462 : curr_bank = fd_banks_pool_ele( bank_pool, curr_bank->parent_idx );
689 462 : }
690 :
691 225 : fd_stake_history_t stake_history[1];
692 225 : fd_sysvar_cache_stake_history_view( &bank->f.sysvar_cache, stake_history );
693 :
694 483 : for( ulong i=pool_indices_len; i>0; i-- ) {
695 258 : ushort idx = pool_indices[i-1UL];
696 258 : fd_stake_delegations_mark_delta( stake_delegations, bank->f.epoch, stake_history, &bank->f.warmup_cooldown_rate_epoch, idx );
697 258 : }
698 225 : }
699 :
700 : static inline void
701 : fd_bank_stake_delegation_unmark_deltas( fd_banks_t * banks,
702 : fd_bank_t * bank,
703 225 : fd_stake_delegations_t * stake_delegations ) {
704 :
705 225 : ushort pool_indices[ banks->max_total_banks ];
706 225 : ulong pool_indices_len = 0UL;
707 :
708 225 : fd_bank_t * bank_pool = fd_banks_get_bank_pool( banks );
709 :
710 225 : fd_bank_t * curr_bank = fd_banks_pool_ele( bank_pool, bank->idx );
711 687 : while( !!curr_bank ) {
712 462 : if( curr_bank->stake_delegations_fork_id!=USHORT_MAX ) {
713 258 : pool_indices[pool_indices_len++] = curr_bank->stake_delegations_fork_id;
714 258 : }
715 462 : curr_bank = fd_banks_pool_ele( bank_pool, curr_bank->parent_idx );
716 462 : }
717 :
718 225 : fd_stake_history_t stake_history_[1];
719 225 : fd_stake_history_t * stake_history = fd_sysvar_cache_stake_history_view( &bank->f.sysvar_cache, stake_history_ );
720 :
721 483 : for( ulong i=pool_indices_len; i>0; i-- ) {
722 258 : ushort idx = pool_indices[i-1UL];
723 258 : fd_stake_delegations_unmark_delta( stake_delegations, bank->f.epoch-1UL, stake_history, &bank->f.warmup_cooldown_rate_epoch, idx );
724 258 : }
725 225 : }
726 :
727 :
728 : fd_stake_delegations_t *
729 : fd_bank_stake_delegations_frontier_query( fd_banks_t * banks,
730 225 : fd_bank_t * bank ) {
731 225 : fd_stake_delegations_t * stake_delegations = fd_banks_get_stake_delegations( banks );
732 225 : fd_bank_stake_delegation_mark_deltas( banks, bank, stake_delegations );
733 :
734 225 : return stake_delegations;
735 225 : }
736 :
737 : void
738 : fd_bank_stake_delegations_end_frontier_query( fd_banks_t * banks,
739 225 : fd_bank_t * bank ) {
740 225 : fd_stake_delegations_t * stake_delegations = fd_banks_get_stake_delegations( banks );
741 225 : fd_bank_stake_delegation_unmark_deltas( banks, bank, stake_delegations );
742 225 : }
743 :
744 :
745 : fd_stake_delegations_t *
746 3645 : fd_banks_stake_delegations_root_query( fd_banks_t * banks ) {
747 3645 : return fd_banks_get_stake_delegations( banks );
748 3645 : }
749 :
750 : ulong
751 : fd_banks_new_votes_fork_indices( fd_bank_t * bank,
752 174 : ushort * fork_indices_out ) {
753 174 : fd_banks_t * banks = fd_type_pun( (uchar *)bank - bank->banks_data_offset );
754 174 : fd_bank_t * bank_pool = fd_banks_get_bank_pool( banks );
755 174 : ulong cnt = 0UL;
756 :
757 174 : fd_bank_t * curr = fd_banks_pool_ele( bank_pool, bank->idx );
758 528 : while( !!curr ) {
759 354 : if( curr->new_votes_fork_id!=USHORT_MAX ) {
760 180 : fork_indices_out[cnt++] = curr->new_votes_fork_id;
761 180 : }
762 354 : curr = fd_banks_pool_ele( bank_pool, curr->parent_idx );
763 354 : }
764 174 : return cnt;
765 174 : }
766 :
767 : void
768 : fd_banks_advance_root( fd_banks_t * banks,
769 546 : ulong root_bank_idx ) {
770 :
771 546 : fd_bank_t * bank_pool = fd_banks_get_bank_pool( banks );
772 :
773 : /* We want to replace the old root with the new root. This means we
774 : have to remove banks that aren't descendants of the new root. */
775 :
776 546 : fd_bank_t * old_root = fd_banks_root( banks );
777 546 : FD_CHECK_CRIT( old_root->refcnt==0UL, "refcnt for old root bank is nonzero" );
778 :
779 546 : fd_bank_t * new_root = fd_banks_pool_ele( bank_pool, root_bank_idx );
780 :
781 546 : fd_bank_apply_deltas( banks, new_root );
782 :
783 546 : fd_new_votes_t * new_votes = fd_banks_get_new_votes( banks );
784 546 : fd_new_votes_evict_fork( new_votes, new_root->new_votes_fork_id );
785 546 : new_root->new_votes_fork_id = USHORT_MAX;
786 :
787 546 : fd_stake_delegations_t * stake_delegations = fd_banks_get_stake_delegations( banks );
788 546 : fd_stake_delegations_evict_fork( stake_delegations, new_root->stake_delegations_fork_id );
789 546 : new_root->stake_delegations_fork_id = USHORT_MAX;
790 :
791 : /* Now that the deltas have been applied, we can remove all nodes
792 : that are not direct descendants of the new root. */
793 546 : fd_bank_t * head = fd_banks_pool_ele( bank_pool, old_root->idx );
794 546 : head->next = ULONG_MAX;
795 546 : fd_bank_t * tail = head;
796 :
797 1143 : while( head ) {
798 597 : fd_bank_t * child = fd_banks_pool_ele( bank_pool, head->child_idx );
799 :
800 1194 : while( FD_LIKELY( child ) ) {
801 :
802 597 : if( FD_LIKELY( child!=new_root ) ) {
803 51 : if( FD_UNLIKELY( child->refcnt!=0UL ) ) {
804 0 : FD_LOG_CRIT(( "refcnt for child bank at index %lu is %lu", child->idx, child->refcnt ));
805 0 : }
806 :
807 : /* Update tail pointers */
808 51 : tail->next = child->idx;
809 51 : tail = fd_banks_pool_ele( bank_pool, tail->next );
810 51 : tail->next = fd_banks_pool_idx_null( bank_pool );
811 51 : }
812 :
813 597 : child = fd_banks_pool_ele( bank_pool, child->sibling_idx );
814 597 : }
815 :
816 597 : fd_bank_t * next = fd_banks_pool_ele( bank_pool, head->next );
817 :
818 : /* It is possible for a bank that never finished replaying to be
819 : pruned away. If the bank was never frozen, then it's possible
820 : that the bank still owns a cost tracker pool element. If this
821 : is the case, we need to release the pool element. */
822 597 : fd_bank_cost_tracker_t * cost_tracker_pool = fd_banks_get_cost_tracker_pool( banks );
823 597 : if( head->cost_tracker_pool_idx!=fd_bank_cost_tracker_pool_idx_null( cost_tracker_pool ) ) {
824 9 : FD_LOG_DEBUG(( "releasing cost tracker pool element for bank at index %lu", head->idx ));
825 9 : fd_bank_cost_tracker_pool_idx_release( cost_tracker_pool, head->cost_tracker_pool_idx );
826 9 : head->cost_tracker_pool_idx = fd_bank_cost_tracker_pool_idx_null( cost_tracker_pool );
827 9 : }
828 :
829 597 : head->stake_rewards_fork_id = UCHAR_MAX;
830 597 : head->vote_stakes_fork_id = USHORT_MAX;
831 :
832 597 : if( head->new_votes_fork_id!=USHORT_MAX ) {
833 48 : FD_LOG_DEBUG(( "evicting new votes fork (bank_idx=%lu, fork_idx=%u)", head->idx, head->new_votes_fork_id ));
834 48 : fd_new_votes_evict_fork( new_votes, head->new_votes_fork_id );
835 48 : head->new_votes_fork_id = USHORT_MAX;
836 48 : }
837 :
838 597 : if( head->stake_delegations_fork_id!=USHORT_MAX ) {
839 54 : FD_LOG_DEBUG(( "evicting stake delegation fork (bank_idx=%lu, fork_idx=%u)", head->idx, head->stake_delegations_fork_id ));
840 54 : fd_stake_delegations_evict_fork( stake_delegations, head->stake_delegations_fork_id );
841 54 : head->stake_delegations_fork_id = USHORT_MAX;
842 54 : }
843 :
844 597 : head->state = FD_BANK_STATE_INACTIVE;
845 597 : fd_banks_pool_ele_release( bank_pool, head );
846 597 : head = next;
847 597 : }
848 :
849 : /* new_root is detached from old_root and becomes the only root.
850 : Clear sibling_idx too so traversals cannot follow a stale link to
851 : a bank index that was just pruned and later reused. */
852 546 : new_root->parent_idx = ULONG_MAX;
853 546 : new_root->sibling_idx = ULONG_MAX;
854 546 : banks->root_idx = new_root->idx;
855 :
856 546 : fd_vote_stakes_t * vote_stakes = fd_banks_get_vote_stakes( banks );
857 546 : fd_vote_stakes_advance_root( vote_stakes, new_root->vote_stakes_fork_id );
858 546 : }
859 :
860 : /* Is the fork tree starting at the given bank entirely eligible for
861 : pruning? Returns 1 for yes, 0 for no.
862 :
863 : See comment in fd_replay_tile.c for more details on safe pruning. */
864 : static int
865 : fd_banks_subtree_can_be_pruned( fd_bank_t * bank_pool,
866 27 : fd_bank_t * bank ) {
867 :
868 27 : if( bank->refcnt!=0UL ) return 0;
869 :
870 : /* Recursively check all children. */
871 24 : ulong child_idx = bank->child_idx;
872 33 : while( child_idx!=fd_banks_pool_idx_null( bank_pool ) ) {
873 9 : fd_bank_t * child = fd_banks_pool_ele( bank_pool, child_idx );
874 9 : if( !fd_banks_subtree_can_be_pruned( bank_pool, child ) ) return 0;
875 9 : child_idx = child->sibling_idx;
876 9 : }
877 :
878 24 : return 1;
879 24 : }
880 :
881 : int
882 : fd_banks_advance_root_prepare( fd_banks_t * banks,
883 : ulong target_bank_idx,
884 15 : ulong * advanceable_bank_idx_out ) {
885 : /* TODO: An optimization here is to do a single traversal of the tree
886 : that would mark minority forks as dead while accumulating
887 : refcnts to determine which bank is the highest advanceable. */
888 :
889 15 : fd_bank_t * bank_pool = fd_banks_get_bank_pool( banks );
890 :
891 15 : fd_bank_t * root = fd_banks_root( banks );
892 :
893 : /* Early exit if target is the same as the old root. */
894 15 : if( FD_UNLIKELY( root->idx==target_bank_idx ) ) {
895 0 : FD_LOG_WARNING(( "target bank_idx %lu is the same as the old root's bank index %lu", target_bank_idx, root->idx ));
896 0 : return 0;
897 0 : }
898 :
899 : /* Early exit if the root bank still has a reference to it, we can't
900 : advance from it unti it's released. */
901 15 : if( FD_UNLIKELY( root->refcnt!=0UL ) ) {
902 0 : return 0;
903 0 : }
904 :
905 15 : fd_bank_t * target_bank = fd_banks_pool_ele( bank_pool, target_bank_idx );
906 :
907 : /* Walk from target_bank up to root, recording the direct child of
908 : root on the path (prev). We only advance root by one level. */
909 :
910 15 : fd_bank_t * curr = target_bank;
911 15 : fd_bank_t * prev = NULL;
912 57 : while( curr && curr!=root ) {
913 42 : prev = curr;
914 42 : curr = fd_banks_pool_ele( bank_pool, curr->parent_idx );
915 42 : }
916 :
917 : /* If we didn't reach the old root or there is no parent, target is
918 : not a descendant. */
919 15 : if( FD_UNLIKELY( !curr || prev->parent_idx!=root->idx ) ) {
920 0 : FD_LOG_CRIT(( "invariant violation: target bank_idx %lu is not a direct descendant of root bank_idx %lu %lu %lu", target_bank_idx, root->idx, prev->idx, prev->parent_idx ));
921 0 : }
922 :
923 : /* We will at most advance our root bank by one. This means we can
924 : advance our root bank by one if each of the siblings of the
925 : potential new root are eligible for pruning. Each of the sibling
926 : subtrees can be pruned if the subtrees have no active references on
927 : their bank. */
928 15 : ulong advance_candidate_idx = prev->idx;
929 15 : ulong child_idx = root->child_idx;
930 42 : while( child_idx!=fd_banks_pool_idx_null( bank_pool ) ) {
931 30 : fd_bank_t * child_bank = fd_banks_pool_ele( bank_pool, child_idx );
932 30 : if( child_idx!=advance_candidate_idx ) {
933 18 : if( !fd_banks_subtree_can_be_pruned( bank_pool, child_bank ) ) {
934 3 : return 0;
935 3 : }
936 18 : }
937 27 : child_idx = child_bank->sibling_idx;
938 27 : }
939 :
940 12 : fd_bank_t * cand = fd_banks_pool_ele( bank_pool, advance_candidate_idx );
941 12 : FD_CHECK_CRIT( cand->state==FD_BANK_STATE_FROZEN, "advancing root to non-frozen bank" );
942 :
943 12 : *advanceable_bank_idx_out = advance_candidate_idx;
944 12 : return 1;
945 12 : }
946 :
947 : fd_bank_t *
948 : fd_banks_new_bank( fd_banks_t * banks,
949 : ulong parent_bank_idx,
950 : long now,
951 4362 : uchar is_leader ) {
952 :
953 4362 : fd_bank_t * bank_pool = fd_banks_get_bank_pool( banks );
954 4362 : FD_CHECK_CRIT( fd_banks_pool_free( bank_pool )!=0UL, "invariant violation: no free bank indices available" );
955 :
956 4362 : ulong child_bank_idx = fd_banks_pool_idx_acquire( bank_pool );
957 4362 : fd_bank_t * child_bank = fd_banks_pool_ele( bank_pool, child_bank_idx );
958 4362 : FD_CHECK_CRIT( child_bank->state==FD_BANK_STATE_INACTIVE, "invariant violation: bank for bank index is already initialized" );
959 :
960 4362 : ulong null_idx = fd_banks_pool_idx_null( bank_pool );
961 :
962 4362 : child_bank->bank_seq = FD_ATOMIC_FETCH_AND_ADD( &banks->bank_seq, 1UL );
963 4362 : child_bank->parent_idx = null_idx;
964 4362 : child_bank->child_idx = null_idx;
965 4362 : child_bank->sibling_idx = null_idx;
966 4362 : child_bank->next = null_idx;
967 4362 : child_bank->state = FD_BANK_STATE_INIT;
968 4362 : child_bank->refcnt = 0UL;
969 4362 : child_bank->is_leader = is_leader;
970 :
971 4362 : child_bank->stake_delegations_fork_id = USHORT_MAX;
972 4362 : child_bank->new_votes_fork_id = USHORT_MAX;
973 4362 : child_bank->parent_accdb_fork_id.val = USHORT_MAX;
974 :
975 : /* Then make sure that the parent bank is valid and frozen. */
976 :
977 4362 : fd_bank_t * parent_bank = fd_banks_pool_ele( bank_pool, parent_bank_idx );
978 4362 : FD_CHECK_CRIT( parent_bank->state!=FD_BANK_STATE_INACTIVE && parent_bank->state!=FD_BANK_STATE_DEAD, "invariant violation: parent bank is dead or inactive" );
979 :
980 : /* Link node->parent */
981 4362 : child_bank->parent_idx = parent_bank_idx;
982 : /* Link parent->node and sibling->node */
983 4362 : if( FD_LIKELY( parent_bank->child_idx==null_idx ) ) {
984 : /* This is the first child so set as left-most child */
985 4284 : parent_bank->child_idx = child_bank_idx;
986 :
987 4284 : } else {
988 : /* Already have children so iterate to right-most sibling. */
989 78 : fd_bank_t * curr_bank = fd_banks_pool_ele( bank_pool, parent_bank->child_idx );
990 105 : while( curr_bank->sibling_idx != null_idx ) curr_bank = fd_banks_pool_ele( bank_pool, curr_bank->sibling_idx );
991 : /* Link to right-most sibling. */
992 78 : curr_bank->sibling_idx = child_bank_idx;
993 78 : }
994 :
995 4362 : child_bank->first_fec_set_received_nanos = now;
996 4362 : child_bank->first_transaction_scheduled_nanos = 0L;
997 4362 : child_bank->last_transaction_finished_nanos = 0L;
998 :
999 4362 : return child_bank;
1000 4362 : }
1001 :
1002 : /* Mark everything in the fork tree starting at the given bank dead. */
1003 :
1004 : static ulong
1005 : fd_banks_subtree_mark_dead( fd_banks_t * banks,
1006 : fd_bank_t * bank_pool,
1007 : fd_bank_t * bank,
1008 36 : ulong * opt_idxs ) {
1009 36 : if( FD_UNLIKELY( !bank ) ) FD_LOG_CRIT(( "invariant violation: bank is NULL" ));
1010 :
1011 36 : ulong idxs_cnt = 0UL;
1012 36 : bank->state = FD_BANK_STATE_DEAD;
1013 36 : fd_banks_dead_push_head( fd_banks_get_dead_banks_deque( banks ), (fd_bank_idx_seq_t){ .idx = bank->idx, .seq = bank->bank_seq } );
1014 36 : if( opt_idxs ) opt_idxs[ idxs_cnt ] = bank->idx;
1015 36 : idxs_cnt++;
1016 :
1017 : /* Recursively mark all children as dead. */
1018 36 : ulong child_idx = bank->child_idx;
1019 45 : while( child_idx!=fd_banks_pool_idx_null( bank_pool ) ) {
1020 9 : fd_bank_t * child = fd_banks_pool_ele( bank_pool, child_idx );
1021 9 : ulong * child_idxs = opt_idxs ? opt_idxs+idxs_cnt : NULL;
1022 9 : idxs_cnt += fd_banks_subtree_mark_dead( banks, bank_pool, child, child_idxs );
1023 9 : child_idx = child->sibling_idx;
1024 9 : }
1025 :
1026 36 : return idxs_cnt;
1027 36 : }
1028 :
1029 : void
1030 : fd_banks_mark_bank_dead( fd_banks_t * banks,
1031 : ulong bank_idx,
1032 : ulong * opt_idxs,
1033 27 : ulong * opt_idxs_cnt ) {
1034 27 : fd_bank_t * bank_pool = fd_banks_get_bank_pool( banks );
1035 27 : fd_bank_t * bank = fd_banks_pool_ele( bank_pool, bank_idx );
1036 :
1037 27 : ulong idxs_cnt = fd_banks_subtree_mark_dead( banks, bank_pool, bank, opt_idxs );
1038 27 : if( opt_idxs_cnt ) *opt_idxs_cnt = idxs_cnt;
1039 27 : }
1040 :
1041 : int
1042 : fd_banks_prune_one_dead_bank( fd_banks_t * banks,
1043 54 : fd_banks_prune_cancel_info_t * cancel ) {
1044 54 : fd_bank_idx_seq_t * dead_banks_queue = fd_banks_get_dead_banks_deque( banks );
1045 54 : fd_bank_t * bank_pool = fd_banks_get_bank_pool( banks );
1046 54 : ulong null_idx = fd_banks_pool_idx_null( bank_pool );
1047 57 : while( !fd_banks_dead_empty( dead_banks_queue ) ) {
1048 36 : fd_bank_idx_seq_t * head = fd_banks_dead_peek_head( dead_banks_queue );
1049 36 : fd_bank_t * bank = fd_banks_pool_ele( bank_pool, head->idx );
1050 36 : if( bank->state==FD_BANK_STATE_INACTIVE || bank->bank_seq!=head->seq ) {
1051 3 : fd_banks_dead_pop_head( dead_banks_queue );
1052 3 : continue;
1053 33 : } else if( bank->refcnt!=0UL ) {
1054 3 : break;
1055 3 : }
1056 :
1057 30 : FD_LOG_DEBUG(( "pruning dead bank (idx=%lu)", bank->idx ));
1058 :
1059 30 : int started_replaying = bank->stake_delegations_fork_id!=USHORT_MAX;
1060 :
1061 : /* There are a few cases to consider:
1062 : 1. The to-be-pruned bank is the left-most child of the parent.
1063 : This means that the parent bank's child idx is the
1064 : to-be-pruned bank. In this case, we can simply make the
1065 : left-most sibling of the to-be-pruned bank the new left-most
1066 : child (set parent's banks child idx to the sibling). The
1067 : sibling pointer can be null if the to-be-pruned bank is an
1068 : only child of the parent.
1069 : 2. The to-be-pruned bank is some right child of the parent. In
1070 : this case, the child bank which has a sibling pointer to the
1071 : to-be-pruned bank needs to be updated to point to the sibling
1072 : of the to-be-pruned bank. The sibling can even be null if the
1073 : to-be-pruned bank is the right-most child of the parent.
1074 : */
1075 :
1076 30 : FD_TEST( bank->child_idx==null_idx );
1077 30 : fd_bank_t * parent_bank = fd_banks_pool_ele( bank_pool, bank->parent_idx );
1078 30 : if( parent_bank->child_idx==bank->idx ) {
1079 : /* Case 1: left-most child */
1080 15 : parent_bank->child_idx = bank->sibling_idx;
1081 15 : } else {
1082 : /* Case 2: some right child */
1083 15 : fd_bank_t * curr_bank = fd_banks_pool_ele( bank_pool, parent_bank->child_idx );
1084 21 : while( curr_bank->sibling_idx!=bank->idx ) curr_bank = fd_banks_pool_ele( bank_pool, curr_bank->sibling_idx );
1085 15 : curr_bank->sibling_idx = bank->sibling_idx;
1086 15 : }
1087 30 : bank->parent_idx = null_idx;
1088 30 : bank->sibling_idx = null_idx;
1089 :
1090 30 : if( FD_UNLIKELY( bank->cost_tracker_pool_idx!=null_idx ) ) {
1091 15 : fd_bank_cost_tracker_pool_idx_release( fd_banks_get_cost_tracker_pool( banks ), bank->cost_tracker_pool_idx );
1092 15 : bank->cost_tracker_pool_idx = null_idx;
1093 15 : }
1094 :
1095 30 : fd_stake_delegations_t * stake_delegations = fd_banks_get_stake_delegations( banks );
1096 30 : fd_stake_delegations_evict_fork( stake_delegations, bank->stake_delegations_fork_id );
1097 30 : bank->stake_delegations_fork_id = USHORT_MAX;
1098 :
1099 30 : fd_new_votes_t * new_votes = fd_banks_get_new_votes( banks );
1100 30 : fd_new_votes_evict_fork( new_votes, bank->new_votes_fork_id );
1101 30 : bank->new_votes_fork_id = USHORT_MAX;
1102 :
1103 30 : bank->stake_rewards_fork_id = UCHAR_MAX;
1104 :
1105 30 : if( FD_LIKELY( cancel ) ) {
1106 27 : cancel->bank_idx = bank->idx;
1107 27 : if( FD_LIKELY( started_replaying ) ) {
1108 18 : cancel->txncache_fork_id = bank->txncache_fork_id;
1109 18 : cancel->progcache_fork_id = bank->progcache_fork_id;
1110 18 : cancel->accdb_fork_id = bank->accdb_fork_id;
1111 18 : cancel->slot = bank->f.slot;
1112 18 : cancel->bank_seq = bank->bank_seq;
1113 18 : }
1114 27 : }
1115 :
1116 30 : bank->state = FD_BANK_STATE_INACTIVE;
1117 :
1118 30 : fd_banks_pool_ele_release( bank_pool, bank );
1119 30 : fd_banks_dead_pop_head( dead_banks_queue );
1120 30 : return 1+started_replaying;
1121 30 : }
1122 24 : return 0;
1123 54 : }
1124 :
1125 : void
1126 690 : fd_banks_mark_bank_frozen( fd_bank_t * bank ) {
1127 690 : fd_banks_t * banks = fd_type_pun( (uchar *)bank - bank->banks_data_offset );
1128 :
1129 690 : FD_CHECK_CRIT( bank->state==FD_BANK_STATE_REPLAYABLE, "invariant violation: bank is not replayable" );
1130 690 : bank->state = FD_BANK_STATE_FROZEN;
1131 :
1132 690 : FD_CHECK_CRIT( bank->cost_tracker_pool_idx!=ULONG_MAX, "invariant violation: cost tracker pool index is null" );
1133 690 : fd_bank_cost_tracker_pool_idx_release( fd_banks_get_cost_tracker_pool( banks ), bank->cost_tracker_pool_idx );
1134 690 : bank->cost_tracker_pool_idx = ULONG_MAX;
1135 690 : }
1136 :
1137 : static void
1138 : fd_banks_get_frontier_private( fd_bank_t * bank_pool,
1139 : ulong bank_idx,
1140 : ulong * frontier_indices_out,
1141 144 : ulong * frontier_cnt_out ) {
1142 144 : if( bank_idx==fd_banks_pool_idx_null( bank_pool ) ) return;
1143 :
1144 90 : fd_bank_t * bank = fd_banks_pool_ele( bank_pool, bank_idx );
1145 :
1146 90 : if( bank->child_idx==fd_banks_pool_idx_null( bank_pool ) ) {
1147 45 : if( bank->state!=FD_BANK_STATE_FROZEN && bank->state!=FD_BANK_STATE_DEAD && !bank->is_leader ) {
1148 36 : frontier_indices_out[*frontier_cnt_out] = bank->idx;
1149 36 : (*frontier_cnt_out)++;
1150 36 : }
1151 45 : } else {
1152 45 : fd_banks_get_frontier_private( bank_pool, bank->child_idx, frontier_indices_out, frontier_cnt_out );
1153 45 : }
1154 90 : fd_banks_get_frontier_private( bank_pool, bank->sibling_idx, frontier_indices_out, frontier_cnt_out );
1155 90 : }
1156 :
1157 : void
1158 : fd_banks_get_replay_frontier( fd_banks_t * banks,
1159 : ulong * frontier_indices_out,
1160 9 : ulong * frontier_cnt_out ) {
1161 9 : *frontier_cnt_out = 0UL;
1162 9 : fd_bank_t * bank_pool = fd_banks_get_bank_pool( banks );
1163 9 : fd_banks_get_frontier_private( bank_pool, banks->root_idx, frontier_indices_out, frontier_cnt_out );
1164 9 : }
1165 :
1166 : void
1167 : fd_banks_clear_bank( fd_banks_t * banks,
1168 : fd_bank_t * bank,
1169 3 : ulong max_vote_accounts ) {
1170 :
1171 3 : fd_memset( &bank->f, 0, sizeof(bank->f) );
1172 :
1173 3 : fd_top_votes_init( fd_type_pun( bank->top_votes_t_1_mem ) );
1174 3 : fd_top_votes_init( fd_type_pun( bank->top_votes_t_2_mem ) );
1175 :
1176 : /* We need to acquire a cost tracker element. */
1177 3 : fd_bank_cost_tracker_t * cost_tracker_pool = fd_banks_get_cost_tracker_pool( banks );
1178 3 : if( FD_UNLIKELY( bank->cost_tracker_pool_idx!=fd_bank_cost_tracker_pool_idx_null( cost_tracker_pool ) ) ) {
1179 3 : fd_bank_cost_tracker_pool_idx_release( cost_tracker_pool, bank->cost_tracker_pool_idx );
1180 3 : }
1181 3 : bank->cost_tracker_pool_idx = fd_bank_cost_tracker_pool_idx_acquire( cost_tracker_pool );
1182 :
1183 3 : if( FD_UNLIKELY( bank->new_votes_fork_id!=USHORT_MAX ) ) {
1184 3 : fd_new_votes_evict_fork( fd_banks_get_new_votes( banks ), bank->new_votes_fork_id );
1185 3 : bank->new_votes_fork_id = USHORT_MAX;
1186 3 : }
1187 :
1188 3 : fd_vote_stakes_t * vote_stakes = fd_banks_get_vote_stakes( banks );
1189 3 : ulong expected_vote_accounts = fd_ulong_min( max_vote_accounts, FD_RUNTIME_EXPECTED_VOTE_ACCOUNTS );
1190 3 : fd_vote_stakes_new( vote_stakes, max_vote_accounts, expected_vote_accounts, banks->max_fork_width, 999UL );
1191 3 : }
1192 :
1193 : void
1194 3636 : fd_banks_clear( fd_banks_t * banks ) {
1195 :
1196 3636 : fd_bank_t * bank_pool = fd_banks_get_bank_pool( banks );
1197 3636 : fd_bank_cost_tracker_t * cost_tracker_pool = fd_banks_get_cost_tracker_pool( banks );
1198 :
1199 61812 : for( ulong i=0UL; i<banks->max_total_banks; i++ ) {
1200 58176 : fd_bank_t * bank = fd_banks_pool_ele( bank_pool, i );
1201 58176 : bank->state = FD_BANK_STATE_INACTIVE;
1202 58176 : bank->cost_tracker_pool_idx = fd_bank_cost_tracker_pool_idx_null( cost_tracker_pool );
1203 58176 : bank->new_votes_fork_id = USHORT_MAX;
1204 58176 : }
1205 :
1206 3636 : fd_banks_pool_reset( bank_pool );
1207 3636 : fd_bank_cost_tracker_pool_reset( cost_tracker_pool );
1208 3636 : fd_banks_dead_remove_all( fd_banks_get_dead_banks_deque( banks ) );
1209 :
1210 3636 : fd_vote_stakes_reset( fd_banks_get_vote_stakes( banks ) );
1211 3636 : fd_new_votes_reset( fd_banks_get_new_votes( banks ) );
1212 3636 : fd_stake_delegations_reset( fd_banks_get_stake_delegations( banks ) );
1213 :
1214 3636 : fd_stake_rewards_clear( fd_banks_get_stake_rewards( banks ) );
1215 :
1216 : banks->root_idx = ULONG_MAX;
1217 3636 : banks->bank_seq = 1UL; /* start at 1 so 0 is reserved as an invalid bank_seq sentinel */
1218 3636 : }
|