LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_txncache_private.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 9 11 81.8 %
Date: 2026-08-29 04:30:01 Functions: 1 5 20.0 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_runtime_fd_txncache_private_h
       2             : #define HEADER_fd_src_flamenco_runtime_fd_txncache_private_h
       3             : 
       4             : #include "fd_txncache_shmem.h"
       5             : #include "../fd_flamenco_base.h"
       6             : #include "../fd_rwlock.h"
       7             : 
       8             : /* The number of transactions in each page.  This needs to be high
       9             :    enough to amoritze the cost of caller code reserving pages from,
      10             :    and returning pages to the pool, but not so high that the memory
      11             :    wasted from blockhashes with only one transaction is significant. */
      12             : 
      13        1053 : #define FD_TXNCACHE_TXNS_PER_PAGE (8192UL)
      14             : 
      15             : /* The maximum distance a transaction blockhash reference can be
      16             :    (inclusive).  For example, if no slots were skipped, and the value is
      17             :    151, slot 300 is allowed to reference blockhashes from slots
      18             :    [149, 300). */
      19         306 : #define FD_TXNCACHE_MAX_BLOCKHASH_DISTANCE (151UL)
      20             : 
      21             : struct __attribute__((packed)) fd_txncache_single_txn {
      22             :   uint  blockcache_next; /* Pointer to the next element in the blockcache hash chain containing this entry from the pool. */
      23             :   uint  generation;      /* The generation of the fork when this transaction was inserted.  Used to
      24             :                             determine if the transaction is still valid for a fork that might have
      25             :                             advanced since insertion. */
      26             : 
      27             :   fd_txncache_fork_id_t fork_id; /* Fork that the transaction was executed on.  A transaction might be in the cache
      28             :                                     multiple times if it was executed on multiple forks. */
      29             :   uchar txnhash[ 20UL ]; /* The transaction message hash, truncated to 20 bytes.  The hash is not always the first 20
      30             :                             bytes, but is 20 bytes starting at some arbitrary offset given by the txnhash_offset value
      31             :                             of the containing blockcache entry. */
      32             : };
      33             : 
      34             : typedef struct fd_txncache_single_txn fd_txncache_single_txn_t;
      35             : 
      36             : FD_STATIC_ASSERT( sizeof(fd_txncache_single_txn_t)==30UL, fd_txncache_single_txn );
      37             : 
      38             : struct fd_txncache_txnpage {
      39             :   ushort                   free; /* The number of free txn entries in this page. */
      40             :   fd_txncache_single_txn_t txns[ FD_TXNCACHE_TXNS_PER_PAGE][ 1 ]; /* The transactions in the page. */
      41             : };
      42             : 
      43             : typedef struct fd_txncache_txnpage fd_txncache_txnpage_t;
      44             : 
      45             : struct fd_txncache_blockcache_shmem {
      46             :   fd_txncache_fork_id_t parent_id;
      47             :   fd_txncache_fork_id_t child_id;
      48             :   fd_txncache_fork_id_t sibling_id;
      49             : 
      50             :   int frozen;            /* This is used to enforce invariants on the caller of the txncache.
      51             :                             -1: invalid
      52             :                              0: active
      53             :                              1: semi frozen, only happens during snapshot load
      54             :                              2: frozen, should not be modified */
      55             : 
      56             :   uint generation;
      57             : 
      58             :   fd_hash_t blockhash;   /* The blockhash that this entry is for. */
      59             :   ulong txnhash_offset;  /* To save memory, the Agave validator decided to truncate the hash of transactions stored in
      60             :                             this memory to 20 bytes rather than 32 bytes.  The bytes used are not the first 20 as you
      61             :                             might expect, but instead the first 20 starting at some random offset into the transaction
      62             :                             hash (starting between 0 and len(hash)-20, a/k/a 44 for signatures, and 12 for hashes).
      63             : 
      64             :                             In an unfortunate turn, the offset is also propagated to peers via. snapshot responses,
      65             :                             which only communicate the offset and the respective 20 bytes.  To make sure we are
      66             :                             deduplicating incoming transactions correctly, we must replicate this system even though
      67             :                             it would be easier to just always take the first 20 bytes.  For transactions that we
      68             :                             insert into the cache ourselves, we do just always use a key_offset of zero, so this is
      69             :                             only nonzero when constructed form a peer snapshot. */
      70             : 
      71             :   ushort pages_cnt;      /* The number of txnpages currently in use to store the transactions in this blockcache. */
      72             : 
      73             :   struct {
      74             :     ulong next;
      75             :   } pool;
      76             : 
      77             :   struct {
      78             :     ulong next;
      79             :   } slist;
      80             : 
      81             :   struct {
      82             :     ulong next;
      83             :     ulong prev;
      84             :   } blockhash_map;
      85             : };
      86             : 
      87             : typedef struct fd_txncache_blockcache_shmem fd_txncache_blockcache_shmem_t;
      88             : 
      89             : #define POOL_NAME       blockcache_pool
      90             : #define POOL_T          fd_txncache_blockcache_shmem_t
      91             : #define POOL_IDX_T      ulong
      92        8022 : #define POOL_NEXT       pool.next
      93             : #define POOL_IMPL_STYLE 1
      94             : #include "../../util/tmpl/fd_pool.c"
      95             : 
      96             : #define MAP_NAME               blockhash_map
      97             : #define MAP_KEY                blockhash
      98             : #define MAP_ELE_T              fd_txncache_blockcache_shmem_t
      99             : #define MAP_KEY_T              fd_hash_t
     100             : #define MAP_PREV               blockhash_map.prev
     101           0 : #define MAP_NEXT               blockhash_map.next
     102         654 : #define MAP_KEY_EQ(k0,k1)      fd_hash_eq( k0, k1 )
     103        4959 : #define MAP_KEY_HASH(key,seed) (__extension__({ (void)(seed); fd_ulong_load_8_fast( (key)->uc ); }))
     104             : #define MAP_OPTIMIZE_RANDOM_ACCESS_REMOVAL 1
     105             : #define MAP_MULTI              1
     106             : #define MAP_IMPL_STYLE         1
     107             : #include "../../util/tmpl/fd_map_chain.c"
     108             : 
     109             : #define SLIST_NAME       root_slist
     110             : #define SLIST_ELE_T      fd_txncache_blockcache_shmem_t
     111           0 : #define SLIST_IDX_T      ulong
     112        4056 : #define SLIST_NEXT       slist.next
     113             : #define SLIST_IMPL_STYLE 1
     114             : #include "../../util/tmpl/fd_slist.c"
     115             : 
     116             : #define SET_NAME descends_set
     117             : #include "../../util/tmpl/fd_set_dynamic.c"
     118             : 
     119             : struct __attribute__((aligned(FD_TXNCACHE_SHMEM_ALIGN))) fd_txncache_shmem_private {
     120             :   /* The txncache is a concurrent structure and will be accessed by multiple threads
     121             :      concurrently.  Insertion and querying only take a read lock as they can be done
     122             :      lockless but all other operations will take a write lock internally.
     123             : 
     124             :      The lock needs to be aligned to 128 bytes to avoid false sharing with other
     125             :      data that might be on the same cache line. */
     126             :   fd_rwlock_t lock[ 1 ] __attribute__((aligned(128UL)));
     127             : 
     128             :   ulong  txn_per_slot_max;
     129             :   ulong  active_slots_max;
     130             :   ulong  bucket_cnt;      /* Hash buckets per blockcache.  Decoupled from txn_per_slot_max (load
     131             :                              factor 8) to reduce the heads arrays' memory footprint. */
     132             :   ushort txnpages_per_blockhash_max;
     133             :   ushort max_txnpages;
     134             : 
     135             :   uint blockcache_generation; /* Incremented for every blockcache. */
     136             :   ushort txnpages_free_cnt; /* The number of pages in the txnpages that are not currently in use. */
     137             : 
     138             :   ulong root_cnt;
     139             :   root_slist_t root_ll[1]; /* A singly linked list of the forks that are roots of fork chains.  The tail is the
     140             :                               most recently added root, the head is the oldest root.  This is used to identify
     141             :                               which forks can be pruned when a new root is added. */
     142             : 
     143             :   ulong seed;
     144             :   ulong magic; /* ==FD_TXNCACHE_SHMEM_MAGIC */
     145             : };
     146             : 
     147             : FD_PROTOTYPES_BEGIN
     148             : 
     149             : FD_FN_CONST ushort
     150             : fd_txncache_max_txnpages_per_blockhash( ulong max_active_slots,
     151             :                                         ulong max_txn_per_slot,
     152             :                                         int   larger_max_cost_per_block );
     153             : 
     154             : FD_FN_CONST ushort
     155             : fd_txncache_max_txnpages( ulong max_active_slots,
     156             :                           ulong max_txn_per_slot,
     157             :                           int   larger_max_cost_per_block );
     158             : 
     159             : FD_FN_CONST static inline ulong
     160         183 : fd_txncache_bucket_cnt( ulong max_txn_per_slot ) {
     161         183 :   return fd_ulong_max( 1UL, (max_txn_per_slot+7UL)/8UL );
     162         183 : }
     163             : 
     164             : FD_PROTOTYPES_END
     165             : 
     166             : #endif /* HEADER_fd_src_flamenco_runtime_fd_txncache_private_h */

Generated by: LCOV version 1.14