LCOV - code coverage report
Current view: top level - discof/replay - fd_replay_tile_private.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 11 0.0 %
Date: 2026-09-17 04:28:31 Functions: 0 0 -

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

Generated by: LCOV version 1.14