LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_bank.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 11 16 68.8 %
Date: 2026-11-11 12:40:43 Functions: 5 168 3.0 %

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_runtime_fd_bank_h
       2             : #define HEADER_fd_src_flamenco_runtime_fd_bank_h
       3             : 
       4             : #include "../leaders/fd_leaders.h"
       5             : #include "../features/fd_features.h"
       6             : #include "../stakes/fd_stake_delegations.h"
       7             : #include "../stakes/fd_vote_stakes.h"
       8             : #include "../stakes/fd_epoch_credits.h"
       9             : #include "../fd_rwlock.h"
      10             : #include "fd_blockhashes.h"
      11             : #include "fd_cost_tracker_store.h"
      12             : #include "fd_slot_params.h"
      13             : #include "sysvar/fd_sysvar_cache.h"
      14             : #include "../../ballet/lthash/fd_lthash.h"
      15             : #include "fd_txncache_shmem.h"
      16             : #include "../progcache/fd_progcache_base.h"
      17             : 
      18             : FD_PROTOTYPES_BEGIN
      19             : 
      20          12 : #define FD_BANKS_MAGIC     (0XF17EDA2C7EBA2451) /* FIREDANCER BANKS V1 */
      21           0 : #define FD_BANKS_MAX_BANKS (65534UL)
      22         204 : #define FD_BANKS_ALIGN     (128UL)
      23             : 
      24             : /* A fd_bank_t struct is the representation of the bank state on Solana
      25             :    for a given block.  More specifically, the bank state corresponds to
      26             :    all information needed during execution that is not stored on-chain,
      27             :    but is instead cached in a validator's memory.  Each of these bank
      28             :    fields are represented by a member of the fd_bank_t struct.
      29             : 
      30             :    Management of fd_bank_t structs must be fork-aware: the state of each
      31             :    fd_bank_t must be based on the fd_bank_t of its parent block.  This
      32             :    state is managed by the fd_banks_t struct.
      33             : 
      34             :    In order to support fork-awareness, there are several key features
      35             :    that fd_banks_t and fd_bank_t MUST support:
      36             :    1. Query for any non-rooted block's bank: create a fast lookup
      37             :       from bank index to bank
      38             :    2. Be able to create a new bank for a given block from the bank of
      39             :       that block's parent and maintain some tree-like structure to
      40             :       track the parent-child relationships: copy the contents from a
      41             :       parent bank into a child bank.
      42             :    3. Prune the set of active banks to keep the root updated as the
      43             :       network progresses: free resources of fd_bank_t structs that
      44             :       are are not direct descendants of the root bank (remove parents
      45             :       and any competing lineages).  When a bank is marked as dead (ie.
      46             :       if the block corresponding to the bank is invalid), it also must
      47             :       be able to be eagerly pruned away.
      48             :    4. Each bank will have field(s) that are concurrently read/write
      49             :       from multiple threads: add read-write locks to the fields that are
      50             :       concurrently written to.
      51             :    5. In practice, a bank state for a given block can be very large and
      52             :       not all of the fields are written to every block.  Therefore, it
      53             :       can be very expensive to copy the entire bank state for a given
      54             :       block each time a bank is created.  In order to avoid large
      55             :       memcpys, we can use a CoW mechanism for certain fields.
      56             :    6. In a similar vein, some fields are very large and are not written
      57             :       to very often, and are only read at the epoch boundary.  The most
      58             :       notable example is the stake delegations cache.  In order to
      59             :       handle this, we can use a delta-based approach where each bank
      60             :       only has a delta of the stake delegations.  The root bank will own
      61             :       the full set of stake delegations.  This means that the deltas are
      62             :       only applied to the root bank as each bank gets rooted.  If the
      63             :       caller needs to access the full set of stake delegations for a
      64             :       given bank, they can assemble the full set of stake delegations by
      65             :       applying all of the deltas from the current bank and all of its
      66             :       ancestors up to the root bank.
      67             : 
      68             :   fd_banks_t is represented by a left-child, right-sibling n-ary tree
      69             :   (inspired by fd_ghost) to keep track of the parent-child fork tree.
      70             :   The underlying data structure is a pool of fd_bank_t structs.  Banks
      71             :   are then accessed via an index into the bank pool (bank index).
      72             : 
      73             :   NOTE: The reason fd_banks_t is keyed by bank index and not by slot is
      74             :   to handle block equivocation: if there are two different blocks for
      75             :   the same slot, we need to be able to differentiate and handle both
      76             :   blocks against different banks.  As mentioned above, the bank index is
      77             :   just an index into the bank pool.  The caller is responsible for
      78             :   establishing a mapping from the bank index (which is managed by
      79             :   fd_banks_t) and runtime state (e.g. slot number).
      80             : 
      81             :   The fields in fd_bank_t can be categorized into two groups:
      82             :   1. Simple fields: these are fields which don't need any special
      83             :      handling and are laid out contiguously in the fd_bank_t struct
      84             :      at bank->f.<field>.
      85             :   2. Complex fields: these are fields which need special handling
      86             :      (e.g. locking, copy on write semantics, delta-based semantics).
      87             :      These types are not templatized and are manually defined below.
      88             : 
      89             :   Each field that is CoW has its own memory pool. The memory
      90             :   corresponding to the field is not located in the fd_bank_t struct and
      91             :   is instead represented by a pool/fork index. When the field is
      92             :   modified, a new element of the pool is acquired and the data is
      93             :   copied over from the parent.
      94             : 
      95             :   fd_stake_delegations_t stores its full state in fd_banks_t in
      96             :   out-of-line memory, with each bank carrying the fork index for its
      97             :   delta.
      98             : 
      99             :   The cost tracker is allocated from a pool.  The lifetime of a cost
     100             :   tracker element starts when the bank is linked to a parent with a
     101             :   call to fd_banks_clone_from_parent() which makes the bank replayable.
     102             :   The lifetime of a cost tracker element ends when the bank is frozen
     103             :   or removed by root advancement or pruning.
     104             : 
     105             :   The lthash is a simple field that is laid out contiguously in the
     106             :   fd_bank_t struct, but is not templatized and it has its own lock.
     107             : 
     108             :   So, when a bank is cloned from a parent, the non CoW fields are copied
     109             :   over and the CoW fields just copy over a pool index. The CoW behavior
     110             :   is completely abstracted away from the caller as callers have to
     111             :   query/modify fields using specific APIs.
     112             : 
     113             :   The memory for the banks is bounded by the max number of unrooted
     114             :   blocks at any given time.  Large per-fork state (vote stakes t-1
     115             :   sets, epoch credits, cost trackers) is backed by a file with an
     116             :   in-memory cache of cache_cnt entries.  See fd_banks_footprint() for
     117             :   more details.
     118             : 
     119             :   There are also some important states that a bank can be in:
     120             :   - Initialized: This bank has been created and linked to a parent bank
     121             :     index with a call to fd_banks_new_bank().  However, it is not yet
     122             :     replayable.
     123             :   - Replayable: This bank has inherited state from its parent and now
     124             :     transactions can be executed against it.  For a bank to become
     125             :     replayable, it must've been initialized beforehand.
     126             :   - Dead: This bank has been marked as dead.  This means that the block
     127             :     that this bank is associated with is invalid.  A bank can be marked
     128             :     dead before, during, or after it has finished replaying (i.e. the
     129             :     bank being marked dead just needs to be initialized).  A bank
     130             :     can still be executing transactions while it is marked dead, but it
     131             :     shouldn't be dispatched any more work.  In other words, a key
     132             :     invariant is that a bank's reference count should NEVER be increased
     133             :     after it has been marked dead.
     134             :   - Frozen: This bank has been marked as frozen and no other tasks
     135             :     should be dispatched to it.  Any bank-specific resources will be
     136             :     released (e.g. cost tracker element).  A bank can be marked frozen
     137             :     if the bank has finished executing all of its transactions.  A bank
     138             :     can only be copied from a parent bank (fd_banks_clone_from_parent)
     139             :     if the parent bank is frozen or prunable.  The program will crash
     140             :     if this invariant is violated.
     141             :   - Prunable: This bank has been marked for pruning away due to memory
     142             :     pressure on the banks.  Additional references on the bank should not
     143             :     be accumulated after the bank has been marked prunable and once
     144             :     references reach zero, it is safe to evict the bank and free any
     145             :     related resources.  At most one bank may be prunable.  It must be a
     146             :     non-root, non-leader leaf in the initialized, replayable, or frozen
     147             :     state.
     148             : 
     149             :   The usage pattern is as follows:
     150             : 
     151             :    To create an initial bank:
     152             :    fd_bank_t * bank_init = fd_banks_init_bank( banks );
     153             : 
     154             :    To create a new bank.  This simply provisions the memory for the bank
     155             :    but it should not be used to execute transactions against.
     156             :    ulong bank_index = fd_banks_new_bank( banks, parent_bank_index, now, is_leader )->idx;
     157             : 
     158             :    To clone bank from parent banks.  This makes a bank replayable by
     159             :    copying over the state from the parent bank into the child.  It
     160             :    assumes that the bank index has been previously provisioned by a call
     161             :    to fd_banks_new_bank and that the parent bank is frozen or prunable.
     162             :    fd_bank_t * bank_clone = fd_banks_clone_from_parent( banks, bank_index );
     163             : 
     164             :    To ensure that the bank index we want to advance our root to is safe
     165             :    and that there are no outstanding references to the banks that are
     166             :    not descendants of the target bank.
     167             :    fd_banks_advance_root_prepare( banks, target_bank_idx, &advanceable_bank_idx_out );
     168             : 
     169             :    To advance the root bank.  This assumes that the bank index is "safe"
     170             :    to advance to.  This means that none of the ancestors of the bank
     171             :    index have a non-zero reference count.
     172             :    fd_banks_advance_root( banks, bank_index, stake_history );
     173             : 
     174             :    To query some arbitrary bank:
     175             :    fd_bank_t * bank_query = fd_banks_bank_query( banks, bank_index );
     176             : 
     177             :   To access a simple field in the bank:
     178             : 
     179             :   ulong slot = bank->f.slot;
     180             :   bank->f.slot = slot;
     181             : 
     182             :   If a bank is marked dead, the caller should call
     183             :   fd_banks_mark_bank_dead() to mark the bank and all of its descendants
     184             :   as dead.  This does not actually free the underlying resources that
     185             :   the dead bank has allocated and instead just queues them up for
     186             :   pruning:
     187             :   fd_banks_mark_bank_dead( banks, dead_bank_idx, NULL, NULL );
     188             : 
     189             :   To actually prune away any dead banks, the caller should call:
     190             :   fd_banks_prune_one_bank( banks, cancel_info )
     191             : 
     192             :   The data used by an fd_bank_t or an fd_banks_t is stored in an
     193             :   fd_banks_t struct.
     194             : 
     195             :   If the fields are not templatized, their accessor and modifier
     196             :   patterns vary and are documented below.
     197             : */
     198             : 
     199             : /* The banks follow a state machine that generally transitions forward:
     200             :    All banks start off as INACTIVE.  Once a bank is provisioned (when
     201             :    the first FEC is received from the reassembler), it is in the state
     202             :    INIT; at this point, the bank is not yet replayable but the memory
     203             :    has been reserved.  At this point, it is part of the bank tree and
     204             :    additional children bank can be assigned to the bank.  Once the bank
     205             :    is replayable, it is moved from INIT to REPLAYABLE and any relevant
     206             :    state is copied over from the parent bank.  We know that the parent
     207             :    bank is done executing at this point.  Transactions can now be
     208             :    dispatched and scheduled against the bank.  If the block for the bank
     209             :    is done executing then it transitions to the state FROZEN and the
     210             :    fields in the bank should no longer change.
     211             : 
     212             :    A bank can be marked DEAD even before it enters the replayable or
     213             :    frozen state.  A dead bank can only transition to INACTIVE.
     214             : 
     215             :       INACTIVE -> INIT -> REPLAYABLE -> FROZEN -> INACTIVE
     216             :                    |  \       |  \  \        |
     217             :                    |   v      |   v  v       v
     218             :                    |  DEAD    |  DEAD PRUNABLE
     219             :                    |    \     |   /      |
     220             :                    v     v    v  v       v
     221             :               PRUNABLE   INACTIVE   INACTIVE
     222             :                    |  \
     223             :                    v   v
     224             :                  DEAD  INACTIVE
     225             : 
     226             :     A bank can also transition directly from INIT or REPLAYABLE to
     227             :     INACTIVE when root advancement prunes an unrooted, unreferenced
     228             :     sibling subtree. */
     229             : 
     230          24 : #define FD_BANK_STATE_INACTIVE   (0UL)
     231          12 : #define FD_BANK_STATE_INIT       (1UL)
     232          12 : #define FD_BANK_STATE_REPLAYABLE (2UL)
     233          12 : #define FD_BANK_STATE_FROZEN     (3UL)
     234           0 : #define FD_BANK_STATE_DEAD       (4UL)
     235           0 : #define FD_BANK_STATE_PRUNABLE   (5UL)
     236             : 
     237       71130 : #define FD_BANK_LTHASH_MODE_INBAND     (0) /* Hash every write into f.lthash. */
     238           0 : #define FD_BANK_LTHASH_MODE_OOB_RECORD (1) /* Start of block.  Record the pubkey in lthash_rec instead of hashing. */
     239           0 : #define FD_BANK_LTHASH_MODE_OOB_SKIP   (2) /* Transaction execution.  Neither hash nor record. */
     240             : 
     241             : /* This is the list of pubkeys written while the bank was in OOB_RECORD
     242             :    mode, one entry per write, in write order and not deduplicated.  keys
     243             :    has room for max entries, cnt of which are used. */
     244             : 
     245             : struct fd_bank_lthash_rec {
     246             :   ulong         cnt;
     247             :   ulong         max;
     248             :   fd_pubkey_t * keys;
     249             : };
     250             : typedef struct fd_bank_lthash_rec fd_bank_lthash_rec_t;
     251             : 
     252             : 
     253             : struct fd_bank {
     254             : 
     255             :   /* Fields used for internal pool and bank management */
     256             :   ulong idx;         /* current fork idx of the bank (synchronized with the pool index) */
     257             :   ulong next;        /* reserved for internal use by pool and fd_banks_advance_root */
     258             :   ulong parent_idx;  /* index of the parent in the node pool */
     259             :   ulong child_idx;   /* index of the left-child in the node pool */
     260             :   ulong sibling_idx; /* index of the right-sibling in the node pool */
     261             :   ulong dead_prev;   /* dead banks list links, only valid while the bank is dead */
     262             :   ulong dead_next;
     263             :   ulong state;       /* keeps track of the state of the bank */
     264             :   ulong bank_seq;    /* app-wide bank sequence number */
     265             :   uchar is_leader;   /* whether the bank is the leader */
     266             :   fd_pubkey_t leader; /* slot leader of this block */
     267             : 
     268             :   fd_txncache_fork_id_t  txncache_fork_id __attribute__((aligned(64UL)));
     269             :   fd_progcache_fork_id_t progcache_fork_id;
     270             :   fd_accdb_fork_id_t     accdb_fork_id;
     271             :   fd_accdb_fork_id_t     parent_accdb_fork_id;
     272             :   ushort                 vote_stakes_fork_id;
     273             :   ushort                 stake_rewards_fork_id;
     274             :   ushort                 stake_delegations_fork_id;
     275             :   ushort                 epoch_credits_fork_id;
     276             :   ushort                 cost_tracker_fork_id;
     277             : 
     278             :   ulong banks_data_offset; /* offset from this fd_bank_t back to fd_banks_t */
     279             : 
     280             :   /* Written by replay only, on its own line */
     281             : 
     282             :   ulong refcnt __attribute__((aligned(64UL))); /* reference count on the bank, see replay for more details */
     283             : 
     284             :   long first_fec_set_received_nanos;
     285             :   long preparation_begin_nanos;
     286             :   long first_transaction_scheduled_nanos;
     287             :   long last_transaction_finished_nanos;
     288             :   long block_completed_nanos;
     289             : 
     290             :   ulong footer_task_cnt;
     291             :   ulong execution_fees_pre_settle; /* for publish once those are done */
     292             :   ulong priority_fees_pre_settle;
     293             : 
     294             :   /* These fields should only be accessed by the replay and executor
     295             :      tiles.  The lock is taken per transaction, so it sits on its own
     296             :      line.  The mode fields share the line because they change only
     297             :      while no exec tile is working on the bank.  lthash_rec points into
     298             :      replay tile private memory and is valid only in OOB_RECORD mode,
     299             :      which only the replay tile sets. */
     300             :   fd_rwlock_t            lthash_lock __attribute__((aligned(64UL)));
     301             :   uchar                  lthash_mode;
     302             :   fd_bank_lthash_rec_t * lthash_rec;
     303             : 
     304             :   struct {
     305             :     fd_lthash_value_t      lthash;
     306             :     fd_blockhashes_t       block_hash_queue;
     307             :     fd_fee_rate_governor_t fee_rate_governor;
     308             :     ulong                  rbh_lamports_per_sig;
     309             :     ulong                  slot;
     310             :     ulong                  parent_slot;
     311             :     ulong                  capitalization;
     312             :     ulong                  parent_signature_cnt;
     313             :     ulong                  parent_txn_count; /* cumulative txn_count of all ancestors */
     314             :     ulong                  tick_height;
     315             :     ulong                  max_tick_height;
     316             :     ulong                  ticks_per_slot;
     317             :     ulong                  genesis_creation_time;
     318             :     fd_inflation_t         inflation;
     319             :     ulong                  cluster_type;
     320             :     ulong                  total_epoch_stake; /* total staked to active vote accounts */
     321             :     ulong                  total_effective_stake; /* effective stake from stake delegations */
     322             :     ulong                  total_activating_stake;
     323             :     ulong                  total_deactivating_stake;
     324             :     ulong                  warmup_cooldown_rate_epoch; /* epoch when reduce_stake_warmup_cooldown */
     325             :     ulong                  block_height;
     326             :     ulong                  execution_fees;
     327             :     ulong                  priority_fees;
     328             :     ulong                  tips;
     329             :     ulong                  signature_count;
     330             :     fd_hash_t              poh;
     331             :     ulong                  hard_fork_cnt;
     332             :     fd_hard_fork_t         hard_forks[ FD_HARD_FORKS_MAX ]; /* never changes at runtime, required for snapshot creation */
     333             :     fd_hash_t              bank_hash;
     334             :     fd_hash_t              prev_bank_hash;
     335             :     fd_epoch_schedule_t    epoch_schedule;
     336             :     fd_rent_t              rent;
     337             :     fd_features_t          features;
     338             :     ulong                  txn_count;
     339             :     ulong                  nonvote_txn_count;
     340             :     ulong                  failed_txn_count;
     341             :     ulong                  nonvote_failed_txn_count;
     342             :     ulong                  total_compute_units_used;
     343             :     ulong                  shred_cnt;
     344             :     ulong                  epoch;
     345             :     ulong                  identity_vote_idx;
     346             :     fd_slot_params_t       slot_params; /* parameters that need to change with the reduce_slot_time feature gates */
     347             :     fd_slot_params_t       slot_params_default; /* slot params this cluster uses when no reduce_slot_time gate is active */
     348             :     fd_hash_t              block_id;
     349             :     ulong                  alpenglow_migration_slot;
     350             :   } f;
     351             : 
     352             : };
     353             : typedef struct fd_bank fd_bank_t;
     354             : 
     355             : FD_STATIC_ASSERT( offsetof(fd_bank_t, txncache_fork_id)%64UL==0UL, fd_bank_exec_line );
     356             : FD_STATIC_ASSERT( offsetof(fd_bank_t, banks_data_offset)+sizeof(ulong)-offsetof(fd_bank_t, txncache_fork_id)<=64UL, fd_bank_exec_line_sz );
     357             : FD_STATIC_ASSERT( offsetof(fd_bank_t, refcnt)%64UL==0UL, fd_bank_refcnt_line );
     358             : FD_STATIC_ASSERT( offsetof(fd_bank_t, lthash_lock)%64UL==0UL, fd_bank_lthash_lock_line );
     359             : FD_STATIC_ASSERT( offsetof(fd_bank_t, f)-offsetof(fd_bank_t, lthash_lock)>=64UL, fd_bank_lthash_lock_alone );
     360             : 
     361             : struct fd_banks_prune_cancel_info {
     362             :   fd_txncache_fork_id_t  txncache_fork_id;
     363             :   fd_progcache_fork_id_t progcache_fork_id;
     364             :   fd_accdb_fork_id_t     accdb_fork_id;
     365             :   ulong                  slot;
     366             :   ulong                  bank_seq;
     367             :   ulong                  bank_idx;
     368             : };
     369             : typedef struct fd_banks_prune_cancel_info fd_banks_prune_cancel_info_t;
     370             : 
     371             : fd_stake_delegations_t *
     372             : fd_bank_stake_delegations_modify( fd_bank_t * bank );
     373             : 
     374             : /* fd_banks_t is the main struct used to manage the bank state.  It can
     375             :    be used to query/modify/clone/publish the bank state.
     376             : 
     377             :    fd_banks_t contains some metadata to a pool to manage the banks.
     378             :    It also contains pointers to the CoW pools.
     379             : 
     380             :    The data is laid out contiguously in memory starting from fd_banks_t;
     381             :    this can be seen in fd_banks_footprint(). */
     382             : 
     383             : struct fd_banks {
     384             :   ulong magic;                       /* ==FD_BANKS_MAGIC */
     385             :   int   report_runtime_diffs;        /* telemetry: emit the runtime events; report_runtime_diffs flag */
     386             :   ulong max_total_banks;             /* Maximum number of banks */
     387             :   ulong cache_cnt;                   /* In-memory entries of each disk backed per-fork store */
     388             :   ulong max_stake_accounts;          /* Maximum number of stake accounts */
     389             :   ulong max_vote_accounts;           /* Maximum number of vote accounts */
     390             :   ulong root_idx;                    /* root idx */
     391             :   ulong bank_seq;                    /* app-wide bank sequence number counter; starts at 1 (0 is reserved as an invalid bank_seq sentinel) */
     392             :   ulong evict_rr_idx;                /* internal index for round-robin banks eviction */
     393             :   ulong prunable_idx;                /* index of pending prunable bank, ULONG_MAX if none */
     394             : 
     395             :   ulong curr_fork_width;
     396             : 
     397             :   ulong pool_offset; /* offset of pool from banks */
     398             : 
     399             :   ulong cost_tracker_offset; /* offset of cost tracker pool from banks */
     400             : 
     401             :   ulong stake_rewards_offset;
     402             : 
     403             :   ulong dead_banks_offset;
     404             : 
     405             :   ulong epoch_credits_offset;
     406             : 
     407             :   /* Leader schedules for two adjacent epochs are allocated out-of-line.
     408             :      Computing a new schedule replaces the older of the two. */
     409             : 
     410             :   ulong epoch_leaders_offset;
     411             :   ulong epoch_leaders_footprint;
     412             : 
     413             :   ulong stake_delegations_offset;
     414             :   ulong vote_stakes_offset;
     415             : };
     416             : typedef struct fd_banks fd_banks_t;
     417             : 
     418             : /* fd_bank_report_runtime_diffs returns the banks-wide runtime-events
     419             :    flag (set once at replay tile init) for a bank.  Callers use it to
     420             :    gate fd_event_runtime calls. */
     421             : 
     422             : static inline int
     423        4523 : fd_bank_report_runtime_diffs( fd_bank_t const * bank ) {
     424        4523 :   fd_banks_t const * banks_data = fd_type_pun_const( (uchar const *)bank - bank->banks_data_offset );
     425        4523 :   return banks_data->report_runtime_diffs;
     426        4523 : }
     427             : 
     428             : /* fd_bank_lthash_record appends pubkey to bank->lthash_rec.  The bank
     429             :    must be in OOB_RECORD mode, and there must be free space for the
     430             :    pubkey. */
     431             : 
     432             : void
     433             : fd_bank_lthash_record( fd_bank_t * bank,
     434             :                        uchar const pubkey[ static 32 ] );
     435             : 
     436             : /* Bank accessors and mutators.  Different accessors are emitted for
     437             :    different types depending on if the field has a lock or not. */
     438             : 
     439             : fd_epoch_credits_store_t *
     440             : fd_bank_epoch_credits( fd_bank_t const * bank );
     441             : 
     442             : fd_stake_rewards_t const *
     443             : fd_bank_stake_rewards_query( fd_bank_t * bank );
     444             : 
     445             : fd_stake_rewards_t *
     446             : fd_bank_stake_rewards_modify( fd_bank_t * bank );
     447             : 
     448             : fd_epoch_leaders_t const *
     449             : fd_bank_epoch_leaders_query( fd_bank_t const * bank,
     450             :                              ulong             epoch );
     451             : 
     452             : fd_epoch_leaders_t *
     453             : fd_bank_epoch_leaders_modify( fd_bank_t * bank,
     454             :                               ulong       epoch );
     455             : 
     456             : fd_vote_stakes_t *
     457             : fd_bank_vote_stakes( fd_bank_t const * bank );
     458             : 
     459             : fd_cost_tracker_store_t *
     460             : fd_bank_cost_tracker( fd_bank_t const * bank );
     461             : 
     462             : fd_lthash_value_t const *
     463             : fd_bank_lthash_locking_query( fd_bank_t * bank );
     464             : 
     465             : void
     466             : fd_bank_lthash_end_locking_query( fd_bank_t * bank );
     467             : 
     468             : fd_lthash_value_t *
     469             : fd_bank_lthash_locking_modify( fd_bank_t * bank );
     470             : 
     471             : void
     472             : fd_bank_lthash_end_locking_modify( fd_bank_t * bank );
     473             : 
     474             : /* fd_banks_stake_delegations_root_query() will return a pointer to the
     475             :    full stake delegations for the current root. This function should
     476             :    only be called on boot. */
     477             : 
     478             : fd_stake_delegations_t *
     479             : fd_banks_stake_delegations_root_query( fd_banks_t * banks );
     480             : 
     481             : /* fd_banks_pool_used_cnt returns the number of bank pool elements
     482             :    currently in use. */
     483             : 
     484             : ulong
     485             : fd_banks_pool_used_cnt( fd_banks_t * banks );
     486             : 
     487             : /* fd_banks_pool_max_cnt returns the max number of bank pool elements. */
     488             : 
     489             : ulong
     490             : fd_banks_pool_max_cnt( fd_banks_t * banks );
     491             : 
     492             : /* fd_banks_stake_delegations_evict_bank_fork evicts the stake
     493             :    delegations fork for the given bank.  This is used to clean up
     494             :    resources during teardown. */
     495             : 
     496             : void
     497             : fd_banks_stake_delegations_evict_bank_fork( fd_banks_t * banks,
     498             :                                             fd_bank_t *  bank );
     499             : 
     500             : /* fd_banks_root() returns a pointer to the root bank respectively. */
     501             : 
     502             : fd_bank_t *
     503             : fd_banks_root( fd_banks_t * banks );
     504             : 
     505             : /* fd_banks_align() returns the alignment of fd_banks_t */
     506             : 
     507             : ulong
     508             : fd_banks_align( void );
     509             : 
     510             : /* fd_banks_footprint() returns the footprint of fd_banks_t.  This
     511             :    includes the struct itself but also the footprint for all of the
     512             :    pools.
     513             : 
     514             :    The footprint of fd_banks_t is determined by the total number
     515             :    of banks that the bank manages.  This is an analog for the max number
     516             :    of unrooted blocks the bank can manage at any given time.  Large
     517             :    per-fork structs (cost trackers, epoch credits and t-1 vote stakes)
     518             :    keep cache_cnt entries in memory and spill the rest to disk.  Returns
     519             :    0 if cache_cnt is 0. */
     520             : 
     521             : ulong
     522             : fd_banks_footprint( ulong max_total_banks,
     523             :                     ulong cache_cnt,
     524             :                     ulong max_stake_accounts,
     525             :                     ulong max_vote_accounts );
     526             : 
     527             : /* fd_banks_new() creates a new fd_banks_t struct.  This function
     528             :    lays out the memory for all of the constituent fd_bank_t structs
     529             :    and pools depending on max_total_banks.  stake_delegations_fd identifies the backing file for
     530             :    this instance's stake delegation store. */
     531             : 
     532             : void *
     533             : fd_banks_new( void * mem,
     534             :               int    stake_delegations_fd,
     535             :               ulong  max_total_banks,
     536             :               ulong  cache_cnt,
     537             :               ulong  max_stake_accounts,
     538             :               ulong  max_disk_records,
     539             :               ulong  max_vote_accounts,
     540             :               ulong  bench_max_cost_per_block, /* [development.bench], floors the block cost limit */
     541             :               ulong  seed );
     542             : 
     543             : /* fd_banks_join() joins an fd_banks_t struct.  It takes in a valid
     544             :    banks_data_mem.  Returns a pointer to the joined fd_banks_t struct
     545             :    on success and NULL on failure (logs details). */
     546             : 
     547             : fd_banks_t *
     548             : fd_banks_join( void * banks_data_mem );
     549             : 
     550             : /* fd_banks_init_bank() initializes a new bank in the bank manager.
     551             :    This should only be used during bootup.  The bank is set to the
     552             :    FROZEN state (skipping INIT/REPLAYABLE since no replay is needed for
     553             :    the initial root) and is established as the root bank. */
     554             : 
     555             : fd_bank_t *
     556             : fd_banks_init_bank( fd_banks_t * banks );
     557             : 
     558             : /* fd_banks_bank_query returns a bank for a given bank index. */
     559             : 
     560             : fd_bank_t *
     561             : fd_banks_bank_query( fd_banks_t * banks,
     562             :                      ulong        bank_idx );
     563             : 
     564             : fd_bank_t *
     565             : fd_banks_get_parent( fd_banks_t * banks,
     566             :                      fd_bank_t *  bank );
     567             : 
     568             : /* fd_banks_clone_from_parent() clones a bank from a parent bank.
     569             :    This function links the child bank to its parent bank and copies
     570             :    over the data from the parent bank to the child.  This function
     571             :    assumes that the child and parent banks both have been allocated.
     572             :    The parent bank must be frozen or prunable and the child bank must be
     573             :    initialized but not yet used.  It also assumes that the parent bank
     574             :    is not dead.
     575             : 
     576             :    A more detailed note: not all of the data is copied over and this
     577             :    is a shallow clone.  All of the CoW fields are not copied over and
     578             :    will only be done so if the caller explicitly calls
     579             :    fd_bank_{*}_modify().  This naming was chosen to emulate the
     580             :    semantics of the Agave client. */
     581             : 
     582             : fd_bank_t *
     583             : fd_banks_clone_from_parent( fd_banks_t * banks,
     584             :                             ulong        bank_idx );
     585             : 
     586             : /* fd_banks_advance_root() advances the root bank to the bank manager.
     587             :    This should only be used when a bank is no longer needed and has no
     588             :    active refcnts.  This will prune off the bank from the bank manager.
     589             :    An invariant of this function is that the new root bank should be a
     590             :    child of the current root bank.
     591             : 
     592             :    All banks that are ancestors or siblings of the new root bank will be
     593             :    cancelled and their resources will be released back to the pool.
     594             :    stake_history is the new root's StakeHistory sysvar (or NULL). */
     595             : 
     596             : void
     597             : fd_banks_advance_root( fd_banks_t *               banks,
     598             :                        ulong                      bank_idx,
     599             :                        fd_stake_history_t const * stake_history );
     600             : 
     601             : /* fd_banks_clear releases all banks back to the pool and resets the
     602             :    banks manager to its post-new state.  Assumes no active references to
     603             :    any bank.  WARNING: collision risk, resets bank_seq to 1 (0 is the
     604             :    reserved invalid sentinel). */
     605             : 
     606             : void
     607             : fd_banks_clear( fd_banks_t * banks );
     608             : 
     609             : /* fd_banks_advance_root_prepare returns the highest block that can be
     610             :    safely advanced between the current root of the fork tree and the
     611             :    target block.  See the note on safe publishing for more details.  In
     612             :    general, a node in the fork tree can be pruned if:
     613             :    (1) the node itself can be pruned, and
     614             :    (2) all subtrees (except for the one on the rooted fork) forking off
     615             :        of the node can be pruned.
     616             : 
     617             :    This function is read-only: it does not modify any bank state.  It
     618             :    walks from the target bank up to the current root to find the direct
     619             :    child of root on the path, then checks whether all sibling subtrees
     620             :    of that child can be pruned.
     621             : 
     622             :    Highest advanceable block is written to the out pointer.  Returns 1
     623             :    if the advanceable block can be advanced beyond the current root.
     624             :    Returns 0 if no such block can be found (e.g. the root still has a
     625             :    non-zero refcnt, or a sibling subtree cannot be pruned).  We will
     626             :    ONLY advance our advanceable_bank_idx to a child of the current root.
     627             :    In order to advance to the target bank,
     628             :    fd_banks_advance_root_prepare() must be called repeatedly. */
     629             : 
     630             : int
     631             : fd_banks_advance_root_prepare( fd_banks_t * banks,
     632             :                                ulong        target_bank_idx,
     633             :                                ulong *      advanceable_bank_idx_out );
     634             : 
     635             : /* fd_banks_mark_bank_dead marks the current bank (and all of its
     636             :    descendants) as dead.  Already-dead banks are not reported again.  If
     637             :    opt_idxs is non-NULL, it is populated with each bank index newly
     638             :    marked dead.  The caller is responsible for ensuring the buffer is
     639             :    large enough to hold the whole subtree.  If opt_idxs_cnt is non-NULL,
     640             :    it is set to the number of banks newly marked dead.  The caller is
     641             :    still responsible for handling the behavior of the dead bank
     642             :    correctly.  After a bank is marked dead, the caller should never
     643             :    increment the reference count on the bank. */
     644             : 
     645             : void
     646             : fd_banks_mark_bank_dead( fd_banks_t * banks,
     647             :                          ulong        bank_idx,
     648             :                          ulong *      opt_idxs,
     649             :                          ulong *      opt_idxs_cnt );
     650             : 
     651             : /* fd_banks_prune_one_bank will try to prune one bank that was
     652             :    marked as dead or prunable.  It will not prune a bank that has a
     653             :    non-zero reference count.  Returns 0 if nothing was pruned, 1 if a
     654             :    bank was pruned but no accdb/txncache cancellation is needed, or 2 if
     655             :    a bank was pruned and cancellation is needed.  Whenever a bank is
     656             :    pruned (returns 1 or 2), cancel->bank_idx is populated if cancel is
     657             :    non-NULL.  The remaining cancel fields are only populated if
     658             :    available. */
     659             : 
     660             : int
     661             : fd_banks_prune_one_bank( fd_banks_t *                   banks,
     662             :                          fd_banks_prune_cancel_info_t * cancel );
     663             : 
     664             : /* fd_banks_mark_bank_frozen marks the current bank as frozen.  This
     665             :    should be done when the bank is no longer being updated: it should be
     666             :    done at the end of a slot.  This also releases the memory for the
     667             :    cost tracker which only has to be persisted from the start of a slot
     668             :    to the end. */
     669             : 
     670             : void
     671             : fd_banks_mark_bank_frozen( fd_bank_t * bank );
     672             : 
     673             : /* fd_banks_new_bank reserves a bank index for a new bank.  New bank
     674             :    indices should always be available.  After this function is called,
     675             :    the bank will be linked to its parent bank, but not yet replayable.
     676             :    After a call to fd_banks_clone_from_parent, the bank will be
     677             :    replayable.  This assumes that there is a parent bank which exists
     678             :    and that there are available bank indices in the bank pool.  It also
     679             :    assumes that the parent bank is not dead, inactive, or prunable. */
     680             : 
     681             : fd_bank_t *
     682             : fd_banks_new_bank( fd_banks_t * banks,
     683             :                    ulong        parent_bank_idx,
     684             :                    long         now,
     685             :                    uchar        is_leader );
     686             : 
     687             : 
     688             : /* fd_banks_get_evictable_bank selects one evictable leaf according to
     689             :    the current fd_banks eviction policy, marks it prunable, records it
     690             :    as pending, and returns its bank index.  Eviction collects all
     691             :    eligible leaves in DFS order (left-child, then siblings) and picks
     692             :    banks->evict_rr_idx % leaf_count, then increments evict_rr_idx.
     693             :    Only a single leaf may be prunable at a time (prunable_idx).
     694             :    The eviction is selected in a round-robin manner to avoid a livelock
     695             :    where we repeatedly evict and replay the same bank, halting progress.
     696             :    The root, leader banks (or banks we were previously leaders for),
     697             :    dead banks, inactive banks, already prunable banks, and
     698             :    protected_bank are not evictable.  Pass NULL for protected_bank if no
     699             :    additional bank needs protection.  Returns ULONG_MAX if there is no
     700             :    evictable bank, or if a prunable bank is already pending pruning.
     701             :    TODO: It is possible that we can still wedge under very adverse
     702             :    conditions even with the round-robin eviction policy.  The starting
     703             :    evict_idx is different for each validator, ensuring that some nodes
     704             :    will still be able to make forward progress. */
     705             : 
     706             : ulong
     707             : fd_banks_get_evictable_bank( fd_banks_t *      banks,
     708             :                              fd_bank_t const * protected_bank );
     709             : 
     710             : /* fd_banks_can_start_bank returns 1 if banks has capacity to start
     711             :    preparing another child bank. */
     712             : 
     713             : int
     714             : fd_banks_can_start_bank( fd_banks_t * banks );
     715             : 
     716             : /* fd_banks_clear_bank() clears the contents of a bank. This should ONLY
     717             :    be used with banks that have no children and should only be used in
     718             :    testing and fuzzing.  WARNING: This should NOT be used in production.
     719             : 
     720             :    This function will memset all non-CoW fields to 0.
     721             : 
     722             :    For all CoW fields, we will reset the indices to its parent. */
     723             : 
     724             : void
     725             : fd_banks_clear_bank( fd_banks_t * banks,
     726             :                      fd_bank_t *  bank );
     727             : 
     728             : FD_PROTOTYPES_END
     729             : 
     730             : #endif /* HEADER_fd_src_flamenco_runtime_fd_bank_h */

Generated by: LCOV version 1.14