Line data Source code
1 : #ifndef HEADER_fd_src_discof_replay_fd_replay_tile_private_h
2 : #define HEADER_fd_src_discof_replay_fd_replay_tile_private_h
3 :
4 : #include "fd_vote_tracker.h"
5 : #include "../../disco/fd_clock_tile.h"
6 : #include "../../disco/store/fd_store.h"
7 : #include "../../disco/bundle/fd_bundle_crank.h"
8 : #include "../../disco/keyguard/fd_keyswitch.h"
9 : #include "../../disco/node_info/fd_node_info.h"
10 : #include "../../disco/wait_info/fd_wait_info.h"
11 : #include "../../discof/poh/fd_poh.h"
12 : #include "../../discof/rotor/fd_rotor_tile.h"
13 : #include "../../discof/replay/fd_sched.h"
14 : #include "../../discof/votor/fd_votor_tile.h"
15 : #include "../../flamenco/capture/fd_capture_ctx.h"
16 : #include "../../flamenco/genesis/fd_genesis_parse.h"
17 : #include "../../flamenco/leaders/fd_multi_epoch_leaders.h"
18 : #include "../../flamenco/progcache/fd_progcache.h"
19 : #include "../../flamenco/alpenglow/fd_alpenglow.h"
20 : #include "../../flamenco/runtime/fd_bank.h"
21 : #include "../../flamenco/runtime/fd_txncache.h"
22 : #include "../../flamenco/runtime/tests/fd_dump_pb.h"
23 : #include "../../disco/events/generated/fd_event_gen.h"
24 : #include "../../util/fd_hash32.h"
25 : #include "../../ballet/bmtree/fd_bmtree.h"
26 : #include <stdio.h>
27 :
28 : struct fd_replay_in_link {
29 : fd_wksp_t * mem;
30 : ulong chunk0;
31 : ulong wmark;
32 : ulong mtu;
33 : };
34 :
35 : typedef struct fd_replay_in_link fd_replay_in_link_t;
36 :
37 : struct fd_replay_out_link {
38 : ulong idx;
39 : fd_wksp_t * mem;
40 : ulong chunk0;
41 : ulong wmark;
42 : ulong chunk;
43 : };
44 :
45 : typedef struct fd_replay_out_link fd_replay_out_link_t;
46 :
47 : struct fd_block_id_ele {
48 : fd_hash_t latest_mr; /* merkle root of the latest observed FEC set. This is NEVER the
49 : block id: on completion it holds the last FEC set's merkle root,
50 : which the next block's shreds chain off (the cmr). */
51 : fd_hash_t dmr; /* block id (double merkle root). Only valid once block_id_seen is
52 : set. */
53 : ag_block_id_t block_info; /* key for the compound map */
54 : uint latest_fec_idx;
55 : int block_id_seen;
56 : ulong slot;
57 : ulong bank_seq;
58 : ulong ag_next_;
59 : uint fec_cnt;
60 : };
61 : typedef struct fd_block_id_ele fd_block_id_ele_t;
62 :
63 : struct fd_reception_stats {
64 : ulong bank_seq; /* alpenglow guard: valid iff ==bank->bank_seq */
65 : uint fec_set_idx;
66 :
67 : union {
68 : fd_rotor_fec_metrics_t rotor;
69 : } metrics;
70 : };
71 : typedef struct fd_reception_stats fd_reception_stats_t;
72 :
73 0 : #define FD_REPLAY_TXN_TIMING_SLOTS (16UL)
74 :
75 : struct fd_replay_txn_timing {
76 : long received_ns;
77 :
78 : long parsed_ticks;
79 : long sigverify_disp_ticks;
80 : long sigverify_done_ticks;
81 : long exec_disp_ticks;
82 : long exec_done_ticks;
83 : };
84 :
85 : typedef struct fd_replay_txn_timing fd_replay_txn_timing_t;
86 :
87 : struct fd_replay_txn_timing_slot {
88 : struct {
89 : ulong next;
90 : } pool;
91 :
92 : ulong cnt;
93 : };
94 :
95 : typedef struct fd_replay_txn_timing_slot fd_replay_txn_timing_slot_t;
96 :
97 : #define POOL_NAME fd_timing_slot_pool
98 0 : #define POOL_T fd_replay_txn_timing_slot_t
99 0 : #define POOL_NEXT pool.next
100 : #include "../../util/tmpl/fd_pool.c"
101 :
102 : /* fd_ag_block_id_map indexes the same fd_block_id_ele_t array by the
103 : compound {slot, block_id} key. A block that is still being received
104 : through turbing is keyed by {slot, 0}: the DMR is only known once the
105 : slot-complete FEC arrives. FECs of a block thus resolve their bank
106 : via {slot, 0} without any per-FEC re-keying; on slot complete the
107 : entry is re-keyed once to the real {slot, block_id}.
108 :
109 : For blocks that were repaired due to a votor block id event, the
110 : block id is known at the slot start. So the entry is keyed by {slot,
111 : block_id} from the start and never rekeyed. */
112 :
113 : #define MAP_NAME fd_ag_block_id_map
114 : #define MAP_ELE_T fd_block_id_ele_t
115 : #define MAP_KEY_T ag_block_id_t
116 0 : #define MAP_KEY block_info
117 0 : #define MAP_NEXT ag_next_
118 0 : #define MAP_KEY_EQ(k0,k1) (ag_block_id_eq( (k0), (k1) ))
119 0 : #define MAP_KEY_HASH(key,seed) (fd_hash( (seed), (key), sizeof(ag_block_id_t) ))
120 : #include "../../util/tmpl/fd_map_chain.c"
121 :
122 : FD_STATIC_ASSERT( FD_EVENT_BLOCK_COMPLETED_TXN_TIMING_MAX>=FD_MAX_TXN_PER_SLOT, txn_timing_ships_full_block );
123 :
124 : struct fd_replay_tile {
125 : fd_wksp_t * wksp;
126 :
127 : uint rng_seed;
128 : fd_rng_t rng[ 1 ];
129 :
130 : fd_clock_tile_t clock[1];
131 :
132 : fd_progcache_join_t progcache[1];
133 :
134 : fd_accdb_t * accdb;
135 : fd_txncache_t * txncache;
136 : fd_store_t * store;
137 : fd_store_map_t map_join[1];
138 : int store_disk_fd;
139 : fd_banks_t * banks;
140 :
141 : /* This flag is 1 If we have seen a vote signature that our node has
142 : sent out get rooted at least one time. The value is 0 otherwise.
143 : We can't become leader and pack blocks until this flag has been
144 : set. This parallels the Agave 'has_new_vote_been_rooted'. */
145 : int identity_vote_rooted;
146 : int wait_for_vote_to_start_leader; /* FD_BOOLAU_{FALSE,TRUE,AUTO} */
147 :
148 : /* vote_account_staked is 1 if stake was delegated to our vote
149 : account at boot. vote_account_inadmissible is 1 while our staked
150 : vote account fails the admission ticket filter, or passes it but
151 : has not yet been admitted at an epoch boundary. */
152 : int vote_account_staked;
153 : int vote_account_inadmissible;
154 :
155 : /* wfs_enabled is 1 if the validator is booted in
156 : wait_for_supermajority mode. In this mode replay (and, by extension,
157 : downstream consumers) is not allowed to make progress until 80% of
158 : the cluster has published their ContactInfo in Gossip with a
159 : shred version matching expected_shred_version. When this happens,
160 : wfs_complete will be set to 1. */
161 : int wfs_enabled;
162 : int wfs_complete;
163 :
164 : ulong wait_for_supermajority_at_slot;
165 : fd_hash_t expected_bank_hash;
166 : int wfs_hash_is_zero;
167 :
168 : ulong blockhash_seed;
169 : fd_reception_stats_t * reception_stats;
170 : ulong reception_stats_cnt;
171 :
172 : /* When a bank is evicted, the replayable chain of FECs delivered from rotor is broken. i.e.
173 : we lose context for a parent we needed to replay off of. When this happens,
174 : on the first FEC we see we can't replay, we need to drain everything in the dcache
175 : until there's something we can replay off of. Set this flag to enter that state (i.e. ignore FECs
176 : until there's one we can replay. )*/
177 : int drain_rotor_fecs;
178 :
179 : fd_sched_t * sched;
180 : ulong in_cnt;
181 : ulong execrp_idle_cnt;
182 :
183 : ulong vote_tracker_seed;
184 : fd_vote_tracker_t * vote_tracker;
185 :
186 : uint has_genesis_hash:1;
187 : uint has_cluster_type:1;
188 : uint has_genesis_timestamp:1;
189 : uint has_expected_genesis_timestamp:1;
190 :
191 : char genesis_path[ PATH_MAX ];
192 : fd_hash_t genesis_hash[1];
193 : fd_genesis_t * genesis;
194 : ulong cluster_type;
195 : ulong genesis_timestamp;
196 : ulong expected_genesis_timestamp;
197 :
198 : ulong hard_fork_cnt;
199 : fd_hard_fork_t hard_forks[ FD_HARD_FORKS_MAX ];
200 :
201 : ushort expected_shred_version; /* from config, 0 if unset */
202 : ushort ipecho_shred_version; /* from the entrypoints via ipecho, 0 until it answers */
203 : ushort shred_version; /* 0 until computed. the two above only cross-check
204 : it, and replay holds off executing until it is known. */
205 :
206 : ulong enable_features_cnt;
207 : char enable_features[ 16 ][ FD_BASE58_ENCODED_32_SZ ];
208 :
209 : /* A note on publishing ...
210 :
211 : The watermarks are used to publish our fork-aware structures. For
212 : example, store, banks, and txncache need to be published to release
213 : resources occupied by rooted or dead blocks. In general,
214 : publishing has the effect of pruning forks in those structures,
215 : indicating that it is ok to release the memory being occupied by
216 : the blocks on said forks. Finalization determines the latest
217 : block on the consensus rooted fork. As soon as we can,
218 : we should move the published root as close as possible to the
219 : latest consensus root, publishing/pruning everything on the fork
220 : tree along the way. That is, all the blocks that directly descend
221 : from the current published root (inclusive) to the new published
222 : root (exclusive) on the rooted fork, as well as all the minority
223 : forks that branch from said blocks.
224 :
225 : Ideally, we'd move the published root to the consensus root
226 : immediately upon receiving a new consensus root. However, that's
227 : not always safe to do. One thing we need to be careful about is
228 : making sure that there are no more users/consumers of
229 : soon-to-be-pruned blocks, lest a use-after-free occurs. This can
230 : be done by using a reference counter for each block. Any
231 : concurrent activity, such as transaction execution in the exec
232 : tiles, should retain a refcnt on the block for as
233 : long as it needs access to the shared fork-aware structures related
234 : to that block. Eventually, refcnt on a given block will drop down
235 : to 0 as the block either finishes replaying or gets marked as dead,
236 : and any other tile that has retained a refcnt on the block releases
237 : it. At that point, it becomes a candidate for pruning. The key to
238 : safe publishing then becomes figuring out how far we could advance
239 : the published root, such that every minority fork branching off of
240 : blocks in between the current published root (inclusive) and the
241 : new published root (exclusive) is safe to be pruned. This is a
242 : straightforward tree traversal, where if a block B on the rooted
243 : fork has refcnt 0, and all minority forks branching off of B also
244 : have refcnt 0, then B is safe to be pruned. We advance the
245 : published root to the farthest consecutively prunable block on the
246 : rooted fork. Note that rotor presents the replay tile with a clean
247 : view of the world where every block is chained off of a parent
248 : block. So there are no orpahned/dangling tree nodes to worry
249 : about. The world is a nice single tree as far as replay is
250 : concerned.
251 :
252 : In the following fork tree, every node is a block and the number in
253 : parentheses is the refcnt on the block. The chain marked with
254 : double slashes is the rooted fork. Suppose the published root is
255 : at block P, and consensus root is at block T. We can't publish
256 : past block P because Q has refcnt 1.
257 :
258 :
259 : P(0)
260 : / \\
261 : Q(1) A(0)
262 : / || \
263 : X(0) B(0) C(0)
264 : / || \
265 : Y(0) M(0) R(0)
266 : / || / \
267 : D(2) T(0) J(0) L(0)
268 : ||
269 : ..
270 : ..
271 : ..
272 : ||
273 : blocks we might be actively replaying
274 :
275 :
276 : When refcnt on Q drops to 0, we would be able to advance the
277 : published root to block M, because blocks P, A, and B, as well as
278 : all subtrees branching off of them, have refcnt 0, and therefore
279 : can be pruned. Block M itself cannot be pruned yet because its
280 : child block D has refcnt 2. After publishing/pruning, the fork
281 : tree would be:
282 :
283 :
284 : M(0)
285 : / ||
286 : D(2) T(0)
287 : ||
288 : ..
289 : ..
290 : ..
291 : ||
292 : blocks we might be actively replaying
293 :
294 :
295 : As a result, the shared fork-aware structures can free resources
296 : for blocks P, A, B, and all subtrees branching off of them.
297 :
298 : For the reference counting part, the replay tile is the sole entity
299 : that can update the refcnt. This ensures that all refcnt increment
300 : and decrement attempts are serialized at the replay tile, and that
301 : there are no racy resurrection of a soon-to-be-pruned block. If a
302 : refcnt increment request arrives after a block has been pruned,
303 : replay simply rejects the request.
304 :
305 : A note on the implementation of the above ...
306 :
307 : Upon receiving a new consensus root, we descend down the rooted
308 : fork from the current published root to the new consensus root. On
309 : each node/block of the rooted fork, we do a summation of the refcnt
310 : on the block and all the minority fork blocks branching from the
311 : block. If the summation is 0, the block is safe for pruning. We
312 : advance the published root to the far end of the consecutive run of
313 : 0 refcnt sums originating from the current published root. On our
314 : descent down the minority forks, we also mark any block that hasn't
315 : finished replaying as dead, so we don't waste time executing them.
316 : No more transactions shall be dispatched for execution from dead
317 : blocks.
318 :
319 : Blocks start out with a refcnt of 0. Other tiles may send a
320 : request to the replay tile for a reference on a block. The
321 : transaction dispatcher is another source of refcnt updates. On
322 : every dispatch of a transaction for block B, we increment the
323 : refcnt for B. And on every transaction finalization, we decrement
324 : the refcnt for B. This means that whenever the refcnt on a block
325 : is 0, there is no more reference on that block from the execution
326 : pipeline. While it might be tempting to simply increment the
327 : refcnt once when we start replaying a block, and decrement the
328 : refcnt once when we finish a block, this more fine-grained refcnt
329 : update strategy allows for aborting and potentially immediate
330 : pruning of blocks under interleaved block replay. Upon receiving a
331 : new consensus root, we can simply look at the refcnt on minority
332 : fork blocks, and a refcnt of 0 would imply that the block is safe
333 : for pruning, even if we haven't finished replaying it. Without the
334 : fine-grained refcnt, we would need to first stop dispatching from
335 : the aborted block, and then wait for a full drain of the execution
336 : pipeline to know for sure that there are no more in-flight
337 : transactions executing on the aborted block. Note that this will
338 : allow the refcnt on any block to transiently drop down to 0. We
339 : will not mistakenly prune an actively replaying block, aka a leaf
340 : node, that is chaining off of the rooted fork, because the
341 : consensus root is always an ancestor of the actively replaying tip.
342 : */
343 : fd_hash_t consensus_root; /* finalized and replayed */
344 : ulong consensus_root_slot; /* slot number of the above. */
345 : fd_hash_t notified_root; /* The most recent consensus root sent to sched, RPC, and resolv. */
346 : ulong notified_root_slot; /* slot number of the above. */
347 : fd_bank_t * notified_root_bank; /* bank held by sched, RPC, and resolv for the notified root. */
348 : ulong published_root_slot; /* slot number of the published root. */
349 : ulong published_root_bank_idx; /* bank index of the published root. */
350 :
351 : /* ALPENGLOW-ONLY. Watermarks marking the finalized but unreplayed
352 : slots. lo is the oldest and held until replay reaches it. hi is
353 : the newest and continuously updated. If the gap between hi and lo
354 : exceeds max_live_slots, Firedancer halts. */
355 : ag_block_id_t finalized_block_id_lo;
356 : ag_block_id_t finalized_block_id_hi;
357 :
358 : /* Randomly generated block id for the initial genesis/snapshot slot.
359 : Used as a fallback when the snapshot manifest does not contain a
360 : block_id (block_id will be populated in Agave 4.1 snapshots and
361 : will be required in Agave 4.2). */
362 :
363 : fd_hash_t initial_block_id;
364 :
365 : /* The merkle root of the snapshot slot's block.
366 : Only present in snapshots generated by Agave >=4.1. */
367 :
368 : int has_manifest_block_id;
369 : fd_hash_t manifest_block_id;
370 :
371 : /* We need to maintain a tile-local mapping of block-ids to bank index
372 : and vice versa. This translation layer is needed for conversion
373 : since votor operates on block-ids and downstream consumers of FEC
374 : sets operate on bank indices. This mapping must happen both ways:
375 : 1. votor sends us block ids and we must map them to bank indices.
376 : 2. when a block is completed, we must map the bank index to a block
377 : id to send a slot complete message. */
378 : ulong block_id_len;
379 : ulong max_live_slots;
380 : fd_block_id_ele_t * block_id_arr;
381 : ulong * dead_idxs; /* max_live_slots scratch for mark_bank_dead */
382 :
383 : fd_hash_t * fec_chain;
384 :
385 : ulong ag_block_id_map_seed;
386 : fd_ag_block_id_map_t * ag_block_id_map;
387 :
388 : /* Capture-related configs */
389 : fd_capture_ctx_t * capture_ctx;
390 : FILE * capture_file;
391 : fd_capture_link_buf_t cap_repl_out[1];
392 :
393 : /* Protobuf dumping context for debugging runtime execution and
394 : collecting seed corpora. */
395 : fd_dump_proto_ctx_t * dump_proto_ctx;
396 :
397 : /* Per-txn lifecycle timing capture. The scheduler's txn_info_pool
398 : entries are recycled the moment a txn completes, so the ticks are
399 : copied out at completion time into a leased capture slot, indexed by
400 : the txn's position in the block. A full-depth buffer per live bank
401 : would be ~9.6 GiB, but only a handful of blocks replay concurrently,
402 : so a small pool of full-depth slots is leased to banks as they start
403 : replaying. A block that cannot get a slot (more than
404 : FD_REPLAY_TXN_TIMING_SLOTS blocks replaying at once) captures
405 : nothing. Slot depth is max_txn_per_slot, so the records sit in a
406 : side array sized at footprint time. */
407 : fd_replay_txn_timing_slot_t * timing_slot_pool; /* fd_pool, FD_REPLAY_TXN_TIMING_SLOTS elements */
408 : fd_replay_txn_timing_t * timing_rec; /* [FD_REPLAY_TXN_TIMING_SLOTS*max_txn_per_slot], slot i at i*max_txn_per_slot */
409 : ulong * timing_slot_of_bank; /* [max_live_slots] bank_idx -> pool idx or idx_null */
410 :
411 : /* Whether the runtime has been booted either from snapshot loading
412 : or from genesis. */
413 : int is_booted;
414 :
415 : fd_multi_epoch_leaders_t * mleaders;
416 :
417 : ulong max_txn_per_slot;
418 : ulong max_shreds_per_block;
419 :
420 : /* When we transition to becoming leader, we can only unbecome leader
421 : if we have received a block id from the FEC reassembler, and a
422 : message from PoH that the leader slot has ended. After both of
423 : these conditions are met, then we are free to unbecome leader.
424 : Exception: a slot aborted by a reset unbecomes leader on the PoH
425 : slot-ended message alone; no block id will ever arrive for it. */
426 : uint is_leader : 1;
427 : uint supports_leader : 1;
428 : int recv_poh;
429 :
430 : ulong leader_execution_fees; /* ALPENGLOW-ONLY */
431 : ulong leader_priority_fees; /* ALPENGLOW-ONLY */
432 : ulong leader_tips; /* ALPENGLOW-ONLY */
433 : fd_block_footer_t leader_footer[ 1 ];
434 :
435 : fd_votor_certed_t votor_final[ 1 ]; /* ALPENGLOW-ONLY: highest finalization, fast over slow at the same slot */
436 : fd_votor_leader_t votor_leader[ 1 ]; /* ALPENGLOW-ONLY: ParentReady trigger behind next_leader_slot */
437 : ulong votor_parent_ready_slot; /* ALPENGLOW-ONLY: highest window start certs made ParentReady */
438 : long leader_window_start_ns; /* ALPENGLOW-ONLY: ParentReady time of the window we are leading */
439 : fd_votor_reward_t votor_reward[ FD_NUM_SLOTS_FOR_REWARD+AG_SLOTS_PER_WINDOW+1UL ];
440 :
441 : ulong next_leader_slot;
442 : long next_leader_tickcount;
443 :
444 :
445 : ulong next_leader_query_start;
446 : ulong next_leader_query_slot;
447 :
448 : double tick_per_ns;
449 : ulong highwater_leader_slot;
450 : ulong reset_slot;
451 : ulong epoch_end_slot;
452 : ulong slots_per_epoch;
453 : ulong ns_per_slot;
454 :
455 : /* Caught up to the cluster: replay has completed a slot within a few
456 : slots of the cluster tip. Rotor tracks the tip and ships it on
457 : each delivered FEC, because rotor delivers only
458 : replayable FECs in order and their slots track replay itself. */
459 : int caught_up;
460 : ulong catch_up_max_fec_slot;
461 : ulong catch_up_tip_advance_cnt;
462 : long boot_timestamp_nanos;
463 :
464 : fd_hash_t reset_dmr; /* double merkle root of the reset block */
465 : long reset_timestamp_nanos;
466 : fd_bank_t * leader_bank;
467 :
468 : struct {
469 : ulong slot;
470 : long became_leader_nanos;
471 : long leader_slot_start_nanos;
472 : long first_fec_returned_nanos;
473 : ulong microblock_count;
474 : ulong pack_block_cost;
475 : ulong pack_vote_cost;
476 : ulong pack_data_bytes;
477 : ulong bundle_txn_count;
478 : int pack_end_reason;
479 : long pack_start_nanos;
480 : long pack_end_nanos;
481 : ulong timing_table_idx;
482 : } leader_stats;
483 :
484 : fd_pubkey_t identity_pubkey[1];
485 : ulong identity_idx;
486 : int identity_dirty;
487 :
488 : int has_vote_account;
489 : fd_pubkey_t vote_account[ 1 ];
490 :
491 : fd_node_info_box_t * node_info; /* shared */
492 : fd_wait_info_box_t * wait_info; /* shared */
493 :
494 : /* Delinquency, published through wait_info only; not a metric. */
495 : int delinquent_known;
496 : ulong delinquent_sample_slot;
497 : ulong delinquent_stake_lamports;
498 : ulong cluster_active_stake_lamports;
499 : /* Alpenglow-only delinquency tracking, from the block footer reward
500 : certs since last_vote_slot stalls without vote transactions.
501 : Indexed by alpenglow rank, which is epoch-scoped. */
502 : ulong ag_last_voted[ AG_VAT_MAX ];
503 : ulong ag_last_voted_epoch; /* ULONG_MAX before the first reward cert */
504 : ulong ag_last_settled; /* highest settled slot observed */
505 : ulong ag_stamp_since; /* first slot stamped into an empty table */
506 :
507 : /* Signing payload of each exec tile's footer cert verify task */
508 : uchar cert_payload [ FD_SCHED_MAX_EXEC_TILE_CNT ][ FD_ALPENGLOW_CERT_PAYLOAD_MAX ];
509 : ulong cert_payload_sz[ FD_SCHED_MAX_EXEC_TILE_CNT ];
510 :
511 : fd_keyswitch_t * keyswitch;
512 : int halt_replay;
513 :
514 : ulong resolv_tile_cnt;
515 :
516 : int in_kind[ 128 ];
517 : fd_replay_in_link_t in[ 128 ];
518 :
519 : ulong exec_cnt;
520 : fd_replay_out_link_t exec_out[ FD_SCHED_MAX_EXEC_TILE_CNT ];
521 :
522 : fd_replay_out_link_t replay_out[1];
523 : fd_replay_out_link_t slot_out[1];
524 : fd_replay_out_link_t rotor_out[1]; /* REPLAY_SIG_MISSING_FEC */
525 : ulong const * slot_out_seq;
526 : fd_replay_out_link_t snapmk_out[1];
527 : ulong admin_out_idx;
528 :
529 : fd_replay_out_link_t epoch_out[1];
530 :
531 : /* The rpc tile needs to occasionally own a reference to a live bank.
532 : Replay needs to know if the rpc as a consumer is enabled so it can
533 : increment the bank's refcnt before publishing bank_idx. */
534 : int rpc_enabled;
535 :
536 : /* For dumping blocks to protobuf. For backtest only. */
537 : fd_block_dump_ctx_t * block_dump_ctx;
538 :
539 : /* We need a few pieces of information to compute the right addresses
540 : for bundle crank information that we need to send to pack. */
541 : struct {
542 : int enabled;
543 : fd_pubkey_t vote_account;
544 : fd_bundle_crank_gen_t gen[1];
545 : } bundle;
546 :
547 : /* snapshot producer */
548 : struct {
549 : uint supported:1;
550 : uint active:1;
551 : uint incremental:1;
552 : ulong bank_idx;
553 : ulong scheduled_at_slot;
554 : ulong full_interval_blocks;
555 : ulong next_full_block_height;
556 : ulong incremental_interval_blocks;
557 : ulong next_incremental_block_height;
558 : ulong base_slot;
559 : ulong snap_finished_full;
560 : ulong snap_finished_incr;
561 : ulong snap_produced_incr_cnt;
562 : fd_epoch_credits_view_t epoch_credits_view[1];
563 : } snapmk;
564 :
565 : struct {
566 : fd_histf_t store_query_work[1];
567 : ulong store_query_cnt;
568 : ulong store_query_missing_cnt;
569 :
570 : ulong slots_total;
571 : ulong transactions_total;
572 :
573 : ulong reasm_latest_slot;
574 : ulong reasm_latest_fec_idx;
575 :
576 : ulong sched_full;
577 : ulong leader_bid_wait;
578 : ulong banks_full;
579 : ulong parent_unavailable;
580 : ulong leader_slot_already_produced;
581 : ulong leader_window_superseded;
582 : ulong fec_rooted_past;
583 : ulong storage_root_behind;
584 :
585 : ulong voted_slot; /* monotone, ULONG_MAX if none */
586 : } metrics;
587 :
588 : uchar __attribute__((aligned(FD_MULTI_EPOCH_LEADERS_ALIGN))) mleaders_mem[ FD_MULTI_EPOCH_LEADERS_FOOTPRINT ];
589 :
590 : ulong runtime_stack_seed;
591 : fd_runtime_stack_t * runtime_stack;
592 :
593 : fd_footer_cache_t * footer_cache;
594 :
595 : fd_event_block_completed_t * block_completed_event;
596 :
597 : fd_leader_txn_timing_table_t const * leader_txn_timing;
598 :
599 : /* If non-zero, emit the runtime events during replay. */
600 : int report_runtime_diffs;
601 : };
602 :
603 : typedef struct fd_replay_tile fd_replay_tile_t;
604 :
605 : #endif /* HEADER_fd_src_discof_replay_fd_replay_tile_private_h */
|