LCOV - code coverage report
Current view: top level - discof/replay - fd_sched.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 50 0.0 %
Date: 2026-10-22 18:10:43 Functions: 0 0 -

          Line data    Source code
       1             : #ifndef HEADER_fd_src_discof_replay_fd_sched_h
       2             : #define HEADER_fd_src_discof_replay_fd_sched_h
       3             : 
       4             : #include "fd_rdisp.h"
       5             : #include "../../flamenco/alpenglow/fd_block_marker.h"
       6             : #include "../../disco/fd_txn_p.h"
       7             : #include "../../disco/store/fd_store.h" /* for fd_store_fec_t */
       8             : #include "../../flamenco/accdb/fd_accdb.h"
       9             : #include "../../disco/fd_clock_tile.h"
      10             : 
      11             : /* Max microblocks (including ticks) that fit in a block's shreds;
      12             :    scaled with max_shreds_per_block at runtime. */
      13           0 : #define FD_SCHED_MAX_MBLK_PER_SLOT (FD_SHRED_DATA_PAYLOAD_MAX_PER_SLOT/sizeof(fd_microblock_hdr_t))
      14             : 
      15             : /* Most exec tiles a scheduler can dispatch to. */
      16           0 : #define FD_SCHED_MAX_EXEC_TILE_CNT (64UL)
      17             : 
      18             : /* Most banks with transactions in flight at once, one per staging
      19             :    lane. */
      20           0 : #define FD_SCHED_MAX_STAGING_LANES_LOG (2)
      21           0 : #define FD_SCHED_MAX_STAGING_LANES     (1UL<<FD_SCHED_MAX_STAGING_LANES_LOG)
      22             : 
      23             : /* fd_sched wraps all the smarts and mechanical chores around scheduling
      24             :    transactions for replay execution.  It is built on top of the
      25             :    dispatcher fd_rdisp.  The dispatcher is responsible for high
      26             :    performance lane-based scheduling of transactions.  On top of that,
      27             :    we add fork-aware management of lanes, and policies regarding which
      28             :    lanes to prioritize for execution.
      29             : 
      30             :    Conceptually, transactions in a block form a DAG.  We would like to
      31             :    make our way through a block with a sufficient degree of parallelism,
      32             :    such that the execution time of the critical path of the DAG is the
      33             :    limiting factor.  The dispatcher does a good job of emerging the
      34             :    critical path of the DAG on the fly.  Blocks are tracked by the
      35             :    dispatcher either as a block staged on a lane, or as an unstaged
      36             :    block.  When a block is staged, it will enjoy the most intelligent
      37             :    online scheduling that the dispatcher has to offer.  Lanes have to
      38             :    consist of linear chains of blocks down a fork.  So to map a fork
      39             :    tree to lanes, we will need multiple lanes.  Ideally, every branch in
      40             :    the fork tree sits on some lane.  However, memory footprint limits us
      41             :    to a few number of lanes.
      42             : 
      43             :    This module implements a state machine for ensuring that blocks enter
      44             :    into and exit out of lanes in an orderly fashion.  The public APIs of
      45             :    this module are invoked to drive state transitions on a small number
      46             :    of events, such as new transactions arriving, or transactions
      47             :    completing, or a block being aborted/abandoned.  We also implement
      48             :    policies for deciding which blocks get staged onto lanes, or evicted
      49             :    from lanes, as well as which lanes to prioritize for execution.
      50             : 
      51             : 
      52             :    The general order in which calls happen under the normal case is:
      53             : 
      54             :    fd_sched_fec_ingest()* ... fd_sched_txn_next_ready()* ... fd_sched_txn_done()* ...
      55             :    more ingest, more ready, more done ...
      56             :    ...
      57             :    fd_sched_txn_next_ready() indicates that the last transaction in the block is being scheduled
      58             :    fd_sched_txn_done()*
      59             :    fd_sched_block_is_done()
      60             :    end-of-block processing in caller
      61             :    fd_sched_txn_next_ready() starts returning transactions from the next block
      62             :    more ingest, more ready, more done ...
      63             :    ... */
      64             : 
      65           0 : #define FD_SCHED_MIN_DEPTH 478
      66             : #define FD_SCHED_MAX_DEPTH FD_RDISP_MAX_DEPTH
      67             : 
      68             : struct fd_sched;
      69             : typedef struct fd_sched fd_sched_t;
      70             : 
      71             : struct fd_sched_alut_ctx {
      72             :   fd_accdb_t *       accdb;
      73             :   fd_accdb_fork_id_t fork_id;
      74             :   ulong              els; /* Effective lookup slot. */
      75             : };
      76             : typedef struct fd_sched_alut_ctx fd_sched_alut_ctx_t;
      77             : 
      78             : struct fd_sched_fec {
      79             :   ulong            bank_idx;            /* Index of the block.  Assumed to be in [0, block_cnt_max).  Caller
      80             :                                            is responsible for ensuring that bank idx is in bounds and unique
      81             :                                            across equivocated blocks. */
      82             :   ulong            parent_bank_idx;     /* Index of the parent block.  Assumed to be in [0, block_cnt_max).
      83             :                                            Caller is responsible for ensuring that parent bank idx is in
      84             :                                            bounds and unique across equivocated blocks. */
      85             :   ulong            slot;                /* Slot number of the block. */
      86             :   ulong            parent_slot;         /* Slot number of the parent block. */
      87             :   fd_store_fec_t * fec;                 /* FEC set metadata. */
      88             :   uchar          * data;                /* Resolved laddr of the FEC set data buffer. */
      89             :   uint             shred_cnt;           /* Number of shreds in the FEC set. */
      90             :   uint             is_last_in_batch:1;  /* Set if this is the last FEC set in the batch; relevant because the
      91             :                                            parser should ignore trailing bytes at the end of a batch. */
      92             :   uint             is_last_in_block:1;  /* Set if this is the last FEC set in the block. */
      93             :   uint             is_first_in_block:1; /* Set if this is the first FEC set in the block.  Bank should increment refcnt for sched if such a FEC set has been ingested by sched. */
      94             :   long             completed_ns;        /* Network arrival (wallclock ns) of the shred that completed this FEC set; 0 if unavailable. */
      95             : 
      96             :   fd_sched_alut_ctx_t alut_ctx[ 1 ];
      97             : };
      98             : typedef struct fd_sched_fec fd_sched_fec_t;
      99             : 
     100             : /* The state of a transaction.  Non mutually exclusive. */
     101           0 : #define FD_SCHED_TXN_EXEC_DONE      (0x0001UL)
     102           0 : #define FD_SCHED_TXN_SIGVERIFY_DONE (0x0002UL)
     103           0 : #define FD_SCHED_TXN_IS_COMMITTABLE (0x0004UL)
     104           0 : #define FD_SCHED_TXN_IS_FEES_ONLY   (0x0008UL)
     105           0 : #define FD_SCHED_TXN_IS_NOOP        (0x0010UL)
     106             : #define FD_SCHED_TXN_REPLAY_DONE    (FD_SCHED_TXN_EXEC_DONE|FD_SCHED_TXN_SIGVERIFY_DONE)
     107             : 
     108             : struct fd_sched_txn_info {
     109             :    ulong flags;
     110             :    int   txn_err;
     111             :    uint  next_idx;
     112             :    long  received_ns;
     113             :    int   is_simple_vote;
     114             : 
     115             :    /* LONG_MAX if stage was not reached */
     116             :    long  tick_parsed;
     117             :    long  tick_sigverify_disp;
     118             :    long  tick_sigverify_done;
     119             :    long  tick_exec_disp;
     120             :    long  tick_exec_done;
     121             :    long  tick_load_start;
     122             :    long  tick_check_start;
     123             :    long  tick_exec_start;
     124             :    long  tick_commit_start;
     125             :    long  tick_commit_end;
     126             : 
     127             :    ulong slot;
     128             :    ulong bank_seq;
     129             :    ulong index_in_slot; /* 0-indexed position of this transaction within its block. */
     130             :    ulong exec_tile_idx;
     131             :    ulong sigverify_exec_tile_idx;
     132             :    uint  compute_units_consumed; /* possibly zero if is_committable is zero */
     133             :    ulong max_compute_units;
     134             :    ulong transaction_fee;
     135             :    ulong priority_fee;
     136             :    ulong tips;
     137             : };
     138             : typedef struct fd_sched_txn_info fd_sched_txn_info_t;
     139             : 
     140             : /* The scheduler may return one of the following types of tasks for the
     141             :    replay tile.
     142             : 
     143             :    e - passed down to exec tiles.
     144             :    i - replay completes the task immediately.
     145             :    q - replay may either do it immediately or queue the task up. */
     146           0 : #define FD_SCHED_TT_NULL          (0UL)
     147           0 : #define FD_SCHED_TT_BLOCK_START   (1UL) /* (i) Start-of-block processing. */
     148           0 : #define FD_SCHED_TT_BLOCK_END     (2UL) /* (q) End-of-block processing. */
     149           0 : #define FD_SCHED_TT_TXN_EXEC      (3UL) /* (e) Transaction execution. */
     150           0 : #define FD_SCHED_TT_TXN_SIGVERIFY (4UL) /* (e) Transaction sigverify. */
     151             : #define FD_SCHED_TT_LTHASH        (5UL) /* (e) Account lthash. */
     152           0 : #define FD_SCHED_TT_POH_HASH      (6UL) /* (e) PoH hashing. */
     153           0 : #define FD_SCHED_TT_MARK_DEAD     (7UL) /* (i) Mark the block dead. */
     154           0 : #define FD_SCHED_TT_CERT_VERIFY   (8UL) /* (e) Footer cert verify. */
     155             : 
     156             : struct fd_sched_block_start {
     157             :   ulong bank_idx;        /* Same as in fd_sched_fec_t. */
     158             :   ulong parent_bank_idx; /* Same as in fd_sched_fec_t. */
     159             :   ulong slot;            /* Slot number of the block. */
     160             : };
     161             : typedef struct fd_sched_block_start fd_sched_block_start_t;
     162             : 
     163             : struct fd_sched_block_end {
     164             :   ulong bank_idx;
     165             : };
     166             : typedef struct fd_sched_block_end fd_sched_block_end_t;
     167             : 
     168             : struct fd_sched_txn_exec {
     169             :   ulong bank_idx;
     170             :   ulong slot;
     171             :   ulong txn_idx;
     172             :   ulong exec_idx;
     173             : };
     174             : typedef struct fd_sched_txn_exec fd_sched_txn_exec_t;
     175             : 
     176             : struct fd_sched_txn_sigverify {
     177             :   ulong bank_idx;
     178             :   ulong txn_idx;
     179             :   ulong exec_idx;
     180             : };
     181             : typedef struct fd_sched_txn_sigverify fd_sched_txn_sigverify_t;
     182             : 
     183             : #define FD_SCHED_POH_PARA 16
     184             : struct fd_sched_poh_hash {
     185             :   ulong     bank_idx;
     186             :   ulong     exec_idx;
     187             :   ulong     cnt;     /* In [1,FD_SCHED_POH_PARA] */
     188             :   ulong     hashcnt; /* Same for every element of the batch */
     189             :   ulong     mblk_idx[ FD_SCHED_POH_PARA ];
     190             :   fd_hash_t hash    [ FD_SCHED_POH_PARA ];
     191             : };
     192             : typedef struct fd_sched_poh_hash fd_sched_poh_hash_t;
     193             : 
     194             : struct fd_sched_mark_dead {
     195             :   ulong     bank_idx;
     196             : };
     197             : typedef struct fd_sched_mark_dead fd_sched_mark_dead_t;
     198             : 
     199             : struct fd_sched_task {
     200             :   ulong task_type; /* Set to one of the task types defined above. */
     201             :   union {
     202             :     fd_sched_block_start_t   block_start[ 1 ];
     203             :     fd_sched_block_end_t     block_end[ 1 ];
     204             :     fd_sched_txn_exec_t      txn_exec[ 1 ];
     205             :     fd_sched_txn_sigverify_t txn_sigverify[ 1 ];
     206             :     fd_sched_poh_hash_t      poh_hash[ 1 ];
     207             :     fd_sched_mark_dead_t     mark_dead[ 1 ];
     208             :   };
     209             : };
     210             : typedef struct fd_sched_task fd_sched_task_t;
     211             : 
     212             : 
     213           0 : #define FD_SCHED_DEAD_REASON_NONE                        (0)  /* Block was not ruled invalid by the scheduler.  The replay tile may still rule it invalid, unbeknownst to the scheduler. */
     214           0 : #define FD_SCHED_DEAD_REASON_UNPARSEABLE_CONTENT         (1)  /* Bytes at the head of the stream failed to parse out as any structure (transaction, microblock header, or count) within the largest size a valid block allows: malformed content. */
     215           0 : #define FD_SCHED_DEAD_REASON_SHORT_BLOCK                 (2)  /* Block bytes ended short of the microblocks and transactions declared. */
     216           0 : #define FD_SCHED_DEAD_REASON_TOO_MANY_TXNS               (3)  /* More transactions than a valid block can hold. */
     217           0 : #define FD_SCHED_DEAD_REASON_TOO_MANY_MICROBLOCKS        (4)  /* More microblocks than a valid block can hold. */
     218           0 : #define FD_SCHED_DEAD_REASON_DUPLICATE_ACCOUNT           (5)  /* Transaction referenced the same account more than once. */
     219           0 : #define FD_SCHED_DEAD_REASON_TRAILING_ENTRY              (6)  /* Block did not end on a tick. */
     220           0 : #define FD_SCHED_DEAD_REASON_TOO_MANY_TICKS              (7)  /* More ticks than required. */
     221           0 : #define FD_SCHED_DEAD_REASON_TOO_FEW_TICKS               (8)  /* Fewer ticks than required. */
     222           0 : #define FD_SCHED_DEAD_REASON_ZERO_MICROBLOCKS            (9)  /* A batch header declared zero microblocks. */
     223           0 : #define FD_SCHED_DEAD_REASON_WRONG_HASHES_PER_TICK       (10) /* Tick hash count did not advance the expected hashes per tick. */
     224           0 : #define FD_SCHED_DEAD_REASON_INCONSISTENT_TICK_HASHES    (11) /* Tick hash count differs from the block's preceding ticks, detected at FEC ingest. */
     225           0 : #define FD_SCHED_DEAD_REASON_TICK_HASHES_OVERFLOW        (12) /* More hashes since the last tick than hashes per tick allows. */
     226           0 : #define FD_SCHED_DEAD_REASON_TICK_HASHES_OVERFLOW_INGEST (13) /* Tick header declared more hashes than can fit before the next tick, detected at FEC ingest. */
     227           0 : #define FD_SCHED_DEAD_REASON_ZERO_HASH_TICK              (14) /* Tick advanced zero hashes; PoH params were unknown when the tick parsed. */
     228           0 : #define FD_SCHED_DEAD_REASON_ZERO_HASH_TICK_INGEST       (15) /* Tick advanced zero hashes, detected at FEC ingest. */
     229           0 : #define FD_SCHED_DEAD_REASON_TICK_HASH_MISMATCH          (16) /* PoH hash of a tick did not verify. */
     230           0 : #define FD_SCHED_DEAD_REASON_ENTRY_HASH_MISMATCH         (17) /* PoH hash of a transaction entry did not verify, detected when the entry's PoH hashing task completed. */
     231           0 : #define FD_SCHED_DEAD_REASON_ENTRY_HASH_MISMATCH_INGEST  (18) /* PoH hash of a transaction entry did not verify, detected at FEC ingest when a later FEC set completed the entry's transactions. */
     232           0 : #define FD_SCHED_DEAD_REASON_DEAD_ANCESTOR               (19) /* The block went down with its lineage.  Whether the lineage was discarded or ruled invalid is distinguished by fd_sched_block_is_discarded. */
     233           0 : #define FD_SCHED_DEAD_REASON_BAD_BLOCK_MARKER            (20) /* An Alpenglow block marker (header, footer, genesis certificate or update parent) failed to parse or had an unknown kind. */
     234           0 : #define FD_SCHED_DEAD_REASON_ALPENGLOW_HASH_CNT          (21) /* An Alpenglow block had an entry whose hash count was not exactly one, detected at FEC ingest. */
     235             : /* Alpenglow block structure, mirroring agave's BlockComponentProcessor:
     236             :    header | [genesis cert] | entries* | footer | alpentick */
     237           0 : #define FD_SCHED_DEAD_REASON_MISSING_PARENT_MARKER       (22) /* An Alpenglow block carried an entry batch or footer before any block header. */
     238           0 : #define FD_SCHED_DEAD_REASON_MULTIPLE_BLOCK_HEADERS      (23) /* An Alpenglow block carried more than one block header. */
     239           0 : #define FD_SCHED_DEAD_REASON_GENESIS_CERT_OUT_OF_ORDER   (24) /* An Alpenglow genesis certificate marker did not immediately follow the block header. */
     240           0 : #define FD_SCHED_DEAD_REASON_MULTIPLE_BLOCK_FOOTERS      (25) /* An Alpenglow block carried more than one block footer. */
     241           0 : #define FD_SCHED_DEAD_REASON_ENTRY_AFTER_BLOCK_FOOTER    (26) /* An Alpenglow block carried an entry batch other than the alpentick after its footer. */
     242           0 : #define FD_SCHED_DEAD_REASON_INVALID_ALPENTICK_POSITION  (27) /* An Alpenglow block ended without the alpentick directly after its footer. */
     243           0 : #define FD_SCHED_DEAD_REASON_MISSING_BLOCK_FOOTER        (28) /* An Alpenglow block ended without a block footer. */
     244           0 : #define FD_SCHED_DEAD_REASON_SPURIOUS_UPDATE_PARENT      (29) /* An Alpenglow block carried an UpdateParent marker where none is valid: before the header or after the footer. */
     245             : /* Cause to pass to fd_sched_block_abandon().  A block is considered
     246             :    invalid when it violates the protocol, so validity is a function of
     247             :    the block's content.  A block may be discarded (temporarily) because
     248             :    the validator is under resource pressure.  A block may be discarded
     249             :    (permanently) if consensus converged on an alternative fork, which is
     250             :    done implicitly in fd_sched_root_notify() for the minority forks it
     251             :    abandons. */
     252           0 : #define FD_SCHED_ABANDON_DISCARDED (0)
     253           0 : #define FD_SCHED_ABANDON_INVALID   (1)
     254             : 
     255             : struct __attribute__((packed)) fd_microblock_hdr {
     256             :   /* Number of PoH hashes between this and last microblock */
     257             :   /* 0x00 */ ulong hash_cnt;
     258             : 
     259             :   /* PoH state after evaluating this microblock (including all
     260             :      appends and mixin). The input to the poh calculation of the first
     261             :      microblock is the last hash of the parent block, otherwise it is the
     262             :      hash of the previous microblock. */
     263             :   /* 0x08 */ uchar hash[32];
     264             : 
     265             :   /* Number of transactions in this microblock */
     266             :   /* 0x28 */ ulong txn_cnt;
     267             : };
     268             : typedef struct fd_microblock_hdr fd_microblock_hdr_t;
     269             : 
     270             : FD_PROTOTYPES_BEGIN
     271             : 
     272             : /* fd_sched_{align,footprint} return the required alignment and
     273             :    footprint in bytes for a region of memory to be used as a scheduler.
     274             :    footprint silently returns 0 if params are invalid (thus convenient
     275             :    to validate params).
     276             : 
     277             :    depth controls the reorder buffer transaction count (~1 million
     278             :    recommended for live replay, ~10k recommended for async replay).
     279             :    block_cnt_max is the maximum number of blocks that will be tracked by
     280             :    the scheduler.  max_shreds_per_block bounds the data shreds a block
     281             :    may hold (the shred tile enforces the same limit upstream, sched
     282             :    asserts it); a block declaring more than max_txn_per_slot
     283             :    transactions is ruled invalid.  FD_SHRED_BLK_MAX and
     284             :    FD_MAX_TXN_PER_SLOT in production. */
     285             : 
     286             : ulong
     287             : fd_sched_align( void );
     288             : 
     289             : ulong
     290             : fd_sched_footprint( ulong depth,                /* in [FD_SCHED_MIN_DEPTH,FD_SCHED_MAX_DEPTH] */
     291             :                     ulong block_cnt_max,        /* >= 1 */
     292             :                     ulong max_shreds_per_block, /* in [1,UINT_MAX] */
     293             :                     ulong max_txn_per_slot );   /* in [1,UINT_MAX] */
     294             : 
     295             : /* fd_sched_new creates a sched object backed by the given memory region
     296             :    (conforming to align() and footprint()).  Returns NULL if any
     297             :    parameter is invalid. */
     298             : 
     299             : void *
     300             : fd_sched_new( void *     mem,
     301             :               fd_rng_t * rng,
     302             :               ulong      depth,
     303             :               ulong      block_cnt_max,
     304             :               ulong      max_shreds_per_block,
     305             :               ulong      max_txn_per_slot,
     306             :               ulong      exec_cnt,
     307             :               int        is_alpenglow );
     308             : 
     309             : fd_sched_t *
     310             : fd_sched_join( void * mem );
     311             : 
     312             : /* Add the data in the FEC set to the scheduler.  If is_last_fec is 1,
     313             :    then this is the last FEC set in the block.  Transactions may span
     314             :    FEC set boundaries.  The scheduler is responsible for incrementally
     315             :    parsing transactions from concatenated FEC set data.  Assumes that
     316             :    FEC sets are delivered in replay order.  That is, forks form a
     317             :    partial ordering over FEC sets: in-order per fork, but arbitrary
     318             :    ordering across forks.  The fork tree is implied by the stream of
     319             :    parent-child relationships delivered in FEC sets.  Also assumes that
     320             :    there is enough space in the scheduler to ingest the FEC set.  The
     321             :    caller should generally call fd_sched_fec_can_ingest() first.
     322             : 
     323             :    Returns 1 on success, 0 if the block is bad and should be marked
     324             :    dead. */
     325             : FD_WARN_UNUSED int
     326             : fd_sched_fec_ingest( fd_sched_t * sched, fd_sched_fec_t * fec );
     327             : 
     328             : /* Check if there is enough space in the scheduler to ingest the data in
     329             :    the FEC set.  Returns 1 if there is, 0 otherwise.  This is a cheap
     330             :    and conservative check. */
     331             : int
     332             : fd_sched_fec_can_ingest( fd_sched_t * sched, fd_sched_fec_t * fec );
     333             : 
     334             : /* Returns the number of worst-case FEC sets sched can ingest. This is a
     335             :    cheap and conservative check. */
     336             : ulong
     337             : fd_sched_can_ingest_cnt( fd_sched_t * sched );
     338             : 
     339             : /* Returns 1 if sched is drained, 0 otherwise.  A drained scheduler will
     340             :    not return more work.  Otherwise, next_ready will return more work,
     341             :    so long as there are exec tiles available. */
     342             : int
     343             : fd_sched_is_drained( fd_sched_t * sched );
     344             : 
     345             : /* Returns 1 if the active block has not been started yet, i.e. the
     346             :    next task next_ready returns for it is a BLOCK_START, 0 otherwise. */
     347             : int
     348             : fd_sched_block_start_pending( fd_sched_t * sched );
     349             : 
     350             : /* fd_sched_cert_dispatch claims up to cnt idle exec tiles for footer
     351             :    cert verify tasks of the active block, whose BLOCK_END is signaled
     352             :    and not done yet.  Returns the claimed tiles (bit i for tile i).
     353             :    Each completes with fd_sched_task_done( FD_SCHED_TT_CERT_VERIFY,
     354             :    ULONG_MAX, i, NULL ), and the block is not done until all have. */
     355             : 
     356             : ulong
     357             : fd_sched_cert_dispatch( fd_sched_t * sched,
     358             :                         ulong        bank_idx,
     359             :                         ulong        cnt );
     360             : 
     361             : /* Obtain a transaction eligible for execution.  This implies that all
     362             :    prior transactions with w-r or w-w conflicts have completed.
     363             :    Information regarding the scheduled transaction is written to the out
     364             :    pointer.  Returns 1 on success, 0 on failure.  Failures are generally
     365             :    transient and non-fatal, and are simply an indication that no
     366             :    transaction is ready for execution yet.  When in-flight transactions
     367             :    retire or when more FEC sets are ingested, more transactions may
     368             :    become ready for execution.
     369             : 
     370             :    Transactions on the same fork will be returned in a way that
     371             :    maintains the serial fiction.  That is, reordering can happen, but
     372             :    only within the constraint that transactions appear to be ready in
     373             :    the order in which they occur in the block.  Transactions from
     374             :    different forks may interleave, and the caller should be prepared to
     375             :    switch execution context in response to interleavings.  The scheduler
     376             :    will barrier on block boundaries, in the sense that transactions from
     377             :    a subsequent block will not be returned for execution until all
     378             :    transactions from the previous block have completed.  This gives the
     379             :    caller a chance to perform end-of-block processing before
     380             :    transactions from a subsequent block start executing.  In general,
     381             :    the caller should check if the last transaction in the current block
     382             :    is done, and if so, do end-of-block processing before calling this
     383             :    function to start the next block.
     384             : 
     385             :    In addition to returning transactions for execution, this function
     386             :    may also return a sigverify task.  Sigverify can be completed
     387             :    asynchronously outside the critical path of transaction execution, as
     388             :    long as every transaction in a block passes sigverify before we
     389             :    commit the block.  The scheduler prioritizes actual execution of
     390             :    transactions over sigverify, and in general sigverify tasks are only
     391             :    returned when no real transaction can be dispatched.  In other words,
     392             :    the scheduler tries to exploit idle cycles in the exec tiles during
     393             :    times of low parallelism critical path progression.
     394             : 
     395             :    This function may also return a PoH hashing task.  These tasks are
     396             :    lower priority than transaction execution, but higher priority than
     397             :    sigverify.  This is because sigverify tasks are generally bite-sized,
     398             :    whereas PoH hashing can be longer, so we would like to get started on
     399             :    hashing sooner rather than later. */
     400             : ulong
     401             : fd_sched_task_next_ready( fd_sched_t * sched, fd_sched_task_t * out );
     402             : 
     403             : /* Mark a task as complete.  For transaction execution, this means that
     404             :    the effects of the execution are now visible on any core that could
     405             :    execute a subsequent transaction.  Returns FD_SCHED_DEAD_REASON_NONE
     406             :    (0) on success.  If, given the result of the task, the block turns
     407             :    out to be bad, returns the nonzero FD_SCHED_DEAD_REASON_* it was
     408             :    ruled bad for.  Only PoH tasks can rule a block bad, and not only
     409             :    for a PoH hash mismatch: eager tick verification also runs on this
     410             :    path.
     411             : 
     412             :    If a block has been abandoned or marked dead for any reason, it'll be
     413             :    pruned the moment in-flight task count hits 0 due to the last task
     414             :    completing.  Then, in the immediate ensuing stem run loop,
     415             :    sched_pruned_next() will return the index for the corresponding bank
     416             :    so the refcnt can be decremented for sched.
     417             : 
     418             :    The transaction at the given index may be freed upon return from this
     419             :    function.  Nonetheless, as long as there is no intervening FEC
     420             :    ingestion, it would still be safe to query the transaction using
     421             :    get_txn(). */
     422             : int
     423             : fd_sched_task_done( fd_sched_t * sched, ulong task_type, ulong txn_idx, ulong exec_idx, void * data );
     424             : 
     425             : /* Abandon a block.  This means that we are no longer interested in
     426             :    executing the block.  This also implies that any block which chains
     427             :    off of the provided block shall be abandoned.  This is mainly used
     428             :    when a block is aborted because we decided that it would be a
     429             :    dead/invalid block, and so there's no point in spending resources
     430             :    executing it.  The scheduler will no longer return transactions from
     431             :    abandoned blocks for execution.  This should only be invoked on an
     432             :    actively replayed block, and should only be invoked once on it.
     433             : 
     434             :    For the purposes of bank lifetime management, sched is a subsidiary
     435             :    of banks.  So while sched sets things in motion for a bad block to be
     436             :    eagerly pruned, banks/replay is the sole initiator of actual pruning.
     437             :    The way this works is that an abandoned block will have its refcnt
     438             :    queued for release by sched as soon as, and only if, the block has no
     439             :    more in-flight tasks associated with it.  No sooner, no later.  In
     440             :    the immediate ensuing stem run loop, sched_pruned_next() will return
     441             :    the index for the corresponding bank so the refcnt can be decremented
     442             :    for sched.  After that point, banks will eventually instruct sched to
     443             :    prune the block, when all other components release their refcnts on
     444             :    said bank.  Then the bank_idx may be recycled for another block.
     445             : 
     446             :    Pass FD_SCHED_ABANDON_INVALID if the block is ruled invalid for any
     447             :    reason, or FD_SCHED_ABANDON_DISCARDED if we are merely giving up on
     448             :    it without fault, e.g. eviction under resource pressure.  Descendants
     449             :    inherit the flavor: they record DEAD_ANCESTOR, and are marked
     450             :    discarded iff the lineage was discarded, provided they have no dead
     451             :    reason of their own.  A block that is already going down keeps the
     452             :    flavor it went down with, so a later abandon cannot re-label it. */
     453             : void
     454             : fd_sched_block_abandon( fd_sched_t * sched, ulong bank_idx, int cause );
     455             : 
     456             : /* fd_sched_get_dead_reason returns the scheduler's reason (one of
     457             :    FD_SCHED_DEAD_REASON_*) for why the block at bank_idx went down.
     458             :    Returns FD_SCHED_DEAD_REASON_NONE if the block itself was merely
     459             :    discarded (root advance, eviction) or if no block is currently
     460             :    tracked at bank_idx.  Descendants of a discarded lineage carry
     461             :    DEAD_ANCESTOR like any other lineage death;
     462             :    fd_sched_block_is_discarded disambiguates discarded from
     463             :    ruled-invalid.  The recorded reason is the first one; later failures
     464             :    on an already-dead block (e.g. an in-flight PoH task draining after
     465             :    the block was abandoned) do not overwrite it. */
     466             : int
     467             : fd_sched_get_dead_reason( fd_sched_t * sched, ulong bank_idx );
     468             : 
     469             : /* fd_sched_block_is_discarded returns 1 if the block went down with a
     470             :    discarded (not invalid) lineage, 0 otherwise (including when no
     471             :    block is tracked at bank_idx).  Never set on a block that has a dead
     472             :    reason of its own, so it does not mask the scheduler's own verdict. */
     473             : int
     474             : fd_sched_block_is_discarded( fd_sched_t * sched, ulong bank_idx );
     475             : 
     476             : /* Prune the given block including descendants of it. */
     477             : void
     478             : fd_sched_cancel( fd_sched_t * sched, ulong bank_idx );
     479             : 
     480             : /* Add a block as immediately done to the scheduler.  This is useful for
     481             :    installing the snapshot slot, or for informing the scheduler of a
     482             :    packed leader block.  Parent block should be ULONG_MAX for the
     483             :    snapshot slot, and otherwise a block that hasn't been pruned. */
     484             : void
     485             : fd_sched_block_add_done( fd_sched_t * sched, ulong bank_idx, ulong parent_bank_idx, ulong slot );
     486             : 
     487             : /* Advance the root, pruning all blocks across forks that do not descend
     488             :    from the new root.  Assumes the new root is in the fork tree and
     489             :    connected to the current root.  Also assumes that there are no more
     490             :    in-flight transactions from the soon-to-be-pruned blocks.  This
     491             :    should be called after root_notify() and the caller is responsible
     492             :    for figuring out the new root to safely prune to. */
     493             : void
     494             : fd_sched_advance_root( fd_sched_t * sched, ulong root_idx );
     495             : 
     496             : /* Notify the scheduler of a new root.  This has the effect of calling
     497             :    abandon() on all minority forks that do not descend from the new
     498             :    root.  Shortly after a call to this function, in-flight transactions
     499             :    from these abandoned blocks should retire from the execution
     500             :    pipeline, and the new root will be safe for pruning. */
     501             : void
     502             : fd_sched_root_notify( fd_sched_t * sched, ulong root_idx );
     503             : 
     504             : /* Returns the index of a bank whose refcnt should be decremented for
     505             :    sched.  This function should be called in a loop to drain all
     506             :    outstanding refcnt decrements before any other sched API is called in
     507             :    a stem run loop.  Returns ULONG_MAX when there are no more
     508             :    outstanding references from sched and the loop should break. */
     509             : ulong
     510             : fd_sched_pruned_block_next( fd_sched_t * sched );
     511             : 
     512             : void
     513             : fd_sched_set_poh_params( fd_sched_t * sched, ulong bank_idx, ulong tick_height, ulong max_tick_height, ulong hashes_per_tick, fd_hash_t const * start_poh );
     514             : 
     515             : /* fd_sched_block_verify_ticks sets the tick window and verifies
     516             :    ticks on bank_idx (shred fuzz harness, no exec).  Returns
     517             :    FD_SCHED_DEAD_REASON_NONE (0) if valid, else the
     518             :    FD_SCHED_DEAD_REASON_* the ticks are invalid for.  Does not rule the
     519             :    block invalid; the caller decides what to do with the verdict. */
     520             : int
     521             : fd_sched_block_verify_ticks( fd_sched_t * sched,
     522             :                              ulong        bank_idx,
     523             :                              ulong        tick_height,
     524             :                              ulong        max_tick_height,
     525             :                              ulong        hashes_per_tick );
     526             : 
     527             : /* fd_sched_set_bypass_poh_verify configures whether the per-microblock
     528             :    PoH end_hash comparison in maybe_mixin is bypassed.  This is intended
     529             :    for test and fuzz harnesses: the expected end_hash is carried in the
     530             :    shred payload, so comparing it would reject any mutated input before
     531             :    the deeper parse/tick logic is exercised.  Production call sites
     532             :    should leave this disabled. */
     533             : void
     534             : fd_sched_set_bypass_poh_verify( fd_sched_t * sched, int bypass_poh_verify );
     535             : 
     536             : /* fd_sched_set_bypass_alut_resolution bypasses ALUT resolution during
     537             :    parsing (test/fuzz: no accounts DB).  ALUT txns become serializing.
     538             :    Production call sites should leave this disabled. */
     539             : void
     540             : fd_sched_set_bypass_alut_resolution( fd_sched_t * sched, int bypass_alut_resolution );
     541             : 
     542             : fd_txn_p_t *
     543             : fd_sched_get_txn( fd_sched_t * sched, ulong txn_idx );
     544             : 
     545             : fd_sched_txn_info_t *
     546             : fd_sched_get_txn_info( fd_sched_t * sched, ulong txn_idx );
     547             : 
     548             : fd_hash_t *
     549             : fd_sched_get_poh( fd_sched_t * sched, ulong bank_idx );
     550             : 
     551             : uint
     552             : fd_sched_get_shred_cnt( fd_sched_t * sched, ulong bank_idx );
     553             : 
     554             : /* fd_sched_get_footer returns the block footer, or NULL if no footer
     555             :    marker has been parsed for the block.  The shapes were validated at
     556             :    parse time; the signatures are not verified.  The footer stays valid
     557             :    until the block is pruned. */
     558             : fd_block_footer_t const *
     559             : fd_sched_get_footer( fd_sched_t * sched, ulong bank_idx );
     560             : 
     561             : void
     562             : fd_sched_metrics_write( fd_sched_t *            sched,
     563             :                         fd_clock_tile_t const * clock );
     564             : 
     565             : /* Serialize the current state as a cstr to the returned buffer.  Caller
     566             :    may read from the buffer until the next invocation of any fd_sched
     567             :    function. */
     568             : char *
     569             : fd_sched_get_state_cstr( fd_sched_t * sched );
     570             : 
     571             : void *
     572             : fd_sched_leave( fd_sched_t * sched );
     573             : 
     574             : void *
     575             : fd_sched_delete( void * mem );
     576             : 
     577             : FD_PROTOTYPES_END
     578             : 
     579             : #endif /* HEADER_fd_src_discof_replay_fd_sched_h */

Generated by: LCOV version 1.14