LCOV - code coverage report
Current view: top level - discof/backup - fd_txncache_writer.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 4 4 100.0 %
Date: 2026-09-17 04:28:31 Functions: 0 0 -

          Line data    Source code
       1             : #ifndef HEADER_fd_src_discof_backup_fd_txncache_writer_h
       2             : #define HEADER_fd_src_discof_backup_fd_txncache_writer_h
       3             : 
       4             : /* fd_txncache_writer serializes the rooted part of a txncache into the
       5             :    snapshots/status_cache file of a Solana snapshot (bincode
       6             :    Vec<SlotDelta>), shaped the way Agave writes it: one slot delta per
       7             :    recent rooted slot with a block, holding the transactions that
       8             :    executed in that slot, grouped by the blockhash they referenced.
       9             :    Holds txncache read locks while walking the txncache. */
      10             : 
      11             : #include "../../flamenco/runtime/fd_txncache.h"
      12             : #include "../../flamenco/runtime/fd_txncache_shmem.h"
      13             : 
      14             : /* FD_TXNCACHE_WRITER_MAX_SLOT_DELTAS is the number of slot deltas a
      15             :    status cache holds, mirroring Agave's StatusCache::max_root_entries
      16             :    (default MAX_ROOT_ENTRIES = MAX_RECENT_BLOCKHASHES = 300; the
      17             :    constant status_cache::MAX_CACHE_ENTRIES up to v3.x).  Snapshot load
      18             :    walks the SlotHistory sysvar back from the snapshot slot and requires
      19             :    a slot delta for each of the newest max_root_entries slots that has
      20             :    a block.  No shipped Agave changes it from 300; if it ever becomes
      21             :    configurable, this and FD_SLOT_DELTA_MAX_ENTRIES must follow.
      22             :    https://github.com/anza-xyz/agave/blob/v3.1.8/runtime/src/snapshot_bank_utils.rs#L609 */
      23             : 
      24       17751 : #define FD_TXNCACHE_WRITER_MAX_SLOT_DELTAS (300UL)
      25             : 
      26      653847 : #define FD_TXNCACHE_WRITER_MAX_BLOCKHASHES (FD_TXNCACHE_MAX_SLOT_DELTAS+1UL)
      27             : 
      28             : #define FD_TXNCACHE_WRITER_MAX_GROUPS (FD_TXNCACHE_WRITER_MAX_SLOT_DELTAS*FD_TXNCACHE_WRITER_MAX_BLOCKHASHES)
      29             : 
      30             : /* FD_TXNCACHE_WRITER_BUF_MIN is the smallest output buffer
      31             :    fd_txncache_writer_serialize accepts (fits any single record).
      32             :    Serialization emits whole records only and stops when the next one
      33             :    does not fit; the caller comes back with more room. */
      34             : 
      35          21 : #define FD_TXNCACHE_WRITER_BUF_MIN (4096UL)
      36             : 
      37           6 : #define FD_TXNCACHE_WRITER_RELOCK_THRESH (1UL<<16)
      38             : 
      39             : struct fd_txncache_writer_blockhash_desc {
      40             :   ulong blockcache_idx; /* blockcache pool index */
      41             :   uint  generation;     /* blockcache generation at init, detects reuse */
      42             :   uchar blockhash[ 32UL ];
      43             :   ulong txnhash_offset;
      44             : };
      45             : 
      46             : typedef struct fd_txncache_writer_blockhash_desc fd_txncache_writer_blockhash_desc_t;
      47             : 
      48             : /* A group is one non-empty (execution slot, referenced blockhash) pair
      49             :    and serializes as one wire group in one slot delta.  The dense group
      50             :    key is a position in slots[] paired with a position in
      51             :    blockhash_descs[]. */
      52             : struct fd_txncache_writer_group {
      53             :   ushort slot_i;
      54             :   ushort blockhash_i;
      55             :   uint   entry_cnt;        /* transactions in the group */
      56             :   uint   arena_entry_off;
      57             :   uint   filled_entry_cnt; /* entries copied so far in the current fill */
      58             : };
      59             : 
      60             : typedef struct fd_txncache_writer_group fd_txncache_writer_group_t;
      61             : 
      62             : typedef uchar fd_txnhash_t[ 20UL ];
      63             : 
      64             : struct fd_txncache_writer {
      65             :   uint              state;
      66             :   fd_txncache_t *   tc;
      67             :   ulong             snapshot_slot;
      68             :   ulong             snapshot_root_idx;
      69             :   uint              snapshot_root_generation;
      70             : 
      71             :   /* SlotDeltas (ascending). */
      72             :   ulong             slots[ FD_TXNCACHE_WRITER_MAX_SLOT_DELTAS ];
      73             :   ulong             slot_cnt;
      74             :   ulong             group_cnt_by_slot_i[ FD_TXNCACHE_WRITER_MAX_SLOT_DELTAS ];
      75             : 
      76             :   /* Referenced blockhash descriptors, oldest rooted blockcache first. */
      77             :   fd_txncache_writer_blockhash_desc_t blockhash_descs[ FD_TXNCACHE_WRITER_MAX_BLOCKHASHES ];
      78             :   ulong                               blockhash_cnt;
      79             :   ushort                              fork_id_to_slot_i[ USHORT_MAX+1UL ];
      80             : 
      81             :   /* Groups in wire order (slot ascending, then blockhash descriptor ascending). */
      82             :   uint                       entry_cnt_by_key[ FD_TXNCACHE_WRITER_MAX_GROUPS ];
      83             :   uint                       group_i_by_key[ FD_TXNCACHE_WRITER_MAX_GROUPS ];
      84             :   fd_txncache_writer_group_t groups[ FD_TXNCACHE_WRITER_MAX_GROUPS ];
      85             :   ulong                      group_cnt;
      86             :   ulong                      entry_cnt; /* Transactions across all groups. */
      87             : 
      88             :   /* Scratchpad for collecting transaction hashes in serialization
      89             :      order. */
      90             :   fd_txnhash_t * arena;
      91             :   ulong          arena_entry_cnt_max;
      92             :   ulong          batch_hi;
      93             : 
      94             :   /* Serialization cursor. */
      95             :   ulong             slot_i;  /* Next slot delta. */
      96             :   ulong             group_i; /* Next group. */
      97             :   ulong             entry_i; /* Next entry of the current group. */
      98             : };
      99             : 
     100             : typedef struct fd_txncache_writer fd_txncache_writer_t;
     101             : 
     102             : FD_PROTOTYPES_BEGIN
     103             : 
     104             : /* Returns the arena size the writer recommends for a txncache whose
     105             :    blocks hold at most max_txn_per_slot transactions.
     106             : 
     107             :    The writer stages transaction hashes in an arena the caller provides.
     108             :    The txncache stores transactions by referenced blockhash while the
     109             :    wire format wants them by execution slot, so the writer counts every
     110             :    group in one walk of the txncache, then fills the arena with as many
     111             :    consecutive groups as fit per further walk.  A single group that does
     112             :    not fit the arena is fatal.  Caller should use this function to size
     113             :    the arena.
     114             : 
     115             :    The arena must be aligned to fd_txncache_writer_arena_align(). */
     116             : 
     117             : FD_FN_CONST ulong
     118             : fd_txncache_writer_arena_sz( ulong max_txn_per_slot );
     119             : 
     120             : FD_FN_CONST ulong
     121             : fd_txncache_writer_arena_align( void );
     122             : 
     123             : /* fd_txncache_writer_init prepares writer to serialize the status
     124             :    cache of tc as of the rooted fork fork_id, which must be the most
     125             :    recent root.  snapshot_slot is the fork's slot.  slot_history points
     126             :    to the slot_history_sz byte bincode encoding of the SlotHistory
     127             :    sysvar in the bank's sysvar cache, which decides which slots get a
     128             :    slot delta and names each execution slot.  arena is the arena_sz byte
     129             :    staging area.
     130             : 
     131             :    Walks the whole txncache once to count the transactions of every
     132             :    (slot, blockhash) group, so the serialized size is known on return.
     133             : 
     134             :    Returns writer on success.  Returns NULL if fork_id is not the most
     135             :    recent root or if more than one rooted blockhash descriptor lacks a
     136             :    named execution slot.  Replay should not be advancing the root while
     137             :    a snapshot is in progress, so snapmk treats NULL as fatal. */
     138             : 
     139             : fd_txncache_writer_t *
     140             : fd_txncache_writer_init( fd_txncache_writer_t * writer,
     141             :                          fd_txncache_t *        tc,
     142             :                          fd_txncache_fork_id_t  fork_id,
     143             :                          ulong                  snapshot_slot,
     144             :                          uchar const *          slot_history,
     145             :                          ulong                  slot_history_sz,
     146             :                          void *                 arena,
     147             :                          ulong                  arena_sz );
     148             : 
     149             : /* fd_txncache_writer_serialized_sz returns the exact size in bytes of
     150             :    the status cache an initialized writer will produce. */
     151             : 
     152             : FD_FN_PURE ulong
     153             : fd_txncache_writer_serialized_sz( fd_txncache_writer_t const * writer );
     154             : 
     155             : /* fd_txncache_writer_serialize writes the next chunk of the status
     156             :    cache to out_buf (buf_sz>=FD_TXNCACHE_WRITER_BUF_MIN).  Returns the
     157             :    chunk size, or zero once the whole status cache was written.  May
     158             :    walk the txncache to fill the arena with the next batch of groups. */
     159             : 
     160             : ulong
     161             : fd_txncache_writer_serialize( fd_txncache_writer_t * writer,
     162             :                               uchar *                out_buf,
     163             :                               ulong                  buf_sz );
     164             : 
     165             : FD_PROTOTYPES_END
     166             : 
     167             : #endif /* HEADER_fd_src_discof_backup_fd_txncache_writer_h */

Generated by: LCOV version 1.14