LCOV - code coverage report
Current view: top level - disco/pack - fd_pack.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 1810 1956 92.5 %
Date: 2026-11-10 04:25:15 Functions: 48 56 85.7 %

          Line data    Source code
       1             : #define FD_UNALIGNED_ACCESS_STYLE 0
       2             : #include "fd_pack.h"
       3             : 
       4             : #define SORT_NAME        fd_pack_writer_cost_sort
       5         711 : #define SORT_KEY_T       fd_pack_addr_use_t
       6         447 : #define SORT_BEFORE(a,b) (FD_PACK_TOP_WRITERS_SORT_BEFORE(a,b))
       7             : #define SORT_FN_ATTR     __attribute__((no_sanitize("address", "undefined"))) /* excessive ASan slowdown */
       8             : #include "../../util/tmpl/fd_sort.c"
       9             : 
      10             : #include "fd_pack_cost.h"
      11             : #include "fd_pack_bitset.h"
      12             : #include "fd_pack_unwritable.h"
      13             : #include "fd_chkdup.h"
      14             : #include "fd_pack_tip_prog_blacklist.h"
      15             : #include <math.h> /* for sqrt */
      16             : #include <stddef.h> /* for offsetof */
      17             : #include "../metrics/fd_metrics.h"
      18             : #include "../../util/fd_hash32.h"
      19             : 
      20             : #define FD_PACK_USE_NON_TEMPORAL_MEMCPY 1
      21             : 
      22             : #if FD_HAS_AVX512 && FD_PACK_USE_NON_TEMPORAL_MEMCPY
      23             : #include "../../util/simd/fd_nt_memcpy.h"
      24        4504 : #define pack_memcpy_out  fd_memcpy_nt_nofence
      25        5080 : #define pack_memcpy_fini() _mm_sfence()
      26             : #else
      27        9008 : #define pack_memcpy_out  fd_memcpy
      28             : #define pack_memcpy_fini()
      29             : #endif
      30             : 
      31             : /* Declare a bunch of helper structs used for pack-internal data
      32             :    structures. */
      33             : typedef struct {
      34             :   fd_acct_addr_t key;
      35             : } wrapped_acct_t;
      36             : 
      37             : /* fd_pack_ord_txn_t: An fd_txn_p_t with information required to order
      38             :    it by priority. */
      39             : struct fd_pack_private_ord_txn {
      40             :   /* It's important that there be no padding here (asserted below)
      41             :      because the code casts back and forth from pointers to this element
      42             :      to pointers to the whole struct. */
      43             :   union {
      44             :     fd_txn_p_t   txn[1];  /* txn is an alias for txn_e->txnp */
      45             :     fd_txn_e_t   txn_e[1];
      46             :     fd_txn_e_t   _txn_e;  /* Non-array type needed for map_chain */
      47             :   };
      48             : 
      49             :   /* Since this struct can be in one of several trees, it's helpful to
      50             :      store which tree.  This should be one of the FD_ORD_TXN_ROOT_*
      51             :      values. */
      52             :   int root;
      53             : 
      54             :   /* The sig2txn map_chain fields */
      55             :   ushort sigmap_next;
      56             :   ushort sigmap_prev;
      57             : 
      58             :   /* Each transaction is inserted with an expiration "time."  This code
      59             :      doesn't care about the units (blocks, rdtsc tick, ns, etc.), and
      60             :      doesn't require transactions to be inserted in expiration date
      61             :      order. */
      62             :   ulong expires_at;
      63             :   /* expq_idx: When this object is part of one of the treaps, it's
      64             :      also in the expiration priority queue.  This field (which is
      65             :      manipulated behind the scenes by the fd_prq code) stores where so
      66             :      that if we delete this transaction, we can also delete it from the
      67             :      expiration priority queue. */
      68             :   ulong expq_idx;
      69             : 
      70             :   /* The noncemap map_chain fields */
      71             :   ushort noncemap_next;
      72             :   ushort noncemap_prev;
      73             :   /* For nonce transactions, we store the provided expires_at value here
      74             :      for use by the noncemap comparison functionality.  The actual
      75             :      expires_at value for nonce transactions is rewritten */
      76             :   ulong  nonce_expires_at;
      77             : 
      78             :   /* We want rewards*compute_est to fit in a ulong so that r1/c1 < r2/c2 can be
      79             :      computed as r1*c2 < r2*c1, with the product fitting in a ulong.
      80             :      compute_est has a small natural limit of mid-20 bits. rewards doesn't have
      81             :      a natural limit, so there is some argument to be made for raising the
      82             :      limit for rewards to 40ish bits. The struct has better packing with
      83             :      uint/uint though. */
      84             :   uint                __attribute__((aligned(64))) /* We want the treap fields and the bitsets
      85             :                                                        to be on the same double cache line pair */
      86             :                rewards;     /* in Lamports */
      87             :   uint         compute_est; /* in compute units */
      88             : 
      89             :   /* The treap fields */
      90             :   ushort left;
      91             :   ushort right;
      92             :   ushort parent;
      93             :   ushort prio;
      94             :   ushort prev;
      95             :   ushort next;
      96             : 
      97             :   /* skip: if we skip this transaction more than FD_PACK_SKIP_CNT times
      98             :      for reasons that won't go away until the end of the block, then we
      99             :      want to skip it very quickly.  If skip is in [1, FD_PACK_SKIP_CNT],
     100             :      then that means we have to skip it `skip` more times before taking
     101             :      any action.  If skip>FD_PACK_SKIP_CNT, then it is a compressed slot
     102             :      number during which it should be skipped, and we'll skip it until
     103             :      the compressed slot reaches a new value.  skip is never 0. */
     104             :   ushort skip;
     105             : 
     106             :   FD_PACK_BITSET_DECLARE( rw_bitset ); /* all accts this txn references */
     107             :   FD_PACK_BITSET_DECLARE(  w_bitset ); /* accts this txn write-locks    */
     108             : 
     109             : };
     110             : typedef struct fd_pack_private_ord_txn fd_pack_ord_txn_t;
     111             : 
     112             : /* We require that the payload starts at byte 0 of fd_pack_ord_txn_t,
     113             :    because we cast back and forth between fd_txn_p_t* and
     114             :    fd_pack_ord_txn_t*.
     115             :    GCC and Clang seem to disagree on the rules of offsetof. */
     116             : FD_STATIC_ASSERT( offsetof( fd_pack_ord_txn_t, txn          )==0UL, fd_pack_ord_txn_t );
     117             : #if FD_USING_CLANG
     118             : FD_STATIC_ASSERT( offsetof( fd_txn_p_t,             payload )==0UL, fd_pack_ord_txn_t );
     119             : #else
     120             : FD_STATIC_ASSERT( offsetof( fd_pack_ord_txn_t, txn->payload )==0UL, fd_pack_ord_txn_t );
     121             : FD_STATIC_ASSERT( offsetof( fd_pack_ord_txn_t, txn_e->txnp  )==0UL, fd_pack_ord_txn_t );
     122             : #endif
     123             : 
     124             : /* FD_ORD_TXN_ROOT is essentially a small union packed into an int.  The low
     125             :    byte is the "tag".  The higher 3 bytes depend on the low byte. */
     126     1911642 : #define FD_ORD_TXN_ROOT_TAG_MASK                    0xFF
     127     3061317 : #define FD_ORD_TXN_ROOT_FREE                        0
     128       35302 : #define FD_ORD_TXN_ROOT_PENDING                     1
     129     3766698 : #define FD_ORD_TXN_ROOT_PENDING_BUNDLE              2
     130       30067 : #define FD_ORD_TXN_ROOT_PENALTY( idx )             (3 | (idx)<<8)
     131        1249 : #define FD_ORD_TXN_ROOT_PRE_ROTATION_BUNDLE( idx ) (4 | (idx)<<8)
     132         672 : #define FD_ORD_TXN_ROOT_NEXT_AUCTION                5
     133             : 
     134             : /* if root & TAG_MASK == PENALTY, then PENALTY_ACCT_IDX(root) gives the index
     135             :    in the transaction's list of account addresses of which penalty treap the
     136             :    transaction is in. */
     137             : #define FD_ORD_TXN_ROOT_PENALTY_ACCT_IDX( root )      (((root) & 0xFF00)>>8)
     138             : /* if root & TAG_MASK == PRE_ROTATION_BUNDLE, then
     139             :    PRE_ROTATION_BUNDLE_IDX(root) gives the index in
     140             :    pre_rotation_bundles of the bundle the transaction is in. */
     141         379 : #define FD_ORD_TXN_ROOT_PRE_ROTATION_BUNDLE_IDX( root ) (((root) & 0xFF00)>>8)
     142             : 
     143      163182 : #define FD_PACK_IN_USE_WRITABLE    (0x8000000000000000UL)
     144      137908 : #define FD_PACK_IN_USE_BIT_CLEARED (0x4000000000000000UL)
     145             : 
     146             : /* Each non-empty microblock we schedule also has an overhead of 48
     147             :    bytes that counts towards shed limits.  That comes from the 32 byte
     148             :    hash, the hash count (8 bytes) and the transaction count (8 bytes).
     149             :    We don't have to pay this overhead if the microblock is empty, since
     150             :    those microblocks get dropped. */
     151       31344 : #define MICROBLOCK_DATA_OVERHEAD 48UL
     152             : 
     153             : FD_STATIC_ASSERT( sizeof(fd_acct_addr_t)==sizeof(fd_pubkey_t), "" );
     154             : 
     155             : /* fd_pack_expq_t: An element of an fd_prq to sort the transactions by
     156             :    timeout.  This structure has several invariants for entries
     157             :    corresponding to pending transactions:
     158             :      expires_at == txn->expires_at
     159             :      txn->exp_prq_idx is the index of this structure
     160             :    Notice that prq is an array-based heap, which means the indexes of
     161             :    elements change.  The PRQ_TMP_ST macro is hijacked to keep that
     162             :    invariant up to date.
     163             : 
     164             :    Note: this could be easier if fd_heap supported deleting from the
     165             :    middle, but that's not possible with the current design of fd_heap,
     166             :    which omits a parent pointer for improved performance. */
     167             : struct fd_pack_expq {
     168             :   ulong               expires_at;
     169             :   fd_pack_ord_txn_t * txn;
     170             : };
     171             : typedef struct fd_pack_expq fd_pack_expq_t;
     172             : 
     173             : 
     174             : /* fd_pack_bitset_acct_mapping_t: An element of an fd_map_dynamic that
     175             :    maps an account address to the number of transactions that are
     176             :    referencing it and the bit that is reserved to indicate it in the
     177             :    bitset, if any. */
     178             : struct fd_pack_bitset_acct_mapping {
     179             :   fd_acct_addr_t key; /* account address */
     180             :   ulong          ref_cnt;
     181             : 
     182             :   /* first_instance and first_instance_was_write are only valid when
     183             :      bit==FD_PACK_BITSET_FIRST_INSTANCE, which is set when ref_cnt
     184             :      transitions from 0 to 1.  These just exist to implement the
     185             :      optimization that accounts referenced a single time aren't
     186             :      allocated a bit, but this seems to be an important optimization. */
     187             :   fd_pack_ord_txn_t * first_instance;
     188             :   int                 first_instance_was_write;
     189             : 
     190             :   /* bit is in [0, FD_PACK_BITSET_MAX) U
     191             :      { FD_PACK_BITSET_FIRST_INSTANCE, FD_PACK_BITSET_SLOWPATH }. */
     192             :   ushort              bit;
     193             : };
     194             : typedef struct fd_pack_bitset_acct_mapping fd_pack_bitset_acct_mapping_t;
     195             : 
     196             : 
     197             : struct fd_pack_wcost_ele {
     198             :   fd_acct_addr_t key; /* account address */
     199             :   ulong          total_cost;
     200             :   union {
     201             :     uint         map_next;
     202             :     uint         pool_next;
     203             :   };
     204             :   uint           map_prev;
     205             :   uint           dlist_next;
     206             :   uint           dlist_prev;
     207             : };
     208             : typedef struct fd_pack_wcost_ele fd_pack_wcost_ele_t;
     209             : 
     210             : 
     211             : /* pack maintains a small state machine related to initializer bundles.
     212             :    See the header file for more details about it, but it's
     213             :    also summarized here:
     214             :    * NOT_INITIALIZED: The starting state for each block
     215             :    * PENDING: an initializer bundle has been scheduled, but pack has
     216             :      not observed its result yet, so we don't know if it was successful
     217             :      or not.
     218             :    * FAILED: the most recently scheduled initializer bundle failed
     219             :      for reasons other than already being executed.  Most commonly, this
     220             :      could be because of a bug in the code that generated the
     221             :      initializer bundle, a lack of fee payer balance, or an expired
     222             :      blockhash.
     223             :    * READY: the most recently scheduled initialization bundle succeeded
     224             :      and normal bundles can be scheduled in this slot. */
     225         594 : #define FD_PACK_IB_STATE_NOT_INITIALIZED 0
     226           6 : #define FD_PACK_IB_STATE_PENDING         1
     227           3 : #define FD_PACK_IB_STATE_FAILED          2
     228         165 : #define FD_PACK_IB_STATE_READY           3
     229             : 
     230             : 
     231             : /* Returns 1 if x.rewards/x.compute < y.rewards/y.compute. Not robust. */
     232     7638032 : #define COMPARE_WORSE(x,y) ( ((ulong)((x)->rewards)*(ulong)((y)->compute_est)) < ((ulong)((y)->rewards)*(ulong)((x)->compute_est)) )
     233             : 
     234             : /* Declare all the data structures */
     235             : 
     236             : 
     237             : /* Define the big max-"heap" that we pull transactions off to schedule.
     238             :    The priority is given by reward/compute.  We may want to add in some
     239             :    additional terms at a later point.  In order to cheaply remove nodes,
     240             :    we actually use a treap.  */
     241             : #define POOL_NAME       trp_pool
     242        1728 : #define POOL_T          fd_pack_ord_txn_t
     243             : #define POOL_IDX_T      ushort
     244     4451862 : #define POOL_NEXT       parent
     245             : #include "../../util/tmpl/fd_pool.c"
     246             : 
     247             : #define TREAP_T         fd_pack_ord_txn_t
     248             : #define TREAP_NAME      treap
     249             : #define TREAP_QUERY_T   void *                                         /* We don't use query ... */
     250             : #define TREAP_CMP(a,b)  (__extension__({ (void)(a); (void)(b); -1; })) /* which means we don't need to give a real
     251             :                                                                           implementation to cmp either */
     252    28666338 : #define TREAP_IDX_T     ushort
     253             : #define TREAP_OPTIMIZE_ITERATION 1
     254     7638032 : #define TREAP_LT        COMPARE_WORSE
     255             : #include "../../util/tmpl/fd_treap.c"
     256             : 
     257             : 
     258             : #define MAP_NAME              sig2txn
     259             : #define MAP_OPTIMIZE_RANDOM_ACCESS_REMOVAL 1
     260             : #define MAP_MULTI              1
     261     3795417 : #define MAP_ELE_T              fd_pack_ord_txn_t
     262     5695097 : #define MAP_PREV               sigmap_prev
     263     8865361 : #define MAP_NEXT               sigmap_next
     264     5689466 : #define MAP_IDX_T              ushort
     265             : 
     266             : #define MAP_KEY_T              fd_txn_e_t
     267     3828292 : #define MAP_KEY                _txn_e
     268    13262092 : #define TXNE_TO_SIG(ptr)       (__extension__({ fd_txn_p_t const * __p = (ptr)->txnp; __p->payload + TXN(__p)->signature_off;  }))
     269     3773148 : #define MAP_KEY_EQ(k0,k1)      (!memcmp( TXNE_TO_SIG(k0), TXNE_TO_SIG(k1), FD_TXN_SIGNATURE_SZ) )
     270     5715796 : #define MAP_KEY_HASH(key,seed) fd_hash( (seed), TXNE_TO_SIG(key), 64UL )
     271             : #include "../../util/tmpl/fd_map_chain.c"
     272             : 
     273             : 
     274             : /* noncemap: A map from (nonce account, nonce authority) to a durable
     275             :    nonce transaction containing it.  We only want to allow one
     276             :    transaction in the pool at a time with a given (nonce account, nonce
     277             :    authority) tuple value, keeping the one with the blockhash value
     278             :    derived from the newest blockhash, breaking ties by value.  The
     279             :    question is: can adding this limitation cause us to throw out
     280             :    potentially valuable transaction?  The answer is yes, but only very
     281             :    rarely, and the savings are worth it.  Suppose we have durable nonce
     282             :    transactions t1 and t2 that advance the same nonce account.
     283             : 
     284             :    If t1 and t2 have the same recent blockhash value:
     285             :    - If t1 lands on chain, then it will advance the nonce account, and
     286             :    t2 certainly cannot land on chain.
     287             :    - If t1 fails with AlreadyExecuted, that means the nonce account was
     288             :    advanced when t1 landed in a previous block, so t2 will certainly not
     289             :    land on chain either.
     290             :    - If t1 fails with BlockhashNotFound, then the nonce account was
     291             :    advanced in some previous transaction, so again, t2 will certainly
     292             :    not land on chain.
     293             :    - If t1 does not land on chain because of an issue with the fee
     294             :    payer, it's possible that t2 could land on chain if it used a
     295             :    different fee payer, but historical data shows this is unlikely.
     296             :    - If t1 does not land on chain because it is part of a bundle that
     297             :    fails for an unrelated reason, it's possible that t2 could land on
     298             :    chain, but again, historical data says this is rare.
     299             : 
     300             :    Otherwise, suppose t1's recent blockhash value is the value based on
     301             :    slot s1's blockhash (which is written to nonce accounts when
     302             :    executing in slot s1+1) and similarly for s2, and that s1<s2.
     303             :    Then we'll throw out t1 and only try to pack t2.
     304             : 
     305             :    The sender will only send t2 if they think the nonce account contains
     306             :    (or will contain) the value based on slot s2's blockhash, which means
     307             :    they think a transaction landed or will land in slot s2+1.
     308             :    If a transaction updating the nonce account did land in slot s2+1,
     309             :    then t1 can never land, so throwing it out is safe.
     310             :    It's possible, but seems unlikely, that the sender could be
     311             :    speculating and has only seen slot s2 but not s2+1 yet.  In that
     312             :    case, if we are leader for both s2+1, we could pack t1 in s2+1 and t2
     313             :    in a later slot.  Again, this is a case where we'll take the small
     314             :    hit in exchange for the simplification.
     315             : 
     316             :    We need to include the nonce authority in the hash to prevent one
     317             :    user from being able to DoS another user. */
     318             : 
     319             : typedef struct {
     320             :   fd_acct_addr_t const * nonce_acct;
     321             :   fd_acct_addr_t const * nonce_auth;
     322             : } noncemap_extract_t;
     323             : 
     324             : /* k must be a valid, durable nonce transaction.  No error checking is
     325             :    done. */
     326             : static inline void
     327             : noncemap_extract( fd_txn_e_t const   * k,
     328        3514 :                   noncemap_extract_t * out ) {
     329        3514 :   fd_txn_t const * txn = TXN(k->txnp);
     330             : 
     331        3514 :   ulong nonce_idx = k->txnp->payload[ txn->instr[ 0 ].acct_off+0 ];
     332        3514 :   ulong autho_idx = k->txnp->payload[ txn->instr[ 0 ].acct_off+2 ];
     333             : 
     334        3514 :   ulong imm_cnt = fd_txn_account_cnt( txn, FD_TXN_ACCT_CAT_IMM );
     335        3514 :   fd_acct_addr_t const * accts   = fd_txn_get_acct_addrs( txn, k->txnp->payload );
     336        3514 :   out->nonce_acct = nonce_idx<imm_cnt ? accts+nonce_idx : k->alt_accts+(nonce_idx-imm_cnt);
     337             :   /* The nonce authority must be a signer, so it must be an immediate
     338             :      account. */
     339        3514 :   out->nonce_auth = accts+autho_idx;
     340        3514 : }
     341             : 
     342             : static inline int
     343             : noncemap_key_eq_internal( fd_txn_e_t const * k0,
     344         192 :                           fd_txn_e_t const * k1 ) {
     345         192 :   noncemap_extract_t e0[1], e1[1];
     346         192 :   noncemap_extract( k0, e0 );
     347         192 :   noncemap_extract( k1, e1 );
     348             : 
     349         192 :   if( FD_UNLIKELY( memcmp( e0->nonce_acct,       e1->nonce_acct,       32UL ) ) ) return 0;
     350         186 :   if( FD_UNLIKELY( memcmp( e0->nonce_auth,       e1->nonce_auth,       32UL ) ) ) return 0;
     351         186 :   return 1;
     352         186 : }
     353             : 
     354             : #if FD_HAS_INT128
     355             : 
     356             : /* unrolled xxHash3 */
     357             : 
     358             : static inline ulong
     359             : noncemap_key_hash_internal( ulong              seed,
     360        3130 :                             fd_txn_e_t const * k ) {
     361        3130 :   noncemap_extract_t e[1];
     362        3130 :   noncemap_extract( k, e );
     363             : 
     364        3130 :   ulong k0 = FD_LOAD( ulong, e->nonce_acct->b   + 0 );
     365        3130 :   ulong k1 = FD_LOAD( ulong, e->nonce_acct->b   + 8 );
     366        3130 :   ulong k2 = FD_LOAD( ulong, e->nonce_acct->b   +16 );
     367        3130 :   ulong k3 = FD_LOAD( ulong, e->nonce_acct->b   +24 );
     368        3130 :   ulong k4 = FD_LOAD( ulong, e->nonce_auth->b   + 0 );
     369        3130 :   ulong k5 = FD_LOAD( ulong, e->nonce_auth->b   + 8 );
     370        3130 :   ulong k6 = FD_LOAD( ulong, e->nonce_auth->b   +16 );
     371        3130 :   ulong k7 = FD_LOAD( ulong, e->nonce_auth->b   +24 );
     372             : 
     373        3130 :   ulong acc = 96 * 0x9E3779B185EBCA87ULL;
     374        3130 :   acc += fd_xxh3_mix16b( k4, k5, 0xcb00c391bb52283cUL, 0xa32e531b8b65d088UL, seed );
     375        3130 :   acc += fd_xxh3_mix16b( k6, k7, 0x4ef90da297486471UL, 0xd8acdea946ef1938UL, seed );
     376        3130 :   acc += fd_xxh3_mix16b( k2, k3, 0x78e5c0cc4ee679cbUL, 0x2172ffcc7dd05a82UL, seed );
     377        3130 :   acc += fd_xxh3_mix16b( k0, k1, 0xbe4ba423396cfeb8UL, 0x1cad21f72c81017cUL, seed );
     378        3130 :   acc = acc ^ (acc >> 37);
     379        3130 :   acc *= 0x165667919E3779F9ULL;
     380        3130 :   acc = acc ^ (acc >> 32);
     381        3130 :   return acc;
     382        3130 : }
     383             : 
     384             : #else
     385             : 
     386             : static inline ulong
     387             : noncemap_key_hash_internal( ulong              seed,
     388             :                             fd_txn_e_t const * k ) {
     389             :   noncemap_extract_t e[1];
     390             :   noncemap_extract( k, e );
     391             : 
     392             :   uchar buf[ 64 ];
     393             :   memcpy( buf,      e->nonce_acct->b,     32UL );
     394             :   memcpy( buf+32UL, e->nonce_auth->b,     32UL );
     395             :   return fd_hash( seed, buf, 64UL );
     396             : }
     397             : 
     398             : #endif
     399             : 
     400             : #define MAP_NAME               noncemap
     401             : #define MAP_OPTIMIZE_RANDOM_ACCESS_REMOVAL 1
     402             : #define MAP_MULTI              0
     403         384 : #define MAP_ELE_T              fd_pack_ord_txn_t
     404         415 : #define MAP_PREV               noncemap_prev
     405         979 : #define MAP_NEXT               noncemap_next
     406        4755 : #define MAP_IDX_T              ushort
     407             : #define MAP_KEY_T              fd_txn_e_t
     408         787 : #define MAP_KEY                _txn_e
     409         192 : #define MAP_KEY_EQ(k0,k1)      noncemap_key_eq_internal( (k0), (k1) )
     410        3130 : #define MAP_KEY_HASH(key,seed) noncemap_key_hash_internal( (seed), (key) )
     411             : #include "../../util/tmpl/fd_map_chain.c"
     412             : 
     413             : 
     414             : static const fd_acct_addr_t null_addr = { 0 };
     415             : 
     416             : #define MAP_NAME              acct_uses
     417     2374962 : #define MAP_T                 fd_pack_addr_use_t
     418     2486391 : #define MAP_KEY_T             fd_acct_addr_t
     419    12137327 : #define MAP_KEY_NULL          null_addr
     420             : #if FD_HAS_AVX
     421     2486391 : # define MAP_KEY_INVAL(k)     _mm256_testz_si256( wb_ldu( (k).b ), wb_ldu( (k).b ) )
     422             : #else
     423             : # define MAP_KEY_INVAL(k)     MAP_KEY_EQUAL(k, null_addr)
     424             : #endif
     425     2264099 : #define MAP_KEY_EQUAL(k0,k1)  (!memcmp((k0).b,(k1).b, FD_TXN_ACCT_ADDR_SZ))
     426             : #define MAP_KEY_EQUAL_IS_SLOW 1
     427             : #define MAP_MEMOIZE           0
     428     8226542 : #define MAP_KEY_HASH(key,s)   ((uint)fd_hash32( (key).b, (s) ))
     429             : #include "../../util/tmpl/fd_map_dynamic.c"
     430             : 
     431             : #define MAP_NAME              wcost_map
     432        4842 : #define MAP_ELE_T             fd_pack_wcost_ele_t
     433             : #define MAP_KEY_T             fd_acct_addr_t
     434      191137 : #define MAP_IDX_T             uint
     435       17232 : #define MAP_NEXT              map_next
     436       12242 : #define MAP_PREV              map_prev
     437             : #define MAP_OPTIMIZE_RANDOM_ACCESS_REMOVAL 1
     438       94992 : #define MAP_KEY_EQ(k0,k1)     (!memcmp((k0)->b,(k1)->b, FD_TXN_ACCT_ADDR_SZ))
     439      135922 : #define MAP_KEY_HASH(key,s)   ((uint)fd_hash32( (key)->b, (s) ))
     440             : #include "../../util/tmpl/fd_map_chain.c"
     441             : 
     442             : #define POOL_NAME             wcost_pool
     443        1152 : #define POOL_T                fd_pack_wcost_ele_t
     444             : #define POOL_IDX_T            uint
     445    92176915 : #define POOL_NEXT             pool_next
     446             : #include "../../util/tmpl/fd_pool.c"
     447             : 
     448             : #define DLIST_NAME            wcost_dlist
     449             : #define DLIST_ELE_T           fd_pack_wcost_ele_t
     450             : #define DLIST_IDX_T           uint
     451       16915 : #define DLIST_NEXT            dlist_next
     452       12076 : #define DLIST_PREV            dlist_prev
     453             : #include "../../util/tmpl/fd_dlist.c"
     454             : 
     455             : #define MAP_NAME              bitset_map
     456     9863866 : #define MAP_T                 fd_pack_bitset_acct_mapping_t
     457    11819331 : #define MAP_KEY_T             fd_acct_addr_t
     458    85646478 : #define MAP_KEY_NULL          null_addr
     459             : #if FD_HAS_AVX
     460    83152707 : # define MAP_KEY_INVAL(k)     _mm256_testz_si256( wb_ldu( (k).b ), wb_ldu( (k).b ) )
     461             : #else
     462             : # define MAP_KEY_INVAL(k)     MAP_KEY_EQUAL(k, null_addr)
     463             : #endif
     464     7897825 : #define MAP_KEY_EQUAL(k0,k1)  (!memcmp((k0).b,(k1).b, FD_TXN_ACCT_ADDR_SZ))
     465             : #define MAP_KEY_EQUAL_IS_SLOW 1
     466             : #define MAP_MEMOIZE           0
     467     9861544 : #define MAP_KEY_HASH(key,s)   ((uint)fd_hash32( (key).b, (s) ))
     468             : #include "../../util/tmpl/fd_map_dynamic.c"
     469             : 
     470             : 
     471             : #define MAP_NAME              acct_blocklist
     472     5862729 : #define MAP_T                 wrapped_acct_t
     473             : /* Add 1 to the slot cnt to ensure the map is sparse even at capacity */
     474     5881362 : #define MAP_LG_SLOT_CNT       (FD_PACK_ACCT_BLOCKLIST_LG_MAX+1)
     475     5862156 : #define MAP_KEY_T             fd_acct_addr_t
     476       18624 : #define MAP_KEY_NULL          null_addr
     477             : #if FD_HAS_AVX
     478    11726085 : # define MAP_KEY_INVAL(k)     _mm256_testz_si256( wb_ldu( (k).b ), wb_ldu( (k).b ) )
     479             : #else
     480             : # define MAP_KEY_INVAL(k)     MAP_KEY_EQUAL(k, null_addr)
     481             : #endif
     482     5862093 : #define MAP_KEY_EQUAL(k0,k1)  (!memcmp((k0).b,(k1).b, FD_TXN_ACCT_ADDR_SZ))
     483             : /* It would be nice if this were seeded, but since fd_map doesn't have
     484             :    any auxiliary data, there's not a clear place to store the seed.
     485             :    It's okay though, because the insert process is trusted, since it
     486             :    comes from operator config. */
     487     5862147 : #define MAP_KEY_HASH(key)     ((uint)fd_ulong_hash( fd_ulong_load_8( (key).b ) ))
     488             : #define MAP_KEY_EQUAL_IS_SLOW 1
     489             : #define MAP_MEMOIZE           0
     490             : #define MAX_QUERY_OPT         2 /* rare hits */
     491             : #include "../../util/tmpl/fd_map.c"
     492             : 
     493             : /* Since transactions can also expire, we also maintain a parallel
     494             :    priority queue.  This means elements are simultaneously part of the
     495             :    treap (ordered by priority) and the expiration queue (ordered by
     496             :    expiration).  It's tempting to use the priority field of the treap
     497             :    for this purpose, but that can result in degenerate treaps in some
     498             :    cases. */
     499             : #define PRQ_NAME             expq
     500     3873159 : #define PRQ_T                fd_pack_expq_t
     501     3829056 : #define PRQ_TIMEOUT_T        ulong
     502     3829056 : #define PRQ_TIMEOUT          expires_at
     503     1934544 : #define PRQ_TMP_ST(p,t)      do {                                   \
     504     1934544 :                                (p)[0] = (t);                        \
     505     1934544 :                                t.txn->expq_idx = (ulong)((p)-heap); \
     506     1934544 :                              } while( 0 )
     507             : #include "../../util/tmpl/fd_prq.c"
     508             : 
     509             : /* With realistic traffic patterns, we often see many, many transactions
     510             :    competing for the same writable account.  Since only one of these can
     511             :    execute at a time, we sometimes waste lots of scheduling time going
     512             :    through them one at a time.  To combat that, when a transaction
     513             :    writes to an account with more than PENALTY_TREAP_THRESHOLD
     514             :    references (readers or writers), instead of inserting it into the
     515             :    main treap, we insert it into a penalty treap for that specific hot
     516             :    account address.  These transactions are not immediately available
     517             :    for scheduling.  Then, when a transaction that writes to the hot
     518             :    address completes, we move the most lucrative transaction from the
     519             :    penalty treap to the main treap, making it available for scheduling.
     520             :    This policy may slightly violate the price-time priority scheduling
     521             :    approach pack normally uses: if the most lucrative transaction
     522             :    competing for hot state arrives after PENALTY_TREAP_THRESHOLD has
     523             :    been hit, it may be scheduled second instead of first.  However, if
     524             :    the account is in use at the time the new transaction arrives, it
     525             :    will be scheduled next, as desired.  This minor difference seems
     526             :    reasonable to reduce complexity.
     527             : 
     528             :    fd_pack_penalty_treap is one account-specific penalty treap.  All the
     529             :    transactions in the penalty_treap treap write to key.
     530             : 
     531             :    penalty_map is the fd_map_dynamic that maps accounts to their
     532             :    respective penalty treaps. */
     533             : struct fd_pack_penalty_treap {
     534             :   fd_acct_addr_t key;
     535             :   treap_t penalty_treap[1];
     536             : };
     537             : typedef struct fd_pack_penalty_treap fd_pack_penalty_treap_t;
     538             : 
     539             : #define MAP_NAME              penalty_map
     540       73480 : #define MAP_T                 fd_pack_penalty_treap_t
     541       72343 : #define MAP_KEY_T             fd_acct_addr_t
     542     1307661 : #define MAP_KEY_NULL          null_addr
     543             : #if FD_HAS_AVX
     544     1186927 : # define MAP_KEY_INVAL(k)     _mm256_testz_si256( wb_ldu( (k).b ), wb_ldu( (k).b ) )
     545             : #else
     546             : # define MAP_KEY_INVAL(k)     MAP_KEY_EQUAL(k, null_addr)
     547             : #endif
     548       72301 : #define MAP_KEY_EQUAL(k0,k1)  (!memcmp((k0).b,(k1).b, FD_TXN_ACCT_ADDR_SZ))
     549             : #define MAP_KEY_EQUAL_IS_SLOW 1
     550             : #define MAP_MEMOIZE           0
     551       72322 : #define MAP_KEY_HASH(key,s)   ((uint)fd_hash32( (key).b, (s) ))
     552             : #include "../../util/tmpl/fd_map_dynamic.c"
     553             : 
     554             : /* PENALTY_TREAP_THRESHOLD: How many references to an account do we
     555             :    allow before subsequent transactions that write to the account go to
     556             :    the penalty treap. */
     557     3929241 : #define PENALTY_TREAP_THRESHOLD 64UL
     558             : 
     559             : 
     560             : /* FD_PACK_SKIP_CNT: How many times we'll skip a transaction (for
     561             :    reasons other than account conflicts) before we won't consider it
     562             :    until the next slot.  For performance reasons, this doesn't reset at
     563             :    the end of a slot, so e.g. we might skip twice in slot 1, then three
     564             :    times in slot 2, which would be enough to prevent considering it
     565             :    until slot 3.  The main reason this is not 1 is that some skips that
     566             :    seem permanent until the end of the slot can actually go away based
     567             :    on rebates. */
     568     1917831 : #define FD_PACK_SKIP_CNT 50UL
     569             : 
     570             : /* FD_PACK_PRE_ROTATION_BUNDLE_CAPACITY: the maximum number of the
     571             :    bundles that arrived before our leader rotation which we execute
     572             :    during our leader rotation.  Any extra pre-rotation bundles are
     573             :    dropped, in order of their declared tip. */
     574       13401 : #define FD_PACK_PRE_ROTATION_BUNDLE_CAPACITY 16UL
     575             : 
     576             : /* fd_pack_pre_rotation_bundle represents a single pre-rotation bundle:
     577             :    its transactions, in bundle order, in treap, the declared tip, and
     578             :    the sequence number representing the order of insertion. */
     579             : struct fd_pack_pre_rotation_bundle {
     580             :   treap_t treap[1];
     581             :   ulong   tip;
     582             :   ulong   seq;
     583             : };
     584             : typedef struct fd_pack_pre_rotation_bundle fd_pack_pre_rotation_bundle_t;
     585             : 
     586             : /* Finally, we can now declare the main pack data structure */
     587             : struct fd_pack_private {
     588             :   ulong      pack_depth;
     589             :   ulong      bundle_meta_sz; /* if 0, bundles are disabled */
     590             :   ulong      bank_tile_cnt;
     591             : 
     592             :   fd_pack_limits_t lim[1];
     593             : 
     594             :   ulong      pending_txn_cnt; /* Summed across all treaps */
     595             :   ulong      microblock_cnt; /* How many microblocks have we
     596             :                                 generated in this block? */
     597             :   ulong      data_bytes_consumed; /* How much data is in this block so
     598             :                                      far ? */
     599             :   /* There's a limit on the total amount that transactions in a block
     600             :      can allocate.  How much of that limit have we consumed? */
     601             :   ulong      alloc_consumed;
     602             : 
     603             :   /* counters / gauge for schedule outcome enums */
     604             :   ulong      sched_results[ FD_METRICS_ENUM_PACK_TXN_SCHEDULE_RESULT_CNT ];
     605             : 
     606             :   fd_rng_t * rng;
     607             : 
     608             :   ulong      cumulative_block_cost;
     609             : 
     610             :   /* expire_before: Any transactions with expires_at strictly less than
     611             :      the current expire_before are removed from the available pending
     612             :      transaction.  Here, "expire" is used as a verb: cause all
     613             :      transactions before this time to expire. */
     614             :   ulong      expire_before;
     615             : 
     616             :   /* outstanding_microblock_mask: a bitmask indicating which banking
     617             :      tiles have outstanding microblocks, i.e. fd_pack has generated a
     618             :      microblock for that banking tile and the banking tile has not yet
     619             :      notified fd_pack that it has completed it. */
     620             :   ulong      outstanding_microblock_mask;
     621             : 
     622             :   /* The actual footprint for the pool and maps is allocated
     623             :      in the same order in which they are declared immediately following
     624             :      the struct.  I.e. these pointers point to memory not far after the
     625             :      struct.  The trees are just pointers into the pool so don't take up
     626             :      more space. */
     627             : 
     628             :   fd_pack_ord_txn_t * pool;
     629             : 
     630             :   /* Treaps (sorted by priority) of pending transactions.  We store the
     631             :      transactions that come from bundles separately. */
     632             :   treap_t pending[1];
     633             :   treap_t pending_bundles[1];
     634             : 
     635             :   /* Bundles that arrived before our leader rotation has started are
     636             :      stored in pre_rotation_bundles, one bundle per treap.
     637             :      rotation_end_ns stores the timestamp, in ns, of the end of the
     638             :      last leader rotation, so that we can determine if a bundle arrived
     639             :      during the start of the leader rotation or not.
     640             :      pre_rotation_seq stores an incrementing sequence number, which we
     641             :      use to track the order in which the pre-rotation bundles arrived.
     642             : 
     643             :      We could use a more complex data structure to track the best and
     644             :      worse pre-rotation bundle, but since
     645             :      FD_PACK_PRE_ROTATION_BUNDLE_CAPACITY is so small it's not worth
     646             :      the added complexity. */
     647             :   fd_pack_pre_rotation_bundle_t pre_rotation_bundles[ FD_PACK_PRE_ROTATION_BUNDLE_CAPACITY ];
     648             :   ulong                         pre_rotation_bundle_cnt;
     649             :   ulong                         pre_rotation_seq;
     650             :   long                          rotation_end_ns;
     651             : 
     652             :   /* If an auction is running, new transactions are held in
     653             :      next_auction - they are not eligible to be scheduled. When the
     654             :      auction ends, these are flushed into either the pending or penalty
     655             :      treaps. */
     656             :   treap_t next_auction[1];
     657             :   int     auction_running;
     658             : 
     659             :   /* penalty_treaps: an fd_map_dynamic mapping hotly contended account
     660             :      addresses to treaps of transactions that write to them.  We try not
     661             :      to allow more than roughly PENALTY_TREAP_THRESHOLD transactions in
     662             :      the main treap that write to each account, though this is not
     663             :      exact. */
     664             :   fd_pack_penalty_treap_t * penalty_treaps;
     665             : 
     666             :   /* initializer_bundle_state: The current state of the initialization
     667             :      bundle state machine.  One of the FD_PACK_IB_STATE_* values.  See
     668             :      the long comment in the header and the comments attached to the
     669             :      respective values for a discussion of what each state means and the
     670             :      transitions between them. */
     671             :   int   initializer_bundle_state;
     672             : 
     673             :   /* relative_bundle_idx: the number of bundles that have been inserted
     674             :      since the last time pending_bundles was empty.  See the long
     675             :      comment about encoding this index in the rewards field of each
     676             :      transaction in the bundle, and why it is important that this reset
     677             :      to 0 as frequently as possible. */
     678             :   ulong relative_bundle_idx;
     679             : 
     680             :   /* pending_smallest: keep a conservative estimate of the
     681             :      smallest transaction (by cost units and by bytes) in the pending
     682             :      treap.  Both CUs and bytes should be set to ULONG_MAX if the treap
     683             :      is empty. */
     684             :   fd_pack_smallest_t pending_smallest[1];
     685             : 
     686             :   /* expiration_q: At the same time that a transaction is in exactly one
     687             :      of the above treaps, it is also in the expiration queue, sorted by
     688             :      its expiration time.  This enables deleting all transactions that
     689             :      have expired, regardless of which treap they are in. */
     690             :   fd_pack_expq_t * expiration_q;
     691             : 
     692             :   /* acct_in_use: Map from account address to bitmask indicating which
     693             :      bank tiles are using the account and whether that use is read or
     694             :      write (msb). */
     695             :   fd_pack_addr_use_t   * acct_in_use;
     696             : 
     697             :   /* bitset_{w, rw}_in_use stores a subset of the information in
     698             :      acct_in_use using the compressed set format explained at the top of
     699             :      this file.  rw_in_use stores accounts in use for read or write
     700             :      while w_in_use stores only those in use for write. */
     701             :   FD_PACK_BITSET_DECLARE( bitset_rw_in_use );
     702             :   FD_PACK_BITSET_DECLARE( bitset_w_in_use  );
     703             : 
     704             :   /* writer_costs: Map (fd_map_chain) from account addresses to the sum
     705             :      of costs of transactions that write to the account.  Used for
     706             :      enforcing limits on the max write cost per account per block. */
     707             :   wcost_map_t   * writer_costs;
     708             : 
     709             :   /* written_list: At the end of every slot, we have to clear out
     710             :      writer_costs.  The map is large, but typically very sparsely
     711             :      populated.  As an optimization, we keep a doubly linked list of the
     712             :      elements actually used */
     713             :   wcost_dlist_t  written_list[1];
     714             : 
     715             :   /* writers: This is the fd_pool that backs writer_costs and
     716             :      written_list.  Each element is either in writers (as a fd_pool) OR
     717             :      in both writer_costs and written_list. */
     718             :   fd_pack_wcost_ele_t  * writers;
     719             : 
     720             :   /* top_writers: A simple max heap of the top 5 writers in the slot,
     721             :      used by downstream consumers for monitoring purposes. */
     722             :   fd_pack_addr_use_t top_writers[ FD_PACK_TOP_WRITERS_CNT ];
     723             : 
     724             :   /* At initialization time, the caller can configure a blocklist of
     725             :      accounts.  Any transaction that includes one of these accounts will
     726             :      be rejected.  This is an fd_map, and it's effectively const. */
     727             :   wrapped_acct_t        acct_blocklist[ 2*FD_PACK_ACCT_BLOCKLIST_MAX ];
     728             : 
     729             :   /* Noncemap is a map_chain that maps from tuples (nonce account,
     730             :      nonce authority) to a transaction.  This
     731             :      map stores exactly the transactions in pool that have the nonce
     732             :      flag set. */
     733             :   noncemap_t * noncemap;
     734             : 
     735             :   sig2txn_t * signature_map; /* Stores pointers into pool for deleting by signature */
     736             : 
     737             :   /* bundle_temp_map: A fd_map_dynamic (although it could be an fd_map)
     738             :      used during fd_pack_try_schedule_bundle to store information about
     739             :      what accounts are used by transactions in the bundle.  It's empty
     740             :      (in a map sense) outside of calls to try_schedule_bundle, and each
     741             :      call to try_schedule_bundle clears it after use.  If bundles are
     742             :      disabled, this is a valid fd_map_dynamic, but it's as small as
     743             :      convenient and remains empty. */
     744             :   fd_pack_addr_use_t * bundle_temp_map;
     745             : 
     746             : 
     747             :   /* use_by_bank: An array of size (max_txn_per_microblock *
     748             :      FD_TXN_ACCT_ADDR_MAX + 1) for each banking tile.  Addressed as
     749             :      use_by_bank[i][j] where i is in [0, bank_tile_cnt) and j is in
     750             :      [0, use_by_bank_cnt[i]).  Used to release account locks when a
     751             :      microblock finishes.
     752             : 
     753             :      use_by_bank_txn[i][j] stores the cumulative end offset in
     754             :      use_by_bank[i] for transaction j in the outstanding microblock.
     755             :      Indexed by i in [0, bank_tile_cnt) and j in
     756             :      [0, max_txn_per_microblock). */
     757             :   fd_pack_addr_use_t * use_by_bank    [ FD_PACK_MAX_EXECLE_TILES ];
     758             :   ulong                use_by_bank_cnt[ FD_PACK_MAX_EXECLE_TILES ];
     759             :   ulong *              use_by_bank_txn[ FD_PACK_MAX_EXECLE_TILES ];
     760             : 
     761             :   fd_histf_t txn_per_microblock[ 1 ];
     762             : 
     763             :   fd_histf_t scheduled_cus_per_block[ 1 ];
     764             :   fd_histf_t rebated_cus_per_block  [ 1 ];
     765             :   fd_histf_t net_cus_per_block      [ 1 ];
     766             :   fd_histf_t pct_cus_per_block      [ 1 ];
     767             :   ulong      cumulative_rebated_cus;
     768             : 
     769             : 
     770             :   /* compressed_slot_number: a number in (FD_PACK_SKIP_CNT, USHORT_MAX]
     771             :      that advances each time we start packing for a new slot. */
     772             :   ushort     compressed_slot_number;
     773             : 
     774             :   /* bitset_avail: a stack of which bits are not currently reserved and
     775             :      can be used to represent an account address.
     776             :      Indexed [0, bitset_avail_cnt].  Element 0 is fixed at
     777             :      FD_PACK_BITSET_SLOWPATH. */
     778             :   ushort bitset_avail[ 1UL+FD_PACK_BITSET_MAX ];
     779             :   ulong  bitset_avail_cnt;
     780             : 
     781             :   /* acct_to_bitset: an fd_map_dynamic that maps acct addresses to the
     782             :      reference count, which bit, etc. */
     783             :   fd_pack_bitset_acct_mapping_t * acct_to_bitset;
     784             : 
     785             :   /* chdkup: scratch memory chkdup needs for its internal processing */
     786             :   fd_chkdup_t chkdup[ 1 ];
     787             : 
     788             :   /* bundle_meta: an array, parallel to the pool, with each element
     789             :      having size bundle_meta_sz.  I.e. if pool[i] has an associated
     790             :      bundle meta, it's located at bundle_meta[j] for j in
     791             :      [i*bundle_meta_sz, (i+1)*bundle_meta_sz). */
     792             :   void * bundle_meta;
     793             : };
     794             : 
     795             : typedef struct fd_pack_private fd_pack_t;
     796             : 
     797             : FD_STATIC_ASSERT( offsetof(fd_pack_t, pending_txn_cnt)==FD_PACK_PENDING_TXN_CNT_OFF, txn_cnt_off );
     798             : 
     799             : /* Forward-declare some helper functions */
     800             : static ulong delete_transaction( fd_pack_t * pack, fd_pack_ord_txn_t * txn, int delete_full_bundle, int move_from_penalty_treap );
     801             : static inline void insert_bundle_impl( fd_pack_t * pack, ulong bundle_idx, ulong txn_cnt, fd_pack_ord_txn_t * * bundle, ulong expires_at );
     802             : static inline ulong insert_pre_rotation_bundle_impl( fd_pack_t * pack, ulong txn_cnt, fd_pack_ord_txn_t * * bundle, ulong expires_at, ulong pre_rotation_tip );
     803             : 
     804             : FD_FN_PURE ulong
     805             : fd_pack_footprint( ulong                    pack_depth,
     806             :                    ulong                    bundle_meta_sz,
     807             :                    ulong                    bank_tile_cnt,
     808         567 :                    fd_pack_limits_t const * limits         ) {
     809         567 :   if( FD_UNLIKELY( (bank_tile_cnt==0) | (bank_tile_cnt>FD_PACK_MAX_EXECLE_TILES) ) ) return 0UL;
     810         567 :   if( FD_UNLIKELY( pack_depth<4UL ) ) return 0UL;
     811             : 
     812         567 :   int enable_bundles = !!bundle_meta_sz;
     813         567 :   ulong l;
     814         567 :   ulong extra_depth        = fd_ulong_if( enable_bundles, 1UL+2UL*FD_PACK_MAX_TXN_PER_BUNDLE, 1UL ); /* space for use between init and fini */
     815         567 :   ulong max_acct_in_treap  = pack_depth * FD_TXN_ACCT_ADDR_MAX;
     816         567 :   ulong max_txn_per_mblk   = fd_ulong_max( limits->max_txn_per_microblock,
     817         567 :                                            fd_ulong_if( enable_bundles, FD_PACK_MAX_TXN_PER_BUNDLE, 0UL ) );
     818         567 :   ulong max_acct_in_flight = bank_tile_cnt * (FD_TXN_ACCT_ADDR_MAX * max_txn_per_mblk + 1UL);
     819         567 :   ulong max_txn_in_flight  = bank_tile_cnt * max_txn_per_mblk;
     820             : 
     821         567 :   ulong max_w_per_block    = fd_ulong_min( limits->max_cost_per_block / FD_PACK_COST_PER_WRITABLE_ACCT,
     822         567 :                                            max_txn_per_mblk * limits->max_microblocks_per_block * FD_TXN_ACCT_ADDR_MAX );
     823         567 :   ulong wcost_chain_cnt    = wcost_map_chain_cnt_est( max_w_per_block );
     824         567 :   ulong bundle_temp_accts  = fd_ulong_if( enable_bundles, FD_PACK_MAX_TXN_PER_BUNDLE*FD_TXN_ACCT_ADDR_MAX, 1UL );
     825         567 :   ulong sig_chain_cnt      = sig2txn_chain_cnt_est( pack_depth );
     826         567 :   ulong nonce_chain_cnt    = noncemap_chain_cnt_est( pack_depth );
     827             : 
     828             :   /* log base 2, but with a 2* so that the hash table stays sparse */
     829         567 :   int lg_uses_tbl_sz = fd_ulong_find_msb( fd_ulong_pow2_up( 2UL*max_acct_in_flight                        ) );
     830         567 :   int lg_acct_in_trp = fd_ulong_find_msb( fd_ulong_pow2_up( 2UL*max_acct_in_treap                         ) );
     831         567 :   int lg_penalty_trp = fd_ulong_find_msb( fd_ulong_pow2_up( 2UL*max_acct_in_treap/PENALTY_TREAP_THRESHOLD ) );
     832         567 :   int lg_bundle_temp = fd_ulong_find_msb( fd_ulong_pow2_up( 2UL*bundle_temp_accts                         ) );
     833             : 
     834         567 :   l = FD_LAYOUT_INIT;
     835         567 :   l = FD_LAYOUT_APPEND( l, FD_PACK_ALIGN,       sizeof(fd_pack_t)                               );
     836         567 :   l = FD_LAYOUT_APPEND( l, trp_pool_align (),   trp_pool_footprint ( pack_depth+extra_depth   ) ); /* pool           */
     837         567 :   l = FD_LAYOUT_APPEND( l, penalty_map_align(), penalty_map_footprint( lg_penalty_trp         ) ); /* penalty_treaps */
     838         567 :   l = FD_LAYOUT_APPEND( l, expq_align     (),   expq_footprint     ( pack_depth               ) ); /* expiration prq */
     839         567 :   l = FD_LAYOUT_APPEND( l, acct_uses_align(),   acct_uses_footprint( lg_uses_tbl_sz           ) ); /* acct_in_use    */
     840         567 :   l = FD_LAYOUT_APPEND( l, wcost_map_align(),   wcost_map_footprint( wcost_chain_cnt          ) ); /* writer_costs   */
     841         567 :   l = FD_LAYOUT_APPEND( l, wcost_pool_align(),  wcost_pool_footprint( max_w_per_block         ) ); /* writers        */
     842         567 :   l = FD_LAYOUT_APPEND( l, noncemap_align (),   noncemap_footprint ( nonce_chain_cnt          ) ); /* noncemap       */
     843         567 :   l = FD_LAYOUT_APPEND( l, sig2txn_align  (),   sig2txn_footprint  ( sig_chain_cnt            ) ); /* signature_map  */
     844         567 :   l = FD_LAYOUT_APPEND( l, acct_uses_align(),   acct_uses_footprint( lg_bundle_temp           ) ); /* bundle_temp_map*/
     845         567 :   l = FD_LAYOUT_APPEND( l, 32UL,                sizeof(fd_pack_addr_use_t)*max_acct_in_flight   ); /* use_by_bank    */
     846         567 :   l = FD_LAYOUT_APPEND( l, 32UL,                sizeof(ulong)*max_txn_in_flight                 ); /* use_by_bank_txn*/
     847         567 :   l = FD_LAYOUT_APPEND( l, bitset_map_align(),  bitset_map_footprint( lg_acct_in_trp          ) ); /* acct_to_bitset */
     848         567 :   l = FD_LAYOUT_APPEND( l, 64UL,                (pack_depth+extra_depth)*bundle_meta_sz         ); /* bundle_meta */
     849         567 :   return FD_LAYOUT_FINI( l, FD_PACK_ALIGN );
     850         567 : }
     851             : 
     852             : void *
     853             : fd_pack_new( void                   * mem,
     854             :              ulong                    pack_depth,
     855             :              ulong                    bundle_meta_sz,
     856             :              ulong                    bank_tile_cnt,
     857             :              fd_pack_limits_t const * limits,
     858             :              fd_acct_addr_t const *   acct_blocklist,
     859             :              ulong                    acct_blocklist_cnt,
     860         582 :              fd_rng_t               * rng           ) {
     861             : 
     862         582 :   int enable_bundles = !!bundle_meta_sz;
     863         582 :   ulong extra_depth        = fd_ulong_if( enable_bundles, 1UL+2UL*FD_PACK_MAX_TXN_PER_BUNDLE, 1UL );
     864         582 :   ulong max_acct_in_treap  = pack_depth * FD_TXN_ACCT_ADDR_MAX;
     865         582 :   ulong max_txn_per_mblk   = fd_ulong_max( limits->max_txn_per_microblock,
     866         582 :                                            fd_ulong_if( enable_bundles, FD_PACK_MAX_TXN_PER_BUNDLE, 0UL ) );
     867         582 :   ulong max_acct_in_flight = bank_tile_cnt * (FD_TXN_ACCT_ADDR_MAX * max_txn_per_mblk + 1UL);
     868         582 :   ulong max_txn_in_flight  = bank_tile_cnt * max_txn_per_mblk;
     869             : 
     870         582 :   ulong max_w_per_block    = fd_ulong_min( limits->max_cost_per_block / FD_PACK_COST_PER_WRITABLE_ACCT,
     871         582 :                                            max_txn_per_mblk * limits->max_microblocks_per_block * FD_TXN_ACCT_ADDR_MAX );
     872         582 :   ulong wcost_chain_cnt    = wcost_map_chain_cnt_est( max_w_per_block );
     873         582 :   ulong bundle_temp_accts  = fd_ulong_if( enable_bundles, FD_PACK_MAX_TXN_PER_BUNDLE*FD_TXN_ACCT_ADDR_MAX, 1UL );
     874         582 :   ulong sig_chain_cnt      = sig2txn_chain_cnt_est( pack_depth );
     875         582 :   ulong nonce_chain_cnt    = noncemap_chain_cnt_est( pack_depth );
     876             : 
     877             :   /* log base 2, but with a 2* so that the hash table stays sparse */
     878         582 :   int lg_uses_tbl_sz = fd_ulong_find_msb( fd_ulong_pow2_up( 2UL*max_acct_in_flight                        ) );
     879         582 :   int lg_acct_in_trp = fd_ulong_find_msb( fd_ulong_pow2_up( 2UL*max_acct_in_treap                         ) );
     880         582 :   int lg_penalty_trp = fd_ulong_find_msb( fd_ulong_pow2_up( 2UL*max_acct_in_treap/PENALTY_TREAP_THRESHOLD ) );
     881         582 :   int lg_bundle_temp = fd_ulong_find_msb( fd_ulong_pow2_up( 2UL*bundle_temp_accts                         ) );
     882             : 
     883         582 :   FD_SCRATCH_ALLOC_INIT( l, mem );
     884         582 :   fd_pack_t * pack    = FD_SCRATCH_ALLOC_APPEND( l,  FD_PACK_ALIGN,       sizeof(fd_pack_t)                             );
     885             :   /* The pool has one extra element that is used between insert_init and
     886             :      cancel/fini. */
     887         582 :   void * _pool        = FD_SCRATCH_ALLOC_APPEND( l,  trp_pool_align(),    trp_pool_footprint ( pack_depth+extra_depth ) );
     888         582 :   void * _penalty_map = FD_SCRATCH_ALLOC_APPEND( l,  penalty_map_align(), penalty_map_footprint( lg_penalty_trp       ) );
     889         582 :   void * _expq        = FD_SCRATCH_ALLOC_APPEND( l,  expq_align(),        expq_footprint     ( pack_depth             ) );
     890         582 :   void * _uses        = FD_SCRATCH_ALLOC_APPEND( l,  acct_uses_align(),   acct_uses_footprint( lg_uses_tbl_sz         ) );
     891         582 :   void * _writer_cost = FD_SCRATCH_ALLOC_APPEND( l,  wcost_map_align(),   wcost_map_footprint( wcost_chain_cnt        ) );
     892         582 :   void * _written_lst = FD_SCRATCH_ALLOC_APPEND( l,  wcost_pool_align(),  wcost_pool_footprint( max_w_per_block       ) );
     893         582 :   void * _noncemap    = FD_SCRATCH_ALLOC_APPEND( l,  noncemap_align(),    noncemap_footprint ( nonce_chain_cnt        ) );
     894         582 :   void * _sig_map     = FD_SCRATCH_ALLOC_APPEND( l,  sig2txn_align(),     sig2txn_footprint  ( sig_chain_cnt          ) );
     895         582 :   void * _bundle_temp = FD_SCRATCH_ALLOC_APPEND( l,  acct_uses_align(),   acct_uses_footprint( lg_bundle_temp         ) );
     896         582 :   void * _use_by_bank = FD_SCRATCH_ALLOC_APPEND( l,  32UL,                sizeof(fd_pack_addr_use_t)*max_acct_in_flight );
     897         582 :   void * _use_by_txn  = FD_SCRATCH_ALLOC_APPEND( l,  32UL,                sizeof(ulong)*max_txn_in_flight               );
     898         582 :   void * _acct_bitset = FD_SCRATCH_ALLOC_APPEND( l,  bitset_map_align(),  bitset_map_footprint( lg_acct_in_trp        ) );
     899         582 :   void * bundle_meta  = FD_SCRATCH_ALLOC_APPEND( l,  64UL,                (pack_depth+extra_depth)*bundle_meta_sz       );
     900             : 
     901         582 :   pack->pack_depth                  = pack_depth;
     902         582 :   pack->bundle_meta_sz              = bundle_meta_sz;
     903         582 :   pack->bank_tile_cnt               = bank_tile_cnt;
     904         582 :   pack->lim[0]                      = *limits;
     905         582 :   pack->pending_txn_cnt             = 0UL;
     906         582 :   pack->microblock_cnt              = 0UL;
     907         582 :   pack->data_bytes_consumed         = 0UL;
     908         582 :   pack->alloc_consumed              = 0UL;
     909         582 :   memset( pack->sched_results, 0, sizeof(pack->sched_results) );
     910         582 :   pack->rng                         = rng;
     911         582 :   pack->cumulative_block_cost       = 0UL;
     912         582 :   pack->expire_before               = 0UL;
     913         582 :   pack->outstanding_microblock_mask = 0UL;
     914         582 :   pack->cumulative_rebated_cus      = 0UL;
     915         582 :   pack->initializer_bundle_state    = FD_PACK_IB_STATE_NOT_INITIALIZED;
     916         582 :   pack->relative_bundle_idx         = 1UL;
     917             : 
     918         582 :   acct_blocklist_new( pack->acct_blocklist );
     919         582 :   int ins_failed = acct_blocklist_cnt>FD_PACK_ACCT_BLOCKLIST_MAX;
     920         648 :   for( ulong i=0UL; (!ins_failed) & (i<acct_blocklist_cnt); i++ ) {
     921          66 :     ins_failed |= acct_blocklist_key_inval( acct_blocklist[i] ) ||
     922          66 :                   (NULL==acct_blocklist_insert( pack->acct_blocklist, acct_blocklist[i] ));
     923          66 :   }
     924         582 :   if( FD_UNLIKELY( ins_failed ) ) {
     925           6 :     FD_LOG_WARNING(( "constructing the account blocklist failed.  Ensure the list contains no more than %lu "
     926           6 :                      "entries, and does not contain duplicates or the System Program (11...111)", FD_PACK_ACCT_BLOCKLIST_MAX ));
     927           6 :     return NULL;
     928           6 :   }
     929             : 
     930         576 :   trp_pool_new(  _pool,        pack_depth+extra_depth );
     931             : 
     932         576 :   fd_pack_ord_txn_t * pool = trp_pool_join( _pool );
     933         576 :   treap_seed( pool, pack_depth+extra_depth, fd_rng_ulong( rng ) );
     934      620700 :   for( ulong i=0UL; i<pack_depth+extra_depth; i++ ) pool[i].root = FD_ORD_TXN_ROOT_FREE;
     935             : 
     936         576 :   (void)trp_pool_leave( pool );
     937             : 
     938         576 :   penalty_map_new( _penalty_map, lg_penalty_trp, fd_rng_ulong( rng ) );
     939             : 
     940             :   /* These treaps can have at most pack_depth elements at any moment,
     941             :      but they come from a pool of size pack_depth+extra_depth. */
     942         576 :   treap_new( (void*)pack->pending,         pack_depth+extra_depth );
     943         576 :   treap_new( (void*)pack->pending_bundles, pack_depth+extra_depth );
     944         576 :   treap_new( (void*)pack->next_auction,    pack_depth+extra_depth );
     945        9792 :   for( ulong i=0UL; i<FD_PACK_PRE_ROTATION_BUNDLE_CAPACITY; i++ ) {
     946        9216 :     treap_new( (void*)pack->pre_rotation_bundles[ i ].treap, pack_depth+extra_depth );
     947        9216 :   }
     948             : 
     949         576 :   pack->pre_rotation_bundle_cnt = 0UL;
     950         576 :   pack->pre_rotation_seq        = 0UL;
     951         576 :   pack->rotation_end_ns         = 0L;
     952         576 :   pack->auction_running         = 0;
     953             : 
     954         576 :   pack->pending_smallest->cus         = ULONG_MAX;
     955         576 :   pack->pending_smallest->bytes       = ULONG_MAX;
     956             : 
     957         576 :   expq_new( _expq, pack_depth );
     958             : 
     959         576 :   FD_PACK_BITSET_CLEAR( pack->bitset_rw_in_use );
     960         576 :   FD_PACK_BITSET_CLEAR( pack->bitset_w_in_use  );
     961             : 
     962         576 :   acct_uses_new( _uses,        lg_uses_tbl_sz, fd_rng_ulong( rng ) );
     963         576 :   acct_uses_new( _bundle_temp, lg_bundle_temp, fd_rng_ulong( rng ) );
     964             : 
     965         576 :   wcost_map_new  ( _writer_cost, wcost_chain_cnt, fd_rng_ulong( rng ) );
     966         576 :   wcost_dlist_new( pack->written_list                                 );
     967         576 :   wcost_pool_new ( _written_lst, max_w_per_block                      );
     968             : 
     969         576 :   noncemap_new( _noncemap, nonce_chain_cnt, fd_rng_ulong( rng ) );
     970             : 
     971         576 :   sig2txn_new( _sig_map, sig_chain_cnt, fd_rng_ulong( rng ) );
     972             : 
     973         576 :   fd_pack_addr_use_t * use_by_bank     = (fd_pack_addr_use_t *)_use_by_bank;
     974         576 :   ulong *              use_by_bank_txn = (ulong *)_use_by_txn;
     975        6852 :   for( ulong i=0UL; i<bank_tile_cnt; i++ ) {
     976        6276 :     pack->use_by_bank    [i] = use_by_bank + i*(FD_TXN_ACCT_ADDR_MAX*max_txn_per_mblk+1UL);
     977        6276 :     pack->use_by_bank_cnt[i] = 0UL;
     978        6276 :     pack->use_by_bank_txn[i] = use_by_bank_txn + i*max_txn_per_mblk;
     979        6276 :     pack->use_by_bank_txn[i][0] = 0UL;
     980        6276 :   }
     981       30012 :   for( ulong i=bank_tile_cnt; i<FD_PACK_MAX_EXECLE_TILES; i++ ) {
     982       29436 :     pack->use_by_bank    [i] = NULL;
     983       29436 :     pack->use_by_bank_cnt[i] = 0UL;
     984       29436 :     pack->use_by_bank_txn[i] = NULL;
     985       29436 :   }
     986             : 
     987         576 :   fd_histf_new( pack->txn_per_microblock, FD_MHIST_MIN( PACK, TXN_PER_MICROBLOCK ),
     988         576 :                                           FD_MHIST_MAX( PACK, TXN_PER_MICROBLOCK ) );
     989             : 
     990         576 :   fd_histf_new( pack->scheduled_cus_per_block, FD_MHIST_MIN( PACK, COST_SCHEDULED_PER_BLOCK ),
     991         576 :                                                FD_MHIST_MAX( PACK, COST_SCHEDULED_PER_BLOCK ) );
     992         576 :   fd_histf_new( pack->rebated_cus_per_block,   FD_MHIST_MIN( PACK, CU_REBATED_PER_BLOCK     ),
     993         576 :                                                FD_MHIST_MAX( PACK, CU_REBATED_PER_BLOCK     ) );
     994         576 :   fd_histf_new( pack->net_cus_per_block,       FD_MHIST_MIN( PACK, COST_NET_PER_BLOCK       ),
     995         576 :                                                FD_MHIST_MAX( PACK, COST_NET_PER_BLOCK       ) );
     996         576 :   fd_histf_new( pack->pct_cus_per_block,       FD_MHIST_MIN( PACK, COST_PER_BLOCK_PCT       ),
     997         576 :                                                FD_MHIST_MAX( PACK, COST_PER_BLOCK_PCT       ) );
     998             : 
     999         576 :   pack->compressed_slot_number = (ushort)(FD_PACK_SKIP_CNT+1);
    1000             : 
    1001         576 :   pack->bitset_avail[ 0 ] = FD_PACK_BITSET_SLOWPATH;
    1002      197184 :   for( ulong i=0UL; i<FD_PACK_BITSET_MAX; i++ ) pack->bitset_avail[ i+1UL ] = (ushort)i;
    1003         576 :   pack->bitset_avail_cnt = FD_PACK_BITSET_MAX;
    1004             : 
    1005         576 :   bitset_map_new( _acct_bitset, lg_acct_in_trp, fd_rng_ulong( rng ) );
    1006             : 
    1007         576 :   fd_chkdup_new( pack->chkdup, rng );
    1008             : 
    1009         576 :   pack->bundle_meta = bundle_meta;
    1010             : 
    1011         576 :   return mem;
    1012         582 : }
    1013             : 
    1014             : fd_pack_t *
    1015         576 : fd_pack_join( void * mem ) {
    1016         576 :   FD_SCRATCH_ALLOC_INIT( l, mem );
    1017         576 :   fd_pack_t * pack  = FD_SCRATCH_ALLOC_APPEND( l, FD_PACK_ALIGN, sizeof(fd_pack_t) );
    1018             : 
    1019         576 :   int enable_bundles = !!pack->bundle_meta_sz;
    1020         576 :   ulong pack_depth             = pack->pack_depth;
    1021         576 :   ulong extra_depth            = fd_ulong_if( enable_bundles, 1UL+2UL*FD_PACK_MAX_TXN_PER_BUNDLE, 1UL );
    1022         576 :   ulong bank_tile_cnt          = pack->bank_tile_cnt;
    1023         576 :   ulong max_txn_per_microblock = fd_ulong_max( pack->lim->max_txn_per_microblock,
    1024         576 :                                                fd_ulong_if( enable_bundles, FD_PACK_MAX_TXN_PER_BUNDLE, 0UL ) );
    1025             : 
    1026         576 :   ulong max_acct_in_treap  = pack_depth * FD_TXN_ACCT_ADDR_MAX;
    1027         576 :   ulong max_acct_in_flight = bank_tile_cnt * (FD_TXN_ACCT_ADDR_MAX * max_txn_per_microblock + 1UL);
    1028         576 :   ulong max_txn_in_flight  = bank_tile_cnt * max_txn_per_microblock;
    1029         576 :   ulong max_w_per_block    = fd_ulong_min( pack->lim->max_cost_per_block / FD_PACK_COST_PER_WRITABLE_ACCT,
    1030         576 :                                            max_txn_per_microblock * pack->lim->max_microblocks_per_block * FD_TXN_ACCT_ADDR_MAX );
    1031         576 :   ulong wcost_chain_cnt    = wcost_map_chain_cnt_est( max_w_per_block );
    1032         576 :   ulong bundle_temp_accts  = fd_ulong_if( enable_bundles, FD_PACK_MAX_TXN_PER_BUNDLE*FD_TXN_ACCT_ADDR_MAX, 1UL );
    1033         576 :   ulong sig_chain_cnt      = sig2txn_chain_cnt_est( pack_depth );
    1034         576 :   ulong nonce_chain_cnt    = noncemap_chain_cnt_est( pack_depth );
    1035             : 
    1036         576 :   int lg_uses_tbl_sz = fd_ulong_find_msb( fd_ulong_pow2_up( 2UL*max_acct_in_flight                        ) );
    1037         576 :   int lg_acct_in_trp = fd_ulong_find_msb( fd_ulong_pow2_up( 2UL*max_acct_in_treap                         ) );
    1038         576 :   int lg_penalty_trp = fd_ulong_find_msb( fd_ulong_pow2_up( 2UL*max_acct_in_treap/PENALTY_TREAP_THRESHOLD ) );
    1039         576 :   int lg_bundle_temp = fd_ulong_find_msb( fd_ulong_pow2_up( 2UL*bundle_temp_accts                         ) );
    1040             : 
    1041             : 
    1042         576 :   pack->pool          = trp_pool_join(   FD_SCRATCH_ALLOC_APPEND( l, trp_pool_align(),   trp_pool_footprint   ( pack_depth+extra_depth  ) ) );
    1043         576 :   pack->penalty_treaps= penalty_map_join(FD_SCRATCH_ALLOC_APPEND( l, penalty_map_align(),penalty_map_footprint( lg_penalty_trp          ) ) );
    1044         576 :   pack->expiration_q  = expq_join    (   FD_SCRATCH_ALLOC_APPEND( l, expq_align(),       expq_footprint       ( pack_depth              ) ) );
    1045         576 :   pack->acct_in_use   = acct_uses_join(  FD_SCRATCH_ALLOC_APPEND( l, acct_uses_align(),  acct_uses_footprint  ( lg_uses_tbl_sz          ) ) );
    1046         576 :   pack->writer_costs  = wcost_map_join(  FD_SCRATCH_ALLOC_APPEND( l, wcost_map_align(),  wcost_map_footprint  ( wcost_chain_cnt         ) ) );
    1047         576 :   pack->writers       = wcost_pool_join( FD_SCRATCH_ALLOC_APPEND( l, wcost_pool_align(), wcost_pool_footprint( max_w_per_block          ) ) );
    1048         576 :   pack->noncemap      = noncemap_join(   FD_SCRATCH_ALLOC_APPEND( l, noncemap_align(),   noncemap_footprint   ( nonce_chain_cnt         ) ) );
    1049         576 :   pack->signature_map = sig2txn_join(    FD_SCRATCH_ALLOC_APPEND( l, sig2txn_align(),    sig2txn_footprint    ( sig_chain_cnt           ) ) );
    1050         576 :   pack->bundle_temp_map=acct_uses_join(  FD_SCRATCH_ALLOC_APPEND( l, acct_uses_align(),  acct_uses_footprint  ( lg_bundle_temp          ) ) );
    1051         576 :   /* */                                  FD_SCRATCH_ALLOC_APPEND( l, 32UL,               sizeof(fd_pack_addr_use_t)*max_acct_in_flight      );
    1052         576 :   /* */                                  FD_SCRATCH_ALLOC_APPEND( l, 32UL,               sizeof(ulong)*max_txn_in_flight                    );
    1053         576 :   pack->acct_to_bitset= bitset_map_join( FD_SCRATCH_ALLOC_APPEND( l, bitset_map_align(), bitset_map_footprint( lg_acct_in_trp           ) ) );
    1054         576 :   /* */                                  FD_SCRATCH_ALLOC_APPEND( l, 64UL,               (pack_depth+extra_depth)*pack->bundle_meta_sz      );
    1055             : 
    1056         576 :   wcost_dlist_join( pack->written_list );
    1057             : 
    1058         576 :   FD_MGAUGE_SET( PACK, TXN_PENDING_CAPACITY, pack->pack_depth );
    1059         576 :   memset( pack->top_writers, 0, sizeof(pack->top_writers) );
    1060             : 
    1061         576 :   return pack;
    1062         576 : }
    1063             : 
    1064             : 
    1065             : /* Returns 0 on failure, 1 on success. */
    1066             : static int
    1067             : fd_pack_estimate_rewards_and_compute( fd_txn_e_t             * txne,
    1068             :                                       fd_pack_ord_txn_t      * out,
    1069     1917423 :                                       fd_pack_limits_t const * lim ) {
    1070     1917423 :   fd_txn_t * txn = TXN(txne->txnp);
    1071     1917423 :   ulong sig_rewards = FD_PACK_FEE_PER_SIGNATURE * txn->signature_cnt; /* Easily in [5000, 635000] */
    1072             : 
    1073     1917423 :   ulong requested_execution_cus;
    1074     1917423 :   ulong priority_rewards;
    1075     1917423 :   ulong precompile_sigs;
    1076     1917423 :   ulong requested_loaded_accounts_data_cost;
    1077     1917423 :   ulong allocated_data;
    1078     1917423 :   ulong cost_estimate = fd_pack_compute_cost( txn, txne->txnp->payload, &requested_execution_cus, &priority_rewards, &precompile_sigs, &requested_loaded_accounts_data_cost, &allocated_data );
    1079             : 
    1080     1917423 :   if( FD_UNLIKELY( !cost_estimate ) ) return 0;
    1081             : 
    1082     1917420 :   sig_rewards += FD_PACK_FEE_PER_SIGNATURE * precompile_sigs;
    1083     1917420 :   sig_rewards = sig_rewards * FD_PACK_TXN_FEE_BURN_PCT / 100UL;
    1084             : 
    1085             :   /* No fancy CU estimation in this version of pack
    1086             :   for( ulong i=0UL; i<(ulong)txn->instr_cnt; i++ ) {
    1087             :     uchar prog_id_idx = txn->instr[ i ].program_id;
    1088             :     fd_acct_addr_t const * acct_addr = fd_txn_get_acct_addrs( txn, txnp->payload ) + (ulong)prog_id_idx;
    1089             :   }
    1090             :   */
    1091     1917420 :   out->rewards                              = (priority_rewards < (UINT_MAX - sig_rewards)) ? (uint)(sig_rewards + priority_rewards) : UINT_MAX;
    1092     1917420 :   out->compute_est                          = (uint)cost_estimate;
    1093     1917420 :   out->txn->pack_cu.requested_exec_plus_acct_data_cus = (uint)(requested_execution_cus + requested_loaded_accounts_data_cost);
    1094     1917420 :   out->txn->pack_cu.non_execution_cus       = (uint)(cost_estimate - requested_execution_cus - requested_loaded_accounts_data_cost);
    1095     1917420 :   out->txn->pack_alloc                      = (uint)allocated_data;
    1096             : 
    1097             :   /* If a transaction allocates a lot, we want to treat it as if it
    1098             :      requests more CUs.  However, we use compute_est in the block
    1099             :      limit calculations, so we can't touch it.  To have the same
    1100             :      effect, we decrease rewards.
    1101             :      divisor is 1 unless
    1102             :             allocated_data                       cost_estimate
    1103             :       ----------------------------    >=       ------------------
    1104             :       max_allocated_data_per_block             max_cost_per_block
    1105             : 
    1106             :      0       <=allocated_data      <=20 * 1024^2
    1107             :      30*10^6 <= max_cost_per_block < 2^32
    1108             :      1020    <= cost_estimate      < 1.6 * 10^6
    1109             :      50*10^6 <= max_allocated_data_per_block <= 100 * 1000^2
    1110             :                 (changes with the slot time duration)
    1111             :      So the numerator (<2^57) and denominator (<2^48) can't overflow.
    1112             :      Both cost_estimate and max_allocated_data_per_block non-zero,
    1113             :      so the denominator is never zero.
    1114             :      */
    1115     1917420 :   ulong divisor = 1UL + (allocated_data * lim->max_cost_per_block) / (cost_estimate * lim->max_allocated_data_per_block);
    1116     1917420 :   out->rewards /= (uint)divisor;
    1117             : 
    1118     1917420 :   return 1;
    1119     1917423 : }
    1120             : 
    1121             : /* Returns 0 on failure, 1 if not a durable nonce transaction, and 2 if
    1122             :    it is.  FIXME: These return codes are set to harmonize with
    1123             :    estimate_rewards_and_compute but -1/0/1 makes a lot more sense to me.
    1124             :    */
    1125             : static int
    1126     1917420 : fd_pack_validate_durable_nonce( fd_txn_e_t * txne ) {
    1127     1917420 :   fd_txn_t const * txn = TXN(txne->txnp);
    1128             : 
    1129             :   /* First instruction invokes system program with 4 bytes of
    1130             :      instruction data with the little-endian value 4.  It also has 3
    1131             :      accounts: the nonce account, recent blockhashes sysvar, and the
    1132             :      nonce authority.  It seems like technically the nonce authority may
    1133             :      not need to be passed in, but we disallow that.  We also allow
    1134             :      trailing data and trailing accounts.  We want to organize the
    1135             :      checks somewhat to minimize cache misses. */
    1136     1917420 :   if( FD_UNLIKELY( txn->instr_cnt==0            ) ) return 1;
    1137     1917420 :   if( FD_UNLIKELY( txn->instr[ 0 ].data_sz<4UL  ) ) return 1;
    1138     1917420 :   if( FD_UNLIKELY( txn->instr[ 0 ].acct_cnt<3UL ) ) return 1; /* It seems like technically 2 is allowed, but never used */
    1139        5004 :   if( FD_LIKELY  ( fd_uint_load_4( txne->txnp->payload + txn->instr[ 0 ].data_off )!=4U ) ) return 1;
    1140             :   /* The program has to be a static account */
    1141        1194 :   fd_acct_addr_t const * accts = fd_txn_get_acct_addrs( txn, txne->txnp->payload );
    1142        1194 :   if( FD_UNLIKELY( !fd_memeq( accts[ txn->instr[ 0 ].program_id ].b, null_addr.b, 32UL       ) ) ) return 1;
    1143             :   /* SIMD-0242 requires the nonce account to be static. */
    1144        1194 :   if( FD_UNLIKELY( txne->txnp->payload[ txn->instr[ 0 ].acct_off ]>=txn->acct_addr_cnt ) ) return 1;
    1145        1191 :   if( FD_UNLIKELY( !fd_txn_is_writable( txn, txne->txnp->payload[ txn->instr[ 0 ].acct_off ] ) ) ) return 1;
    1146        1182 :   if( FD_UNLIKELY( !fd_txn_is_signer( txn, txne->txnp->payload[ txn->instr[ 0 ].acct_off+2 ] ) ) ) return 0;
    1147             :   /* We could check recent blockhash, but it's not necessary */
    1148        1179 :   return 2;
    1149        1182 : }
    1150             : 
    1151             : /* Can the fee payer afford to pay a transaction with the specified
    1152             :    price?  Returns 1 if so, 0 otherwise.  This is just a stub that
    1153             :    always returns 1 for now, and the real check is deferred to the bank
    1154             :    tile.  In general, this function can't be totally accurate, because
    1155             :    the transactions immediately prior to this one can affect the balance
    1156             :    of this fee payer, but a simple check here may be helpful for
    1157             :    reducing spam. */
    1158             : static int
    1159             : fd_pack_can_fee_payer_afford( fd_acct_addr_t const * acct_addr,
    1160     1917411 :                               ulong                  price /* in lamports */) {
    1161     1917411 :   (void)acct_addr;
    1162     1917411 :   (void)price;
    1163     1917411 :   return 1;
    1164     1917411 : }
    1165             : 
    1166             : 
    1167             : 
    1168             : 
    1169             : 
    1170             : fd_txn_e_t *
    1171       32943 : fd_pack_insert_txn_init( fd_pack_t * pack ) {
    1172       32943 :   fd_pack_ord_txn_t * ord = trp_pool_ele_acquire( pack->pool );
    1173             :   /* fini clears the bitsets; nothing on the way there touches those
    1174             :      lines and a just-evicted element has them cold.  The two sets are
    1175             :      adjacent and span at most two lines, whatever the bitset mode. */
    1176       32943 :   __builtin_prefetch( &ord->rw_bitset,                                         1, 3 );
    1177       32943 :   __builtin_prefetch( (uchar const *)&ord->w_bitset+sizeof(ord->w_bitset)-1UL, 1, 3 );
    1178       32943 :   return ord->txn_e;
    1179       32943 : }
    1180           0 : void         fd_pack_insert_txn_cancel( fd_pack_t * pack, fd_txn_e_t * txn ) { trp_pool_ele_release( pack->pool, (fd_pack_ord_txn_t*)txn ); }
    1181             : 
    1182          75 : #define REJECT( reason ) do {                                       \
    1183          75 :                            trp_pool_ele_release( pack->pool, ord ); \
    1184          75 :                            return FD_PACK_INSERT_REJECT_ ## reason; \
    1185          75 :                          } while( 0 )
    1186             : 
    1187             : /* These require txn, accts, and alt to be defined as per usual */
    1188    35409679 : #define ACCT_IDX_TO_PTR( idx ) (__extension__( {                                               \
    1189    35409679 :       ulong __idx = (ulong)(idx);                                                              \
    1190    35409679 :       ulong __imm = fd_txn_account_cnt( txn, FD_TXN_ACCT_CAT_IMM );                            \
    1191    35409679 :       __idx<__imm ? accts+__idx : alt+(__idx-__imm);                                           \
    1192    35409679 :       }))
    1193    35379426 : #define ACCT_ITER_TO_PTR( iter ) ACCT_IDX_TO_PTR( fd_txn_acct_iter_idx( iter ) )
    1194             : 
    1195             : 
    1196             : /* Tries to find the worst transaction in any treap in pack.  If that
    1197             :    transaction's score is worse than or equal to threshold_score, it
    1198             :    initiates a delete and returns the number of deleted transactions
    1199             :    (potentially more than 1 for a bundle).  If it's higher than
    1200             :    threshold_score, it returns 0.  To force this function to delete the
    1201             :    worst transaction if there are any eligible ones, pass FLT_MAX as
    1202             :    threshold_score. */
    1203             : static inline ulong
    1204             : delete_worst( fd_pack_t * pack,
    1205        3156 :               float       threshold_score ) {
    1206             :   /* If the tree is full, we want to see if this is better than the
    1207             :      worst element in the pool before inserting.  If the new transaction
    1208             :      is better than that one, we'll delete it and insert the new
    1209             :      transaction. Otherwise, we'll throw away this transaction.
    1210             : 
    1211             :      We want to bias the definition of "worst" here to provide better
    1212             :      quality of service.  For example, if the pool is filled with
    1213             :      transactions that all write to the same account, we want to bias
    1214             :      towards treating one of those transactions as the worst, even if
    1215             :      they pay slightly higher fees per computer unit, since we know we
    1216             :      won't actually be able to schedule them all.
    1217             : 
    1218             :      This is a tricky task, however.  All our notions of priority and
    1219             :      better/worse are based on static information about the transaction,
    1220             :      and there's not an easy way to take into account global
    1221             :      information, for example, how many other transactions contend with
    1222             :      this one.  One idea is to build a heap (not a treap, since we only
    1223             :      need pop-min, insert, and delete) with one element for each element
    1224             :      in the pool, with a "delete me" score that's related but not
    1225             :      identical to the normal score.  This would allow building in some
    1226             :      global information.  The downside is that the global information
    1227             :      that gets integrated is static.  E.g. if you bias a transaction's
    1228             :      "delete me" score to make it more likely to be deleted because
    1229             :      there are many conflicting transactions in the pool, the score
    1230             :      stays biased, even if the global conditions change (unless you come
    1231             :      up with some complicated re-scoring scheme).  This can work, since
    1232             :      when the pool is full, the global bias factors are unlikely to
    1233             :      change significantly at the relevant timescales.
    1234             : 
    1235             :      However, rather than this, we implement a simpler probabilistic
    1236             :      scheme.  We'll sample M transactions, find the worst transaction in
    1237             :      each of the M treaps, compute a "delete me" score for those <= M
    1238             :      transactions, and delete the worst.  If one penalty treap is
    1239             :      starting to get big, then it becomes very likely that the random
    1240             :      sample will find it and choose to delete a transaction from it.
    1241             : 
    1242             :      The exact formula for the "delete me" score should be the matter of
    1243             :      some more intense quantitative research.  For now, we'll just use
    1244             :      this:
    1245             : 
    1246             :      Treap with N transactions        Scale Factor
    1247             :      Pending                      1.0
    1248             :      Next auction                 same as pending
    1249             :      Penalty treap                1.0 at <= 100 transactions, then sqrt(100/N)
    1250             :      Pending bundles              inf (since the rewards value is fudged)
    1251             : 
    1252             :      We'll also use M=8. */
    1253             : 
    1254        3156 :   float worst_score = FLT_MAX;
    1255        3156 :   fd_pack_ord_txn_t * worst = NULL;
    1256        3156 :   uint  pool_max = (uint)trp_pool_max( pack->pool );
    1257        3156 :   ulong samples[ 8UL ];
    1258       28404 :   for( ulong i=0UL; i<8UL; i++ ) {
    1259             :     /* Roll all 8 first so the root loads (8 cold lines) overlap */
    1260       25248 :     samples[ i ] = fd_rng_uint_roll( pack->rng, pool_max );
    1261       25248 :     __builtin_prefetch( &pack->pool[ samples[ i ] ].root, 0, 3 );
    1262       25248 :   }
    1263       28404 :   for( ulong i=0UL; i<8UL; i++ ) {
    1264       25248 :     ulong sample_i = samples[ i ];
    1265             : 
    1266       25248 :     fd_pack_ord_txn_t * sample = &pack->pool[ sample_i ];
    1267             :     /* Presumably if we're calling this, the pool is almost entirely
    1268             :        full, so the probability of choosing a free one is small.  If
    1269             :        it does happen, find the first one that isn't free. */
    1270       28016 :     while( FD_UNLIKELY( sample->root==FD_ORD_TXN_ROOT_FREE ) ) sample = &pack->pool[ (++sample_i)%pool_max ];
    1271             : 
    1272       25248 :     int       root_idx   = sample->root;
    1273       25248 :     float     multiplier = 0.0f; /* The smaller this is, the more biased we'll be to deleting it */
    1274       25248 :     treap_t * treap;
    1275       25248 :     switch( root_idx & FD_ORD_TXN_ROOT_TAG_MASK ) {
    1276           0 :       default:
    1277           0 :       case FD_ORD_TXN_ROOT_FREE: {
    1278           0 :         FD_LOG_CRIT(( "Double free detected" ));
    1279           0 :         return ULONG_MAX; /* Can't be hit */
    1280           0 :       }
    1281        3637 :       case FD_ORD_TXN_ROOT_PENDING: {
    1282        3637 :         treap = pack->pending;
    1283        3637 :         multiplier = 1.0f;
    1284        3637 :         break;
    1285           0 :       }
    1286           0 :       case FD_ORD_TXN_ROOT_NEXT_AUCTION: {
    1287           0 :         treap = pack->next_auction;
    1288           0 :         multiplier = 1.0f;
    1289           0 :         break;
    1290           0 :       }
    1291           0 :       case FD_ORD_TXN_ROOT_PENDING_BUNDLE: {
    1292             :         /* We don't have a way to tell how much these actually pay in
    1293             :            rewards, so we just assume they are very high. */
    1294           0 :         treap = pack->pending_bundles;
    1295             :         /* We cap rewards at UINT_MAX lamports for estimation, and min
    1296             :            CUs is about 1000, which means rewards/compute < 5e6.
    1297             :            FLT_MAX is around 3e38. That means, 1e20*rewards/compute is
    1298             :            much less than FLT_MAX, so we won't have any issues with
    1299             :            overflow.  On the other hand, if rewards==1 lamport and
    1300             :            compute is 2 million CUs, 1e20*1/2e6 is still higher than any
    1301             :            normal transaction. */
    1302           0 :         multiplier = 1e20f;
    1303           0 :         break;
    1304           0 :       }
    1305         355 :       case FD_ORD_TXN_ROOT_PRE_ROTATION_BUNDLE( 0 ): {
    1306         355 :         treap      = pack->pre_rotation_bundles[ FD_ORD_TXN_ROOT_PRE_ROTATION_BUNDLE_IDX( root_idx ) ].treap;
    1307         355 :         multiplier = 1e20f;
    1308         355 :         break;
    1309           0 :       }
    1310       21256 :       case FD_ORD_TXN_ROOT_PENALTY( 0 ): {
    1311       21256 :         fd_txn_t * txn = TXN( sample->txn );
    1312       21256 :         fd_acct_addr_t const * accts   = fd_txn_get_acct_addrs( txn, sample->txn->payload );
    1313       21256 :         fd_acct_addr_t const * alt     = sample->txn_e->alt_accts;
    1314       21256 :         fd_acct_addr_t penalty_acct = *ACCT_IDX_TO_PTR( FD_ORD_TXN_ROOT_PENALTY_ACCT_IDX( root_idx ) );
    1315       21256 :         fd_pack_penalty_treap_t * q = penalty_map_query( pack->penalty_treaps, penalty_acct, NULL );
    1316       21256 :         FD_TEST( q );
    1317       21256 :         ulong cnt = treap_ele_cnt( q->penalty_treap );
    1318       21256 :         treap = q->penalty_treap;
    1319             : 
    1320       21256 :         multiplier = sqrtf( 100.0f / (float)fd_ulong_max( 100UL, cnt ) );
    1321       21256 :         break;
    1322       21256 :       }
    1323       25248 :     }
    1324             :     /* Get the worst from the sampled treap */
    1325       25248 :     treap_fwd_iter_t _cur=treap_fwd_iter_init( treap, pack->pool );
    1326       25248 :     FD_TEST( !treap_fwd_iter_done( _cur ) ); /* It can't be empty because we just sampled an element from it. */
    1327       25248 :     sample = treap_fwd_iter_ele( _cur, pack->pool );
    1328             : 
    1329       25248 :     float score = multiplier * (float)sample->rewards / (float)sample->compute_est;
    1330       25248 :     worst = fd_ptr_if( score<worst_score, sample, worst );
    1331       25248 :     worst_score = fd_float_if( worst_score<score, worst_score, score );
    1332       25248 :   }
    1333             : 
    1334        3156 :   if( FD_UNLIKELY( !worst                      ) ) return 0;
    1335        3156 :   if( FD_UNLIKELY( threshold_score<worst_score ) ) return 0;
    1336             : 
    1337             :   /* The next eviction most likely takes worst's in-order successor;
    1338             :      warm what delete_transaction reads of it: the treap node, the
    1339             :      payload's account addresses, the metadata and the parsed txn. */
    1340        3123 :   treap_fwd_iter_t nxt = treap_fwd_iter_next( (treap_fwd_iter_t)treap_idx_fast( worst, pack->pool ), pack->pool );
    1341        3123 :   if( FD_LIKELY( !treap_fwd_iter_done( nxt ) ) ) {
    1342        3123 :     fd_pack_ord_txn_t const * n = pack->pool + nxt;
    1343        3123 :     __builtin_prefetch( &n->root,              0, 3 );
    1344        3123 :     __builtin_prefetch( &n->rewards,           0, 3 );
    1345        3123 :     __builtin_prefetch( n->txn->payload+ 64UL, 0, 3 );
    1346        3123 :     __builtin_prefetch( n->txn->payload+128UL, 0, 3 );
    1347        3123 :     __builtin_prefetch( &n->txn->payload_sz,   0, 3 );
    1348        3123 :     __builtin_prefetch( TXN( n->txn ),         0, 3 );
    1349        3123 :   }
    1350             : 
    1351        3123 :   return delete_transaction( pack, worst, 1, 1 );
    1352        3156 : }
    1353             : 
    1354             : static inline int
    1355             : validate_transaction( fd_pack_t               * pack,
    1356             :                       fd_pack_ord_txn_t const * ord,
    1357             :                       fd_txn_t          const * txn,
    1358             :                       fd_acct_addr_t    const * accts,
    1359             :                       fd_acct_addr_t    const * alt,
    1360     1917411 :                       int                       check_bundle_blacklist ) {
    1361     1917411 :   int writes_to_sysvar = 0;
    1362     1917411 :   for( fd_txn_acct_iter_t iter=fd_txn_acct_iter_init( txn, FD_TXN_ACCT_CAT_WRITABLE );
    1363     3886029 :       iter!=fd_txn_acct_iter_end(); iter=fd_txn_acct_iter_next( iter ) ) {
    1364     1968618 :     writes_to_sysvar |= fd_pack_unwritable_contains( ACCT_ITER_TO_PTR( iter ) );
    1365     1968618 :   }
    1366             : 
    1367     1917411 :   int bundle_blacklist = 0;
    1368     1917411 :   int acct_blocklist   = 0;
    1369     1917411 :   for( fd_txn_acct_iter_t iter=fd_txn_acct_iter_init( txn, FD_TXN_ACCT_CAT_ALL );
    1370     7781274 :       iter!=fd_txn_acct_iter_end(); iter=fd_txn_acct_iter_next( iter ) ) {
    1371     5863863 :     bundle_blacklist |= (3==fd_pack_tip_prog_check_blacklist( ACCT_ITER_TO_PTR( iter ) ));
    1372             :     /* querying for the inval key is a violation of the fd_map
    1373             :        contract, even though it's actually fine... */
    1374     5863863 :     acct_blocklist   |= (!acct_blocklist_key_inval( *ACCT_ITER_TO_PTR( iter ) )) &&
    1375     5863863 :                         !!acct_blocklist_query( pack->acct_blocklist, *ACCT_ITER_TO_PTR( iter ), NULL );
    1376     5863863 :   }
    1377             : 
    1378     1917411 :   fd_chkdup_t * chkdup = pack->chkdup;
    1379     1917411 :   ulong imm_cnt = fd_txn_account_cnt( txn, FD_TXN_ACCT_CAT_IMM );
    1380     1917411 :   ulong alt_cnt = fd_txn_account_cnt( txn, FD_TXN_ACCT_CAT_ALT );
    1381             : 
    1382             :   /* Throw out transactions ... */
    1383             :   /*           ... that are unfunded */
    1384     1917411 :   if( FD_UNLIKELY( !fd_pack_can_fee_payer_afford( accts, ord->rewards    ) ) ) return FD_PACK_INSERT_REJECT_UNAFFORDABLE;
    1385             :   /*           ... that are so big they'll never run */
    1386     1917411 :   if( FD_UNLIKELY( ord->compute_est >= pack->lim->max_cost_per_block       ) ) return FD_PACK_INSERT_REJECT_TOO_LARGE;
    1387             :   /*           ... that load too many accounts (ignoring 9LZdXeKGeBV6hRLdxS1rHbHoEUsKqesCC2ZAPTPKJAbK) */
    1388     1917411 :   if( FD_UNLIKELY( fd_txn_account_cnt( txn, FD_TXN_ACCT_CAT_ALL )>64UL     ) ) return FD_PACK_INSERT_REJECT_ACCOUNT_CNT;
    1389             :   /*           ... that duplicate an account address */
    1390     1917408 :   if( FD_UNLIKELY( fd_chkdup_check( chkdup, accts, imm_cnt, alt, alt_cnt ) ) ) return FD_PACK_INSERT_REJECT_DUPLICATE_ACCT;
    1391             :   /*           ... that try to write to a sysvar */
    1392     1917405 :   if( FD_UNLIKELY( writes_to_sysvar                                        ) ) return FD_PACK_INSERT_REJECT_WRITES_SYSVAR;
    1393             :   /*           ... that use an account that violates bundle rules */
    1394     1917312 :   if( FD_UNLIKELY( bundle_blacklist & !!check_bundle_blacklist             ) ) return FD_PACK_INSERT_REJECT_BUNDLE_BLACKLIST;
    1395             :   /*           ... that use a blocklisted account */
    1396     1917312 :   if( FD_UNLIKELY( acct_blocklist                                          ) ) return FD_PACK_INSERT_REJECT_ACCT_BLOCKLIST;
    1397             : 
    1398     1917297 :   return 0;
    1399     1917312 : }
    1400             : 
    1401             : 
    1402             : 
    1403             : /* returns cumulative penalty "points", i.e. the sum of the populated
    1404             :    section of penalties (which also tells the caller how much of the
    1405             :    array is populated. */
    1406             : static inline ulong
    1407             : populate_bitsets( fd_pack_t         * pack,
    1408             :                   fd_pack_ord_txn_t * ord,
    1409             :                   ushort              penalties  [ static FD_TXN_ACCT_ADDR_MAX ],
    1410     1916187 :                   uchar               penalty_idx[ static FD_TXN_ACCT_ADDR_MAX ] ) {
    1411     1916187 :   FD_PACK_BITSET_CLEAR( ord->rw_bitset );
    1412     1916187 :   FD_PACK_BITSET_CLEAR( ord->w_bitset  );
    1413             : 
    1414     1916187 :   fd_txn_t * txn   = TXN(ord->txn);
    1415     1916187 :   uchar * payload  = ord->txn->payload;
    1416             : 
    1417     1916187 :   fd_acct_addr_t const * accts   = fd_txn_get_acct_addrs( txn, payload );
    1418     1916187 :   fd_acct_addr_t const * alt     = ord->txn_e->alt_accts;
    1419             : 
    1420     1916187 :   ulong  cumulative_penalty = 0UL;
    1421     1916187 :   ulong  penalty_i          = 0UL;
    1422             : 
    1423             :   /* Scheduling this transaction looks every account up in acct_in_use,
    1424             :      whose slot for a fresh account is a cold line; warm them now. */
    1425     1916187 :   {
    1426     1916187 :     ulong uses_seed = acct_uses_seed( pack->acct_in_use );
    1427     1916187 :     ulong uses_mask = acct_uses_slot_cnt( pack->acct_in_use )-1UL;
    1428     1916187 :     for( fd_txn_acct_iter_t iter=fd_txn_acct_iter_init( txn, FD_TXN_ACCT_CAT_WRITABLE|FD_TXN_ACCT_CAT_READONLY );
    1429     7769097 :         iter!=fd_txn_acct_iter_end(); iter=fd_txn_acct_iter_next( iter ) ) {
    1430     5852910 :       ulong slot = acct_uses_key_hash( *ACCT_ITER_TO_PTR( iter ), uses_seed ) & uses_mask;
    1431     5852910 :       __builtin_prefetch( pack->acct_in_use+slot, 0, 2 );
    1432     5852910 :     }
    1433     1916187 :   }
    1434             : 
    1435     1916187 :   for( fd_txn_acct_iter_t iter=fd_txn_acct_iter_init( txn, FD_TXN_ACCT_CAT_WRITABLE );
    1436     3879945 :       iter!=fd_txn_acct_iter_end(); iter=fd_txn_acct_iter_next( iter ) ) {
    1437     1963758 :     fd_acct_addr_t acct = *ACCT_ITER_TO_PTR( iter );
    1438     1963758 :     fd_pack_bitset_acct_mapping_t * q = bitset_map_query( pack->acct_to_bitset, acct, NULL );
    1439     1963758 :     if( FD_UNLIKELY( q==NULL ) ) {
    1440     1939732 :       q = bitset_map_insert( pack->acct_to_bitset, acct );
    1441     1939732 :       q->ref_cnt                  = 0UL;
    1442     1939732 :       q->first_instance           = ord;
    1443     1939732 :       q->first_instance_was_write = 1;
    1444     1939732 :       q->bit                      = FD_PACK_BITSET_FIRST_INSTANCE;
    1445     1939732 :     } else if( FD_UNLIKELY( q->bit == FD_PACK_BITSET_FIRST_INSTANCE ) ) {
    1446        1874 :       q->bit = pack->bitset_avail[ pack->bitset_avail_cnt ];
    1447        1874 :       pack->bitset_avail_cnt = fd_ulong_if( !!pack->bitset_avail_cnt, pack->bitset_avail_cnt-1UL, 0UL );
    1448             : 
    1449        1874 :       FD_PACK_BITSET_SETN( q->first_instance->rw_bitset, q->bit );
    1450        1874 :       if( q->first_instance_was_write ) FD_PACK_BITSET_SETN( q->first_instance->w_bitset, q->bit );
    1451        1874 :     }
    1452     1963758 :     ulong penalty = fd_ulong_max( q->ref_cnt, PENALTY_TREAP_THRESHOLD )-PENALTY_TREAP_THRESHOLD;
    1453     1963758 :     if( FD_UNLIKELY( penalty ) ) {
    1454       17667 :       penalties  [ penalty_i ] = (ushort)penalty;
    1455       17667 :       penalty_idx[ penalty_i ] = (uchar )fd_txn_acct_iter_idx( iter );
    1456       17667 :       penalty_i++;
    1457       17667 :       cumulative_penalty += penalty;
    1458       17667 :     }
    1459             : 
    1460     1963758 :     q->ref_cnt++;
    1461     1963758 :     FD_PACK_BITSET_SETN( ord->rw_bitset, q->bit );
    1462     1963758 :     FD_PACK_BITSET_SETN( ord->w_bitset , q->bit );
    1463     1963758 :   }
    1464             : 
    1465     1916187 :   for( fd_txn_acct_iter_t iter=fd_txn_acct_iter_init( txn, FD_TXN_ACCT_CAT_READONLY );
    1466     5805339 :       iter!=fd_txn_acct_iter_end(); iter=fd_txn_acct_iter_next( iter ) ) {
    1467             : 
    1468     3889152 :     fd_acct_addr_t acct = *ACCT_ITER_TO_PTR( iter );
    1469     3889152 :     if( FD_UNLIKELY( fd_pack_unwritable_contains( &acct ) ) ) continue;
    1470             : 
    1471     1964106 :     fd_pack_bitset_acct_mapping_t * q = bitset_map_query( pack->acct_to_bitset, acct, NULL );
    1472     1964106 :     if( FD_UNLIKELY( q==NULL ) ) {
    1473       24135 :       q = bitset_map_insert( pack->acct_to_bitset, acct );
    1474       24135 :       q->ref_cnt                  = 0UL;
    1475       24135 :       q->first_instance           = ord;
    1476       24135 :       q->first_instance_was_write = 0;
    1477       24135 :       q->bit                      = FD_PACK_BITSET_FIRST_INSTANCE;
    1478     1939971 :     } else if( FD_UNLIKELY( q->bit == FD_PACK_BITSET_FIRST_INSTANCE ) ) {
    1479        3729 :       q->bit = pack->bitset_avail[ pack->bitset_avail_cnt ];
    1480        3729 :       pack->bitset_avail_cnt = fd_ulong_if( !!pack->bitset_avail_cnt, pack->bitset_avail_cnt-1UL, 0UL );
    1481             : 
    1482        3729 :       FD_PACK_BITSET_SETN( q->first_instance->rw_bitset, q->bit );
    1483        3729 :       if( q->first_instance_was_write ) FD_PACK_BITSET_SETN( q->first_instance->w_bitset, q->bit );
    1484        3729 :     }
    1485             : 
    1486     1964106 :     q->ref_cnt++;
    1487     1964106 :     FD_PACK_BITSET_SETN( ord->rw_bitset, q->bit );
    1488     1964106 :   }
    1489     1916187 :   return cumulative_penalty;
    1490     1916187 : }
    1491             : 
    1492             : static void
    1493             : insert_txn( fd_pack_t         * pack,
    1494       32757 :             fd_pack_ord_txn_t * ord ) {
    1495             :   /* If an auction is running, all incoming transactions should be
    1496             :        held in next_auction until the auction has ended. */
    1497       32757 :   if( pack->auction_running ) {
    1498          12 :     ord->root = FD_ORD_TXN_ROOT_NEXT_AUCTION;
    1499          12 :     treap_ele_insert( pack->next_auction, ord, pack->pool );
    1500          12 :     return;
    1501          12 :   }
    1502             : 
    1503       32745 :   fd_txn_t *             txn     = TXN( ord->txn );
    1504       32745 :   fd_acct_addr_t const * accts   = fd_txn_get_acct_addrs( txn, ord->txn->payload );
    1505       32745 :   fd_acct_addr_t const * alt     = ord->txn_e->alt_accts;
    1506             : 
    1507             :   /* Since the pool uses ushorts, the size of the pool is < USHORT_MAX.
    1508             :      Each transaction can reference an account at most once, which means
    1509             :      that the total number of references for an account is < USHORT_MAX.
    1510             :      If these were ulongs, the array would be 512B, which is kind of a
    1511             :      lot to zero out.*/
    1512       32745 :   ushort penalties[ FD_TXN_ACCT_ADDR_MAX ] = {0};
    1513       32745 :   uchar  penalty_idx[ FD_TXN_ACCT_ADDR_MAX ];
    1514       32745 :   ulong cumulative_penalty = populate_bitsets( pack, ord, penalties, penalty_idx );
    1515             : 
    1516       32745 :   treap_t * insert_into = pack->pending;
    1517             : 
    1518       32745 :   if( FD_UNLIKELY( cumulative_penalty ) ) { /* Optimize for high parallelism case */
    1519             :     /* Compute a weighted random choice */
    1520        6159 :     ulong roll = (ulong)fd_rng_uint_roll( pack->rng, (uint)cumulative_penalty ); /* cumulative_penalty < USHORT_MAX*64 < UINT_MAX */
    1521        6159 :     ulong i = 0UL;
    1522             :     /* Find the right one.  This can be done in O(log N), but I imagine
    1523             :        N is normally so small that doesn't matter. */
    1524       11941 :     while( roll>=penalties[i] ) roll -= (ulong)penalties[i++];
    1525             : 
    1526        6159 :     fd_acct_addr_t penalty_acct = *ACCT_IDX_TO_PTR( penalty_idx[i] );
    1527        6159 :     fd_pack_penalty_treap_t * q = penalty_map_query( pack->penalty_treaps, penalty_acct, NULL );
    1528        6159 :     if( FD_UNLIKELY( q==NULL ) ) {
    1529          21 :       q = penalty_map_insert( pack->penalty_treaps, penalty_acct );
    1530          21 :       treap_new( q->penalty_treap, trp_pool_max( pack->pool ) );
    1531          21 :     }
    1532        6159 :     insert_into = q->penalty_treap;
    1533        6159 :     ord->root = FD_ORD_TXN_ROOT_PENALTY( penalty_idx[i] );
    1534       26586 :   } else {
    1535       26586 :     ord->root = FD_ORD_TXN_ROOT_PENDING;
    1536             : 
    1537       26586 :     pack->pending_smallest->cus   = fd_ulong_min( pack->pending_smallest->cus,   ord->compute_est      );
    1538       26586 :     pack->pending_smallest->bytes = fd_ulong_min( pack->pending_smallest->bytes, ord->txn->payload_sz );
    1539       26586 :   }
    1540             : 
    1541       32745 :   treap_ele_insert( insert_into, ord, pack->pool );
    1542       32745 : }
    1543             : 
    1544             : int
    1545             : fd_pack_insert_txn_fini( fd_pack_t  * pack,
    1546             :                          fd_txn_e_t * txne,
    1547             :                          ulong        expires_at,
    1548       32943 :                          ulong      * delete_cnt ) {
    1549       32943 :   *delete_cnt = 0UL;
    1550             : 
    1551       32943 :   fd_pack_ord_txn_t * ord = (fd_pack_ord_txn_t *)txne;
    1552             : 
    1553       32943 :   fd_txn_t * txn   = TXN(txne->txnp);
    1554       32943 :   uchar * payload  = txne->txnp->payload;
    1555             : 
    1556       32943 :   fd_acct_addr_t const * accts   = fd_txn_get_acct_addrs( txn, payload );
    1557       32943 :   fd_acct_addr_t const * alt     = ord->txn_e->alt_accts;
    1558             : 
    1559       32943 :   int est_result = fd_pack_estimate_rewards_and_compute( txne, ord, pack->lim );
    1560       32943 :   if( FD_UNLIKELY( !est_result ) ) REJECT( ESTIMATION_FAIL );
    1561             : 
    1562       32940 :   int nonce_result = fd_pack_validate_durable_nonce( txne );
    1563       32940 :   if( FD_UNLIKELY( !nonce_result ) ) REJECT( INVALID_NONCE );
    1564       32937 :   int is_durable_nonce = nonce_result==2;
    1565       32937 :   ord->txn->flags &= ~FD_TXN_P_FLAGS_DURABLE_NONCE;
    1566       32937 :   ord->txn->flags |= fd_uint_if( is_durable_nonce, FD_TXN_P_FLAGS_DURABLE_NONCE, 0U );
    1567             : 
    1568       32937 :   int validation_result = validate_transaction( pack, ord, txn, accts, alt, !!pack->bundle_meta_sz );
    1569       32937 :   if( FD_UNLIKELY( validation_result ) ) {
    1570         114 :     trp_pool_ele_release( pack->pool, ord );
    1571         114 :     return validation_result;
    1572         114 :   }
    1573             : 
    1574             :   /* Reject any transactions that have already expired */
    1575       32823 :   if( FD_UNLIKELY( (!is_durable_nonce) & (expires_at<pack->expire_before )) ) REJECT( EXPIRED          );
    1576             : 
    1577       32799 :   ord->nonce_expires_at = fd_ulong_if( is_durable_nonce, expires_at, 0UL );
    1578             : 
    1579       32799 :   int replaces = 0;
    1580             :   /* If it's a durable nonce and we already have one, delete one or the
    1581             :      other. */
    1582       32799 :   if( FD_UNLIKELY( is_durable_nonce ) ) {
    1583         135 :     fd_pack_ord_txn_t * same_nonce = noncemap_ele_query( pack->noncemap, txne, NULL, pack->pool );
    1584         135 :     if( FD_LIKELY( same_nonce ) ) { /* Seems like most nonce transactions are effectively duplicates */
    1585         111 :       if( FD_LIKELY( same_nonce->root == FD_ORD_TXN_ROOT_PENDING_BUNDLE || (same_nonce->root & FD_ORD_TXN_ROOT_TAG_MASK) == FD_ORD_TXN_ROOT_PRE_ROTATION_BUNDLE( 0 ) ||
    1586         111 :             same_nonce->nonce_expires_at>expires_at ||
    1587         111 :             (same_nonce->nonce_expires_at==expires_at && COMPARE_WORSE( ord, same_nonce ) ) ) ) REJECT( NONCE_PRIORITY );
    1588          99 :       ulong _delete_cnt = delete_transaction( pack, same_nonce, 0, 0 ); /* Not a bundle, so delete_full_bundle is 0 */
    1589          99 :       *delete_cnt += _delete_cnt;
    1590          99 :       replaces = 1;
    1591          99 :     }
    1592             :     /* Replace the expires_at value with a synthetic one to give nonce
    1593             :        transactions a finite lifetime. */
    1594         123 :     expires_at = pack->expire_before + FD_PACK_NONCE_SYNTHETIC_LIFETIME;
    1595         123 :   }
    1596             : 
    1597       32787 :   ord->expires_at = expires_at;
    1598             : 
    1599       32787 :   if( FD_UNLIKELY( pack->pending_txn_cnt == pack->pack_depth ) ) {
    1600        3156 :     float threshold_score = (float)ord->rewards/(float)ord->compute_est;
    1601        3156 :     ulong _delete_cnt = delete_worst( pack, threshold_score );
    1602        3156 :     *delete_cnt += _delete_cnt;
    1603        3156 :     if( FD_UNLIKELY( !_delete_cnt ) ) REJECT( PRIORITY );
    1604        3123 :     replaces = 1;
    1605        3123 :   }
    1606             : 
    1607       32754 :   ord->txn->flags &= ~(FD_TXN_P_FLAGS_BUNDLE | FD_TXN_P_FLAGS_INITIALIZER_BUNDLE);
    1608       32754 :   ord->skip = FD_PACK_SKIP_CNT;
    1609             : 
    1610             :   /* At this point, we know we have space to insert the transaction and
    1611             :      we've committed to insert it. */
    1612             : 
    1613       32754 :   insert_txn( pack, ord );
    1614             : 
    1615       32754 :   pack->pending_txn_cnt++;
    1616             : 
    1617       32754 :   sig2txn_ele_insert( pack->signature_map, ord, pack->pool );
    1618             : 
    1619       32754 :   if( FD_UNLIKELY( is_durable_nonce ) ) noncemap_ele_insert( pack->noncemap, ord, pack->pool );
    1620             : 
    1621       32754 :   fd_pack_expq_t temp[ 1 ] = {{ .expires_at = expires_at, .txn = ord }};
    1622       32754 :   expq_insert( pack->expiration_q, temp );
    1623             : 
    1624       32754 :   return (replaces<<1) | (is_durable_nonce<<2);
    1625       32787 : }
    1626             : #undef REJECT
    1627             : 
    1628             : fd_txn_e_t * const *
    1629             : fd_pack_insert_bundle_init( fd_pack_t          * pack,
    1630             :                             fd_txn_e_t *       * bundle,
    1631     1882965 :                             ulong                txn_cnt ) {
    1632     1882965 :   FD_TEST( txn_cnt<=FD_PACK_MAX_TXN_PER_BUNDLE  );
    1633     1882965 :   FD_TEST( trp_pool_free( pack->pool )>=txn_cnt );
    1634     3767475 :   for( ulong i=0UL; i<txn_cnt; i++ ) bundle[ i ] = trp_pool_ele_acquire( pack->pool )->txn_e;
    1635     1882965 :   return bundle;
    1636     1882965 : }
    1637             : 
    1638             : void
    1639             : fd_pack_insert_bundle_cancel( fd_pack_t          * pack,
    1640             :                               fd_txn_e_t * const * bundle,
    1641         261 :                               ulong                txn_cnt ) {
    1642             :   /* There's no real reason these have to be released in reverse, but it
    1643             :      seems fitting to release them in the opposite order they were
    1644             :      acquired. */
    1645        1329 :   for( ulong i=0UL; i<txn_cnt; i++ ) trp_pool_ele_release( pack->pool, (fd_pack_ord_txn_t*)bundle[ txn_cnt-1UL-i ] );
    1646         261 : }
    1647             : 
    1648             : /* Explained below */
    1649             : #define BUNDLE_L_PRIME 37896771UL
    1650             : #define BUNDLE_N       313721UL
    1651     1883475 : #define RC_TO_REL_BUNDLE_IDX( r, c ) (BUNDLE_N - ((ulong)(r) * 1UL<<32)/((ulong)(c) * BUNDLE_L_PRIME))
    1652             : 
    1653             : /* bundle_txn_declared_tip returns the tip that this transaction sends
    1654             :    to the tip accounts using top-level System program transfers.
    1655             : 
    1656             :    This does not include tips paid during CPI calls. */
    1657             : static ulong
    1658         198 : bundle_txn_declared_tip( fd_pack_ord_txn_t const * ord ) {
    1659         198 :   fd_txn_t       const * txn     = TXN( ord->txn );
    1660         198 :   uchar          const * payload = ord->txn->payload;
    1661         198 :   fd_acct_addr_t const * accts   = fd_txn_get_acct_addrs( txn, payload );
    1662         198 :   fd_acct_addr_t const * alt     = ord->txn_e->alt_accts;
    1663             : 
    1664         198 :   ulong tip = 0UL;
    1665         618 :   for( ulong i=0UL; i<(ulong)txn->instr_cnt; i++ ) {
    1666         420 :     fd_txn_instr_t const * instr = txn->instr+i;
    1667         420 :     uchar          const * data  = payload + instr->data_off;
    1668         420 :     if( FD_LIKELY( (instr->data_sz<12) | (instr->acct_cnt<2) || FD_LOAD( uint, data )!=2U ) ) continue;
    1669         186 :     if( FD_LIKELY( memcmp( accts[ instr->program_id ].b, &(uchar[32]){ 0 }, FD_TXN_ACCT_ADDR_SZ ) ) ) continue;
    1670         186 :     if( fd_pack_tip_is_tip_account( ACCT_IDX_TO_PTR( payload[ instr->acct_off+1UL ] ) ) ) tip = fd_ulong_sat_add( tip, FD_LOAD( ulong, data+4UL ) );
    1671         186 :   }
    1672         198 :   return tip;
    1673         198 : }
    1674             : 
    1675             : /* pre_rotation_bundle_worse returns 1 if bundle x has a smaller tip,
    1676             :    or the same tip but arrived later.  */
    1677             : static inline int
    1678             : pre_rotation_bundle_worse( fd_pack_pre_rotation_bundle_t const * x,
    1679         621 :                            fd_pack_pre_rotation_bundle_t const * y ) {
    1680         621 :   return (x->tip<y->tip) | ((x->tip==y->tip) & (x->seq>y->seq));
    1681         621 : }
    1682             : 
    1683             : static inline ulong
    1684          90 : pre_rotation_best_bundle_idx( fd_pack_t const * pack ) {
    1685          90 :   ulong best = ULONG_MAX;
    1686        1530 :   for( ulong i=0UL; i<FD_PACK_PRE_ROTATION_BUNDLE_CAPACITY; i++ ) {
    1687        1440 :     if( !treap_ele_cnt( pack->pre_rotation_bundles[ i ].treap ) ) continue;
    1688         468 :     if( best==ULONG_MAX || pre_rotation_bundle_worse( pack->pre_rotation_bundles+best, pack->pre_rotation_bundles+i ) ) {
    1689         417 :       best = i;
    1690         417 :     }
    1691         468 :   }
    1692          90 :   return best;
    1693          90 : }
    1694             : 
    1695             : static inline ulong
    1696          15 : pre_rotation_worst_bundle_idx( fd_pack_t const * pack ) {
    1697          15 :   ulong worst = ULONG_MAX;
    1698         255 :   for( ulong i=0UL; i<FD_PACK_PRE_ROTATION_BUNDLE_CAPACITY; i++ ) {
    1699         240 :     if( !treap_ele_cnt( pack->pre_rotation_bundles[ i ].treap ) ) continue;
    1700         240 :     if( worst==ULONG_MAX || pre_rotation_bundle_worse( pack->pre_rotation_bundles+i, pack->pre_rotation_bundles+worst ) ) {
    1701          60 :       worst = i;
    1702          60 :     }
    1703         240 :   }
    1704          15 :   return worst;
    1705          15 : }
    1706             : 
    1707             : static inline void
    1708             : pre_rotation_bundle_remove( fd_pack_t                     * pack,
    1709             :                             fd_pack_pre_rotation_bundle_t * pre_rotation_bundle,
    1710         108 :                             ulong                           idx ) {
    1711         108 :   treap_idx_remove( pre_rotation_bundle->treap, idx, pack->pool );
    1712         108 :   if( !treap_ele_cnt( pre_rotation_bundle->treap ) ) {
    1713          96 :     pack->pre_rotation_bundle_cnt--;
    1714          96 :   }
    1715         108 : }
    1716             : 
    1717             : int
    1718             : fd_pack_insert_bundle_fini( fd_pack_t          * pack,
    1719             :                             fd_txn_e_t * const * bundle,
    1720             :                             ulong                txn_cnt,
    1721             :                             ulong                expires_at,
    1722             :                             int                  initializer_bundle,
    1723             :                             void         const * bundle_meta,
    1724     1882965 :                             ulong              * delete_cnt ) {
    1725             : 
    1726     1882965 :   int err = 0;
    1727     1882965 :   *delete_cnt = 0UL;
    1728             : 
    1729     1882965 :   ulong pending_b_txn_cnt = treap_ele_cnt( pack->pending_bundles );
    1730     1882965 :   int is_pre_rotation     = (bundle[ 0 ]->txnp->scheduler_arrival_time_nanos>=pack->rotation_end_ns) & (!initializer_bundle);
    1731             :     /* We want to prevent bundles from consuming the whole treap, but in
    1732             :        general, we assume bundles are lucrative.  We'll set the policy
    1733             :        on capping bundles at half of the pack depth.  We assume that the
    1734             :        bundles are coming in a pre-prioritized order, so it doesn't make
    1735             :        sense to drop an earlier bundle for this one.  That means that
    1736             :        really, the best thing to do is drop this one. */
    1737     1882965 :   if( FD_UNLIKELY( (!initializer_bundle)&(pending_b_txn_cnt+txn_cnt>pack->pack_depth/2UL) ) ) err = FD_PACK_INSERT_REJECT_PRIORITY;
    1738             : 
    1739     1882965 :   if( FD_UNLIKELY( expires_at<pack->expire_before                                         ) ) err = FD_PACK_INSERT_REJECT_EXPIRED;
    1740             : 
    1741             :   /* Before evicting a transaction in favour of a pre-rotation
    1742             :      bundle, check that the bundle will actually be inserted into the
    1743             :      pre-rotation treap: it's valid and has a high enough tip.
    1744             : 
    1745             :      Otherwise, we could end up discarding a transaction with a
    1746             :      duplicate nonce, but because the conflicting bundle didn't
    1747             :      actually make it into the pre-rotation treap we would have
    1748             :      discarded the transaction unnecessarily. */
    1749     1882965 :   ulong pre_rotation_tip = 0UL;
    1750     1882965 :   fd_pack_pre_rotation_bundle_t cand[ 1 ] = {{ .tip = 0UL, .seq = pack->pre_rotation_seq }};
    1751     1882965 :   if( FD_UNLIKELY( is_pre_rotation & !err ) ) {
    1752         378 :     for( ulong i=0UL; i<txn_cnt; i++ ) {
    1753         198 :       pre_rotation_tip = fd_ulong_sat_add( pre_rotation_tip, bundle_txn_declared_tip( (fd_pack_ord_txn_t *)bundle[ i ] ) );
    1754         198 :     }
    1755         180 :     cand->tip = pre_rotation_tip;
    1756         180 :     if( FD_UNLIKELY( pack->pre_rotation_bundle_cnt>=FD_PACK_PRE_ROTATION_BUNDLE_CAPACITY ) ) {
    1757             :       /* If we have to evict a pre-rotation bundle from the treap,
    1758             :          check that the new bundle we are inserting does in fact have a
    1759             :          higher tip than the lowest already in the treap. */
    1760          12 :       ulong worst = pre_rotation_worst_bundle_idx( pack );
    1761          12 :       if( FD_UNLIKELY( !pre_rotation_bundle_worse( pack->pre_rotation_bundles+worst, cand ) ) ) {
    1762           9 :         FD_MCNT_INC( PACK, PRE_ROTATION_BUNDLE_REJECTED, 1UL );
    1763           9 :         err = FD_PACK_INSERT_REJECT_PRIORITY;
    1764           9 :       }
    1765          12 :     }
    1766         180 :   }
    1767             : 
    1768     1882965 :   int   replaces      = 0;
    1769     1882965 :   ulong nonce_txn_cnt = 0UL;
    1770             : 
    1771             :   /* Collect nonce hashes to detect duplicate nonces.
    1772             :      Use a constant-time duplicate-detection algorithm -- Vacant entries
    1773             :      have the MSB set, occupied entries are the noncemap hash, with the
    1774             :      MSB set to 0. */
    1775     1882965 :   ulong nonce_hash63[ FD_PACK_MAX_TXN_PER_BUNDLE ];
    1776    11297790 :   for( ulong i=0UL; i<FD_PACK_MAX_TXN_PER_BUNDLE; i++ ) {
    1777     9414825 :     nonce_hash63[ i ] = ULONG_MAX-i;
    1778     9414825 :   }
    1779             : 
    1780     3767439 :   for( ulong i=0UL; (i<txn_cnt) && !err; i++ ) {
    1781     1884480 :     fd_pack_ord_txn_t * ord = (fd_pack_ord_txn_t *)bundle[ i ];
    1782             : 
    1783     1884480 :     fd_txn_t const * txn     = TXN(bundle[ i ]->txnp);
    1784     1884480 :     uchar    const * payload = bundle[ i ]->txnp->payload;
    1785             : 
    1786     1884480 :     fd_acct_addr_t const * accts   = fd_txn_get_acct_addrs( txn, payload );
    1787     1884480 :     fd_acct_addr_t const * alt     = ord->txn_e->alt_accts;
    1788             : 
    1789     1884480 :     int est_result = fd_pack_estimate_rewards_and_compute( bundle[ i ], ord, pack->lim );
    1790     1884480 :     if( FD_UNLIKELY( est_result==0 ) ) { err = FD_PACK_INSERT_REJECT_ESTIMATION_FAIL;  break; }
    1791     1884480 :     int nonce_result = fd_pack_validate_durable_nonce( ord->txn_e );
    1792     1884480 :     if( FD_UNLIKELY( !nonce_result ) ) { err = FD_PACK_INSERT_REJECT_INVALID_NONCE;    break; }
    1793             :     /* The expires_at field is interpreted differently for nonce vs.
    1794             :        non-nonce transactions, but bundles are required to have the same
    1795             :        value for that field, so we've lost the value we would put in
    1796             :        nonce_expires_at.  Turns out, that's never read for bundles
    1797             :        though.  So for now, we just use the incorrect expires_at.
    1798             :        If you're already getting revert protection from being a bundle,
    1799             :        it seems dumb to use a durable nonce as another form of revert
    1800             :        protection anyway.  We're expecting the sender of the bundles to
    1801             :        do the nonce filtering anyway. */
    1802     1884480 :     int is_durable_nonce = nonce_result==2;
    1803     1884480 :     nonce_txn_cnt += !!is_durable_nonce;
    1804             : 
    1805     1884480 :     bundle[ i ]->txnp->flags |= FD_TXN_P_FLAGS_BUNDLE;
    1806     1884480 :     bundle[ i ]->txnp->flags &= ~(FD_TXN_P_FLAGS_INITIALIZER_BUNDLE | FD_TXN_P_FLAGS_DURABLE_NONCE);
    1807     1884480 :     bundle[ i ]->txnp->flags |= fd_uint_if( initializer_bundle, FD_TXN_P_FLAGS_INITIALIZER_BUNDLE, 0U );
    1808     1884480 :     bundle[ i ]->txnp->flags |= fd_uint_if( is_durable_nonce,   FD_TXN_P_FLAGS_DURABLE_NONCE,      0U );
    1809     1884480 :     ord->skip       = FD_PACK_SKIP_CNT;
    1810     1884480 :     ord->expires_at = expires_at;
    1811             : 
    1812     1884480 :     if( FD_UNLIKELY( is_durable_nonce ) ) {
    1813        1044 :       ord->nonce_expires_at = expires_at;
    1814        1044 :       nonce_hash63[ i ] = noncemap_key_hash( ord->txn_e, pack->noncemap->seed ) & 0x7FFFFFFFFFFFFFFFUL;
    1815        1044 :       fd_pack_ord_txn_t * same_nonce = noncemap_ele_query( pack->noncemap, ord->txn_e, NULL, pack->pool );
    1816        1044 :       if( FD_LIKELY( same_nonce ) ) {
    1817             :         /* bundles take priority over non-bundles, and bundles that run
    1818             :            sooner take priority over bundles that run later.
    1819             : 
    1820             :            Fresh bundles take priority over pre-rotation bundles, and
    1821             :            pre-rotation bundles with higher tips take priority over
    1822             :            pre-rotation bundles with lower tips. */
    1823          15 :         int holder_root     = same_nonce->root & FD_ORD_TXN_ROOT_TAG_MASK;
    1824          15 :         int holder_is_fresh = holder_root==FD_ORD_TXN_ROOT_PENDING_BUNDLE;
    1825          15 :         int holder_is_pre   = holder_root==FD_ORD_TXN_ROOT_PRE_ROTATION_BUNDLE( 0 );
    1826          15 :         int holder_out_tips = (is_pre_rotation & holder_is_pre) && !pre_rotation_bundle_worse( pack->pre_rotation_bundles + FD_ORD_TXN_ROOT_PRE_ROTATION_BUNDLE_IDX( same_nonce->root ), cand );
    1827          15 :         if( FD_UNLIKELY( holder_is_fresh | (holder_is_pre & holder_out_tips) ) ) {
    1828           6 :           err = FD_PACK_INSERT_REJECT_NONCE_PRIORITY;
    1829           6 :           break;
    1830           9 :         } else {
    1831           9 :           ulong _delete_cnt = delete_transaction( pack, same_nonce, 1, 0 );
    1832           9 :           *delete_cnt += _delete_cnt;
    1833           9 :           replaces = 1;
    1834           9 :         }
    1835          15 :       }
    1836        1044 :     }
    1837             : 
    1838     1884474 :     int validation_result = validate_transaction( pack, ord, txn, accts, alt, !initializer_bundle );
    1839     1884474 :     if( FD_UNLIKELY( validation_result ) ) { err = validation_result; break; }
    1840     1884474 :   }
    1841             : 
    1842     1882965 :   if( FD_UNLIKELY( err ) ) {
    1843          18 :     fd_pack_insert_bundle_cancel( pack, bundle, txn_cnt );
    1844          18 :     return err;
    1845          18 :   }
    1846             : 
    1847     1882947 :   if( FD_UNLIKELY( initializer_bundle && pending_b_txn_cnt>0UL ) ) {
    1848           6 :     treap_rev_iter_t _cur=treap_rev_iter_init( pack->pending_bundles, pack->pool );
    1849           6 :     FD_TEST( !treap_rev_iter_done( _cur ) );
    1850           6 :     fd_pack_ord_txn_t * cur = treap_rev_iter_ele( _cur, pack->pool );
    1851           6 :     int is_ib = !!(cur->txn->flags & FD_TXN_P_FLAGS_INITIALIZER_BUNDLE);
    1852             : 
    1853             :     /* Delete the previous IB if there is one */
    1854           6 :     if( FD_UNLIKELY( is_ib && 0UL==RC_TO_REL_BUNDLE_IDX( cur->rewards, cur->compute_est ) ) ) {
    1855           6 :       ulong _delete_cnt = delete_transaction( pack, cur, 1, 0 );
    1856           6 :       *delete_cnt += _delete_cnt;
    1857           6 :     }
    1858           6 :   }
    1859             : 
    1860     1882947 :   while( FD_UNLIKELY( pack->pending_txn_cnt+txn_cnt > pack->pack_depth ) ) {
    1861           0 :     ulong _delete_cnt = delete_worst( pack, FLT_MAX );
    1862           0 :     *delete_cnt += _delete_cnt;
    1863           0 :     if( FD_UNLIKELY( !_delete_cnt ) ) {
    1864           0 :       fd_pack_insert_bundle_cancel( pack, bundle, txn_cnt );
    1865           0 :       return FD_PACK_INSERT_REJECT_PRIORITY;
    1866           0 :     }
    1867           0 :     replaces = 1;
    1868           0 :   }
    1869             : 
    1870     1882947 :   if( FD_UNLIKELY( !pending_b_txn_cnt ) ) {
    1871         681 :     pack->relative_bundle_idx = 1UL;
    1872         681 :   }
    1873             : 
    1874     1882947 :   if( FD_LIKELY( bundle_meta ) ) {
    1875           0 :     memcpy( (uchar *)pack->bundle_meta + (ulong)((fd_pack_ord_txn_t *)bundle[0]-pack->pool)*pack->bundle_meta_sz, bundle_meta, pack->bundle_meta_sz );
    1876           0 :   }
    1877             : 
    1878     1882947 :   if( FD_UNLIKELY( nonce_txn_cnt>1UL ) ) {
    1879             :     /* Do a ILP-friendly duplicate detect, naive O(n^2) algo.  With max
    1880             :        5 txns per bundle, this requires 10 comparisons.  ~ 25 cycle.  */
    1881         375 :     uint conflict_detected = 0u;
    1882        1875 :     for( ulong i=0UL; i<FD_PACK_MAX_TXN_PER_BUNDLE-1; i++ ) {
    1883        5250 :       for( ulong j=i+1; j<FD_PACK_MAX_TXN_PER_BUNDLE; j++ ) {
    1884        3750 :         ulong const ele_i = nonce_hash63[ i ];
    1885        3750 :         ulong const ele_j = nonce_hash63[ j ];
    1886        3750 :         conflict_detected |= (ele_i==ele_j);
    1887        3750 :       }
    1888        1500 :     }
    1889         375 :     if( FD_UNLIKELY( conflict_detected ) ) {
    1890         243 :       fd_pack_insert_bundle_cancel( pack, bundle, txn_cnt );
    1891         243 :       return FD_PACK_INSERT_REJECT_NONCE_CONFLICT;
    1892         243 :     }
    1893         375 :   }
    1894             : 
    1895             :   /* If the bundle is a pre-rotation bundle, insert it into the
    1896             :      pre-rotation treap. */
    1897     1882704 :   if( FD_UNLIKELY( is_pre_rotation ) ) {
    1898         168 :     ulong evicted = insert_pre_rotation_bundle_impl( pack, txn_cnt, (fd_pack_ord_txn_t * *)bundle, expires_at, pre_rotation_tip );
    1899         168 :     *delete_cnt += evicted;
    1900         168 :     replaces    |= evicted>0UL;
    1901         168 :     return (0) | (replaces<<1) | ((!!nonce_txn_cnt)<<2);
    1902         168 :   }
    1903             : 
    1904             :   /* We put bundles in a treap just like all the other transactions, but
    1905             :      we actually want to sort them in a very specific order; the order
    1906             :      within the bundle is determined at bundle creation time, and the
    1907             :      order among the bundles is FIFO.  However, it's going to be a pain
    1908             :      to use a different sorting function for this treap, since it's
    1909             :      fixed as part of the treap creation for performance.  Don't fear
    1910             :      though; we can pull a cool math trick out of the bag to shoehorn
    1911             :      the order we'd like into the sort function we need, and to get even
    1912             :      more.
    1913             : 
    1914             :      Recall that the sort function is r_i/c_i, smallest to largest,
    1915             :      where r_i is the rewards and c_i is the cost units.  r_i and c_i
    1916             :      are both uints, and the comparison is done by cross-multiplication
    1917             :      as ulongs.  We actually use the c_i value for testing if
    1918             :      transactions fit, etc.  so let's assume that's fixed, and we know
    1919             :      it's in the range [1020, 1,551,570].
    1920             : 
    1921             :      This means, if c_0, c_1, ... c_4 are the CU costs of the
    1922             :      transactions in the first bundle, we require r_0/c_0 > r_1/c_1 >
    1923             :      ... > r_4/c_4.  Then, if c_5, ... c_9 are the CU costs of the
    1924             :      transactions in the second bundle, we also require that r_4/c_4 >
    1925             :      r_5/c_5.  For convenience, we'll impose a slightly stronger
    1926             :      constraint: we want the kth bundle to obey L*(N-k) <= r_i/c_i <
    1927             :      L*(N+1-k), for fixed constants L and N, real and integer,
    1928             :      respectively, that we'll determine. For example, this means r_4/c_4
    1929             :      >= L*N > r_5/c_5.  This enables us to group the transactions in the
    1930             :      same bundle more easily.
    1931             : 
    1932             :      For convenience in the math below, we'll set j=N-k and relabel the
    1933             :      transactions from the jth bundle c_0, ... c_4.
    1934             :      From above, we know that Lj <= r_4/c_4.  We'd like to make it as
    1935             :      close as possible given that r_4 is an integers.  Thus, put
    1936             :      r_4 = ceil( c_4 * Lj ).  r_4 is clearly an integer, and it satisfies
    1937             :      the required inequality because:
    1938             :             r_4/c_4 = ceil( c_4 * Lj)/c_4 >= c_4*Lj / c_4 >= Lj.
    1939             : 
    1940             :      Following in the same spirit, put r_3 = ceil( c_3 * (r_4+1)/c_4 ).
    1941             :      Again, r_3 is clearly an integer, and
    1942             :                 r_3/c_3  = ceil(c_3*(r_4+1)/c_4)/c_3
    1943             :                         >= (c_3*(r_4+1))/(c_3 * c_4)
    1944             :                         >= r_4/c_4 + 1/c_4
    1945             :                         >  r_4/c_4.
    1946             :      Following the pattern, we put
    1947             :                 r_2 = ceil( c_2 * (r_3+1)/c_3 )
    1948             :                 r_1 = ceil( c_1 * (r_2+1)/c_2 )
    1949             :                 r_0 = ceil( c_0 * (r_1+1)/c_1 )
    1950             :      which work for the same reason that as r_3.
    1951             : 
    1952             :      We now need for r_0 to satisfy the final inequality with L, and
    1953             :      we'll use this to guide our choice of L.  Theoretically, r_0 can be
    1954             :      expressed in terms of L, j, and c_0, ... c_4, but that's a truly
    1955             :      inscrutible expression.  Instead, we need some bounds so we can get
    1956             :      rid of all the ceil using the property that x <= ceil(x) < x+1.
    1957             :                      c_4 * Lj <= r_4 < c_4 * Lj + 1
    1958             :      The lower bound on r_3 is easy:
    1959             :          r_3 >= c_3 * (c_4 * Lj + 1)/c_4 = c_3 * Lj + c_3/c_4
    1960             :      For the upper bound,
    1961             :          r_3 < 1 + c_3*(r_4+1)/c_4 < 1 + c_3*(c_4*Lj+1 + 1)/c_4
    1962             :                                    = 1 + c_3 * Lj + 2*c_3/c_4
    1963             :      Continuing similarly gives
    1964             :        c_2*Lj +                     c_2/c_3 + c_2/c_4 <= r_2
    1965             :        c_1*Lj +           c_1/c_2 + c_1/c_c + c_1/c_4 <= r_1
    1966             :        c_0*Lj + c_0/c_1 + c_0/c_2 + c_0/c_3 + c_0/c_4 <= r_0
    1967             :      and
    1968             :        r_2 < 1 + c_2*Lj +                       2c_2/c_3 + 2c_2/c_4
    1969             :        r_1 < 1 + c_1*Lj +            2c_1/c_2 + 2c_1/c_3 + 2c_1/c_4
    1970             :        r_0 < 1 + c_0*Lj + 2c_0/c_1 + 2c_0/c_2 + 2c_0/c_3 + 2c_0/c_4.
    1971             : 
    1972             :      Setting L(j+1)>=(1 + c_0*Lj+2c_0/c_1+2c_0/c_2+2c_0/c_3+2c_0/c_4)/c_0
    1973             :      is then sufficient to ensure the whole sequence of 5 fits between Lj
    1974             :      and L(j+1).  Simplifying gives
    1975             :               L<= 1/c_0 + 2/c_1 + 2/c_2 + 2/c_3 + 2/c_4
    1976             :      but L must be a constant and not depend on individual values of c_i,
    1977             :      so, given that c_i >= 1020, we set L = 9/1020.
    1978             : 
    1979             :      Now all that remains is to determine N.  It's a bit unfortunate
    1980             :      that we require N, since it limits our capacity, but it's necessary
    1981             :      in any system that tries to compute priorities to enforce a FIFO
    1982             :      order.  If we've inserted more than N bundles without ever having
    1983             :      the bundle treap go empty, we renumber the pending bundles to make
    1984             :      room, since bundles can't share an ordinal.
    1985             : 
    1986             :      Thus, we'd like to make N as big as possible, avoiding overflow.
    1987             :      r_0, ..., r_4 are all uints, and taking the bounds from above,
    1988             :      given that for any i, i' c_i/c_{i'} <= 1551570/1020 < 1522, we have
    1989             :                r_i < 1 + 1551570 * Lj + 8*1522.
    1990             :      To avoid overflow, we assert the right-hand side is < 2^32, which
    1991             :      implies N <= 313721.
    1992             : 
    1993             :      We want to use a fixed point representation for L so that the
    1994             :      entire computation can be done with integer arithmetic.  We can do
    1995             :      the arithmetic as ulongs, which means defining L' >= L * 2^s, and
    1996             :      we compute ceil( c_4*Lj ) as floor( (c_4 * L' * j + 2^s - 1)/2^s ),
    1997             :      so c_4 * L' * j + 2^s should fit in a ulong.  With j<=N, this gives
    1998             :      s<=32, so we set s=32, which means L' = 37896771 >= 9/1020 * 2^32.
    1999             :      Note that 1 + 1551570 * L' * N + 8*1522 + 2^32 is approximately
    2000             :      2^63.999992.
    2001             : 
    2002             :      Note that this is all checked by a proof of the code translated
    2003             :      into Z3.  Unfortunately CBMC was too slow to prove this code
    2004             :      directly. */
    2005     1882536 :      FD_STATIC_ASSERT( FD_PACK_MIN_TXN_COST==   1020UL, adjust_constants );
    2006     1882536 :      FD_STATIC_ASSERT( FD_PACK_MAX_TXN_COST==1551570UL, adjust_constants );
    2007     3766224 : #define BUNDLE_L_PRIME 37896771UL
    2008     3766224 : #define BUNDLE_N       313721UL
    2009             : 
    2010     1882536 :   if( FD_UNLIKELY( pack->relative_bundle_idx>BUNDLE_N ) ) {
    2011             :     /* Walk worst to best, which is last to first within each bundle.
    2012             :        Only an initializer bundle has ordinal 0, and it keeps it. */
    2013           6 :     ulong new_ordinal = pack->relative_bundle_idx = pending_b_txn_cnt+1UL;
    2014           6 :     ulong old_ordinal = ULONG_MAX;
    2015           6 :     ulong prev_reward = 0UL;
    2016           6 :     ulong prev_cost   = 0UL;
    2017           6 :     for( treap_fwd_iter_t _cur=treap_fwd_iter_init( pack->pending_bundles, pack->pool );
    2018         147 :         !treap_fwd_iter_done( _cur ); _cur=treap_fwd_iter_next( _cur, pack->pool ) ) {
    2019         141 :       fd_pack_ord_txn_t * cur = treap_fwd_iter_ele( _cur, pack->pool );
    2020         141 :       ulong this_ordinal = RC_TO_REL_BUNDLE_IDX( cur->rewards, cur->compute_est );
    2021         141 :       if( this_ordinal!=old_ordinal ) {
    2022          45 :         old_ordinal = this_ordinal;
    2023          45 :         prev_reward = BUNDLE_L_PRIME * (BUNDLE_N - (this_ordinal ? --new_ordinal : 0UL)) - 1UL;
    2024          45 :         prev_cost   = 1UL<<32;
    2025          45 :       }
    2026         141 :       cur->rewards = (uint)(((ulong)cur->compute_est * (prev_reward + 1UL) + prev_cost-1UL)/prev_cost);
    2027         141 :       prev_reward  = cur->rewards;
    2028         141 :       prev_cost    = cur->compute_est;
    2029         141 :     }
    2030           6 :   }
    2031     1882536 :   ulong bundle_idx = fd_ulong_if( initializer_bundle, 0UL, pack->relative_bundle_idx );
    2032     1882536 :   insert_bundle_impl( pack, bundle_idx, txn_cnt, (fd_pack_ord_txn_t * *)bundle, expires_at );
    2033             :   /* if IB this is max( 1, x ), which is x.  Otherwise, this is max(x,
    2034             :      x+1) which is x++ */
    2035     1882536 :   pack->relative_bundle_idx = fd_ulong_max( bundle_idx+1UL, pack->relative_bundle_idx );
    2036             : 
    2037     1882536 :   return (0) | (replaces<<1) | ((!!nonce_txn_cnt)<<2);
    2038     1882704 : }
    2039             : static inline void
    2040             : insert_bundle_impl( fd_pack_t           * pack,
    2041             :                     ulong                 bundle_idx,
    2042             :                     ulong                 txn_cnt,
    2043             :                     fd_pack_ord_txn_t * * bundle,
    2044     1882536 :                     ulong                 expires_at ) {
    2045     1882536 :   ulong prev_reward = ((BUNDLE_L_PRIME * (BUNDLE_N - bundle_idx))) - 1UL;
    2046     1882536 :   ulong prev_cost = 1UL<<32;
    2047             : 
    2048             :   /* Assign last to first */
    2049     3765795 :   for( ulong i=0UL; i<txn_cnt; i++ ) {
    2050     1883259 :     fd_pack_ord_txn_t * ord = bundle[ txn_cnt-1UL - i ];
    2051     1883259 :     ord->rewards = (uint)(((ulong)ord->compute_est * (prev_reward + 1UL) + prev_cost-1UL)/prev_cost);
    2052     1883259 :     ord->root    = FD_ORD_TXN_ROOT_PENDING_BUNDLE;
    2053     1883259 :     prev_reward = ord->rewards;
    2054     1883259 :     prev_cost   = ord->compute_est;
    2055             : 
    2056             :     /* The penalty information isn't used for bundles. */
    2057     1883259 :     ushort penalties  [ FD_TXN_ACCT_ADDR_MAX ];
    2058     1883259 :     uchar  penalty_idx[ FD_TXN_ACCT_ADDR_MAX ];
    2059     1883259 :     populate_bitsets( pack, ord, penalties, penalty_idx );
    2060             : 
    2061     1883259 :     treap_ele_insert( pack->pending_bundles, ord, pack->pool );
    2062     1883259 :     pack->pending_txn_cnt++;
    2063             : 
    2064     1883259 :     if( FD_UNLIKELY( ord->txn->flags & FD_TXN_P_FLAGS_DURABLE_NONCE ) ) noncemap_ele_insert( pack->noncemap, ord, pack->pool );
    2065     1883259 :     sig2txn_ele_insert( pack->signature_map, ord, pack->pool );
    2066             : 
    2067     1883259 :     fd_pack_expq_t temp[ 1 ] = {{ .expires_at = expires_at, .txn = ord }};
    2068     1883259 :     expq_insert( pack->expiration_q, temp );
    2069     1883259 :   }
    2070             : 
    2071     1882536 : }
    2072             : 
    2073             : /* insert_pre_rotation_bundle_impl is like insert_bundle_impl, but puts
    2074             :    the bundle in a free entry of pre_rotation_bundles.  If none is
    2075             :    free, it first evicts the worst bundle.  Returns the number of txns
    2076             :    evicted. */
    2077             : static inline ulong
    2078             : insert_pre_rotation_bundle_impl( fd_pack_t           * pack,
    2079             :                                  ulong                 txn_cnt,
    2080             :                                  fd_pack_ord_txn_t * * bundle,
    2081             :                                  ulong                 expires_at,
    2082         168 :                                  ulong                 pre_rotation_tip ) {
    2083             :   /* Evict from the pre-rotation treap if we have reached the limit */
    2084         168 :   ulong evicted = 0UL;
    2085         168 :   if( FD_UNLIKELY( pack->pre_rotation_bundle_cnt>=FD_PACK_PRE_ROTATION_BUNDLE_CAPACITY ) ) {
    2086           3 :     treap_t           * worst_treap = pack->pre_rotation_bundles[ pre_rotation_worst_bundle_idx( pack ) ].treap;
    2087           3 :     fd_pack_ord_txn_t * worst       = treap_fwd_iter_ele( treap_fwd_iter_init( worst_treap, pack->pool ), pack->pool );
    2088           3 :     evicted = delete_transaction( pack, worst, 1, 0 );
    2089           3 :     FD_MCNT_INC( PACK, PRE_ROTATION_BUNDLE_EVICTED, 1UL );
    2090           3 :   }
    2091             : 
    2092         168 :   ulong pre_rotation_bundle_idx = 0UL;
    2093         939 :   while( treap_ele_cnt( pack->pre_rotation_bundles[ pre_rotation_bundle_idx ].treap ) ) {
    2094         771 :     pre_rotation_bundle_idx++;
    2095         771 :   }
    2096         168 :   fd_pack_pre_rotation_bundle_t * pre_rotation_bundle = pack->pre_rotation_bundles + pre_rotation_bundle_idx;
    2097         168 :   pre_rotation_bundle->tip = pre_rotation_tip;
    2098         168 :   pre_rotation_bundle->seq = pack->pre_rotation_seq++;
    2099             : 
    2100         168 :   ulong prev_reward = ((BUNDLE_L_PRIME * (BUNDLE_N - 1UL))) - 1UL;
    2101         168 :   ulong prev_cost   = 1UL<<32;
    2102             : 
    2103             :   /* Assign last to first */
    2104         351 :   for( ulong i=0UL; i<txn_cnt; i++ ) {
    2105         183 :     fd_pack_ord_txn_t * ord = bundle[ txn_cnt-1UL - i ];
    2106         183 :     ord->rewards = (uint)(((ulong)ord->compute_est * (prev_reward + 1UL) + prev_cost-1UL)/prev_cost);
    2107         183 :     ord->root    = FD_ORD_TXN_ROOT_PRE_ROTATION_BUNDLE( (int)pre_rotation_bundle_idx );
    2108         183 :     prev_reward  = ord->rewards;
    2109         183 :     prev_cost    = ord->compute_est;
    2110             : 
    2111             :     /* The penalty information isn't used for bundles. */
    2112         183 :     ushort penalties  [ FD_TXN_ACCT_ADDR_MAX ];
    2113         183 :     uchar  penalty_idx[ FD_TXN_ACCT_ADDR_MAX ];
    2114         183 :     populate_bitsets( pack, ord, penalties, penalty_idx );
    2115             : 
    2116         183 :     treap_ele_insert( pre_rotation_bundle->treap, ord, pack->pool );
    2117         183 :     pack->pending_txn_cnt++;
    2118             : 
    2119         183 :     if( FD_UNLIKELY( ord->txn->flags & FD_TXN_P_FLAGS_DURABLE_NONCE ) ) noncemap_ele_insert( pack->noncemap, ord, pack->pool );
    2120         183 :     sig2txn_ele_insert( pack->signature_map, ord, pack->pool );
    2121             : 
    2122         183 :     fd_pack_expq_t temp[ 1 ] = {{ .expires_at = expires_at, .txn = ord }};
    2123         183 :     expq_insert( pack->expiration_q, temp );
    2124         183 :   }
    2125             : 
    2126         168 :   pack->pre_rotation_bundle_cnt++;
    2127         168 :   FD_MCNT_INC( PACK, PRE_ROTATION_BUNDLE_INSERTED, 1UL );
    2128         168 :   return evicted;
    2129         168 : }
    2130             : 
    2131             : void const *
    2132           6 : fd_pack_peek_bundle_meta( fd_pack_t const * pack ) {
    2133           6 :   int ib_state = pack->initializer_bundle_state;
    2134           6 :   if( FD_UNLIKELY( (ib_state==FD_PACK_IB_STATE_PENDING) | (ib_state==FD_PACK_IB_STATE_FAILED) ) ) return NULL;
    2135             : 
    2136           6 :   treap_rev_iter_t _cur=treap_rev_iter_init( pack->pending_bundles, pack->pool );
    2137             :   /* If there are no normal bundles, the pre-rotation bundles will
    2138             :      be scheduled. */
    2139           6 :   if( FD_UNLIKELY( treap_rev_iter_done( _cur ) ) ) {
    2140           3 :     ulong best = pre_rotation_best_bundle_idx( pack );
    2141           3 :     if( FD_UNLIKELY( best==ULONG_MAX ) ) return NULL;
    2142           3 :     _cur = treap_rev_iter_init( pack->pre_rotation_bundles[ best ].treap, pack->pool );
    2143           3 :   }
    2144           6 :   if( FD_UNLIKELY( treap_rev_iter_done( _cur ) ) ) return NULL; /* empty */
    2145             : 
    2146           6 :   fd_pack_ord_txn_t * cur = treap_rev_iter_ele( _cur, pack->pool );
    2147           6 :   int is_ib = !!(cur->txn->flags & FD_TXN_P_FLAGS_INITIALIZER_BUNDLE);
    2148           6 :   if( FD_UNLIKELY( is_ib ) ) return NULL;
    2149             : 
    2150           3 :   return (void const *)((uchar const *)pack->bundle_meta + (ulong)_cur * pack->bundle_meta_sz);
    2151           6 : }
    2152             : 
    2153             : void
    2154         162 : fd_pack_set_initializer_bundles_ready( fd_pack_t * pack ) {
    2155         162 :   pack->initializer_bundle_state = FD_PACK_IB_STATE_READY;
    2156         162 : }
    2157             : 
    2158             : void
    2159             : fd_pack_set_rotation_end_ns( fd_pack_t * pack,
    2160         624 :                              long        end_ns ) {
    2161         624 :   pack->rotation_end_ns = end_ns;
    2162         624 : }
    2163             : 
    2164             : void
    2165          63 : fd_pack_metrics_write( fd_pack_t const * pack ) {
    2166          63 :   ulong pending_regular      = treap_ele_cnt( pack->pending         );
    2167          63 :   ulong pending_bundle       = treap_ele_cnt( pack->pending_bundles );
    2168        1071 :   for( ulong i=0UL; i<FD_PACK_PRE_ROTATION_BUNDLE_CAPACITY; i++ ) {
    2169        1008 :     pending_bundle += treap_ele_cnt( pack->pre_rotation_bundles[ i ].treap );
    2170        1008 :   }
    2171          63 :   ulong pending_pre_rotation = pack->pre_rotation_bundle_cnt;
    2172          63 :   ulong next_auction         = treap_ele_cnt( pack->next_auction    );
    2173          63 :   ulong conflicting          = pack->pending_txn_cnt - pending_regular - pending_bundle - next_auction;
    2174          63 :   ulong smallest_cost        = fd_ulong_if( pack->pending_smallest->cus==ULONG_MAX, 0UL, pack->pending_smallest->cus );
    2175          63 :   FD_MGAUGE_SET( PACK, TXN_PENDING_USED_REGULAR,      pending_regular             );
    2176          63 :   FD_MGAUGE_SET( PACK, TXN_PENDING_USED_VOTE,         0UL                         );
    2177          63 :   FD_MGAUGE_SET( PACK, TXN_PENDING_USED_CONFLICTING,  conflicting                 );
    2178          63 :   FD_MGAUGE_SET( PACK, TXN_PENDING_USED_BUNDLE,       pending_bundle              );
    2179          63 :   FD_MGAUGE_SET( PACK, TXN_PENDING_USED_NEXT_AUCTION, next_auction                );
    2180          63 :   FD_MGAUGE_SET( PACK, PRE_ROTATION_BUNDLE_PENDING,   pending_pre_rotation        );
    2181          63 :   FD_MGAUGE_SET( PACK, TXN_PENDING_SMALLEST_COST,     smallest_cost               );
    2182          63 :   FD_MGAUGE_SET( PACK, BLOCK_COST,                    pack->cumulative_block_cost );
    2183             : 
    2184          63 :   FD_MCNT_ENUM_COPY( PACK, TXN_SCHEDULE_ATTEMPTED, pack->sched_results );
    2185          63 : }
    2186             : 
    2187             : void
    2188           0 : fd_pack_get_sched_metrics( fd_pack_t const * pack, ulong * metrics ) {
    2189           0 :   fd_memcpy( metrics, pack->sched_results, sizeof(pack->sched_results) );
    2190           0 : }
    2191             : 
    2192             : typedef struct {
    2193             :   ushort clear_rw_bit;
    2194             :   ushort clear_w_bit;
    2195             : } release_result_t;
    2196             : 
    2197             : static inline release_result_t
    2198             : release_bit_reference( fd_pack_t            * pack,
    2199     3921195 :                        fd_acct_addr_t const * acct ) {
    2200             : 
    2201     3921195 :   fd_pack_bitset_acct_mapping_t * q = bitset_map_query( pack->acct_to_bitset, *acct, NULL );
    2202     3921195 :   FD_TEST( q ); /* q==NULL not be possible */
    2203             : 
    2204     3921195 :   q->ref_cnt--;
    2205             : 
    2206     3921195 :   if( FD_UNLIKELY( q->ref_cnt==0UL ) ) {
    2207     1957501 :     ushort bit = q->bit;
    2208     1957501 :     bitset_map_remove( pack->acct_to_bitset, q );
    2209     1957501 :     if( FD_LIKELY( bit<FD_PACK_BITSET_MAX ) ) pack->bitset_avail[ ++(pack->bitset_avail_cnt) ] = bit;
    2210             : 
    2211     1957501 :     fd_pack_addr_use_t * use = acct_uses_query( pack->acct_in_use,  *acct, NULL );
    2212     1957501 :     if( FD_LIKELY( use ) ) {
    2213       69886 :       use->in_use_by |= FD_PACK_IN_USE_BIT_CLEARED;
    2214       69886 :       release_result_t ret = { .clear_rw_bit = bit,
    2215       69886 :                                .clear_w_bit = fd_ushort_if( !!(use->in_use_by & FD_PACK_IN_USE_WRITABLE), bit, FD_PACK_BITSET_MAX ) };
    2216       69886 :       return ret;
    2217       69886 :     }
    2218     1957501 :   }
    2219     3851309 :   release_result_t ret = { .clear_rw_bit = FD_PACK_BITSET_MAX, .clear_w_bit = FD_PACK_BITSET_MAX };
    2220     3851309 :   return ret;
    2221     3921195 : }
    2222             : 
    2223             : typedef struct {
    2224             :   ulong cus_scheduled;
    2225             :   ulong txns_scheduled;
    2226             :   ulong bytes_scheduled;
    2227             :   ulong alloc_scheduled;
    2228             : } sched_return_t;
    2229             : 
    2230             : static inline sched_return_t
    2231             : fd_pack_schedule_impl( fd_pack_t          * pack,
    2232             :                        treap_t            * sched_from,
    2233             :                        ulong                cu_limit,
    2234             :                        ulong                txn_limit,
    2235             :                        ulong                byte_limit,
    2236             :                        ulong                alloc_limit,
    2237             :                        ulong                bank_tile,
    2238             :                        fd_pack_smallest_t * smallest_in_treap,
    2239             :                        ulong              * use_by_bank_txn,
    2240       14850 :                        fd_txn_e_t         * out ) {
    2241       14850 :   if( FD_UNLIKELY( (cu_limit<smallest_in_treap->cus) | (txn_limit==0UL) | (byte_limit<smallest_in_treap->bytes) ) ) {
    2242         176 :     sched_return_t to_return = { .cus_scheduled = 0UL, .txns_scheduled = 0UL, .bytes_scheduled = 0UL };
    2243         176 :     return to_return;
    2244         176 :   }
    2245             : 
    2246       14674 :   fd_pack_ord_txn_t   * pool         = pack->pool;
    2247       14674 :   fd_pack_addr_use_t  * acct_in_use  = pack->acct_in_use;
    2248       14674 :   wcost_map_t         * writer_costs = pack->writer_costs;
    2249       14674 :   fd_pack_wcost_ele_t * writers      = pack->writers;
    2250       14674 :   wcost_dlist_t       * written_list = pack->written_list;
    2251             : 
    2252       14674 :   FD_PACK_BITSET_DECLARE( bitset_rw_in_use );
    2253       14674 :   FD_PACK_BITSET_DECLARE( bitset_w_in_use  );
    2254       14674 :   FD_PACK_BITSET_COPY( bitset_rw_in_use, pack->bitset_rw_in_use );
    2255       14674 :   FD_PACK_BITSET_COPY( bitset_w_in_use,  pack->bitset_w_in_use  );
    2256             : 
    2257       14674 :   fd_pack_addr_use_t * use_by_bank     = pack->use_by_bank    [bank_tile];
    2258       14674 :   ulong                use_by_bank_cnt = pack->use_by_bank_cnt[bank_tile];
    2259             : 
    2260       14674 :   ulong max_write_cost_per_acct = pack->lim->max_write_cost_per_acct;
    2261             : 
    2262       14674 :   ushort compressed_slot_number = pack->compressed_slot_number;
    2263             : 
    2264       14674 :   ulong txns_scheduled  = 0UL;
    2265       14674 :   ulong cus_scheduled   = 0UL;
    2266       14674 :   ulong bytes_scheduled = 0UL;
    2267       14674 :   ulong alloc_scheduled = 0UL;
    2268             : 
    2269       14674 :   ulong bank_tile_mask = 1UL << bank_tile;
    2270             : 
    2271       14674 :   ulong fast_path     = 0UL;
    2272       14674 :   ulong slow_path     = 0UL;
    2273       14674 :   ulong cu_limit_c    = 0UL;
    2274       14674 :   ulong byte_limit_c  = 0UL;
    2275       14674 :   ulong alloc_limit_c = 0UL;
    2276       14674 :   ulong write_limit_c = 0UL;
    2277       14674 :   ulong skip_c        = 0UL;
    2278             : 
    2279       14674 :   ulong min_cus   = ULONG_MAX;
    2280       14674 :   ulong min_bytes = ULONG_MAX;
    2281             : 
    2282       14674 :   treap_rev_iter_t prev = treap_idx_null();
    2283      240768 :   for( treap_rev_iter_t _cur=treap_rev_iter_init( sched_from, pool ); !treap_rev_iter_done( _cur ); _cur=prev ) {
    2284             :     /* Capture next so that we can delete while we iterate. */
    2285      228907 :     prev = treap_rev_iter_next( _cur, pool );
    2286             : 
    2287      228907 : #   if FD_HAS_X86
    2288      228907 :     _mm_prefetch( &(pool[ prev ].prev),      _MM_HINT_T0 );
    2289      228907 : #   endif
    2290             : 
    2291      228907 :     fd_pack_ord_txn_t * cur = treap_rev_iter_ele( _cur, pool );
    2292             : 
    2293      228907 :     min_cus   = fd_ulong_min( min_cus,   cur->compute_est     );
    2294      228907 :     min_bytes = fd_ulong_min( min_bytes, cur->txn->payload_sz );
    2295             : 
    2296      228907 :     ulong conflicts = 0UL;
    2297             : 
    2298      228907 :     if( FD_UNLIKELY( cur->compute_est>cu_limit ) ) {
    2299             :       /* Too big to be scheduled at the moment, but might be okay for
    2300             :          the next microblock, so we don't want to delay it. */
    2301           0 :       cu_limit_c++;
    2302           0 :       continue;
    2303           0 :     }
    2304             : 
    2305      228907 :     if( FD_UNLIKELY( cur->txn->pack_alloc>alloc_limit ) ) {
    2306             :       /* We don't want to consider this until the next block, but
    2307             :          checking alloc is as cheap as checking cur->skip, so there's
    2308             :          not a big difference. */
    2309          18 :       alloc_limit_c++;
    2310          18 :       continue;
    2311          18 :     }
    2312             : 
    2313             :     /* Likely? Unlikely? */
    2314      228889 :     if( FD_LIKELY( !FD_PACK_BITSET_INTERSECT4_EMPTY( bitset_rw_in_use, bitset_w_in_use, cur->w_bitset, cur->rw_bitset ) ) ) {
    2315      202795 :       fast_path++;
    2316      202795 :       continue;
    2317      202795 :     }
    2318             : 
    2319       26094 :     if( FD_UNLIKELY( cur->skip==compressed_slot_number ) ) {
    2320           0 :       skip_c++;
    2321           0 :       continue;
    2322           0 :     }
    2323             : 
    2324             :     /* If skip>FD_PACK_MAX_SKIP but not compressed_slot_number, it means
    2325             :        it's the compressed slot number of a previous slot.  We don't
    2326             :        care unless we're going to update the value though, so we don't
    2327             :        need to eagerly reset it to FD_PACK_MAX_SKIP.
    2328             :        compressed_slot_number is a ushort, so it's possible for it to
    2329             :        roll over, but the transaction lifetime is much shorter than
    2330             :        that, so it won't be a problem. */
    2331             : 
    2332       26094 :     if( FD_UNLIKELY( cur->txn->payload_sz>byte_limit ) ) {
    2333           6 :       byte_limit_c++;
    2334           6 :       continue;
    2335           6 :     }
    2336             : 
    2337             : 
    2338       26088 :     fd_txn_t const * txn = TXN(cur->txn);
    2339       26088 :     fd_acct_addr_t const * accts   = fd_txn_get_acct_addrs( txn, cur->txn->payload );
    2340       26088 :     fd_acct_addr_t const * alt     = cur->txn_e->alt_accts;
    2341             :     /* Check conflicts between this transaction's writable accounts and
    2342             :        current readers */
    2343       26088 :     for( fd_txn_acct_iter_t iter=fd_txn_acct_iter_init( txn, FD_TXN_ACCT_CAT_WRITABLE );
    2344       84414 :         iter!=fd_txn_acct_iter_end(); iter=fd_txn_acct_iter_next( iter ) ) {
    2345             : 
    2346       58329 :       fd_acct_addr_t acct = *ACCT_ITER_TO_PTR( iter );
    2347             : 
    2348       58329 :       fd_pack_wcost_ele_t const * in_wcost_table = wcost_map_ele_query_const( writer_costs, &acct, NULL, writers );
    2349       58329 :       if( FD_UNLIKELY( in_wcost_table && in_wcost_table->total_cost+cur->compute_est > max_write_cost_per_acct ) ) {
    2350             :         /* Can't be scheduled until the next block */
    2351           3 :         conflicts = ULONG_MAX;
    2352           3 :         break;
    2353           3 :       }
    2354             : 
    2355       58326 :       fd_pack_addr_use_t * use = acct_uses_query( acct_in_use, acct, NULL );
    2356       58326 :       if( FD_UNLIKELY( use ) ) conflicts |= use->in_use_by; /* break? */
    2357       58326 :     }
    2358             : 
    2359       26088 :     if( FD_UNLIKELY( conflicts==ULONG_MAX ) ) {
    2360             :       /* The logic for how to adjust skip is a bit complicated, and we
    2361             :          want to do it branchlessly. Let psc=FD_PACK_SKIP_CNT,
    2362             :            Before                   After
    2363             :              1               compressed_slot_number
    2364             :            x in [2, psc]             x-1
    2365             :            x where x>psc            psc-1
    2366             : 
    2367             :          Set A=min(x, 5), B=min(A-2, compressed_slot_number-1), and
    2368             :          note that compressed_slot_number is in [psc+1, USHORT_MAX].
    2369             :          Then:
    2370             :              x                A     A-2          B      B+1
    2371             :              1                1  USHORT_MAX    csn-1    csn
    2372             :            x in [2, psc]      x     x-2         x-2     x-1
    2373             :            x where x>psc     psc   psc-2       psc-2   psc-1
    2374             :          So B+1 is the desired value. */
    2375           3 :       cur->skip = (ushort)(1+fd_ushort_min( (ushort)(compressed_slot_number-1),
    2376           3 :                                             (ushort)(fd_ushort_min( cur->skip, FD_PACK_SKIP_CNT )-2) ) );
    2377           3 :       write_limit_c++;
    2378           3 :       continue;
    2379           3 :     }
    2380             : 
    2381       26085 :     if( FD_UNLIKELY( conflicts ) ) {
    2382           6 :       slow_path++;
    2383           6 :       continue;
    2384           6 :     }
    2385             : 
    2386             :     /* Check conflicts between this transaction's readonly accounts and
    2387             :        current writers */
    2388       26079 :     for( fd_txn_acct_iter_t iter=fd_txn_acct_iter_init( txn, FD_TXN_ACCT_CAT_READONLY );
    2389      119094 :         iter!=fd_txn_acct_iter_end(); iter=fd_txn_acct_iter_next( iter ) ) {
    2390             : 
    2391       93015 :       fd_acct_addr_t const * acct = ACCT_ITER_TO_PTR( iter );
    2392       93015 :       if( fd_pack_unwritable_contains( acct ) ) continue; /* No need to track sysvars because they can't be writable */
    2393             : 
    2394       65142 :       fd_pack_addr_use_t * use = acct_uses_query( acct_in_use,  *acct, NULL );
    2395       65142 :       if( use ) conflicts |= (use->in_use_by & FD_PACK_IN_USE_WRITABLE) ? use->in_use_by : 0UL;
    2396       65142 :     }
    2397             : 
    2398       26079 :     if( FD_UNLIKELY( conflicts ) ) {
    2399           0 :       slow_path++;
    2400           0 :       continue;
    2401           0 :     }
    2402             : 
    2403             :     /* Include this transaction in the microblock! */
    2404       26079 :     FD_PACK_BITSET_OR( bitset_rw_in_use, cur->rw_bitset );
    2405       26079 :     FD_PACK_BITSET_OR( bitset_w_in_use,  cur->w_bitset  );
    2406             : 
    2407       26079 :     fd_txn_p_t * out_txnp = out->txnp;
    2408       26079 :     if( FD_LIKELY( cur->txn->payload_sz>=1024UL ) ) pack_memcpy_out( out_txnp->payload, cur->txn->payload, cur->txn->payload_sz );
    2409       13287 :     else                                            fd_memcpy      ( out_txnp->payload, cur->txn->payload, cur->txn->payload_sz );
    2410             : 
    2411       26079 :     out_txnp->payload_sz                                = cur->txn->payload_sz;
    2412       26079 :     out_txnp->pack_cu.requested_exec_plus_acct_data_cus = cur->txn->pack_cu.requested_exec_plus_acct_data_cus;
    2413       26079 :     out_txnp->pack_cu.non_execution_cus                 = cur->txn->pack_cu.non_execution_cus;
    2414       26079 :     out_txnp->pack_alloc                                = cur->txn->pack_alloc;
    2415       26079 :     out_txnp->scheduler_arrival_time_nanos              = cur->txn->scheduler_arrival_time_nanos;
    2416       26079 :     out_txnp->first_seen_nanos                          = cur->txn->first_seen_nanos;
    2417       26079 :     out_txnp->source_tpu                                = cur->txn->source_tpu;
    2418       26079 :     out_txnp->source_ipv4                               = cur->txn->source_ipv4;
    2419       26079 :     out_txnp->flags                                     = cur->txn->flags;
    2420       26079 :     fd_memcpy( TXN(out_txnp), txn, fd_txn_footprint( txn->instr_cnt, txn->addr_table_lookup_cnt ) );
    2421             : 
    2422             :     /* Copy the ALT accounts from the source fd_txn_e_t */
    2423       26079 :     ulong alt_acct_cnt = (ulong)txn->addr_table_adtl_cnt;
    2424       26079 :     if( FD_UNLIKELY( alt_acct_cnt ) ) pack_memcpy_out( out->alt_accts, cur->txn_e->alt_accts, alt_acct_cnt*sizeof(fd_acct_addr_t) );
    2425       26079 :     out++;
    2426             : 
    2427       26079 :     for( fd_txn_acct_iter_t iter=fd_txn_acct_iter_init( txn, FD_TXN_ACCT_CAT_WRITABLE );
    2428       84390 :         iter!=fd_txn_acct_iter_end(); iter=fd_txn_acct_iter_next( iter ) ) {
    2429       58311 :       fd_acct_addr_t acct_addr = *ACCT_ITER_TO_PTR( iter );
    2430             : 
    2431       58311 :       fd_pack_wcost_ele_t * in_wcost_table = wcost_map_ele_query( writer_costs, &acct_addr, NULL, writers );
    2432       58311 :       if( !in_wcost_table ) {
    2433       11020 :         in_wcost_table = wcost_pool_ele_acquire( writers );
    2434       11020 :         in_wcost_table->key        = acct_addr;
    2435       11020 :         in_wcost_table->total_cost = 0UL;
    2436       11020 :         wcost_map_ele_insert     ( writer_costs, in_wcost_table, writers );
    2437       11020 :         wcost_dlist_ele_push_tail( written_list, in_wcost_table, writers );
    2438       11020 :       }
    2439       58311 :       in_wcost_table->total_cost += cur->compute_est;
    2440             : 
    2441       58311 :       fd_pack_addr_use_t * use = acct_uses_insert( acct_in_use, acct_addr );
    2442       58311 :       use->in_use_by = bank_tile_mask | FD_PACK_IN_USE_WRITABLE;
    2443             : 
    2444       58311 :       use_by_bank[use_by_bank_cnt++] = *use;
    2445             : 
    2446             :       /* If there aren't any more references to this account in the
    2447             :          heap, it can't cause any conflicts.  That means we actually
    2448             :          don't need to record that we are using it, which is good
    2449             :          because we want to release the bit. */
    2450       58311 :       release_result_t ret = release_bit_reference( pack, &acct_addr );
    2451       58311 :       FD_PACK_BITSET_CLEARN( bitset_rw_in_use, ret.clear_rw_bit );
    2452       58311 :       FD_PACK_BITSET_CLEARN( bitset_w_in_use,  ret.clear_w_bit  );
    2453       58311 :     }
    2454       26079 :     for( fd_txn_acct_iter_t iter=fd_txn_acct_iter_init( txn, FD_TXN_ACCT_CAT_READONLY );
    2455      119094 :         iter!=fd_txn_acct_iter_end(); iter=fd_txn_acct_iter_next( iter ) ) {
    2456             : 
    2457       93015 :       fd_acct_addr_t acct_addr = *ACCT_ITER_TO_PTR( iter );
    2458             : 
    2459       93015 :       if( fd_pack_unwritable_contains( &acct_addr ) ) continue; /* No need to track sysvars because they can't be writable */
    2460             : 
    2461       65142 :       fd_pack_addr_use_t * use = acct_uses_query( acct_in_use,  acct_addr, NULL );
    2462       65142 :       if( !use ) { use = acct_uses_insert( acct_in_use, acct_addr ); use->in_use_by = 0UL; }
    2463             : 
    2464       65142 :       if( !(use->in_use_by & bank_tile_mask) ) use_by_bank[use_by_bank_cnt++] = *use;
    2465       65142 :       use->in_use_by |= bank_tile_mask;
    2466       65142 :       use->in_use_by &= ~FD_PACK_IN_USE_BIT_CLEARED;
    2467             : 
    2468             : 
    2469       65142 :       release_result_t ret = release_bit_reference( pack, &acct_addr );
    2470       65142 :       FD_PACK_BITSET_CLEARN( bitset_rw_in_use, ret.clear_rw_bit );
    2471       65142 :       FD_PACK_BITSET_CLEARN( bitset_w_in_use,  ret.clear_w_bit  );
    2472       65142 :     }
    2473             : 
    2474       26079 :     txns_scheduled  += 1UL;                      txn_limit       -= 1UL;
    2475       26079 :     cus_scheduled   += cur->compute_est;         cu_limit        -= cur->compute_est;
    2476       26079 :     bytes_scheduled += cur->txn->payload_sz;     byte_limit      -= cur->txn->payload_sz;
    2477       26079 :     alloc_scheduled += cur->txn->pack_alloc;     alloc_limit     -= cur->txn->pack_alloc;
    2478             : 
    2479       26079 :     *(use_by_bank_txn++) = use_by_bank_cnt;
    2480             : 
    2481       26079 :     if( FD_UNLIKELY( cur->txn->flags & FD_TXN_P_FLAGS_DURABLE_NONCE ) ) noncemap_ele_remove_fast( pack->noncemap, cur, pack->pool );
    2482       26079 :     sig2txn_ele_remove_fast( pack->signature_map, cur, pool );
    2483             : 
    2484       26079 :     cur->root = FD_ORD_TXN_ROOT_FREE;
    2485       26079 :     expq_remove( pack->expiration_q, cur->expq_idx );
    2486       26079 :     treap_idx_remove( sched_from, _cur, pool );
    2487       26079 :     trp_pool_idx_release( pool, _cur );
    2488       26079 :     pack->pending_txn_cnt--;
    2489             : 
    2490       26079 :     if( FD_UNLIKELY( (cu_limit<smallest_in_treap->cus) | (txn_limit==0UL) | (byte_limit<smallest_in_treap->bytes) ) ) break;
    2491       26079 :   }
    2492             : 
    2493       14674 :   pack->sched_results[ FD_METRICS_ENUM_PACK_TXN_SCHEDULE_RESULT_V_TAKEN_IDX               ] += txns_scheduled;
    2494       14674 :   pack->sched_results[ FD_METRICS_ENUM_PACK_TXN_SCHEDULE_RESULT_V_CU_LIMIT_IDX            ] += cu_limit_c;
    2495       14674 :   pack->sched_results[ FD_METRICS_ENUM_PACK_TXN_SCHEDULE_RESULT_V_CONFLICT_FAST_IDX       ] += fast_path;
    2496       14674 :   pack->sched_results[ FD_METRICS_ENUM_PACK_TXN_SCHEDULE_RESULT_V_BYTE_LIMIT_IDX          ] += byte_limit_c;
    2497       14674 :   pack->sched_results[ FD_METRICS_ENUM_PACK_TXN_SCHEDULE_RESULT_V_ALLOC_LIMIT_IDX         ] += alloc_limit_c;
    2498       14674 :   pack->sched_results[ FD_METRICS_ENUM_PACK_TXN_SCHEDULE_RESULT_V_WRITE_COST_IDX          ] += write_limit_c;
    2499       14674 :   pack->sched_results[ FD_METRICS_ENUM_PACK_TXN_SCHEDULE_RESULT_V_CONFLICT_SLOW_IDX       ] += slow_path;
    2500       14674 :   pack->sched_results[ FD_METRICS_ENUM_PACK_TXN_SCHEDULE_RESULT_V_WRITE_COST_DEFERRED_IDX ] += skip_c;
    2501             : 
    2502             :   /* If we scanned the whole treap and didn't break early, we now have a
    2503             :      better estimate of the smallest. */
    2504       14674 :   if( FD_UNLIKELY( treap_rev_iter_done( prev ) ) ) {
    2505       14405 :     smallest_in_treap->cus   = min_cus;
    2506       14405 :     smallest_in_treap->bytes = min_bytes;
    2507       14405 :   }
    2508             : 
    2509       14674 :   pack->use_by_bank_cnt[bank_tile] = use_by_bank_cnt;
    2510       14674 :   FD_PACK_BITSET_COPY( pack->bitset_rw_in_use, bitset_rw_in_use );
    2511       14674 :   FD_PACK_BITSET_COPY( pack->bitset_w_in_use,  bitset_w_in_use  );
    2512             : 
    2513       14674 :   sched_return_t to_return = { .cus_scheduled=cus_scheduled,     .txns_scheduled=txns_scheduled,
    2514       14674 :                                .bytes_scheduled=bytes_scheduled, .alloc_scheduled=alloc_scheduled };
    2515       14674 :   return to_return;
    2516       14850 : }
    2517             : 
    2518             : int
    2519             : fd_pack_microblock_complete( fd_pack_t * pack,
    2520       14988 :                              ulong       bank_tile ) {
    2521             :   /* If the account is in use writably, and it's in use by this banking
    2522             :      tile, then this banking tile must be the sole writer to it, so it's
    2523             :      always okay to clear the writable bit. */
    2524       14988 :   ulong clear_mask = ~((1UL<<bank_tile) | FD_PACK_IN_USE_WRITABLE);
    2525             : 
    2526             :   /* If nothing outstanding, bail quickly */
    2527       14988 :   if( FD_UNLIKELY( !(pack->outstanding_microblock_mask & (1UL<<bank_tile)) ) ) return 0;
    2528             : 
    2529        8719 :   FD_PACK_BITSET_DECLARE( bitset_rw_in_use );
    2530        8719 :   FD_PACK_BITSET_DECLARE( bitset_w_in_use  );
    2531        8719 :   FD_PACK_BITSET_COPY( bitset_rw_in_use, pack->bitset_rw_in_use );
    2532        8719 :   FD_PACK_BITSET_COPY( bitset_w_in_use,  pack->bitset_w_in_use  );
    2533             : 
    2534        8719 :   fd_pack_addr_use_t * base = pack->use_by_bank[bank_tile];
    2535             : 
    2536        8719 :   fd_pack_ord_txn_t       * best         = NULL;
    2537        8719 :   fd_pack_penalty_treap_t * best_penalty = NULL;
    2538        8719 :   ulong                     txn_cnt      = 0UL;
    2539             : 
    2540      113963 :   for( ulong i=0UL; i<pack->use_by_bank_cnt[bank_tile]; i++ ) {
    2541      105244 :     fd_pack_addr_use_t * use = acct_uses_query( pack->acct_in_use, base[i].key, NULL );
    2542      105244 :     FD_TEST( use );
    2543      105244 :     use->in_use_by &= clear_mask;
    2544             : 
    2545             :     /* In order to properly bound the size of bitset_map, we need to
    2546             :        release the "reference" to the account when we schedule it.
    2547             :        However, that poses a bit of a problem here, because by the time
    2548             :        we complete the microblock, that account could have been assigned
    2549             :        a different bit in the bitset.  The scheduling step tells us if
    2550             :        that is the case, and if so, we know that the bits in
    2551             :        bitset_w_in_use and bitset_rw_in_use were already cleared as
    2552             :        necessary.
    2553             : 
    2554             :        Note that it's possible for BIT_CLEARED to be set and then unset
    2555             :        by later uses, but then the account would be in use on other
    2556             :        banks, so we wouldn't try to observe the old value.  For example:
    2557             :        Suppose bit 0->account A, bit 1->account B, and we have two
    2558             :        transactions that read A, B.  We schedule a microblock to bank 0,
    2559             :        taking both transactions, which sets the counts for A, B to 0,
    2560             :        and releases the bits, clearing bits 0 and 1, and setting
    2561             :        BIT_CLEARED.  Then we get two more transactions that read
    2562             :        accounts C, D, A, B, and they get assigned 0->C, 1->D, 2->A,
    2563             :        3->B.  We try to schedule a microblock to bank 1 that takes one
    2564             :        of those transactions.  This unsets BIT_CLEARED for A, B.
    2565             :        Finally, the first microblock completes.  Even though the bitset
    2566             :        map has the new bits for A and B which are "wrong" compared to
    2567             :        when the transaction was initially scheduled, those bits have
    2568             :        already been cleared and reset properly in the bitset as needed.
    2569             :        A and B will still be in use by bank 1, so we won't clear any
    2570             :        bits.  If, on the other hand, the microblock scheduled to bank 1
    2571             :        completes first, bits 0 and 1 will be cleared for accounts C and
    2572             :        D, while bits 2 and 3 will remain set, which is correct.  Then
    2573             :        when bank 0 completes, bits 2 and 3 will be cleared. */
    2574      105244 :     if( FD_LIKELY( !use->in_use_by ) ) { /* if in_use_by==0, doesn't include BIT_CLEARED */
    2575       39552 :       fd_pack_bitset_acct_mapping_t * q = bitset_map_query( pack->acct_to_bitset, base[i].key, NULL );
    2576       39552 :       FD_TEST( q );
    2577       39552 :       FD_PACK_BITSET_CLEARN( bitset_w_in_use,  q->bit );
    2578       39552 :       FD_PACK_BITSET_CLEARN( bitset_rw_in_use, q->bit );
    2579             : 
    2580             :       /* Because this account is no longer in use, it might be possible
    2581             :          to schedule a transaction that writes to it.  Check its
    2582             :          penalty treap if it has one, and potentially move it to the
    2583             :          main treap. */
    2584       39552 :       fd_pack_penalty_treap_t * p_trp = penalty_map_query( pack->penalty_treaps, base[i].key, NULL );
    2585       39552 :       if( FD_UNLIKELY( p_trp ) ) {
    2586        5507 :         fd_pack_ord_txn_t * best_in_trp = treap_rev_iter_ele( treap_rev_iter_init( p_trp->penalty_treap, pack->pool ), pack->pool );
    2587        5507 :         if( FD_UNLIKELY( !best || COMPARE_WORSE( best, best_in_trp ) ) ) {
    2588        2806 :           best         = best_in_trp;
    2589        2806 :           best_penalty = p_trp;
    2590        2806 :         }
    2591        5507 :       }
    2592       39552 :     }
    2593             : 
    2594      105244 :     if( FD_LIKELY( !(use->in_use_by & ~FD_PACK_IN_USE_BIT_CLEARED) ) ) acct_uses_remove( pack->acct_in_use, use );
    2595             : 
    2596      105244 :     if( FD_UNLIKELY( i+1UL==pack->use_by_bank_txn[ bank_tile ][ txn_cnt ] ) ) {
    2597       25473 :       txn_cnt++;
    2598       25473 :       if( FD_LIKELY( best ) ) {
    2599             :         /* move best to the main treap */
    2600        2806 :         treap_ele_remove( best_penalty->penalty_treap, best, pack->pool );
    2601        2806 :         best->root = FD_ORD_TXN_ROOT_PENDING;
    2602        2806 :         treap_ele_insert( pack->pending,               best, pack->pool );
    2603             : 
    2604        2806 :         pack->pending_smallest->cus   = fd_ulong_min( pack->pending_smallest->cus,   best->compute_est             );
    2605        2806 :         pack->pending_smallest->bytes = fd_ulong_min( pack->pending_smallest->bytes, best->txn_e->txnp->payload_sz );
    2606             : 
    2607        2806 :         if( FD_UNLIKELY( !treap_ele_cnt( best_penalty->penalty_treap ) ) ) {
    2608          12 :           treap_delete( treap_leave( best_penalty->penalty_treap ) );
    2609             :           /* Removal invalidates any pointers we got from
    2610             :              penalty_map_query, but we immediately set these to NULL, so
    2611             :              we're not keeping any pointers around. */
    2612          12 :           penalty_map_remove( pack->penalty_treaps, best_penalty );
    2613          12 :         }
    2614        2806 :         best         = NULL;
    2615        2806 :         best_penalty = NULL;
    2616        2806 :       }
    2617       25473 :     }
    2618      105244 :   }
    2619             : 
    2620        8719 :   pack->use_by_bank_cnt[bank_tile] = 0UL;
    2621             : 
    2622        8719 :   FD_PACK_BITSET_COPY( pack->bitset_rw_in_use, bitset_rw_in_use );
    2623        8719 :   FD_PACK_BITSET_COPY( pack->bitset_w_in_use,  bitset_w_in_use  );
    2624             : 
    2625             :   /* outstanding_microblock_mask never has the writable bit set, so we
    2626             :      don't care about clearing it here either. */
    2627        8719 :   pack->outstanding_microblock_mask &= clear_mask;
    2628        8719 :   return 1;
    2629        8719 : }
    2630             : 
    2631       14859 : #define TRY_BUNDLE_NO_READY_BUNDLES      0
    2632         261 : #define TRY_BUNDLE_HAS_CONFLICTS       (-1)
    2633         261 : #define TRY_BUNDLE_DOES_NOT_FIT        (-2)
    2634         261 : #define TRY_BUNDLE_SUCCESS(n)          ( n) /* schedule bundle with n transactions */
    2635             : static inline int
    2636             : fd_pack_try_schedule_bundle( fd_pack_t  * pack,
    2637             :                              ulong        bank_tile,
    2638       15120 :                              fd_txn_e_t * out ) {
    2639       15120 :   int state = pack->initializer_bundle_state;
    2640       15120 :   if( FD_UNLIKELY( (state==FD_PACK_IB_STATE_PENDING) | (state==FD_PACK_IB_STATE_FAILED ) ) ) return TRY_BUNDLE_NO_READY_BUNDLES;
    2641             : 
    2642       15117 :   fd_pack_ord_txn_t * pool    = pack->pool;
    2643       15117 :   treap_t           * bundles = pack->pending_bundles;
    2644             : 
    2645       15117 :   int require_ib;
    2646       15117 :   if( FD_UNLIKELY( state==FD_PACK_IB_STATE_NOT_INITIALIZED ) ) { require_ib = 1; }
    2647       15117 :   if( FD_LIKELY  ( state==FD_PACK_IB_STATE_READY           ) ) { require_ib = 0; }
    2648             : 
    2649       15117 :   treap_rev_iter_t _cur  = treap_rev_iter_init( bundles, pool );
    2650       15117 :   ulong bundle_idx = ULONG_MAX;
    2651             : 
    2652             :   /* Skip any that we've marked as won't fit in this block */
    2653       15117 :   while( FD_UNLIKELY( !treap_rev_iter_done( _cur ) && treap_rev_iter_ele( _cur, pool )->skip==pack->compressed_slot_number ) ) {
    2654           0 :     _cur = treap_rev_iter_next( _cur, pool );
    2655           0 :     pack->sched_results[ FD_METRICS_ENUM_PACK_TXN_SCHEDULE_RESULT_V_WRITE_COST_DEFERRED_IDX ]++;
    2656           0 :   }
    2657             : 
    2658             :   /* If there are no normal bundles to run, then fall back to the
    2659             :      pre-rotation treap. This is because fresh bundles usually don't
    2660             :      arrive exactly at the start of our leader rotation, so whilst we
    2661             :      are waiting for fresh bundles we should try the pre-rotation ones. */
    2662       15117 :   int                             is_pre_rotation     = 0;
    2663       15117 :   fd_pack_pre_rotation_bundle_t * pre_rotation_bundle = NULL;
    2664       15117 :   if( FD_UNLIKELY( treap_rev_iter_done( _cur ) ) ) {
    2665       14817 :     if( FD_UNLIKELY( require_ib ) ) return TRY_BUNDLE_NO_READY_BUNDLES;
    2666          87 :     is_pre_rotation = 1;
    2667          87 :     ulong best = pre_rotation_best_bundle_idx( pack );
    2668          87 :     if( FD_UNLIKELY( best==ULONG_MAX ) ) return TRY_BUNDLE_NO_READY_BUNDLES;
    2669          81 :     pre_rotation_bundle = pack->pre_rotation_bundles + best;
    2670          81 :     _cur                = treap_rev_iter_init( pre_rotation_bundle->treap, pool );
    2671          81 :   }
    2672             : 
    2673         381 :   if( FD_UNLIKELY( treap_rev_iter_done( _cur ) ) ) return TRY_BUNDLE_NO_READY_BUNDLES;
    2674             : 
    2675         381 :   treap_rev_iter_t   _txn0 = _cur;
    2676         381 :   fd_pack_ord_txn_t * txn0 = treap_rev_iter_ele( _txn0, pool );
    2677         381 :   int is_ib = !!(txn0->txn->flags & FD_TXN_P_FLAGS_INITIALIZER_BUNDLE);
    2678         381 :   bundle_idx = RC_TO_REL_BUNDLE_IDX( txn0->rewards, txn0->compute_est );
    2679             : 
    2680         381 :   if( FD_UNLIKELY( require_ib & !is_ib ) ) return TRY_BUNDLE_NO_READY_BUNDLES;
    2681             : 
    2682             :   /* At this point, we have our candidate bundle, so we'll schedule it
    2683             :      if we can.  If we can't, we won't schedule anything. */
    2684             : 
    2685             : 
    2686         261 :   fd_pack_addr_use_t * bundle_temp_inserted[ FD_PACK_MAX_TXN_PER_BUNDLE * FD_TXN_ACCT_ADDR_MAX ];
    2687         261 :   ulong bundle_temp_inserted_cnt = 0UL;
    2688             : 
    2689         261 :   ulong bank_tile_mask = 1UL << bank_tile;
    2690             : 
    2691         261 :   int doesnt_fit   = 0;
    2692         261 :   int has_conflict = 0;
    2693         261 :   ulong txn_cnt = 0UL;
    2694             : 
    2695         261 :   ulong cu_limit         = pack->lim->max_cost_per_block           - pack->cumulative_block_cost;
    2696         261 :   ulong byte_limit       = pack->lim->max_data_bytes_per_block     - pack->data_bytes_consumed;
    2697         261 :   ulong microblock_limit = pack->lim->max_microblocks_per_block    - pack->microblock_cnt;
    2698         261 :   ulong alloc_limit      = pack->lim->max_allocated_data_per_block - pack->alloc_consumed;
    2699             : 
    2700         261 :   FD_PACK_BITSET_DECLARE( bitset_rw_in_use );
    2701         261 :   FD_PACK_BITSET_DECLARE( bitset_w_in_use  );
    2702         261 :   FD_PACK_BITSET_COPY( bitset_rw_in_use, pack->bitset_rw_in_use );
    2703         261 :   FD_PACK_BITSET_COPY( bitset_w_in_use,  pack->bitset_w_in_use  );
    2704             : 
    2705             :   /* last_use_in_txn_cnt[i+1] Keeps track of the number of accounts that
    2706             :      have their last reference in transaction i of the bundle.  This
    2707             :      esoteric value is important for computing use_by_bank_txn.
    2708             :      last_use_in_txn_cnt[0] is garbage. */
    2709         261 :   ulong last_use_in_txn_cnt[ 1UL+FD_PACK_MAX_TXN_PER_BUNDLE ] = { 0UL };
    2710             : 
    2711         261 :   fd_pack_addr_use_t   null_use[1]    = {{{{ 0 }}, { 0 }}};
    2712         261 :   fd_pack_wcost_ele_t  null_wcost[1]  = { 0 };
    2713             : 
    2714         819 :   while( !(doesnt_fit | has_conflict) & !treap_rev_iter_done( _cur ) ) {
    2715         591 :     fd_pack_ord_txn_t * cur = treap_rev_iter_ele( _cur, pool );
    2716         591 :     ulong this_bundle_idx = RC_TO_REL_BUNDLE_IDX( cur->rewards, cur->compute_est );
    2717         591 :     if( FD_UNLIKELY( this_bundle_idx!=bundle_idx ) ) break;
    2718             : 
    2719         561 :     if( FD_UNLIKELY( cur->compute_est>cu_limit ) ) {
    2720           0 :       doesnt_fit = 1;
    2721           0 :       pack->sched_results[ FD_METRICS_ENUM_PACK_TXN_SCHEDULE_RESULT_V_CU_LIMIT_IDX ]++;
    2722           0 :       break;
    2723           0 :     }
    2724         561 :     cu_limit -= cur->compute_est;
    2725             : 
    2726             :     /* Each transaction in a bundle turns into a microblock */
    2727         561 :     if( FD_UNLIKELY( microblock_limit==0UL ) ) {
    2728           0 :       doesnt_fit = 1;
    2729           0 :       FD_MCNT_INC( PACK, BLOCK_MICROBLOCK_LIMIT_REACHED, 1UL );
    2730           0 :       break;
    2731           0 :     }
    2732         561 :     microblock_limit--;
    2733             : 
    2734         561 :     if( FD_UNLIKELY( cur->txn->payload_sz+MICROBLOCK_DATA_OVERHEAD>byte_limit ) ) {
    2735           0 :       doesnt_fit = 1;
    2736           0 :       pack->sched_results[ FD_METRICS_ENUM_PACK_TXN_SCHEDULE_RESULT_V_BYTE_LIMIT_IDX ]++;
    2737           0 :       break;
    2738           0 :     }
    2739         561 :     byte_limit -= cur->txn->payload_sz + MICROBLOCK_DATA_OVERHEAD;
    2740             : 
    2741         561 :     if( FD_UNLIKELY( cur->txn->pack_alloc>alloc_limit ) ) {
    2742           0 :       doesnt_fit = 1;
    2743           0 :       pack->sched_results[ FD_METRICS_ENUM_PACK_TXN_SCHEDULE_RESULT_V_ALLOC_LIMIT_IDX ]++;
    2744           0 :       break;
    2745           0 :     }
    2746         561 :     alloc_limit -= cur->txn->pack_alloc;
    2747             : 
    2748         561 :     if( FD_UNLIKELY( !FD_PACK_BITSET_INTERSECT4_EMPTY( pack->bitset_rw_in_use, pack->bitset_w_in_use, cur->w_bitset, cur->rw_bitset ) ) ) {
    2749           0 :       has_conflict = 1;
    2750           0 :       pack->sched_results[ FD_METRICS_ENUM_PACK_TXN_SCHEDULE_RESULT_V_CONFLICT_FAST_IDX ]++;
    2751           0 :       break;
    2752           0 :     }
    2753             : 
    2754             :     /* Don't update the actual in-use bitset, because the transactions
    2755             :        in the bundle are allowed to conflict with each other. */
    2756         561 :     FD_PACK_BITSET_OR( bitset_rw_in_use, cur->rw_bitset );
    2757         561 :     FD_PACK_BITSET_OR( bitset_w_in_use,  cur->w_bitset  );
    2758             : 
    2759             : 
    2760         561 :     fd_txn_t const * txn = TXN(cur->txn);
    2761         561 :     fd_acct_addr_t const * accts   = fd_txn_get_acct_addrs( txn, cur->txn->payload );
    2762         561 :     fd_acct_addr_t const * alt     = cur->txn_e->alt_accts;
    2763             : 
    2764             :     /* Check conflicts between this transaction's writable accounts and
    2765             :        current readers */
    2766         561 :     for( fd_txn_acct_iter_t iter=fd_txn_acct_iter_init( txn, FD_TXN_ACCT_CAT_WRITABLE );
    2767        1773 :         iter!=fd_txn_acct_iter_end(); iter=fd_txn_acct_iter_next( iter ) ) {
    2768             : 
    2769        1215 :       fd_acct_addr_t acct = *ACCT_ITER_TO_PTR( iter );
    2770             : 
    2771        1215 :       fd_pack_addr_use_t * in_bundle_temp = acct_uses_query          ( pack->bundle_temp_map, acct, null_use                  );
    2772        1215 :       ulong current_cost                  = wcost_map_ele_query_const( pack->writer_costs,   &acct, null_wcost, pack->writers )->total_cost;
    2773        1215 :       ulong carried_cost                  = (ulong)in_bundle_temp->carried_cost;
    2774        1215 :       if( FD_UNLIKELY( current_cost + carried_cost + cur->compute_est > pack->lim->max_write_cost_per_acct ) ) {
    2775           0 :         doesnt_fit = 1;
    2776           0 :         pack->sched_results[ FD_METRICS_ENUM_PACK_TXN_SCHEDULE_RESULT_V_WRITE_COST_IDX ]++;
    2777           0 :         break;
    2778           0 :       }
    2779             : 
    2780        1215 :       if( FD_LIKELY( in_bundle_temp==null_use ) ) { /* Not in temp bundle table yet */
    2781        1155 :         in_bundle_temp    = acct_uses_insert( pack->bundle_temp_map, acct );
    2782        1155 :         in_bundle_temp->_ = 0UL;
    2783        1155 :         bundle_temp_inserted[ bundle_temp_inserted_cnt++ ] = in_bundle_temp;
    2784        1155 :       }
    2785        1215 :       in_bundle_temp->carried_cost += (uint)cur->compute_est; /* < 2^21, but >0 */
    2786        1215 :       in_bundle_temp->ref_cnt++;
    2787        1215 :       last_use_in_txn_cnt[ in_bundle_temp->last_use_in ]--;
    2788        1215 :       in_bundle_temp->last_use_in = (ushort)(txn_cnt+1UL);
    2789        1215 :       last_use_in_txn_cnt[ in_bundle_temp->last_use_in ]++;
    2790             : 
    2791        1215 :       if( FD_UNLIKELY( acct_uses_query( pack->acct_in_use, acct, null_use )->in_use_by ) ) {
    2792           3 :         has_conflict = 1;
    2793           3 :         pack->sched_results[ FD_METRICS_ENUM_PACK_TXN_SCHEDULE_RESULT_V_CONFLICT_SLOW_IDX ]++;
    2794           3 :         break;
    2795           3 :       }
    2796        1215 :     }
    2797         561 :     if( has_conflict | doesnt_fit ) break;
    2798             : 
    2799             :     /* Check conflicts between this transaction's readonly accounts and
    2800             :        current writers */
    2801         558 :     for( fd_txn_acct_iter_t iter=fd_txn_acct_iter_init( txn, FD_TXN_ACCT_CAT_READONLY );
    2802        2661 :         iter!=fd_txn_acct_iter_end(); iter=fd_txn_acct_iter_next( iter ) ) {
    2803             : 
    2804        2103 :       fd_acct_addr_t const * acct = ACCT_ITER_TO_PTR( iter );
    2805        2103 :       if( fd_pack_unwritable_contains( acct ) ) continue; /* No need to track sysvars because they can't be writable */
    2806             : 
    2807        1401 :       fd_pack_addr_use_t * in_bundle_temp = acct_uses_query( pack->bundle_temp_map, *acct, null_use );
    2808        1401 :       if( FD_LIKELY( in_bundle_temp==null_use ) ) { /* Not in temp bundle table yet */
    2809        1080 :         in_bundle_temp = acct_uses_insert( pack->bundle_temp_map, *acct );
    2810        1080 :         in_bundle_temp->_ = 0UL;
    2811        1080 :         bundle_temp_inserted[ bundle_temp_inserted_cnt++ ] = in_bundle_temp;
    2812        1080 :       }
    2813        1401 :       in_bundle_temp->ref_cnt++;
    2814        1401 :       last_use_in_txn_cnt[ in_bundle_temp->last_use_in ]--;
    2815        1401 :       in_bundle_temp->last_use_in = (ushort)(txn_cnt+1UL);
    2816        1401 :       last_use_in_txn_cnt[ in_bundle_temp->last_use_in ]++;
    2817             : 
    2818        1401 :       if( FD_UNLIKELY( acct_uses_query( pack->acct_in_use,  *acct, null_use )->in_use_by & FD_PACK_IN_USE_WRITABLE ) ) {
    2819           0 :         has_conflict = 1;
    2820           0 :         pack->sched_results[ FD_METRICS_ENUM_PACK_TXN_SCHEDULE_RESULT_V_CONFLICT_SLOW_IDX ]++;
    2821           0 :         break;
    2822           0 :       }
    2823        1401 :     }
    2824             : 
    2825         558 :     if( has_conflict | doesnt_fit ) break;
    2826             : 
    2827         558 :     txn_cnt++;
    2828         558 :     _cur = treap_rev_iter_next( _cur, pool );
    2829         558 :   }
    2830         261 :   int retval = fd_int_if( doesnt_fit, TRY_BUNDLE_DOES_NOT_FIT,
    2831         261 :                                       fd_int_if( has_conflict, TRY_BUNDLE_HAS_CONFLICTS, TRY_BUNDLE_SUCCESS( (int)txn_cnt ) ) );
    2832             : 
    2833         261 :   if( FD_UNLIKELY( retval<=0 ) ) {
    2834           9 :     for( ulong i=0UL; i<bundle_temp_inserted_cnt; i++ ) {
    2835           6 :       acct_uses_remove( pack->bundle_temp_map, bundle_temp_inserted[ bundle_temp_inserted_cnt-i-1UL ] );
    2836           6 :     }
    2837           3 :     FD_TEST( acct_uses_key_cnt( pack->bundle_temp_map )==0UL );
    2838             : 
    2839           3 :     if( FD_UNLIKELY( retval==TRY_BUNDLE_DOES_NOT_FIT ) ) {
    2840             :       /* Decrement the skip count for the bundle we just tried. */
    2841             : 
    2842           0 :       for( _cur=_txn0; !treap_rev_iter_done( _cur ); _cur=treap_rev_iter_next( _cur, pool ) ) {
    2843           0 :         fd_pack_ord_txn_t * cur = treap_rev_iter_ele( _cur, pool );
    2844           0 :         ulong this_bundle_idx = RC_TO_REL_BUNDLE_IDX( cur->rewards, cur->compute_est );
    2845           0 :         if( FD_UNLIKELY( this_bundle_idx!=bundle_idx ) ) break;
    2846             : 
    2847             :         /* See fd_pack_schedule_impl for this line */
    2848           0 :         cur->skip = (ushort)(1+fd_ushort_min( (ushort)(pack->compressed_slot_number-1),
    2849           0 :               (ushort)(fd_ushort_min( cur->skip, FD_PACK_SKIP_CNT )-2) ) );
    2850           0 :       }
    2851           0 :     }
    2852           3 :     return retval;
    2853           3 :   }
    2854             : 
    2855             :   /* This bundle passed validation, so now we'll take it! */
    2856         258 :   pack->outstanding_microblock_mask |= bank_tile_mask;
    2857         258 :   FD_MCNT_INC( PACK, PRE_ROTATION_BUNDLE_SCHEDULED, (ulong)is_pre_rotation );
    2858             : 
    2859         258 :   treap_rev_iter_t   _end  = _cur;
    2860         258 :   treap_rev_iter_t   _next;
    2861             : 
    2862             :   /* We'll carefully incrementally construct use_by_bank and
    2863             :      use_by_bank_txn based on the contents of bundle_temp and
    2864             :      last_use_in_txn_cnt. */
    2865         258 :   fd_pack_addr_use_t * use_by_bank     = pack->use_by_bank    [bank_tile];
    2866         258 :   ulong              * use_by_bank_txn = pack->use_by_bank_txn[bank_tile];
    2867         258 :   ulong cum_sum = 0UL;
    2868         816 :   for( ulong k=0UL; k<txn_cnt; k++ ) { use_by_bank_txn[k] = cum_sum; cum_sum += last_use_in_txn_cnt[ k+1UL ]; }
    2869         258 :   pack->use_by_bank_cnt[bank_tile] = cum_sum;
    2870             : 
    2871             : 
    2872         816 :   for( _cur=_txn0; _cur!=_end; _cur=_next ) {
    2873         558 :     _next = treap_rev_iter_next( _cur, pool );
    2874             : 
    2875         558 :     fd_pack_ord_txn_t * cur = treap_rev_iter_ele( _cur, pool );
    2876         558 :     fd_txn_t const    * txn = TXN(cur->txn);
    2877         558 :     fd_txn_p_t        * out_txnp = out->txnp;
    2878         558 :     if( FD_LIKELY( cur->txn->payload_sz>=1024UL ) ) pack_memcpy_out( out_txnp->payload, cur->txn->payload, cur->txn->payload_sz );
    2879         198 :     else                                            fd_memcpy      ( out_txnp->payload, cur->txn->payload, cur->txn->payload_sz );
    2880         558 :     fd_memcpy( TXN(out_txnp),     txn,               fd_txn_footprint( txn->instr_cnt, txn->addr_table_lookup_cnt ) );
    2881         558 :     out_txnp->payload_sz                      = cur->txn->payload_sz;
    2882         558 :     out_txnp->pack_cu.requested_exec_plus_acct_data_cus = cur->txn->pack_cu.requested_exec_plus_acct_data_cus;
    2883         558 :     out_txnp->pack_cu.non_execution_cus       = cur->txn->pack_cu.non_execution_cus;
    2884         558 :     out_txnp->pack_alloc                      = cur->txn->pack_alloc;
    2885         558 :     out_txnp->scheduler_arrival_time_nanos    = cur->txn->scheduler_arrival_time_nanos;
    2886         558 :     out_txnp->first_seen_nanos                = cur->txn->first_seen_nanos;
    2887         558 :     out_txnp->source_tpu                      = cur->txn->source_tpu;
    2888         558 :     out_txnp->source_ipv4                     = cur->txn->source_ipv4;
    2889         558 :     out_txnp->flags                           = cur->txn->flags;
    2890             :     /* Copy the ALT accounts from the source fd_txn_e_t */
    2891         558 :     ulong alt_acct_cnt = (ulong)txn->addr_table_adtl_cnt;
    2892         558 :     if( FD_UNLIKELY( alt_acct_cnt ) ) pack_memcpy_out( out->alt_accts, cur->txn_e->alt_accts, alt_acct_cnt*sizeof(fd_acct_addr_t) );
    2893         558 :     out++;
    2894             : 
    2895         558 :     pack->cumulative_block_cost += cur->compute_est;
    2896         558 :     pack->data_bytes_consumed   += cur->txn->payload_sz + MICROBLOCK_DATA_OVERHEAD;
    2897         558 :     pack->alloc_consumed        += cur->txn->pack_alloc;
    2898         558 :     pack->microblock_cnt        += 1UL;
    2899             : 
    2900         558 :     if( FD_UNLIKELY( cur->txn->flags & FD_TXN_P_FLAGS_DURABLE_NONCE ) ) noncemap_ele_remove_fast( pack->noncemap, cur, pack->pool );
    2901         558 :     sig2txn_ele_remove_fast( pack->signature_map, cur, pack->pool );
    2902             : 
    2903         558 :     cur->root = FD_ORD_TXN_ROOT_FREE;
    2904         558 :     expq_remove( pack->expiration_q, cur->expq_idx );
    2905         558 :     if( FD_UNLIKELY( is_pre_rotation ) ) pre_rotation_bundle_remove( pack, pre_rotation_bundle, _cur );
    2906         474 :     else                                 treap_idx_remove( pack->pending_bundles, _cur, pack->pool );
    2907         558 :     trp_pool_idx_release( pack->pool, _cur );
    2908         558 :     pack->pending_txn_cnt--;
    2909         558 :   }
    2910             : 
    2911             : 
    2912        2487 :   for( ulong i=0UL; i<bundle_temp_inserted_cnt; i++ ) {
    2913             :     /* In order to clear bundle_temp_map with the typical trick, we need
    2914             :        to iterate through bundle_temp_inserted backwards. */
    2915        2229 :     fd_pack_addr_use_t * addr_use = bundle_temp_inserted[ bundle_temp_inserted_cnt-i-1UL ];
    2916             : 
    2917        2229 :     int any_writers = addr_use->carried_cost>0U; /* Did any transaction in this bundle write lock this account address? */
    2918             : 
    2919        2229 :     if( FD_LIKELY( any_writers ) ) { /* UNLIKELY? */
    2920        1149 :       fd_pack_wcost_ele_t * in_wcost_table = wcost_map_ele_query( pack->writer_costs, &addr_use->key, NULL, pack->writers );
    2921        1149 :       if( !in_wcost_table ) {
    2922        1053 :         in_wcost_table = wcost_pool_ele_acquire( pack->writers );
    2923        1053 :         in_wcost_table->key        = addr_use->key;
    2924        1053 :         in_wcost_table->total_cost = 0UL;
    2925        1053 :         wcost_map_ele_insert     ( pack->writer_costs, in_wcost_table, pack->writers );
    2926        1053 :         wcost_dlist_ele_push_tail( pack->written_list, in_wcost_table, pack->writers );
    2927        1053 :       }
    2928        1149 :       in_wcost_table->total_cost += (ulong)addr_use->carried_cost;
    2929        1149 :     }
    2930             : 
    2931             :     /* in_use_by must be set before releasing the bit reference */
    2932        2229 :     fd_pack_addr_use_t * use = acct_uses_query( pack->acct_in_use, addr_use->key, NULL );
    2933        2229 :     if( !use ) { use = acct_uses_insert( pack->acct_in_use, addr_use->key ); use->in_use_by = 0UL; }
    2934        2229 :     use->in_use_by |= bank_tile_mask | fd_ulong_if( any_writers, FD_PACK_IN_USE_WRITABLE, 0UL );
    2935        2229 :     use->in_use_by &= ~FD_PACK_IN_USE_BIT_CLEARED;
    2936             : 
    2937        2229 :     use_by_bank[ use_by_bank_txn[ addr_use->last_use_in-1UL ]++ ] = *use;
    2938             : 
    2939        4839 :     for( ulong k=0UL; k<(ulong)addr_use->ref_cnt; k++ ) {
    2940        2610 :       release_result_t ret = release_bit_reference( pack, &(addr_use->key) );
    2941        2610 :       FD_PACK_BITSET_CLEARN( bitset_rw_in_use, ret.clear_rw_bit );
    2942        2610 :       FD_PACK_BITSET_CLEARN( bitset_w_in_use,  ret.clear_w_bit  );
    2943        2610 :     }
    2944             : 
    2945        2229 :     acct_uses_remove( pack->bundle_temp_map, addr_use );
    2946        2229 :   }
    2947             : 
    2948         258 :   FD_PACK_BITSET_COPY( pack->bitset_rw_in_use, bitset_rw_in_use );
    2949         258 :   FD_PACK_BITSET_COPY( pack->bitset_w_in_use,  bitset_w_in_use  );
    2950             : 
    2951         258 :   if( FD_UNLIKELY( is_ib ) ) {
    2952           6 :     pack->initializer_bundle_state = FD_PACK_IB_STATE_PENDING;
    2953           6 :   }
    2954         258 :   pack_memcpy_fini();
    2955         258 :   return retval;
    2956         261 : }
    2957             : 
    2958             : 
    2959             : ulong
    2960             : fd_pack_schedule_next_microblock( fd_pack_t *  pack,
    2961             :                                   ulong        total_cus,
    2962             :                                   ulong        bank_tile,
    2963             :                                   int          schedule_flags,
    2964       15243 :                                   fd_txn_e_t * out ) {
    2965             : 
    2966             :   /* TODO: Decide if these are exactly how we want to handle limits */
    2967       15243 :   total_cus = fd_ulong_min( total_cus, pack->lim->max_cost_per_block - pack->cumulative_block_cost );
    2968             : 
    2969       15243 :   if( FD_UNLIKELY( (pack->microblock_cnt>=pack->lim->max_microblocks_per_block) ) ) {
    2970           0 :     FD_MCNT_INC( PACK, BLOCK_MICROBLOCK_LIMIT_REACHED, 1UL );
    2971           0 :     return 0UL;
    2972           0 :   }
    2973       15243 :   if( FD_UNLIKELY( pack->data_bytes_consumed+MICROBLOCK_DATA_OVERHEAD+FD_TXN_MIN_SERIALIZED_SZ>pack->lim->max_data_bytes_per_block) ) {
    2974           0 :     FD_MCNT_INC( PACK, BLOCK_BYTE_LIMIT_REACHED, 1UL );
    2975           0 :     return 0UL;
    2976           0 :   }
    2977             : 
    2978       15243 :   ulong * use_by_bank_txn = pack->use_by_bank_txn[ bank_tile ];
    2979             : 
    2980       15243 : #if FD_HAS_X86
    2981             :   /* out is a cold dcache chunk.  Its payload is streamed, but the
    2982             :      metadata and TXN() lines are regular stores; start those reads for
    2983             :      ownership under the scheduling work. */
    2984       15243 :   _mm_prefetch( (uchar *)out+FD_TPU_MTU,       _MM_HINT_ET0 );
    2985       15243 :   _mm_prefetch( (uchar *)out+FD_TPU_MTU+ 64UL, _MM_HINT_ET0 );
    2986       15243 :   _mm_prefetch( (uchar *)out+FD_TPU_MTU+128UL, _MM_HINT_ET0 );
    2987       15243 : #endif
    2988             : 
    2989       15243 :   ulong cu_limit    = total_cus;
    2990       15243 :   ulong txn_limit   = pack->lim->max_txn_per_microblock;
    2991       15243 :   ulong scheduled   = 0UL;
    2992       15243 :   ulong byte_limit  = pack->lim->max_data_bytes_per_block - pack->data_bytes_consumed - MICROBLOCK_DATA_OVERHEAD;
    2993       15243 :   ulong alloc_limit = pack->lim->max_allocated_data_per_block - pack->alloc_consumed;
    2994             : 
    2995       15243 :   sched_return_t status = {0};
    2996             : 
    2997       15243 :   if( FD_UNLIKELY( schedule_flags & FD_PACK_SCHEDULE_BUNDLE ) ) {
    2998       15120 :     int bundle_result = fd_pack_try_schedule_bundle( pack, bank_tile, out );
    2999       15120 :     if( FD_UNLIKELY( bundle_result>0                         ) ) return (ulong)bundle_result;
    3000       14862 :     if( FD_UNLIKELY( bundle_result==TRY_BUNDLE_HAS_CONFLICTS ) ) return 0UL;
    3001             :     /* in the NO_READY_BUNDLES or DOES_NOT_FIT case, we schedule like
    3002             :        normal. */
    3003             :     /* We have the early returns here because try_schedule_bundle does
    3004             :        the bookkeeping internally, since the calculations are a bit
    3005             :        different in that case. */
    3006       14862 :   }
    3007             : 
    3008             : 
    3009             :   /* Fill the microblock with transactions, votes included */
    3010       14982 :   if( FD_LIKELY( schedule_flags & FD_PACK_SCHEDULE_TXN ) ) {
    3011       14850 :     status = fd_pack_schedule_impl( pack, pack->pending, cu_limit, txn_limit, byte_limit, alloc_limit, bank_tile,
    3012       14850 :         pack->pending_smallest, use_by_bank_txn, out+scheduled );
    3013             : 
    3014       14850 :     scheduled                   += status.txns_scheduled;
    3015       14850 :     pack->cumulative_block_cost += status.cus_scheduled;
    3016       14850 :     pack->data_bytes_consumed   += status.bytes_scheduled;
    3017       14850 :     pack->alloc_consumed        += status.alloc_scheduled;
    3018       14850 :   }
    3019             : 
    3020       14982 :   ulong nonempty = (ulong)(scheduled>0UL);
    3021       14982 :   pack->microblock_cnt              += nonempty;
    3022       14982 :   pack->outstanding_microblock_mask |= nonempty << bank_tile;
    3023       14982 :   pack->data_bytes_consumed         += nonempty * MICROBLOCK_DATA_OVERHEAD;
    3024             : 
    3025       14982 :   fd_histf_sample( pack->txn_per_microblock, scheduled );
    3026             : 
    3027       14982 :   pack_memcpy_fini();
    3028       14982 :   return scheduled;
    3029       15243 : }
    3030             : 
    3031      274398 : ulong fd_pack_bank_tile_cnt       ( fd_pack_t const * pack ) { return pack->bank_tile_cnt;         }
    3032           0 : ulong fd_pack_current_block_cost  ( fd_pack_t const * pack ) { return pack->cumulative_block_cost; }
    3033          15 : ulong fd_pack_next_auction_txn_cnt( fd_pack_t const * pack ) { return treap_ele_cnt( pack->next_auction ); }
    3034           0 : int   fd_pack_auction_running     ( fd_pack_t const * pack ) { return pack->auction_running;       }
    3035             : 
    3036             : /* fd_pack_auction_begin doesn't actually move any transactions
    3037             :    between treaps.  It just sets the auction_running flag, which means
    3038             :    that new transactions enter the next_auction treap instead of the
    3039             :    pending/penalty treaps.  These are not eligible for scheduling until
    3040             :    the auction ends, at which point the transactions in the
    3041             :    next_auction treap are moved into the pending/penalty treaps.
    3042             : 
    3043             :    Transactions already in the pending/penalty treaps, as well as all
    3044             :    new and already received bundles, are still elegible for scheduling
    3045             :    throughout the auction period. */
    3046             : void
    3047           6 : fd_pack_auction_begin( fd_pack_t * pack ) {
    3048           6 :   pack->auction_running = 1;
    3049           6 : }
    3050             : 
    3051             : /* fd_pack_auction_end ends an auction, if there was one running.  It
    3052             :    moves every transaction that was held in next_auction to the
    3053             :    pending/penalty treaps, making them eligible for scheduling. */
    3054             : void
    3055           6 : fd_pack_auction_end( fd_pack_t * pack ) {
    3056           6 :   pack->auction_running = 0;
    3057             : 
    3058             :   /* Flush the next_auction treap, as we now hold these transactions
    3059             :      in either the pending treap or the appropriate penalty treap.
    3060             :      Note that these won't be executed until the start of the next
    3061             :      auction. */
    3062           6 :   fd_pack_ord_txn_t * pool = pack->pool;
    3063           6 :   treap_rev_iter_t    next;
    3064           9 :   for( treap_rev_iter_t cur=treap_rev_iter_init( pack->next_auction, pool ); !treap_rev_iter_done( cur ); cur=next ) {
    3065           3 :     next = treap_rev_iter_next( cur, pool );
    3066           3 :     treap_idx_remove( pack->next_auction, treap_rev_iter_idx( cur ), pool );
    3067           3 :     insert_txn( pack, treap_rev_iter_ele( cur, pool ) );
    3068           3 :   }
    3069           6 : }
    3070             : 
    3071             : 
    3072             : void
    3073           0 : fd_pack_set_block_limits( fd_pack_t * pack, fd_pack_limits_t const * limits ) {
    3074           0 :   FD_TEST( limits->max_cost_per_block      >= FD_PACK_MAX_COST_PER_BLOCK_LOWER_BOUND      );
    3075           0 :   FD_TEST( limits->max_write_cost_per_acct >= FD_PACK_MAX_WRITE_COST_PER_ACCT_LOWER_BOUND );
    3076             : 
    3077           0 :   pack->lim->max_microblocks_per_block    = limits->max_microblocks_per_block;
    3078           0 :   pack->lim->max_data_bytes_per_block     = limits->max_data_bytes_per_block;
    3079           0 :   pack->lim->max_cost_per_block           = limits->max_cost_per_block;
    3080           0 :   pack->lim->max_write_cost_per_acct      = limits->max_write_cost_per_acct;
    3081           0 :   pack->lim->max_allocated_data_per_block = limits->max_allocated_data_per_block;
    3082           0 : }
    3083             : 
    3084             : void
    3085           0 : fd_pack_get_block_limits( fd_pack_t * pack, fd_pack_limits_usage_t * opt_limits_usage, fd_pack_limits_t * opt_limits ) {
    3086           0 :   if( FD_LIKELY( opt_limits_usage ) ) {
    3087           0 :     opt_limits_usage->block_cost          = pack->cumulative_block_cost;
    3088           0 :     opt_limits_usage->block_data_bytes    = pack->data_bytes_consumed;
    3089           0 :     opt_limits_usage->microblocks         = pack->microblock_cnt;
    3090           0 :     opt_limits_usage->alloc               = pack->alloc_consumed;
    3091           0 :   }
    3092           0 :   if( FD_LIKELY( opt_limits ) ) fd_memcpy( opt_limits, pack->lim, sizeof(fd_pack_limits_t) );
    3093           0 : }
    3094             : 
    3095             : void
    3096           0 : fd_pack_get_top_writers( fd_pack_t const * pack, fd_pack_addr_use_t top_writers[static FD_PACK_TOP_WRITERS_CNT] ) {
    3097           0 :   fd_memcpy( top_writers, pack->top_writers, sizeof(pack->top_writers) );
    3098           0 : }
    3099             : 
    3100             : void
    3101           0 : fd_pack_get_pending_smallest( fd_pack_t * pack, fd_pack_smallest_t * opt_pending_smallest ) {
    3102           0 :   if( FD_LIKELY( opt_pending_smallest ) ) fd_memcpy( opt_pending_smallest, pack->pending_smallest, sizeof(fd_pack_smallest_t) );
    3103           0 : }
    3104             : 
    3105             : void
    3106             : fd_pack_rebate_cus( fd_pack_t              * pack,
    3107           9 :                     fd_pack_rebate_t const * rebate ) {
    3108           9 :   if( FD_UNLIKELY( (rebate->ib_result!=0) & (pack->initializer_bundle_state==FD_PACK_IB_STATE_PENDING ) ) ) {
    3109           3 :     pack->initializer_bundle_state = fd_int_if( rebate->ib_result==1, FD_PACK_IB_STATE_READY, FD_PACK_IB_STATE_FAILED );
    3110           3 :   }
    3111             : 
    3112           9 :   pack->cumulative_block_cost  -= rebate->total_cost_rebate;
    3113           9 :   pack->data_bytes_consumed    -= rebate->data_bytes_rebate;
    3114           9 :   pack->alloc_consumed         -= rebate->alloc_rebate;
    3115           9 :   pack->cumulative_rebated_cus += rebate->total_cost_rebate;
    3116             :   /* For now, we want to ignore the microblock count rebate.  There are
    3117             :      3 places the microblock count is kept (here, in the pack tile, and
    3118             :      in the PoH tile), and they all need to count microblocks that end
    3119             :      up being empty in the same way.  It would be better from a
    3120             :      DoS-resistance perspective for them all not to count empty
    3121             :      microblocks towards the total, but there's a race condition:
    3122             :      suppose pack schedules a microblock containing one transaction that
    3123             :      doesn't land on chain, the slot ends, and then pack informs PoH of
    3124             :      the number of microblocks before the final rebate comes through.
    3125             :      This isn't unsolvable, but it's pretty gross, so it's probably
    3126             :      better to just not apply the rebate for now. */
    3127           9 :   (void)rebate->microblock_cnt_rebate;
    3128             : 
    3129           9 :   wcost_map_t * writer_costs = pack->writer_costs;
    3130          21 :   for( ulong i=0UL; i<rebate->writer_cnt; i++ ) {
    3131          12 :     fd_pack_wcost_ele_t * in_wcost_table = wcost_map_ele_query( writer_costs, &rebate->writer_rebates[i].key, NULL, pack->writers );
    3132          12 :     if( FD_UNLIKELY( !in_wcost_table ) ) FD_LOG_ERR(( "Rebate to unknown written account" ));
    3133          12 :     in_wcost_table->total_cost -= rebate->writer_rebates[i].rebate_cus;
    3134             :     /* If the rebate drops it to zero, return it to the pool */
    3135          12 :     if( FD_UNLIKELY( !in_wcost_table->total_cost ) ) {
    3136           3 :       wcost_map_ele_remove_fast( writer_costs,       in_wcost_table, pack->writers );
    3137           3 :       wcost_dlist_ele_remove   ( pack->written_list, in_wcost_table, pack->writers );
    3138           3 :       wcost_pool_ele_release   ( pack->writers,      in_wcost_table );
    3139           3 :     }
    3140          12 :   }
    3141           9 : }
    3142             : 
    3143             : 
    3144             : ulong
    3145             : fd_pack_expire_before( fd_pack_t * pack,
    3146          27 :                        ulong       expire_before ) {
    3147          27 :   expire_before = fd_ulong_max( expire_before, pack->expire_before );
    3148          27 :   ulong deleted_cnt = 0UL;
    3149          27 :   fd_pack_expq_t * prq = pack->expiration_q;
    3150         354 :   while( (expq_cnt( prq )>0UL) & (prq->expires_at<expire_before) ) {
    3151         327 :     fd_pack_ord_txn_t * expired = prq->txn;
    3152             : 
    3153             :     /* fd_pack_delete_transaction also removes it from the heap */
    3154             :     /* All the transactions in the same bundle have the same expiration
    3155             :        time, so this loop will end up deleting them all, even with
    3156             :        delete_full_bundle set to 0. */
    3157         327 :     ulong _delete_cnt = delete_transaction( pack, expired, 0, 1 );
    3158         327 :     deleted_cnt += _delete_cnt;
    3159         327 :     FD_TEST( _delete_cnt );
    3160         327 :   }
    3161             : 
    3162          27 :   pack->expire_before = expire_before;
    3163          27 :   return deleted_cnt;
    3164          27 : }
    3165             : 
    3166             : void
    3167          12 : fd_pack_end_block( fd_pack_t * pack ) {
    3168             :   /* rounded division */
    3169          12 :   ulong pct_cus_per_block = (pack->cumulative_block_cost*100UL + (pack->lim->max_cost_per_block>>1))/pack->lim->max_cost_per_block;
    3170          12 :   fd_histf_sample( pack->pct_cus_per_block,       pct_cus_per_block                                          );
    3171          12 :   fd_histf_sample( pack->net_cus_per_block,       pack->cumulative_block_cost                                );
    3172          12 :   fd_histf_sample( pack->rebated_cus_per_block,   pack->cumulative_rebated_cus                               );
    3173          12 :   fd_histf_sample( pack->scheduled_cus_per_block, pack->cumulative_rebated_cus + pack->cumulative_block_cost );
    3174             : 
    3175          12 :   pack->microblock_cnt              = 0UL;
    3176          12 :   pack->data_bytes_consumed         = 0UL;
    3177          12 :   pack->cumulative_block_cost       = 0UL;
    3178          12 :   pack->cumulative_rebated_cus      = 0UL;
    3179          12 :   pack->outstanding_microblock_mask = 0UL;
    3180          12 :   pack->alloc_consumed              = 0UL;
    3181             : 
    3182          12 :   pack->initializer_bundle_state = FD_PACK_IB_STATE_NOT_INITIALIZED;
    3183             : 
    3184          12 :   acct_uses_clear( pack->acct_in_use  );
    3185          12 :   memset( pack->top_writers, 0, sizeof(pack->top_writers) );
    3186             : 
    3187          12 :   fd_pack_addr_use_t * last_top_writer = pack->top_writers + FD_PACK_TOP_WRITERS_CNT-1UL;
    3188             : 
    3189        4836 :   while( !wcost_dlist_is_empty( pack->written_list, pack->writers ) ) {
    3190        4824 :     fd_pack_wcost_ele_t * writer = wcost_dlist_ele_pop_head( pack->written_list, pack->writers );
    3191        4824 :     if( FD_UNLIKELY( writer->total_cost>last_top_writer->total_cost ) ) {
    3192          66 :       last_top_writer->key        = writer->key;
    3193          66 :       last_top_writer->total_cost = writer->total_cost;
    3194          66 :       fd_pack_writer_cost_sort_insert( pack->top_writers, FD_PACK_TOP_WRITERS_CNT );
    3195          66 :     }
    3196             :     /* Clearing the cost field here is unnecessary (since it gets
    3197             :        cleared on insert), but makes debugging a bit easier. */
    3198        4824 :     writer->total_cost = 0UL;
    3199        4824 :     wcost_map_ele_remove_fast( pack->writer_costs, writer, pack->writers );
    3200        4824 :     wcost_pool_ele_release( pack->writers, writer );
    3201        4824 :   }
    3202             : 
    3203             :   /* compressed_slot_number is > FD_PACK_SKIP_CNT, which means +1 is the
    3204             :      max unless it overflows. */
    3205          12 :   pack->compressed_slot_number = fd_ushort_max( (ushort)(pack->compressed_slot_number+1), (ushort)(FD_PACK_SKIP_CNT+1) );
    3206             : 
    3207          12 :   FD_PACK_BITSET_CLEAR( pack->bitset_rw_in_use );
    3208          12 :   FD_PACK_BITSET_CLEAR( pack->bitset_w_in_use  );
    3209             : 
    3210          24 :   for( ulong i=0UL; i<pack->bank_tile_cnt; i++ ) pack->use_by_bank_cnt[i] = 0UL;
    3211             : 
    3212             :   /* If our stake is low and we don't become leader often, end_block
    3213             :      might get called on the order of O(1/hr), which feels too
    3214             :      infrequent to do anything related to metrics.  However, we only
    3215             :      update the histograms when we are leader, so this is actually a
    3216             :      good place to copy them. */
    3217          12 :   FD_MHIST_COPY( PACK, TXN_PER_MICROBLOCK, pack->txn_per_microblock );
    3218             : 
    3219          12 :   FD_MGAUGE_SET( PACK, BLOCK_COST,               0UL                           );
    3220          12 :   FD_MHIST_COPY( PACK, COST_SCHEDULED_PER_BLOCK, pack->scheduled_cus_per_block );
    3221          12 :   FD_MHIST_COPY( PACK, CU_REBATED_PER_BLOCK,     pack->rebated_cus_per_block   );
    3222          12 :   FD_MHIST_COPY( PACK, COST_NET_PER_BLOCK,       pack->net_cus_per_block       );
    3223          12 :   FD_MHIST_COPY( PACK, COST_PER_BLOCK_PCT,       pack->pct_cus_per_block       );
    3224          12 : }
    3225             : 
    3226             : static void
    3227             : release_tree( treap_t           * treap,
    3228             :               sig2txn_t         * signature_map,
    3229             :               noncemap_t        * noncemap,
    3230         114 :               fd_pack_ord_txn_t * pool ) {
    3231         114 :   treap_fwd_iter_t next;
    3232         126 :   for( treap_fwd_iter_t it=treap_fwd_iter_init( treap, pool ); !treap_fwd_iter_done( it ); it=next ) {
    3233          12 :     next = treap_fwd_iter_next( it, pool );
    3234          12 :     ulong idx = treap_fwd_iter_idx( it );
    3235          12 :     pool[ idx ].root = FD_ORD_TXN_ROOT_FREE;
    3236          12 :     treap_idx_remove       ( treap,         idx, pool );
    3237          12 :     sig2txn_idx_remove_fast( signature_map, idx, pool );
    3238          12 :     trp_pool_idx_release   ( pool,          idx       );
    3239          12 :     if( pool[ idx ].txn->flags & FD_TXN_P_FLAGS_DURABLE_NONCE ) {
    3240           9 :       noncemap_idx_remove_fast( noncemap, idx, pool );
    3241           9 :     }
    3242          12 :   }
    3243         114 : }
    3244             : 
    3245             : void
    3246           6 : fd_pack_clear_all( fd_pack_t * pack ) {
    3247           6 :   pack->pending_txn_cnt        = 0UL;
    3248           6 :   pack->microblock_cnt         = 0UL;
    3249           6 :   pack->cumulative_block_cost  = 0UL;
    3250           6 :   pack->cumulative_rebated_cus = 0UL;
    3251           6 :   pack->data_bytes_consumed    = 0UL;
    3252           6 :   pack->alloc_consumed         = 0UL;
    3253             : 
    3254           6 :   pack->pending_smallest->cus         = ULONG_MAX;
    3255           6 :   pack->pending_smallest->bytes       = ULONG_MAX;
    3256             : 
    3257           6 :   release_tree( pack->pending,         pack->signature_map, pack->noncemap, pack->pool );
    3258           6 :   release_tree( pack->pending_bundles, pack->signature_map, pack->noncemap, pack->pool );
    3259           6 :   release_tree( pack->next_auction,    pack->signature_map, pack->noncemap, pack->pool );
    3260         102 :   for( ulong i=0UL; i<FD_PACK_PRE_ROTATION_BUNDLE_CAPACITY; i++ ) {
    3261          96 :     release_tree( pack->pre_rotation_bundles[ i ].treap, pack->signature_map, pack->noncemap, pack->pool );
    3262          96 :   }
    3263           6 :   pack->pre_rotation_bundle_cnt = 0UL;
    3264             : 
    3265           6 :   ulong const pool_max = trp_pool_max( pack->pool );
    3266        3240 :   for( ulong i=0UL; i<pool_max; i++ ) {
    3267        3234 :     if( FD_UNLIKELY( pack->pool[ i ].root!=FD_ORD_TXN_ROOT_FREE ) ) {
    3268           0 :       fd_pack_ord_txn_t * const del = pack->pool + i;
    3269           0 :       fd_txn_t * txn = TXN( del->txn );
    3270           0 :       fd_acct_addr_t const * accts   = fd_txn_get_acct_addrs( txn, del->txn->payload );
    3271           0 :       fd_acct_addr_t const * alt     = del->txn_e->alt_accts;
    3272           0 :       fd_acct_addr_t penalty_acct = *ACCT_IDX_TO_PTR( FD_ORD_TXN_ROOT_PENALTY_ACCT_IDX( del->root ) );
    3273           0 :       fd_pack_penalty_treap_t * penalty_treap = penalty_map_query( pack->penalty_treaps, penalty_acct, NULL );
    3274           0 :       FD_TEST( penalty_treap );
    3275           0 :       release_tree( penalty_treap->penalty_treap, pack->signature_map, pack->noncemap, pack->pool );
    3276           0 :     }
    3277        3234 :   }
    3278             : 
    3279           6 :   pack->compressed_slot_number = (ushort)(FD_PACK_SKIP_CNT+1);
    3280             : 
    3281           6 :   expq_remove_all( pack->expiration_q );
    3282             : 
    3283           6 :   acct_uses_clear( pack->acct_in_use  );
    3284             : 
    3285          21 :   while( !wcost_dlist_is_empty( pack->written_list, pack->writers ) ) {
    3286          15 :     fd_pack_wcost_ele_t * writer = wcost_dlist_ele_pop_head( pack->written_list, pack->writers );
    3287          15 :     writer->total_cost = 0UL;
    3288          15 :     wcost_map_ele_remove_fast( pack->writer_costs, writer, pack->writers );
    3289          15 :     wcost_pool_ele_release( pack->writers, writer );
    3290          15 :   }
    3291             : 
    3292           6 :   penalty_map_clear( pack->penalty_treaps );
    3293             : 
    3294           6 :   FD_PACK_BITSET_CLEAR( pack->bitset_rw_in_use );
    3295           6 :   FD_PACK_BITSET_CLEAR( pack->bitset_w_in_use  );
    3296           6 :   bitset_map_clear( pack->acct_to_bitset );
    3297           6 :   pack->bitset_avail[ 0 ] = FD_PACK_BITSET_SLOWPATH;
    3298        2054 :   for( ulong i=0UL; i<FD_PACK_BITSET_MAX; i++ ) pack->bitset_avail[ i+1UL ] = (ushort)i;
    3299           6 :   pack->bitset_avail_cnt = FD_PACK_BITSET_MAX;
    3300             : 
    3301          12 :   for( ulong i=0UL; i<pack->bank_tile_cnt; i++ ) pack->use_by_bank_cnt[i] = 0UL;
    3302           6 : }
    3303             : 
    3304             : 
    3305             : /* If delete_full_bundle is non-zero and the transaction to delete is
    3306             :    part of a bundle, the rest of the bundle it is part of will be
    3307             :    deleted as well.
    3308             :    If move_from_penalty_treap is non-zero and the transaction to delete
    3309             :    is in the pending treap, move the best transaction in any of the
    3310             :    conflicting penalty treaps to the pending treap (if there is one). */
    3311             : static ulong
    3312             : delete_transaction( fd_pack_t         * pack,
    3313             :                     fd_pack_ord_txn_t * containing,
    3314             :                     int                 delete_full_bundle,
    3315     1886379 :                     int                 move_from_penalty_treap ) {
    3316             : 
    3317     1886379 :   fd_txn_t * txn = TXN( containing->txn );
    3318     1886379 :   fd_acct_addr_t const * accts   = fd_txn_get_acct_addrs( txn, containing->txn->payload );
    3319     1886379 :   fd_acct_addr_t const * alt     = containing->txn_e->alt_accts;
    3320             : 
    3321     1886379 :   treap_t * root = NULL;
    3322     1886379 :   int root_idx = containing->root;
    3323     1886379 :   fd_pack_penalty_treap_t       * penalty_treap       = NULL;
    3324     1886379 :   fd_pack_pre_rotation_bundle_t * pre_rotation_bundle = NULL;
    3325     1886379 :   switch( root_idx & FD_ORD_TXN_ROOT_TAG_MASK ) {
    3326           0 :     case FD_ORD_TXN_ROOT_FREE:                FD_LOG_CRIT(( "Double free detected" ));
    3327         921 :     case FD_ORD_TXN_ROOT_PENDING:             root = pack->pending;              break;
    3328     1882773 :     case FD_ORD_TXN_ROOT_PENDING_BUNDLE:      root = pack->pending_bundles;      break;
    3329          24 :     case FD_ORD_TXN_ROOT_PRE_ROTATION_BUNDLE( 0 ): {
    3330          24 :       pre_rotation_bundle = pack->pre_rotation_bundles + FD_ORD_TXN_ROOT_PRE_ROTATION_BUNDLE_IDX( root_idx );
    3331          24 :       root                = pre_rotation_bundle->treap;
    3332          24 :       break;
    3333           0 :     }
    3334           9 :     case FD_ORD_TXN_ROOT_NEXT_AUCTION:        root = pack->next_auction;         break;
    3335        2652 :     case FD_ORD_TXN_ROOT_PENALTY( 0 ): {
    3336        2652 :       fd_acct_addr_t penalty_acct = *ACCT_IDX_TO_PTR( FD_ORD_TXN_ROOT_PENALTY_ACCT_IDX( root_idx ) );
    3337        2652 :       penalty_treap = penalty_map_query( pack->penalty_treaps, penalty_acct, NULL );
    3338        2652 :       FD_TEST( penalty_treap );
    3339        2652 :       root = penalty_treap->penalty_treap;
    3340        2652 :       break;
    3341        2652 :     }
    3342     1886379 :   }
    3343             : 
    3344     1886379 :   ulong delete_cnt = 0UL;
    3345     1886379 :   if( FD_UNLIKELY( delete_full_bundle & ((root==pack->pending_bundles) | (!!pre_rotation_bundle)) ) ) {
    3346             :     /* When we delete, the structure of the treap may move around, but
    3347             :        pointers to inside the pool will remain valid */
    3348     1882362 :     fd_pack_ord_txn_t * bundle_ptrs[ FD_PACK_MAX_TXN_PER_BUNDLE-1UL ];
    3349     1882362 :     fd_pack_ord_txn_t * pool       = pack->pool;
    3350     1882362 :     ulong               cnt        = 0UL;
    3351     1882362 :     ulong               bundle_idx = RC_TO_REL_BUNDLE_IDX( containing->rewards, containing->compute_est );
    3352             : 
    3353             :     /* Iterate in both directions from the current transaction */
    3354     1882362 :     for( treap_fwd_iter_t _cur=treap_fwd_iter_next( (treap_fwd_iter_t)treap_idx_fast( containing, pool ), pool );
    3355     1882674 :         !treap_fwd_iter_done( _cur ); _cur=treap_fwd_iter_next( _cur, pool ) ) {
    3356     1882536 :       fd_pack_ord_txn_t * cur = treap_fwd_iter_ele( _cur, pool );
    3357     1882536 :       if( FD_LIKELY( bundle_idx==RC_TO_REL_BUNDLE_IDX( cur->rewards, cur->compute_est ) ) ) {
    3358         312 :         bundle_ptrs[ cnt++ ] = cur;
    3359     1882224 :       } else {
    3360     1882224 :         break;
    3361     1882224 :       }
    3362         312 :       FD_TEST( cnt<FD_PACK_MAX_TXN_PER_BUNDLE );
    3363         312 :     }
    3364             : 
    3365     1882362 :     for( treap_rev_iter_t _cur=treap_rev_iter_next( (treap_rev_iter_t)treap_idx_fast( containing, pool ), pool );
    3366     1882476 :         !treap_rev_iter_done( _cur ); _cur=treap_rev_iter_next( _cur, pool ) ) {
    3367         123 :       fd_pack_ord_txn_t * cur = treap_rev_iter_ele( _cur, pool );
    3368         123 :       if( FD_LIKELY( bundle_idx==RC_TO_REL_BUNDLE_IDX( cur->rewards, cur->compute_est ) ) ) {
    3369         114 :         bundle_ptrs[ cnt++ ] = cur;
    3370         114 :       } else {
    3371           9 :         break;
    3372           9 :       }
    3373         114 :       FD_TEST( cnt<FD_PACK_MAX_TXN_PER_BUNDLE );
    3374         114 :     }
    3375             : 
    3376             :     /* Delete them each, setting delete_full_bundle to 0 to avoid
    3377             :        infinite recursion. */
    3378     1882788 :     for( ulong k=0UL; k<cnt; k++ ) delete_cnt += delete_transaction( pack, bundle_ptrs[ k ], 0, 0 );
    3379     1882362 :   }
    3380             : 
    3381             : 
    3382     1886379 :   if( FD_UNLIKELY( move_from_penalty_treap & (root==pack->pending) ) ) {
    3383             : 
    3384         816 :     fd_pack_ord_txn_t       * best         = NULL;
    3385         816 :     fd_pack_penalty_treap_t * best_penalty = NULL;
    3386             : 
    3387         816 :     for( fd_txn_acct_iter_t iter=fd_txn_acct_iter_init( txn, FD_TXN_ACCT_CAT_WRITABLE );
    3388        3498 :         iter!=fd_txn_acct_iter_end(); iter=fd_txn_acct_iter_next( iter ) ) {
    3389        2682 :       fd_pack_penalty_treap_t * p_trp = penalty_map_query( pack->penalty_treaps, *ACCT_ITER_TO_PTR( iter ), NULL );
    3390        2682 :       if( FD_UNLIKELY( p_trp ) ) {
    3391        1340 :         fd_pack_ord_txn_t * best_in_trp = treap_rev_iter_ele( treap_rev_iter_init( p_trp->penalty_treap, pack->pool ), pack->pool );
    3392        1340 :         if( FD_UNLIKELY( !best || COMPARE_WORSE( best, best_in_trp ) ) ) {
    3393         701 :           best         = best_in_trp;
    3394         701 :           best_penalty = p_trp;
    3395         701 :         }
    3396        1340 :       }
    3397        2682 :     }
    3398             : 
    3399         816 :     if( FD_LIKELY( best ) ) {
    3400             :       /* move best to the main treap */
    3401         701 :       treap_ele_remove( best_penalty->penalty_treap, best, pack->pool );
    3402         701 :       best->root = FD_ORD_TXN_ROOT_PENDING;
    3403         701 :       treap_ele_insert( pack->pending,               best, pack->pool );
    3404             : 
    3405         701 :       pack->pending_smallest->cus   = fd_ulong_min( pack->pending_smallest->cus,   best->compute_est             );
    3406         701 :       pack->pending_smallest->bytes = fd_ulong_min( pack->pending_smallest->bytes, best->txn_e->txnp->payload_sz );
    3407             : 
    3408         701 :       if( FD_UNLIKELY( !treap_ele_cnt( best_penalty->penalty_treap ) ) ) {
    3409           9 :         treap_delete( treap_leave( best_penalty->penalty_treap ) );
    3410           9 :         penalty_map_remove( pack->penalty_treaps, best_penalty );
    3411           9 :       }
    3412         701 :     }
    3413         816 :   }
    3414             : 
    3415             :   /* Transactions which are being held in the next_auction treap never
    3416             :      acquired their bitset reference, so there is nothing to release
    3417             :      here. */
    3418     1886379 :   if( FD_LIKELY( root!=pack->next_auction ) ) {
    3419     1886370 :     for( fd_txn_acct_iter_t iter=fd_txn_acct_iter_init( txn, FD_TXN_ACCT_CAT_ALL );
    3420     7568601 :         iter!=fd_txn_acct_iter_end(); iter=fd_txn_acct_iter_next( iter ) ) {
    3421     5682231 :       if( FD_UNLIKELY( fd_pack_unwritable_contains( ACCT_ITER_TO_PTR( iter ) ) ) ) continue;
    3422             : 
    3423     3795132 :       release_result_t ret = release_bit_reference( pack, ACCT_ITER_TO_PTR( iter ) );
    3424     3795132 :       FD_PACK_BITSET_CLEARN( pack->bitset_rw_in_use, ret.clear_rw_bit );
    3425     3795132 :       FD_PACK_BITSET_CLEARN( pack->bitset_w_in_use,  ret.clear_w_bit  );
    3426     3795132 :     }
    3427     1886370 :   }
    3428             : 
    3429     1886379 :   if( FD_UNLIKELY( containing->txn->flags & FD_TXN_P_FLAGS_DURABLE_NONCE ) ) {
    3430         354 :     noncemap_ele_remove_fast( pack->noncemap, containing, pack->pool );
    3431         354 :   }
    3432     1886379 :   expq_remove( pack->expiration_q, containing->expq_idx );
    3433     1886379 :   if( FD_UNLIKELY( pre_rotation_bundle ) ) pre_rotation_bundle_remove( pack, pre_rotation_bundle, (ulong)(containing-pack->pool) );
    3434     1886355 :   else                                     treap_ele_remove( root, containing, pack->pool );
    3435     1886379 :   containing->root = FD_ORD_TXN_ROOT_FREE;
    3436     1886379 :   sig2txn_ele_remove_fast( pack->signature_map, containing, pack->pool );
    3437     1886379 :   trp_pool_ele_release( pack->pool, containing );
    3438             : 
    3439     1886379 :   delete_cnt += 1UL;
    3440     1886379 :   pack->pending_txn_cnt--;
    3441             : 
    3442     1886379 :   if( FD_UNLIKELY( penalty_treap && treap_ele_cnt( root )==0UL ) ) {
    3443           0 :     penalty_map_remove( pack->penalty_treaps, penalty_treap );
    3444           0 :   }
    3445             : 
    3446     1886379 :   return delete_cnt;
    3447     1886379 : }
    3448             : 
    3449             : ulong
    3450             : fd_pack_delete_transaction( fd_pack_t              * pack,
    3451     1882410 :                             fd_ed25519_sig_t const * sig0 ) {
    3452     1882410 :   ulong cnt = 0;
    3453     1882410 :   ulong next = ULONG_MAX;
    3454             : 
    3455             :   /* sig2txn reads only the signature offset and signature bytes. */
    3456     1882410 :   fd_txn_e_t query_e;
    3457     1882410 :   TXN(query_e.txnp)->signature_off = 0U;
    3458     1882410 :   fd_memcpy( query_e.txnp[0].payload, sig0, FD_TXN_SIGNATURE_SZ );
    3459     1882410 :   for( ulong idx = sig2txn_idx_query_const( pack->signature_map, &query_e, ULONG_MAX, pack->pool );
    3460     3764796 :       idx!=ULONG_MAX; idx=next ) {
    3461             :     /* Iterating while deleting, not just this element, but perhaps the
    3462             :        whole bundle, feels a bit dangerous, but is actually fine because
    3463             :        a bundle can't contain two transactions with the same signature.
    3464             :        That means we know next is not part of the same bundle as idx,
    3465             :        which means that deleting idx will not delete next. */
    3466     1882386 :     next = sig2txn_idx_next_const( idx, ULONG_MAX, pack->pool );
    3467     1882386 :     cnt += delete_transaction( pack, pack->pool+idx, 1, 1 );
    3468     1882386 :   }
    3469             : 
    3470     1882410 :   return cnt;
    3471     1882410 : }
    3472             : 
    3473             : 
    3474             : int
    3475             : fd_pack_verify( fd_pack_t * pack,
    3476         651 :                 void      * scratch ) {
    3477             :   /* Invariants:
    3478             :      sig2txn_query has exact same contents as all treaps combined
    3479             :      root matches treap
    3480             :      Keys of acct_to_bitset is exactly union of all accounts in all
    3481             :             transactions in treaps, with ref counted appropriately
    3482             :      bits in bitset_avail is complement of bits allocated in
    3483             :             acct_to_bitset
    3484             :      expires_at consistent between treap, prq
    3485             :      use_by_bank does not contain duplicates
    3486             :      use_by_bank consistent with acct_in_use
    3487             :      elements in pool but not in a treap have root set to free
    3488             :      all penalty treaps have at least one transaction
    3489             :      all elements in penalty treaps are in the one that the root indicates
    3490             :      */
    3491             : 
    3492             :   /* TODO:
    3493             :      bitset_{r}w_in_use = bitset_map_query( everything in acct_in_use that doesn't have FD_PACK_IN_USE_BIT_CLEARED )
    3494             :      bitset_w_in_use & bitset_rw_in_use == bitset_w_in_use
    3495             :      */
    3496      515033 : #define VERIFY_TEST( cond, ... ) do {   \
    3497      515033 :     if( FD_UNLIKELY( !(cond) ) ) {      \
    3498           0 :       FD_LOG_WARNING(( __VA_ARGS__ ));  \
    3499           0 :       return -(__LINE__);               \
    3500           0 :     }                                   \
    3501      515033 :   } while( 0 )
    3502             : 
    3503         651 :   ulong max_acct_in_treap  = pack->pack_depth * FD_TXN_ACCT_ADDR_MAX;
    3504         651 :   int lg_acct_in_trp = fd_ulong_find_msb( fd_ulong_pow2_up( 2UL*max_acct_in_treap  ) );
    3505         651 :   void * _bitset_map_copy = scratch;
    3506         651 :   void * _bitset_map_orig = bitset_map_leave( pack->acct_to_bitset );
    3507         651 :   fd_memcpy( _bitset_map_copy, _bitset_map_orig, bitset_map_footprint( lg_acct_in_trp ) );
    3508             : 
    3509         651 :   fd_pack_bitset_acct_mapping_t * bitset_copy = bitset_map_join( _bitset_map_copy );
    3510             : 
    3511             :   /* Check that each bit is in exactly one place */
    3512         651 :   FD_PACK_BITSET_DECLARE( processed ); FD_PACK_BITSET_CLEAR( processed );
    3513         651 :   FD_PACK_BITSET_DECLARE( bit       ); FD_PACK_BITSET_CLEAR( bit       );
    3514         651 :   FD_PACK_BITSET_DECLARE( full      ); FD_PACK_BITSET_CLEAR( full      );
    3515             : 
    3516         651 :   if( FD_UNLIKELY( pack->bitset_avail[0]!=FD_PACK_BITSET_SLOWPATH ) ) return -1;
    3517      221893 :   for( ulong i=1UL; i<=pack->bitset_avail_cnt; i++ ) {
    3518      221242 :     FD_PACK_BITSET_CLEAR( bit );
    3519      221242 :     FD_PACK_BITSET_SETN( bit, pack->bitset_avail[ i ] );
    3520      221242 :     VERIFY_TEST( FD_PACK_BITSET_INTERSECT4_EMPTY( bit, bit, processed, processed ),
    3521      221242 :         "bit %hu in avail set twice", pack->bitset_avail[ i ] );
    3522      221242 :     FD_PACK_BITSET_OR( processed, bit );
    3523      221242 :   }
    3524             : 
    3525         651 :   ulong total_references = 0UL;
    3526    71334027 :   for( ulong i=0UL; i<bitset_map_slot_cnt( bitset_copy ); i++ ) {
    3527    71333376 :     if( !bitset_map_key_inval( bitset_copy[ i ].key ) ) {
    3528        4692 :       VERIFY_TEST( bitset_copy[ i ].ref_cnt>0UL, "account address in table with 0 ref count" );
    3529             : 
    3530        4692 :       total_references += bitset_copy[ i ].ref_cnt;
    3531             : 
    3532        4692 :       FD_PACK_BITSET_CLEAR( bit );
    3533        4692 :       FD_PACK_BITSET_SETN( bit, bitset_copy[ i ].bit );
    3534        4692 :       VERIFY_TEST( FD_PACK_BITSET_INTERSECT4_EMPTY( bit, bit, processed, processed ), "bit %hu used twice", bitset_copy[ i ].bit );
    3535        4692 :       FD_PACK_BITSET_OR( processed, bit );
    3536        4692 :     }
    3537    71333376 :   }
    3538      222859 :   for( ulong i=0UL; i<FD_PACK_BITSET_MAX; i++ ) {
    3539      222208 :     FD_PACK_BITSET_CLEAR( bit );
    3540      222208 :     FD_PACK_BITSET_SETN( bit, i );
    3541      222208 :     VERIFY_TEST( !FD_PACK_BITSET_INTERSECT4_EMPTY( bit, bit, processed, processed ), "bit %lu missing", i );
    3542      222208 :     FD_PACK_BITSET_SETN( full, i );
    3543      222208 :   }
    3544             : 
    3545             : 
    3546         651 :   fd_pack_ord_txn_t  * pool = pack->pool;
    3547         651 :   treap_t * treaps   [ 3 ] = { pack->pending, pack->pending_bundles, pack->next_auction };
    3548         651 :   int       root_tags[ 3 ] = { FD_ORD_TXN_ROOT_PENDING, FD_ORD_TXN_ROOT_PENDING_BUNDLE, FD_ORD_TXN_ROOT_NEXT_AUCTION };
    3549         651 :   ulong txn_cnt = 0UL;
    3550             : 
    3551         651 :   ulong const pre_rotation_bundle_max = FD_PACK_PRE_ROTATION_BUNDLE_CAPACITY;
    3552         651 :   ulong pre_rotation_bundle_cnt = 0UL;
    3553       11067 :   for( ulong i=0UL; i<pre_rotation_bundle_max; i++ ) {
    3554       10416 :     ulong cnt = treap_ele_cnt( pack->pre_rotation_bundles[ i ].treap );
    3555       10416 :     pre_rotation_bundle_cnt += (ulong)(cnt>0UL);
    3556       10416 :     VERIFY_TEST( cnt<=FD_PACK_MAX_TXN_PER_BUNDLE, "pre-rotation bundle %lu holds %lu transactions", i, cnt );
    3557       10416 :   }
    3558         651 :   VERIFY_TEST( pre_rotation_bundle_cnt==pack->pre_rotation_bundle_cnt, "pre_rotation_bundle_cnt %lu, found %lu bundles", pack->pre_rotation_bundle_cnt, pre_rotation_bundle_cnt );
    3559             : 
    3560         651 :   VERIFY_TEST( pack->auction_running || !treap_ele_cnt( pack->next_auction ), "next_auction not empty outside an auction" );
    3561             : 
    3562     1127604 :   for( ulong k=0UL; k<3UL+pre_rotation_bundle_max+penalty_map_slot_cnt( pack->penalty_treaps ); k++ ) {
    3563     1126953 :     treap_t * treap = NULL;
    3564             : 
    3565     1126953 :     if( k<3UL ) treap = treaps[ k ];
    3566     1125000 :     else if( k<3UL+pre_rotation_bundle_max ) {
    3567       10416 :       treap = pack->pre_rotation_bundles[ k-3UL ].treap;
    3568       10416 :       if( !treap_ele_cnt( treap ) ) continue;
    3569       10416 :     }
    3570     1114584 :     else if( FD_LIKELY( penalty_map_key_inval( pack->penalty_treaps[ k-3UL-pre_rotation_bundle_max ].key ) ) ) continue;
    3571           0 :     else {
    3572           0 :       treap = pack->penalty_treaps[ k-3UL-pre_rotation_bundle_max ].penalty_treap;
    3573           0 :       VERIFY_TEST( treap_ele_cnt( treap )>0UL, "empty penalty treap in map" );
    3574           0 :     }
    3575             : 
    3576        5127 :     for( treap_rev_iter_t _cur=treap_rev_iter_init( treap, pool ); !treap_rev_iter_done( _cur );
    3577        2610 :         _cur=treap_rev_iter_next( _cur, pool ) ) {
    3578        2517 :       txn_cnt++;
    3579        2517 :       fd_pack_ord_txn_t const * cur = treap_rev_iter_ele_const( _cur, pool );
    3580        2517 :       fd_txn_t const * txn = TXN(cur->txn);
    3581        2517 :       fd_acct_addr_t const * accts   = fd_txn_get_acct_addrs( txn, cur->txn->payload );
    3582        2517 :       fd_acct_addr_t const * alt     = cur->txn_e->alt_accts;
    3583             : 
    3584        2517 :       fd_pack_ord_txn_t const * in_tbl = sig2txn_ele_query_const( pack->signature_map, &cur->_txn_e, NULL, pool );
    3585        2517 :       VERIFY_TEST( in_tbl, "signature missing from sig2txn" );
    3586             : 
    3587        2517 :       ulong expected_root = (k<3UL) ? (ulong)root_tags[ k ] : ((k<3UL+pre_rotation_bundle_max) ? (ulong)FD_ORD_TXN_ROOT_PRE_ROTATION_BUNDLE( 0 ) : (ulong)FD_ORD_TXN_ROOT_PENALTY( 0 ));
    3588        2517 :       VERIFY_TEST( (ulong)(cur->root & FD_ORD_TXN_ROOT_TAG_MASK)==expected_root, "treap element had bad root" );
    3589        2517 :       if( FD_UNLIKELY( (cur->root & FD_ORD_TXN_ROOT_TAG_MASK)==FD_ORD_TXN_ROOT_PRE_ROTATION_BUNDLE( 0 ) ) ) {
    3590         672 :         VERIFY_TEST( (ulong)FD_ORD_TXN_ROOT_PRE_ROTATION_BUNDLE_IDX( cur->root )==k-3UL, "transaction in wrong pre-rotation bundle" );
    3591         672 :       }
    3592        2517 :       if( FD_LIKELY( (cur->root & FD_ORD_TXN_ROOT_TAG_MASK)==FD_ORD_TXN_ROOT_PENALTY(0) ) ) {
    3593           0 :         fd_acct_addr_t const * penalty_acct = ACCT_IDX_TO_PTR( FD_ORD_TXN_ROOT_PENALTY_ACCT_IDX( cur->root ) );
    3594           0 :         VERIFY_TEST( !memcmp( penalty_acct, pack->penalty_treaps[ k-3UL-pre_rotation_bundle_max ].key.b, 32UL ), "transaction in wrong penalty treap" );
    3595           0 :       }
    3596        2517 :       VERIFY_TEST( cur->expires_at>=pack->expire_before, "treap element expired" );
    3597             : 
    3598        2517 :       fd_pack_expq_t const * eq = pack->expiration_q + cur->expq_idx;
    3599        2517 :       VERIFY_TEST( eq->txn==cur, "expq inconsistent" );
    3600        2517 :       VERIFY_TEST( eq->expires_at==cur->expires_at, "expq expires_at inconsistent" );
    3601             : 
    3602        2517 :       if( FD_UNLIKELY( (cur->root & FD_ORD_TXN_ROOT_TAG_MASK)==FD_ORD_TXN_ROOT_NEXT_AUCTION ) ) continue;
    3603             : 
    3604        2508 :       FD_PACK_BITSET_DECLARE( complement );
    3605        2508 :       FD_PACK_BITSET_COPY( complement, full );
    3606        2508 :       for( fd_txn_acct_iter_t iter=fd_txn_acct_iter_init( txn, FD_TXN_ACCT_CAT_WRITABLE );
    3607        8250 :           iter!=fd_txn_acct_iter_end(); iter=fd_txn_acct_iter_next( iter ) ) {
    3608        5742 :         fd_acct_addr_t acct = *ACCT_ITER_TO_PTR( iter );
    3609             : 
    3610        5742 :         fd_pack_bitset_acct_mapping_t * q = bitset_map_query( bitset_copy, acct, NULL );
    3611        5742 :         VERIFY_TEST( q, "account in transaction missing from bitset mapping" );
    3612        5742 :         VERIFY_TEST( q->ref_cnt>0UL, "account in transaction ref_cnt already 0" );
    3613        5742 :         q->ref_cnt--;
    3614        5742 :         total_references--;
    3615             : 
    3616        5742 :         FD_PACK_BITSET_CLEAR( bit );
    3617        5742 :         FD_PACK_BITSET_SETN( bit, q->bit );
    3618        5742 :         if( q->bit<FD_PACK_BITSET_MAX ) {
    3619        2073 :           VERIFY_TEST( !FD_PACK_BITSET_INTERSECT4_EMPTY( bit, bit, cur->rw_bitset, cur->rw_bitset ), "missing from rw bitset" );
    3620        2073 :           VERIFY_TEST( !FD_PACK_BITSET_INTERSECT4_EMPTY( bit, bit, cur->w_bitset,  cur->w_bitset  ), "missing from w bitset" );
    3621        2073 :         }
    3622        5742 :         FD_PACK_BITSET_CLEARN( complement, q->bit );
    3623        5742 :       }
    3624        2508 :       VERIFY_TEST( FD_PACK_BITSET_INTERSECT4_EMPTY( complement, complement, cur->w_bitset,  cur->w_bitset ), "extra in w bitset" );
    3625             : 
    3626        2508 :       for( fd_txn_acct_iter_t iter=fd_txn_acct_iter_init( txn, FD_TXN_ACCT_CAT_READONLY );
    3627        8145 :           iter!=fd_txn_acct_iter_end(); iter=fd_txn_acct_iter_next( iter ) ) {
    3628             : 
    3629        5637 :         fd_acct_addr_t acct = *ACCT_ITER_TO_PTR( iter );
    3630        5637 :         if( FD_UNLIKELY( fd_pack_unwritable_contains( &acct ) ) ) continue;
    3631        2325 :         fd_pack_bitset_acct_mapping_t * q = bitset_map_query( bitset_copy, acct, NULL );
    3632        2325 :         VERIFY_TEST( q, "account in transaction missing from bitset mapping" );
    3633        2325 :         VERIFY_TEST( q->ref_cnt>0UL, "account in transaction ref_cnt already 0" );
    3634        2325 :         q->ref_cnt--;
    3635        2325 :         total_references--;
    3636             : 
    3637        2325 :         FD_PACK_BITSET_CLEAR( bit );
    3638        2325 :         FD_PACK_BITSET_SETN( bit, q->bit );
    3639        2325 :         if( q->bit<FD_PACK_BITSET_MAX ) {
    3640        2268 :           VERIFY_TEST( !FD_PACK_BITSET_INTERSECT4_EMPTY( bit, bit, cur->rw_bitset, cur->rw_bitset ), "missing from rw bitset" );
    3641        2268 :         }
    3642        2325 :         FD_PACK_BITSET_CLEARN( complement, q->bit );
    3643        2325 :       }
    3644        2508 :       VERIFY_TEST( FD_PACK_BITSET_INTERSECT4_EMPTY( complement, complement, cur->rw_bitset,  cur->rw_bitset ), "extra in rw bitset" );
    3645        2508 :     }
    3646        2610 :   }
    3647             : 
    3648         651 :   bitset_map_leave( bitset_copy );
    3649         651 :   VERIFY_TEST( txn_cnt==pack->pending_txn_cnt, "txn_cnt" );
    3650             : 
    3651         651 :   VERIFY_TEST( total_references==0UL, "extra references in bitset mapping" );
    3652         651 :   ulong sig2txn_key_cnt = 0UL;
    3653         651 :   for( sig2txn_iter_t iter = sig2txn_iter_init( pack->signature_map, pool );
    3654        3168 :       !sig2txn_iter_done( iter, pack->signature_map, pool );
    3655        2517 :       iter = sig2txn_iter_next( iter, pack->signature_map, pool ) ) {
    3656        2517 :     sig2txn_key_cnt++;
    3657        2517 :   }
    3658         651 :   VERIFY_TEST( txn_cnt==sig2txn_key_cnt, "extra signatures in sig2txn" );
    3659         651 :   VERIFY_TEST( !sig2txn_verify( pack->signature_map, trp_pool_max( pool ), pool ), "sig2txn corrupt" );
    3660             : 
    3661             :   /* Count noncemap keys */
    3662         651 :   ulong noncemap_key_cnt = 0UL;
    3663         651 :   for( noncemap_iter_t iter = noncemap_iter_init( pack->noncemap, pool );
    3664         711 :       !noncemap_iter_done( iter, pack->noncemap, pool );
    3665         651 :       iter = noncemap_iter_next( iter, pack->noncemap, pool ) ) {
    3666          60 :     noncemap_key_cnt++;
    3667             :     /* Ensure element is in pool */
    3668          60 :     fd_pack_ord_txn_t const * ord = noncemap_iter_ele_const( iter, pack->noncemap, pool );
    3669          60 :     VERIFY_TEST( ord->txn->flags & FD_TXN_P_FLAGS_DURABLE_NONCE, "invalid entry in noncemap" );
    3670             : 
    3671             :     /* Although pack allows multiple transactions with the same
    3672             :        signature in sig2txn (MAP_MULTI==1), the noncemap checks prevent
    3673             :        multiple nonce transactions with the same signature. */
    3674          60 :     VERIFY_TEST( ord==sig2txn_ele_query_const( pack->signature_map, &ord->_txn_e, NULL, pool ), "noncemap and sig2txn desynced" );
    3675          60 :   }
    3676         651 :   VERIFY_TEST( txn_cnt>=noncemap_key_cnt, "phantom txns in noncemap" );
    3677         651 :   VERIFY_TEST( !noncemap_verify( pack->noncemap, trp_pool_max( pool ), pool ), "noncemap corrupt" );
    3678             : 
    3679         651 :   ulong slots_found = 0UL;
    3680         651 :   ulong const pool_max = trp_pool_max( pool );
    3681      528240 :   for( ulong i=0UL; i<pool_max; i++ ) {
    3682      527589 :     fd_pack_ord_txn_t * ord = pack->pool + i;
    3683      527589 :     if( ord->root!=FD_ORD_TXN_ROOT_FREE ) slots_found++;
    3684      527589 :   }
    3685         651 :   VERIFY_TEST( slots_found==txn_cnt, "phantom slots in pool" );
    3686             : 
    3687         651 :   bitset_map_join( _bitset_map_orig );
    3688             : 
    3689         651 :   int lg_uses_tbl_sz = acct_uses_lg_slot_cnt( pack->acct_in_use );
    3690             : 
    3691         651 :   void * _acct_in_use_copy = scratch;
    3692         651 :   void * _acct_in_use_orig = acct_uses_leave( pack->acct_in_use );
    3693         651 :   fd_memcpy( _acct_in_use_copy, _acct_in_use_orig, acct_uses_footprint( lg_uses_tbl_sz ) );
    3694             : 
    3695         651 :   fd_pack_addr_use_t * acct_in_use_copy = acct_uses_join( _acct_in_use_copy );
    3696             : 
    3697         651 :   FD_PACK_BITSET_DECLARE(  w_complement );
    3698         651 :   FD_PACK_BITSET_DECLARE( rw_complement );
    3699         651 :   FD_PACK_BITSET_COPY(  w_complement, full );
    3700         651 :   FD_PACK_BITSET_COPY( rw_complement, full );
    3701             : 
    3702         651 :   FD_PACK_BITSET_DECLARE( rw_bitset );  FD_PACK_BITSET_COPY( rw_bitset, pack->bitset_rw_in_use );
    3703         651 :   FD_PACK_BITSET_DECLARE(  w_bitset );  FD_PACK_BITSET_COPY(  w_bitset, pack->bitset_w_in_use  );
    3704             : 
    3705             : 
    3706         651 :   ulong const EMPTY_MASK = ~(FD_PACK_IN_USE_WRITABLE | FD_PACK_IN_USE_BIT_CLEARED);
    3707             : 
    3708       12675 :   for( ulong bank=0UL; bank<pack->bank_tile_cnt; bank++ ) {
    3709             : 
    3710       12024 :     fd_pack_addr_use_t const * base = pack->use_by_bank[ bank ];
    3711       12024 :     ulong bank_mask = 1UL << bank;
    3712             : 
    3713       12885 :     for( ulong i=0UL; i<pack->use_by_bank_cnt[ bank ]; i++ ) {
    3714         861 :       fd_pack_addr_use_t * use = acct_uses_query( acct_in_use_copy, base[i].key, NULL );
    3715         861 :       VERIFY_TEST( use, "acct in use by bank not in acct_in_use, or in uses_by_bank twice" );
    3716             : 
    3717         861 :       VERIFY_TEST( use->in_use_by & bank_mask, "acct in uses_by_bank doesn't have corresponding bit set in acct_in_use, or it was in the list twice" );
    3718             : 
    3719         861 :       fd_pack_bitset_acct_mapping_t * q = bitset_map_query( pack->acct_to_bitset, base[i].key, NULL );
    3720             :       /* The normal case is that the acct->bit mapping is preserved
    3721             :          while in use by other transactions in the pending list.  This
    3722             :          might not always happen though.  It's okay for the mapping to
    3723             :          get deleted while the acct is in use, which is noted with
    3724             :          BIT_CLEARED.  If that is set, the mapping may not exist, or it
    3725             :          may have been re-created, perhaps with a different bit. */
    3726         861 :       if( q==NULL ) VERIFY_TEST( use->in_use_by & FD_PACK_IN_USE_BIT_CLEARED, "acct in use not in acct_to_bitset, but not marked as cleared" );
    3727           0 :       else if( !(use->in_use_by & FD_PACK_IN_USE_BIT_CLEARED) ) {
    3728           0 :         FD_PACK_BITSET_CLEAR( bit );
    3729           0 :         FD_PACK_BITSET_SETN( bit, q->bit );
    3730           0 :         if( q->bit<FD_PACK_BITSET_MAX ) {
    3731           0 :           VERIFY_TEST( !FD_PACK_BITSET_INTERSECT4_EMPTY( bit, bit, rw_bitset, rw_bitset ), "missing from rw bitset" );
    3732           0 :           if( use->in_use_by & FD_PACK_IN_USE_WRITABLE ) {
    3733           0 :             VERIFY_TEST( !FD_PACK_BITSET_INTERSECT4_EMPTY( bit, bit, w_bitset, w_bitset ), "missing from w bitset" );
    3734           0 :             FD_PACK_BITSET_CLEARN( w_complement, q->bit );
    3735           0 :           }
    3736           0 :         }
    3737           0 :         FD_PACK_BITSET_CLEARN( rw_complement, q->bit );
    3738           0 :       }
    3739         861 :       if( use->in_use_by & FD_PACK_IN_USE_WRITABLE ) VERIFY_TEST( (use->in_use_by & EMPTY_MASK)==bank_mask, "writable, but in use by multiple" );
    3740             : 
    3741         861 :       use->in_use_by &= ~bank_mask;
    3742         861 :       if( !(use->in_use_by & EMPTY_MASK) ) acct_uses_remove( acct_in_use_copy, use );
    3743         861 :     }
    3744       12024 :   }
    3745         651 :   VERIFY_TEST( acct_uses_key_cnt( acct_in_use_copy )==0UL, "stray uses in acct_in_use" );
    3746         651 :   VERIFY_TEST( FD_PACK_BITSET_INTERSECT4_EMPTY( rw_complement, rw_complement, rw_bitset,  rw_bitset ), "extra in rw bitset" );
    3747         651 :   VERIFY_TEST( FD_PACK_BITSET_INTERSECT4_EMPTY(  w_complement,  w_complement,  w_bitset,   w_bitset ), "extra in w bitset" );
    3748             : 
    3749         651 :   acct_uses_leave( acct_in_use_copy );
    3750             : 
    3751         651 :   acct_uses_join( _acct_in_use_orig );
    3752         651 :   return 0;
    3753         651 : }
    3754             : 
    3755         246 : void * fd_pack_leave ( fd_pack_t * pack ) { FD_COMPILER_MFENCE(); return (void *)pack; }
    3756         246 : void * fd_pack_delete( void      * mem  ) { FD_COMPILER_MFENCE(); return mem;          }

Generated by: LCOV version 1.14