LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_txncache_private.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 2 7 28.6 %
Date: 2025-10-13 04:42:14 Functions: 0 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 "../types/fd_types_custom.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           6 : #define FD_TXNCACHE_TXNS_PER_PAGE (16384UL)
      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           3 : #define FD_TXNCACHE_MAX_BLOCKHASH_DISTANCE (151UL)
      20             : 
      21             : struct 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             : 
      24             :   fd_txncache_fork_id_t fork_id; /* Fork that the transaction was executed on.  A transaction might be in the cache
      25             :                                     multiple times if it was executed on multiple forks. */
      26             :   uchar txnhash[ 20UL ]; /* The transaction message hash, truncated to 20 bytes.  The hash is not always the first 20
      27             :                             bytes, but is 20 bytes starting at some arbitrary offset given by the txnhash_offset value
      28             :                             of the containing blockcache entry. */
      29             : };
      30             : 
      31             : typedef struct fd_txncache_single_txn fd_txncache_single_txn_t;
      32             : 
      33             : struct fd_txncache_txnpage {
      34             :   ushort                   free; /* The number of free txn entries in this page. */
      35             :   fd_txncache_single_txn_t txns[ FD_TXNCACHE_TXNS_PER_PAGE][ 1 ]; /* The transactions in the page. */
      36             : };
      37             : 
      38             : typedef struct fd_txncache_txnpage fd_txncache_txnpage_t;
      39             : 
      40             : struct fd_txncache_blockcache_shmem {
      41             :   fd_txncache_fork_id_t parent_id;
      42             :   fd_txncache_fork_id_t child_id;
      43             :   fd_txncache_fork_id_t sibling_id;
      44             : 
      45             :   int frozen;            /* If non-zero, the blockcache is frozen and should not be modified.  This is used to enforce
      46             :                             invariants on the caller of the txncache. */
      47             : 
      48             :   fd_hash_t blockhash;   /* The blockhash that this entry is for. */
      49             :   ulong txnhash_offset;  /* To save memory, the Agave validator decided to truncate the hash of transactions stored in
      50             :                             this memory to 20 bytes rather than 32 bytes.  The bytes used are not the first 20 as you
      51             :                             might expect, but instead the first 20 starting at some random offset into the transaction
      52             :                             hash (starting between 0 and len(hash)-20, a/k/a 44 for signatures, and 12 for hashes).
      53             : 
      54             :                             In an unfortunate turn, the offset is also propogated to peers via. snapshot responses,
      55             :                             which only communicate the offset and the respective 20 bytes.  To make sure we are
      56             :                             deduplicating incoming transactions correctly, we must replicate this system even though
      57             :                             it would be easier to just always take the first 20 bytes.  For transactions that we
      58             :                             insert into the cache ourselves, we do just always use a key_offset of zero, so this is
      59             :                             only nonzero when constructed form a peer snapshot. */
      60             : 
      61             :   ushort pages_cnt;      /* The number of txnpages currently in use to store the transactions in this blockcache. */
      62             : 
      63             :   struct {
      64             :     ulong next;
      65             :   } pool;
      66             : 
      67             :   struct {
      68             :     ulong next;
      69             :   } slist;
      70             : 
      71             :   struct {
      72             :     ulong next;
      73             :     ulong prev;
      74             :   } blockhash_map;
      75             : 
      76             :   struct {
      77             :     ulong next;
      78             :     ulong prev;
      79             :   } fork_map;
      80             : };
      81             : 
      82             : typedef struct fd_txncache_blockcache_shmem fd_txncache_blockcache_shmem_t;
      83             : 
      84             : #define POOL_NAME       blockcache_pool
      85             : #define POOL_T          fd_txncache_blockcache_shmem_t
      86             : #define POOL_IDX_T      ulong
      87           0 : #define POOL_NEXT       pool.next
      88             : #define POOL_IMPL_STYLE 1
      89             : #include "../../util/tmpl/fd_pool.c"
      90             : 
      91             : #define MAP_NAME               blockhash_map
      92             : #define MAP_KEY                blockhash
      93             : #define MAP_ELE_T              fd_txncache_blockcache_shmem_t
      94             : #define MAP_KEY_T              fd_hash_t
      95             : #define MAP_PREV               blockhash_map.prev
      96             : #define MAP_NEXT               blockhash_map.next
      97           0 : #define MAP_KEY_EQ(k0,k1)      fd_hash_eq( k0, k1 )
      98           0 : #define MAP_KEY_HASH(key,seed) (__extension__({ (void)(seed); fd_ulong_load_8_fast( (key)->uc ); }))
      99             : #define MAP_OPTIMIZE_RANDOM_ACCESS_REMOVAL 1
     100             : #define MAP_MULTI              1
     101             : #define MAP_IMPL_STYLE         1
     102             : #include "../../util/tmpl/fd_map_chain.c"
     103             : 
     104             : #define SLIST_NAME       root_slist
     105             : #define SLIST_ELE_T      fd_txncache_blockcache_shmem_t
     106           0 : #define SLIST_IDX_T      ulong
     107           0 : #define SLIST_NEXT       slist.next
     108             : #define SLIST_IMPL_STYLE 1
     109             : #include "../../util/tmpl/fd_slist.c"
     110             : 
     111             : struct __attribute__((aligned(FD_TXNCACHE_SHMEM_ALIGN))) fd_txncache_shmem_private {
     112             :   /* The txncache is a concurrent structure and will be accessed by multiple threads
     113             :      concurrently.  Insertion and querying only take a read lock as they can be done
     114             :      lockless but all other operations will take a write lock internally.
     115             : 
     116             :      The lock needs to be aligned to 128 bytes to avoid false sharing with other
     117             :      data that might be on the same cache line. */
     118             :   fd_rwlock_t lock[ 1 ] __attribute__((aligned(128UL)));
     119             : 
     120             :   ulong  txn_per_slot_max;
     121             :   ulong  active_slots_max;
     122             :   ushort txnpages_per_blockhash_max;
     123             :   ushort max_txnpages;
     124             : 
     125             :   ushort txnpages_free_cnt; /* The number of pages in the txnpages that are not currently in use. */
     126             : 
     127             :   ulong root_cnt;
     128             :   root_slist_t root_ll[1]; /* A singly linked list of the forks that are roots of fork chains.  The tail is the
     129             :                               most recently added root, the head is the oldest root.  This is used to identify
     130             :                               which forks can be pruned when a new root is added. */
     131             : 
     132             :   ulong magic; /* ==FD_TXNCACHE_MAGIC */
     133             : };
     134             : 
     135             : FD_PROTOTYPES_BEGIN
     136             : 
     137             : FD_FN_CONST ushort
     138             : fd_txncache_max_txnpages_per_blockhash( ulong max_active_slots,
     139             :                                         ulong max_txn_per_slot );
     140             : 
     141             : FD_FN_CONST ushort
     142             : fd_txncache_max_txnpages( ulong max_active_slots,
     143             :                           ulong max_txn_per_slot );
     144             : 
     145             : FD_PROTOTYPES_END
     146             : 
     147             : #endif /* HEADER_fd_src_flamenco_runtime_fd_txncache_private_h */

Generated by: LCOV version 1.14