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

Generated by: LCOV version 1.14