LCOV - code coverage report
Current view: top level - disco/pack - fd_pack.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 25 36 69.4 %
Date: 2025-03-20 12:08:36 Functions: 1 66 1.5 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_ballet_pack_fd_pack_h
       2             : #define HEADER_fd_src_ballet_pack_fd_pack_h
       3             : 
       4             : /* fd_pack defines methods that prioritizes Solana transactions,
       5             :    selecting a subset (potentially all) and ordering them to attempt to
       6             :    maximize the overall profitability of the validator. */
       7             : 
       8             : #include "../../ballet/fd_ballet_base.h"
       9             : #include "../../ballet/txn/fd_txn.h"
      10             : #include "fd_est_tbl.h"
      11             : #include "fd_microblock.h"
      12             : #include "fd_pack_rebate_sum.h"
      13             : 
      14           0 : #define FD_PACK_ALIGN     (128UL)
      15             : 
      16       44214 : #define FD_PACK_MAX_BANK_TILES 62UL
      17             : 
      18             : /* NOTE: THE FOLLOWING CONSTANTS ARE CONSENSUS CRITICAL AND CANNOT BE
      19             :    CHANGED WITHOUT COORDINATING WITH ANZA. */
      20       18072 : #define FD_PACK_MAX_COST_PER_BLOCK      (48000000UL)
      21         318 : #define FD_PACK_MAX_VOTE_COST_PER_BLOCK (36000000UL)
      22        2085 : #define FD_PACK_MAX_WRITE_COST_PER_ACCT (12000000UL)
      23    27163617 : #define FD_PACK_FEE_PER_SIGNATURE           (5000UL) /* In lamports */
      24             : 
      25             : /* Each block is limited to 32k parity shreds.  We don't want pack to
      26             :    produce a block with so many transactions we can't shred it, but the
      27             :    correspondence between transactions and parity shreds is somewhat
      28             :    complicated, so we need to use conservative limits.
      29             : 
      30             :    Except for the final batch in the block, the current version of the
      31             :    shred tile shreds microblock batches of size (25431, 63671] bytes,
      32             :    including the microblock headers, but excluding the microblock count.
      33             :    The worst case size by bytes/parity shred is a 25871 byte microblock
      34             :    batch, which produces 31 parity shreds.  The final microblock batch,
      35             :    however, may be as bad as 48 bytes triggering the creation of 17
      36             :    parity shreds.  This gives us a limit of floor((32k - 17)/31)*25871 +
      37             :    48 = 27,319,824 bytes.
      38             : 
      39             :    To get this right, the pack tile needs to add in the 48-byte
      40             :    microblock headers for each microblock, and we also need to subtract
      41             :    out the tick bytes, which aren't known until PoH initialization is
      42             :    complete.
      43             : 
      44             :    Note that the number of parity shreds in each FEC set is always at
      45             :    least as many as the number of data shreds, so we don't need to
      46             :    consider the data shreds limit. */
      47           3 : #define FD_PACK_MAX_DATA_PER_BLOCK (((32UL*1024UL-17UL)/31UL)*25871UL + 48UL)
      48             : 
      49             : /* Optionally allow up to 1M shreds per block for benchmarking. */
      50           0 : #define LARGER_MAX_DATA_PER_BLOCK  (((32UL*32UL*1024UL-17UL)/31UL)*25871UL + 48UL)
      51             : 
      52             : /* ---- End consensus-critical constants */
      53             : 
      54    27192687 : #define FD_TXN_P_FLAGS_IS_SIMPLE_VOTE     ( 1U)
      55    13581750 : #define FD_TXN_P_FLAGS_BUNDLE             ( 2U)
      56    13581876 : #define FD_TXN_P_FLAGS_INITIALIZER_BUNDLE ( 4U)
      57         126 : #define FD_TXN_P_FLAGS_SANITIZE_SUCCESS   ( 8U)
      58         276 : #define FD_TXN_P_FLAGS_EXECUTE_SUCCESS    (16U)
      59           0 : #define FD_TXN_P_FLAGS_FEES_ONLY          (32U)
      60             : 
      61         171 : #define FD_TXN_P_FLAGS_RESULT_MASK  (0xFF000000U)
      62             : 
      63             : /* A bundle is a sequence of between 1 and FD_PACK_MAX_TXN_PER_BUNDLE
      64             :    transactions (both inclusive) that executes and commits atomically.
      65             :  */
      66        4059 : #define FD_PACK_MAX_TXN_PER_BUNDLE      5UL
      67             : 
      68             : 
      69             : /* The Solana network and Firedancer implementation details impose
      70             :    several limits on what pack can produce.  These limits are grouped in
      71             :    this one struct fd_pack_limits_t, which is just a convenient way to
      72             :    pass them around.  The limits listed below are arithmetic limits.
      73             :    The limits imposed by practical constraints are almost certainly
      74             :    much, much tighter. */
      75             : struct fd_pack_limits {
      76             :   /* max_{cost, vote_cost}_per_block, max_write_cost_per_acct are
      77             :      consensus-critical limits and must be agreed on cluster-wide.  A
      78             :      block that consumes more than max_cost_per_block cost units
      79             :      (closely related to, but not identical to CUs) in total is invalid.
      80             :      Similarly, a block where the sum of the cost of all vote
      81             :      transactions exceeds max_vote_cost_per_block cost units is invalid.
      82             :      Similarly, a block in where the sum of the cost of all transactions
      83             :      that write to a given account exceeds max_write_cost_per_acct is
      84             :      invalid. */
      85             :   ulong max_cost_per_block;          /* in [0, ULONG_MAX) */
      86             :   ulong max_vote_cost_per_block;     /* in [0, max_cost_per_block] */
      87             :   ulong max_write_cost_per_acct;     /* in [0, max_cost_per_block] */
      88             : 
      89             :   /* max_data_bytes_per_block is derived from consensus-critical limits
      90             :      on the number of shreds in a block, but is not directly enforced.
      91             :      Separation of concerns means that it's not a good idea for pack to
      92             :      know exactly how the block will be shredded, but at the same time,
      93             :      we don't want to end up in a situation where we produced a block
      94             :      that had too many shreds, because the shred tile's only recourse
      95             :      would be to kill the block.  To address this, pack limits the size
      96             :      of the data it puts into the block to a limit that we can prove
      97             :      will never cause the shred tile to produce too many shreds.
      98             : 
      99             :      This limit includes transaction and microblock headers for
     100             :      non-empty microblocks that pack produces. */
     101             :   ulong max_data_bytes_per_block;    /* in [0, ULONG_MAX - 183] */
     102             : 
     103             :   /* max_txn_per_microblock and max_microblocks_per_block are
     104             :      Firedancer-imposed implementation limits to bound the amount of
     105             :      memory consumption that pack uses.  Pack will produce microblocks
     106             :      with no more than max_txn_per_microblock transactions.
     107             :      Additionally, once pack produces max_microblocks_per_block
     108             :      non-empty microblocks in a block, all subsequent attempts to
     109             :      schedule a microblock will return an empty microblock until
     110             :      fd_pack_end_block is called. */
     111             :   ulong max_txn_per_microblock;      /* in [0, 16777216] */
     112             :   ulong max_microblocks_per_block;   /* in [0, 1e12) */
     113             : 
     114             : };
     115             : typedef struct fd_pack_limits fd_pack_limits_t;
     116             : 
     117             : 
     118             : /* Forward declare opaque handle */
     119             : struct fd_pack_private;
     120             : typedef struct fd_pack_private fd_pack_t;
     121             : 
     122             : /* fd_pack_{align,footprint} return the required alignment and
     123             :    footprint in bytes for a region of memory to be used as a pack
     124             :    object.
     125             : 
     126             :    pack_depth sets the maximum number of pending transactions that pack
     127             :    stores and may eventually schedule.  pack_depth must be at least 4.
     128             : 
     129             :    If bundle_meta_sz is non-zero, then the bundle-related functions on
     130             :    this pack object can be used, and it can schedule bundles.
     131             :    Additionally, if bundle_meta_sz is non-zero, then a region of size
     132             :    bundle_meta_sz bytes (with no additional alignment) will be reserved
     133             :    for each bundle.
     134             : 
     135             :    Note: if you'd like to use bundles, but don't require metadata for
     136             :    the bundles, simply use a small positive value (e.g. 1), always pass
     137             :    NULL in insert_bundle_fini, and never call fd_pack_peek_bundle_meta.
     138             : 
     139             :    bank_tile_cnt sets the number of bank tiles to which this pack object
     140             :    can schedule transactions.  bank_tile_cnt must be in [1,
     141             :    FD_PACK_MAX_BANK_TILES].
     142             : 
     143             :    limits sets various limits for the blocks and microblocks that pack
     144             :    can produce. */
     145             : 
     146           0 : FD_FN_CONST static inline ulong fd_pack_align       ( void ) { return FD_PACK_ALIGN; }
     147             : 
     148             : FD_FN_PURE ulong
     149             : fd_pack_footprint( ulong                    pack_depth,
     150             :                    ulong                    bundle_meta_sz,
     151             :                    ulong                    bank_tile_cnt,
     152             :                    fd_pack_limits_t const * limits );
     153             : 
     154             : 
     155             : /* fd_pack_new formats a region of memory to be suitable for use as a
     156             :    pack object.  mem is a non-NULL pointer to a region of memory in the
     157             :    local address space with the required alignment and footprint.
     158             :    pack_depth, bundle_meta_sz, bank_tile_cnt, and limits are as above.
     159             :    rng is a local join to a random number generator used to perturb
     160             :    estimates.
     161             : 
     162             :    Returns `mem` (which will be properly formatted as a pack object) on
     163             :    success and NULL on failure.  Logs details on failure.  The caller
     164             :    will not be joined to the pack object when this function returns. */
     165             : void * fd_pack_new( void                   * mem,
     166             :                     ulong                    pack_depth,
     167             :                     ulong                    bundle_meta_sz,
     168             :                     ulong                    bank_tile_cnt,
     169             :                     fd_pack_limits_t const * limits,
     170             :                     fd_rng_t               * rng );
     171             : 
     172             : /* fd_pack_join joins the caller to the pack object.  Every successful
     173             :    join should have a matching leave.  Returns mem. */
     174             : fd_pack_t * fd_pack_join( void * mem );
     175             : 
     176             : 
     177             : /* fd_pack_avail_txn_cnt returns the number of transactions that this
     178             :    pack object has available to schedule but that have not been
     179             :    scheduled yet. pack must be a valid local join.  The return value
     180             :    will be in [0, pack_depth). */
     181             : 
     182             : /* For performance reasons, implement this here.  The offset is STATIC_ASSERTed
     183             :    in fd_pack.c. */
     184       48894 : #define FD_PACK_PENDING_TXN_CNT_OFF 72
     185             : FD_FN_PURE static inline ulong
     186       48894 : fd_pack_avail_txn_cnt( fd_pack_t const * pack ) {
     187       48894 :   return *((ulong const *)((uchar const *)pack + FD_PACK_PENDING_TXN_CNT_OFF));
     188       48894 : }
     189             : 
     190             : /* fd_pack_current_block_cost returns the number of CUs that have been
     191             :    scheduled in the current block, net of any rebates.  It should be
     192             :    between 0 and the specified value of max_cost_per_block, but it can
     193             :    be slightly higher due to temporary cost model nonsense.  Due to
     194             :    rebates, this number may decrease as the block progresses.  pack must
     195             :    be a valid local join. */
     196             : FD_FN_PURE ulong fd_pack_current_block_cost( fd_pack_t const * pack );
     197             : 
     198             : /* fd_pack_bank_tile_cnt: returns the value of bank_tile_cnt provided in
     199             :    pack when the pack object was initialized with fd_pack_new.  pack
     200             :    must be a valid local join.  The result will be in [1,
     201             :    FD_PACK_MAX_BANK_TILES]. */
     202             : FD_FN_PURE ulong fd_pack_bank_tile_cnt( fd_pack_t const * pack );
     203             : 
     204             : /* fd_pack_set_block_limits: Updates the limits provided fd_pack_new to
     205             :    the new values.  Any future microblocks produced by this pack object
     206             :    will not cause a block to have more than max_microblocks_per_block
     207             :    non-empty microblocks or more than max_data_bytes_per_block data
     208             :    bytes (counting microblock headers as before).  Limits are inclusive,
     209             :    as per usual (i.e. a block may have exactly
     210             :    max_microblocks_per_block microblocks, but not more).  pack must be
     211             :    a valid local join.
     212             : 
     213             :    The typical place to call this is immediately after
     214             :    fd_pack_end_block; if this is called after some microblocks have been
     215             :    produced for the current block, and the current block already exceeds
     216             :    the limits, all the remaining microblocks in the block will be empty,
     217             :    but the call is valid. */
     218             : void fd_pack_set_block_limits( fd_pack_t * pack, ulong max_microblocks_per_block, ulong max_data_bytes_per_block );
     219             : 
     220             : /* Return values for fd_pack_insert_txn_fini:  Non-negative values
     221             :    indicate the transaction was accepted and may be returned in a future
     222             :    microblock.  Negative values indicate that the transaction was
     223             :    rejected and will never be returned in a future microblock.
     224             :    Transactions can be rejected through no fault of their own, so it
     225             :    doesn't necessarily imply bad behavior.
     226             : 
     227             :    The non-negative (success) codes are essentially a bitflag of two
     228             :    bits:
     229             :     * whether the transaction met the criteria for a simple vote or not,
     230             :     * whether this transaction replaced a previously accepted, low
     231             :       priority transaction, rather than being accepted in addition to all
     232             :       the previously accepted transactions.  Since pack maintains a heap
     233             :       with a fixed max size of pack_depth, replacing transaction is
     234             :       necessary whenever the heap is full.
     235             : 
     236             :    The negative (failure) codes are a normal enumeration (not a
     237             :    bitflag).
     238             :     * PRIORITY: pack's heap was full and the transaction's priority was
     239             :       lower than the worst currently accepted transaction.
     240             :     * DUPLICATE: the transaction is a duplicate of a currently accepted
     241             :       transaction.
     242             :     * UNAFFORDABLE: the fee payer could not afford the transaction fee
     243             :       (not yet implemented).
     244             :     * ADDR_LUT: the transaction tried to load an account from an address
     245             :       lookup table, which is not yet supported.
     246             :     * EXPIRED: the transaction was already expired upon insertion based
     247             :       on the provided value of expires_at compared to the last call to
     248             :       fd_pack_expire_before.
     249             :     * TOO_LARGE: the transaction requested too many CUs and would never
     250             :       be scheduled if it had been accepted.
     251             :     * ACCOUNT_CNT: the transaction tried to load more than 64 account
     252             :       addresses.
     253             :     * DUPLICATE_ACCT: the transaction included an account address twice
     254             :       in its list of account addresses to load.
     255             :     * ESTIMATION_FAIL: estimation of the transaction's compute cost and
     256             :       fee failed, typically because the transaction contained a
     257             :       malformed ComputeBudgetProgram instruction.
     258             :     * WRITES_SYSVAR: the transaction attempts to write-lock a sysvar.
     259             :       Write-locking a sysvar can cause heavy contention.  Agave
     260             :       solves this by downgrading these to read locks, but we instead
     261             :       solve it by refusing to pack such transactions.
     262             :     * BUNDLE_BLACKLIST: bundles are enabled and the transaction uses an
     263             :       account in the bundle blacklist.
     264             : 
     265             :     NOTE: The corresponding enum in metrics.xml must be kept in sync
     266             :     with any changes to these return values. */
     267           0 : #define FD_PACK_INSERT_ACCEPT_VOTE_REPLACE     (  3)
     268      494592 : #define FD_PACK_INSERT_ACCEPT_NONVOTE_REPLACE  (  2)
     269       37596 : #define FD_PACK_INSERT_ACCEPT_VOTE_ADD         (  1)
     270    13049508 : #define FD_PACK_INSERT_ACCEPT_NONVOTE_ADD      (  0)
     271           0 : #define FD_PACK_INSERT_REJECT_PRIORITY         ( -1)
     272             : #define FD_PACK_INSERT_REJECT_DUPLICATE        ( -2)
     273           0 : #define FD_PACK_INSERT_REJECT_UNAFFORDABLE     ( -3)
     274             : #define FD_PACK_INSERT_REJECT_ADDR_LUT         ( -4)
     275          12 : #define FD_PACK_INSERT_REJECT_EXPIRED          ( -5)
     276           0 : #define FD_PACK_INSERT_REJECT_TOO_LARGE        ( -6)
     277           3 : #define FD_PACK_INSERT_REJECT_ACCOUNT_CNT      ( -7)
     278           3 : #define FD_PACK_INSERT_REJECT_DUPLICATE_ACCT   ( -8)
     279           3 : #define FD_PACK_INSERT_REJECT_ESTIMATION_FAIL  ( -9)
     280          93 : #define FD_PACK_INSERT_REJECT_WRITES_SYSVAR    (-10)
     281           0 : #define FD_PACK_INSERT_REJECT_BUNDLE_BLACKLIST (-11)
     282             : 
     283             : /* The FD_PACK_INSERT_{ACCEPT, REJECT}_* values defined above are in the
     284             :    range [-FD_PACK_INSERT_RETVAL_OFF,
     285             :    -FD_PACK_INSERT_RETVAL_OFF+FD_PACK_INSERT_RETVAL_CNT ) */
     286           0 : #define FD_PACK_INSERT_RETVAL_OFF 11
     287           0 : #define FD_PACK_INSERT_RETVAL_CNT 15
     288             : 
     289             : FD_STATIC_ASSERT( FD_PACK_INSERT_REJECT_BUNDLE_BLACKLIST>=-FD_PACK_INSERT_RETVAL_OFF, pack_retval );
     290             : FD_STATIC_ASSERT( FD_PACK_INSERT_ACCEPT_VOTE_REPLACE<FD_PACK_INSERT_RETVAL_CNT-FD_PACK_INSERT_RETVAL_OFF, pack_retval );
     291             : 
     292             : /* fd_pack_insert_txn_{init,fini,cancel} execute the process of
     293             :    inserting a new transaction into the pool of available transactions
     294             :    that may be scheduled by the pack object.
     295             : 
     296             :    fd_pack_insert_txn_init returns a piece of memory from the txnmem
     297             :    region where the transaction should be stored.  The lifetime of this
     298             :    memory is managed by fd_pack as explained below.
     299             : 
     300             :    Every call to fd_pack_insert_init must be paired with a call to
     301             :    exactly one of _fini or _cancel.  Calling fd_pack_insert_txn_fini
     302             :    finalizes the transaction insert process and makes the newly-inserted
     303             :    transaction available for scheduling.  Calling
     304             :    fd_pack_insert_txn_cancel aborts the transaction insertion process.
     305             :    The txn pointer passed to _fini or _cancel must come from the most
     306             :    recent call to _init.
     307             : 
     308             :    The caller of these methods should not retain any read or write
     309             :    interest in the transaction after _fini or _cancel have been called.
     310             : 
     311             :    expires_at (for _fini only) bounds the lifetime of the inserted
     312             :    transaction.  No particular unit is prescribed, and it need not be
     313             :    higher than the previous call to txn_fini.  If fd_pack_expire_before
     314             :    has been previously called with a value larger (strictly) than the
     315             :    provided expires_at, the transaction will be rejected with EXPIRED.
     316             :    See fd_pack_expire_before for more details.
     317             : 
     318             :    pack must be a local join of a pack object.  From the caller's
     319             :    perspective, these functions cannot fail, though pack may reject a
     320             :    transaction for a variety of reasons.  fd_pack_insert_txn_fini
     321             :    returns one of the FD_PACK_INSERT_ACCEPT_* or FD_PACK_INSERT_REJECT_*
     322             :    codes explained above.
     323             :  */
     324             : fd_txn_e_t * fd_pack_insert_txn_init  ( fd_pack_t * pack                                     );
     325             : int          fd_pack_insert_txn_fini  ( fd_pack_t * pack, fd_txn_e_t * txn, ulong expires_at );
     326             : void         fd_pack_insert_txn_cancel( fd_pack_t * pack, fd_txn_e_t * txn                   );
     327             : 
     328             : /* fd_pack_insert_bundle_{init,fini,cancel} are parallel to the
     329             :    similarly named fd_pack_insert_txn functions but can be used to
     330             :    insert a bundle instead of a transaction.
     331             : 
     332             :    fd_pack_insert_bundle_init populates and returns bundle.
     333             :    Specifically, it populates bundle[0], ...  bundle[txn_cnt-1] with
     334             :    pointers to fd_txn_p_t structs that should receive a new transaction.
     335             :    The pointers themselves should not be changed which is what the const
     336             :    indicates, but the contents of the fd_txn_p_t structs must be changed
     337             :    in order for this to be useful.  bundle must be a pointer to the
     338             :    first element of an array of at least txn_cnt pointers.
     339             : 
     340             :    The bundle consists of the transactions in the order they are
     341             :    provided.  I.e. bundle[0] will execute first in the bundle.
     342             : 
     343             :    Like with insert_txn, every call to fd_pack_insert_bundle_init must
     344             :    be paired with a call to exactly one of _fini or _cancel.  Calling
     345             :    fd_pack_insert_bundle_fini finalizes the bundle insertion process and
     346             :    makes the newly-inserted bundle available for scheduling.  Calling
     347             :    fd_pack_insert_bundle_cancel aborts the transaction insertion
     348             :    process.  There can be at most two outstanding bundles, of which one
     349             :    should be an initializer bundle.  The bundle argument passed to _fini
     350             :    or _cancel must be the return value of a call to _init with the same
     351             :    value of txn_cnt.  Additionally, it is okay to interleave calls to
     352             :    the insert_txn family of functions with calls to the insert_bundle
     353             :    family of functions.
     354             : 
     355             :    The caller of these methods should not retain any read or write
     356             :    interest in the fd_txn_p_t structs that the entries of bundle
     357             :    point to after _fini or _cancel have been called.
     358             : 
     359             :    expires_at has the same meaning as above.  Although transactions in
     360             :    the bundle may have different recent blockhashes, all transactions in
     361             :    the bundle have the same expires_at value, since if one expires, the
     362             :    whole bundle becomes invalid.
     363             : 
     364             :    If initializer_bundle is non-zero, this bundle will be inserted at
     365             :    the front of the bundle queue so that it is the next bundle
     366             :    scheduled.  Otherwise, the bundle will be inserted at the back of the
     367             :    bundle queue, and will be scheduled in FIFO order with the rest of
     368             :    the bundles.  If an initializer bundle is already present in pack's
     369             :    pending transactions, that bundle will be deleted.  Additionally, if
     370             :    initializer_bundle is non-zero, the transactions in the bundle will
     371             :    not be checked against the bundle blacklist; otherwise, the check
     372             :    will be performed as normal.  See the section below on initializer
     373             :    bundles for more details.
     374             : 
     375             :    Other than the blacklist check, transactions in a bundle are subject
     376             :    to the same checks as other transactions.  If any transaction in the
     377             :    bundle fails validation, the whole bundle will be rejected.
     378             : 
     379             :    _fini also accepts bundle_meta, an optional opaque pointer to a
     380             :    region of memory of size bundle_meta_sz (as provided in pack_new).
     381             :    If bundle_meta is non-NULL, the contents of the memory will be copied
     382             :    to a metadata region associated with this bundle and can be retrieved
     383             :    later with fd_pack_peek_bundle_meta.  The contents of bundle_meta is
     384             :    not retrievable if initializer_bundle is non-zero, so you may wish to
     385             :    just pass NULL in that case.  This function does not retain any
     386             :    interest in the contents of bundle_meta after it returns.
     387             : 
     388             :    txn_cnt must be in [1, MAX_TXN_PER_BUNDLE].  A txn_cnt of 1 inserts a
     389             :    single-transaction bundle which is transaction with extremely high
     390             :    priority.  That said, inserting transactions as bundles instead of
     391             :    transactions can hurt performance and throughput by introducing
     392             :    unnecessary stalls.
     393             : 
     394             :    fd_pack_insert_bundle_fini returns one of the FD_PACK_INSERT_ACCEPT_*
     395             :    or FD_PACK_INSERT_REJECT_* codes explained above.  If there are
     396             :    multiple reasons for rejecting a bundle, the which of the reasons it
     397             :    returns is unspecified.
     398             : 
     399             :    These functions must not be called if the pack object was initialized
     400             :    with bundle_meta_sz==0. */
     401             : 
     402             : fd_txn_e_t * const * fd_pack_insert_bundle_init  ( fd_pack_t * pack, fd_txn_e_t *       * bundle, ulong txn_cnt                                        );
     403             : int                  fd_pack_insert_bundle_fini  ( fd_pack_t * pack, fd_txn_e_t * const * bundle, ulong txn_cnt,
     404             :                                                    ulong expires_at, int initializer_bundle, void const * bundle_meta );
     405             : void                 fd_pack_insert_bundle_cancel( fd_pack_t * pack, fd_txn_e_t * const * bundle, ulong txn_cnt                                        );
     406             : 
     407             : 
     408             : /* =========== More details about initializer bundles ===============
     409             :    Initializer bundles are a special type of bundle with special support
     410             :    from the pack object to facilitate preparing on-chain state for the
     411             :    execution of bundles by this validator.  This design is a bit
     412             :    complicated, but it eliminates excessive coupling between pack and
     413             :    block engine details.
     414             : 
     415             :    The pack object maintains a small state machine (initializer bundle
     416             :    abbreviated IB):
     417             : 
     418             :       [Not Initialized]  ------------------------->|
     419             :           ^                                        | Schedule an
     420             :           |     End            Rebate shows        | IB
     421             :           |     block          IB failed           |
     422             :           |<----------[Failed]--------------|      v
     423             :           |                               --===[Pending]
     424             :           |<------------------------------/     ^  |
     425             :           |     End block                   /---|  |
     426             :           |                                 |      | Rebate shows
     427             :           |                        Schedule |      | IB succeeded
     428             :           |                      another IB |      |
     429             :           |     End block                   |      V
     430             :           -----------------------------------===[Ready]
     431             : 
     432             : 
     433             :    When attempting to schedule a bundle the pack object checks the
     434             :    state, and employs the following rules:
     435             :    * [Not Initialized]: If the top bundle is an IB, schedule it,
     436             :      removing it like normal, then transition to [Pending].  Otherwise,
     437             :      do not schedule a bundle.
     438             :    * [Pending]: Do not schedule a bundle.
     439             :    * [Failed]: Do not schedule a bundle
     440             :    * [Ready]: Attempt to schedule the next bundle.  If scheduling an IB,
     441             :      transition to [Pending].
     442             : 
     443             :    As described in the state machine, ending the block (via
     444             :    fd_pack_end_block) transitions to [Not Initialized], and calls to
     445             :    fd_pack_rebate_cus control the transition out of [Pending].
     446             : 
     447             :    This design supports a typical block engine system where some state
     448             :    may need to be initialized at the start of the slot and some state
     449             :    may need to change between runs of transactions (e.g. 5 transactions
     450             :    from block builder A followed by 5 transactions from block builder
     451             :    B).  This can be done by inserting an initializer bundle whenever the
     452             :    top non-initializer bundle's metadata state (retrievable with
     453             :    fd_pack_peek_bundle_meta) doesn't match the current on-chain state.
     454             :    Since the initializer bundle will execute before the bundle that was
     455             :    previously the top one, by the time the non-initializer bundle
     456             :    executes, the on-chain state will be correctly configured.  In this
     457             :    scheme, in the rare case that an initializer bundle was inserted but
     458             :    never executed, it should be deleted at the end of the slot.
     459             : 
     460             :    If at the start of the slot, it is determined that the on-chain state
     461             :    is in good shape, the state machine can transition directly to
     462             :    [Ready] by calling fd_pack_set_initializer_bundles_ready.
     463             : 
     464             :    Initializer bundles are not exempt from expiration, but it should not
     465             :    be a problem if they are always inserted with the most recent
     466             :    blockhash and deleted at the end of the slot.
     467             : 
     468             :    Additionally, a bundle marked as an IB is exempted from the bundle
     469             :    account blacklist checks.  For this reason, it's important that IB be
     470             :    generated by trusted code with minimal or sanitized
     471             :    attacker-controlled input. */
     472             : 
     473             : 
     474             : /* fd_pack_peek_bundle_meta returns a constant pointer to the bundle
     475             :    metadata associated with the bundle currently in line to be scheduled
     476             :    next, or NULL in any of the following cases:
     477             :      * There are no bundles
     478             :      * The bundle currently in line to be scheduled next is an IB
     479             :      * The bundle state is currently [Pending] or [Failed].
     480             : 
     481             :    The lifetime of the returned pointer is until the next pack insert,
     482             :    schedule, delete, or expire call.  The size of the region pointed to
     483             :    by the returned pointer is bundle_meta_sz.  If this bundle was
     484             :    inserted with bundle_meta==NULL, then the contents of the region
     485             :    pointed to by the returned pointer are arbitrary, but it will be safe
     486             :    to read.
     487             : 
     488             :    Pack doesn't do anything special to ensure the returned pointer
     489             :    points to memory with any particular alignment.  It will naturally
     490             :    have an alignment of at least GCD( 64, bundle_meta_sz ). */
     491             : void const * fd_pack_peek_bundle_meta( fd_pack_t const * pack );
     492             : 
     493             : /* fd_pack_set_initializer_bundles_ready sets the IB state machine state
     494             :    (see long initializer bundle comment above) to the [Ready] state.
     495             :    This function makes it easy to use bundles without initializer
     496             :    bundles.  pack must be a valid local join. */
     497             : void fd_pack_set_initializer_bundles_ready( fd_pack_t * pack );
     498             : 
     499             : /* fd_pack_schedule_next_microblock schedules pending transactions.
     500             :    These transaction either form a microblock, which is a set of
     501             :    non-conflicting transactions, or a bundle.  The semantics of this
     502             :    function are a bit different depending on which one it picks, but
     503             :    there are some reasons why they both use this function.
     504             : 
     505             :    For both codepaths, pack must be a local join of a pack object.
     506             : 
     507             :    Microblock case:
     508             :    Transactions part of the scheduled microblock are copied to out in no
     509             :    particular order.  The cumulative cost of these transactions will not
     510             :    exceed total_cus, and the number of transactions will not exceed the
     511             :    value of max_txn_per_microblock given in fd_pack_new.
     512             : 
     513             :    The block will not contain more than
     514             :    vote_fraction*max_txn_per_microblock votes, and votes in total will
     515             :    not consume more than vote_fraction*total_cus of the microblock.
     516             : 
     517             :    Bundle case:
     518             :    Transactions part of the scheduled bundled are copied in execution
     519             :    order (i.e. out[0] must be executed first).  The number of
     520             :    transactions will not exceed FD_PACK_MAX_TXN_PER_BUNDLE.
     521             :    max_txn_per_microblock, total_cus, and vote_fraction are ignored,
     522             :    though the block-level limits are respected.
     523             : 
     524             :    Both cases:
     525             :    The non_execution_cus and requested_exec_plus_acct_data_cus fields of
     526             :    each transaction will be populated with the non execution CUs and
     527             :    requested execution CUs (including cus derived from the requested
     528             :    loaded accounts data size), respectively.  The sum of these two
     529             :    values is the total cost of the transaction, i.e. what is used for
     530             :    all limits, including the total_cus value.  The lower 3 bits of the
     531             :    flags field will be populated (simple vote, bundle, initializer
     532             :    bundle). Inspecting these flags is the proper way to tell which
     533             :    codepath executed.
     534             : 
     535             :    Returns the number of transactions in the scheduled microblock or
     536             :    bundle.  The return value may be 0 if there are no eligible
     537             :    transactions at the moment. */
     538             : 
     539             : ulong fd_pack_schedule_next_microblock( fd_pack_t * pack, ulong total_cus, float vote_fraction, ulong bank_tile, fd_txn_p_t * out );
     540             : 
     541             : 
     542             : /* fd_pack_rebate_cus adjusts the compute unit accounting for the
     543             :    specified transactions to take into account the actual consumed CUs
     544             :    after execution.  When a transaction is scheduled by
     545             :    schedule_next_microblock, pack assumes that it uses all the CUs it
     546             :    requests for the purposes of several CU limits.  If it doesn't use
     547             :    all the requested CUs, this function "rebates" them to pack so that
     548             :    they can be consumed by a different transaction in the block.
     549             : 
     550             :    pack must be a valid local join of a pack object.  rebate must point
     551             :    to a valid rebate report produced by fd_pack_rebate_sum_t.
     552             : 
     553             :    IMPORTANT: CU limits are reset at the end of each block, so this
     554             :    should not be called for transactions from a prior block.
     555             :    Specifically, there must not be a call to fd_pack_end_block between
     556             :    the call to schedule_next_microblock this is paired with and the call
     557             :    to rebate_cus.
     558             : 
     559             :    This function operates independently of microblock_complete.  In
     560             :    general, you probably need to call both.  microblock_complete must be
     561             :    called before scheduling another microblock to that bank tile, while
     562             :    rebate_cus is optional and has much more relaxed ordering
     563             :    constraints.  The restriction about intervening calls to end_block
     564             :    and that this must come after schedule_next_microblock are the only
     565             :    ordering constraints. */
     566             : void fd_pack_rebate_cus( fd_pack_t * pack, fd_pack_rebate_t const * rebate );
     567             : 
     568             : /* fd_pack_microblock_complete signals that the bank_tile with index
     569             :    bank_tile has completed its previously scheduled microblock.  This
     570             :    permits the scheduling of transactions that conflict with the
     571             :    previously scheduled microblock.  It is safe to call this multiple
     572             :    times after a microblock or even if bank_tile does not have a
     573             :    previously scheduled; in this case, the function will return 0 and
     574             :    act as a no-op.  Returns 1 if the bank_tile had an outstanding,
     575             :    previously scheduled microblock to mark as completed. */
     576             : int fd_pack_microblock_complete( fd_pack_t * pack, ulong bank_tile );
     577             : 
     578             : /* fd_pack_expire_before deletes all available transactions with
     579             :    expires_at values strictly less than expire_before.  pack must be a
     580             :    local join of a pack object.  Returns the number of transactions
     581             :    deleted.  Subsequent calls to fd_pack_expire_before with the same or
     582             :    a smaller value are no-ops. */
     583             : ulong fd_pack_expire_before( fd_pack_t * pack, ulong expire_before );
     584             : 
     585             : /* fd_pack_delete_txn removes a transaction (identified by its first
     586             :    signature) from the pool of available transactions.  Returns 1 if the
     587             :    transaction was found (and then removed) and 0 if not. */
     588             : int fd_pack_delete_transaction( fd_pack_t * pack, fd_ed25519_sig_t const * sig0 );
     589             : 
     590             : /* fd_pack_end_block resets some state to prepare for the next block.
     591             :    Specifically, the per-block limits are cleared and transactions in
     592             :    the microblocks scheduled after the call to this function are allowed
     593             :    to conflict with transactions in microblocks scheduled before the
     594             :    call to this function, even within gap microblocks. */
     595             : void fd_pack_end_block( fd_pack_t * pack );
     596             : 
     597             : 
     598             : /* fd_pack_clear_all resets the state associated with this pack object.
     599             :    All pending transactions are removed from the pool of available
     600             :    transactions and all limits are reset. */
     601             : void fd_pack_clear_all( fd_pack_t * pack );
     602             : 
     603             : 
     604             : /* fd_pack_metrics_write writes period metric values to the metrics
     605             :    system.  pack must be a valid local join. */
     606             : void
     607             : fd_pack_metrics_write( fd_pack_t const * pack );
     608             : 
     609             : 
     610             : /* fd_pack_leave leaves a local join of a pack object.  Returns pack. */
     611             : void * fd_pack_leave(  fd_pack_t * pack );
     612             : /* fd_pack_delete unformats a memory region used to store a pack object
     613             :    and returns ownership of the memory to the caller.  Returns mem. */
     614             : void * fd_pack_delete( void      * mem  );
     615             : 
     616             : /* fd_pack_verify (for debugging use primarily) checks to ensure several
     617             :    invariants are satisfied.  scratch must point to the first byte of a
     618             :    piece of memory meeting the same alignment and footprint constraints
     619             :    as pack.  Returns 0 on success and a negative value on failure
     620             :    (logging a warning with details). */
     621             : int fd_pack_verify( fd_pack_t * pack, void * scratch );
     622             : 
     623             : FD_PROTOTYPES_END
     624             : #endif /* HEADER_fd_src_ballet_pack_fd_pack_h */

Generated by: LCOV version 1.14