LCOV - code coverage report
Current view: top level - flamenco/runtime - fd_bank.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 12 12 100.0 %
Date: 2026-04-12 06:17:49 Functions: 0 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 "../types/fd_types.h"
       5             : #include "../leaders/fd_leaders.h"
       6             : #include "../features/fd_features.h"
       7             : #include "../stakes/fd_stake_delegations.h"
       8             : #include "../stakes/fd_top_votes.h"
       9             : #include "../stakes/fd_vote_stakes.h"
      10             : #include "../fd_rwlock.h"
      11             : #include "fd_blockhashes.h"
      12             : #include "sysvar/fd_sysvar_cache.h"
      13             : #include "../../ballet/lthash/fd_lthash.h"
      14             : #include "fd_txncache_shmem.h"
      15             : 
      16             : FD_PROTOTYPES_BEGIN
      17             : 
      18         333 : #define FD_BANKS_MAGIC     (0XF17EDA2C7EBA2450) /* FIREDANCER BANKS V0 */
      19          87 : #define FD_BANKS_MAX_BANKS (4096UL)
      20        5703 : #define FD_BANKS_ALIGN     (128UL)
      21             : 
      22             : /* A fd_bank_t struct is the representation of the bank state on Solana
      23             :    for a given block.  More specifically, the bank state corresponds to
      24             :    all information needed during execution that is not stored on-chain,
      25             :    but is instead cached in a validator's memory.  Each of these bank
      26             :    fields are represented by a member of the fd_bank_t struct.
      27             : 
      28             :    Management of fd_bank_t structs must be fork-aware: the state of each
      29             :    fd_bank_t must be based on the fd_bank_t of its parent block.  This
      30             :    state is managed by the fd_banks_t struct.
      31             : 
      32             :    In order to support fork-awareness, there are several key features
      33             :    that fd_banks_t and fd_bank_t MUST support:
      34             :    1. Query for any non-rooted block's bank: create a fast lookup
      35             :       from bank index to bank
      36             :    2. Be able to create a new bank for a given block from the bank of
      37             :       that block's parent and maintain some tree-like structure to
      38             :       track the parent-child relationships: copy the contents from a
      39             :       parent bank into a child bank.
      40             :    3. Prune the set of active banks to keep the root updated as the
      41             :       network progresses: free resources of fd_bank_t structs that
      42             :       are are not direct descendants of the root bank (remove parents
      43             :       and any competing lineages).  When a bank is marked as dead (ie.
      44             :       if the block corresponding to the bank is invalid), it also must
      45             :       be able to be eagerly pruned away.
      46             :    4. Each bank will have field(s) that are concurrently read/write
      47             :       from multiple threads: add read-write locks to the fields that are
      48             :       concurrently written to.
      49             :    5. In practice, a bank state for a given block can be very large and
      50             :       not all of the fields are written to every block.  Therefore, it
      51             :       can be very expensive to copy the entire bank state for a given
      52             :       block each time a bank is created.  In order to avoid large
      53             :       memcpys, we can use a CoW mechanism for certain fields.
      54             :    6. In a similar vein, some fields are very large and are not written
      55             :       to very often, and are only read at the epoch boundary.  The most
      56             :       notable example is the stake delegations cache.  In order to
      57             :       handle this, we can use a delta-based approach where each bank
      58             :       only has a delta of the stake delegations.  The root bank will own
      59             :       the full set of stake delegations.  This means that the deltas are
      60             :       only applied to the root bank as each bank gets rooted.  If the
      61             :       caller needs to access the full set of stake delegations for a
      62             :       given bank, they can assemble the full set of stake delegations by
      63             :       applying all of the deltas from the current bank and all of its
      64             :       ancestors up to the root bank.
      65             : 
      66             :   fd_banks_t is represented by a left-child, right-sibling n-ary tree
      67             :   (inspired by fd_ghost) to keep track of the parent-child fork tree.
      68             :   The underlying data structure is a pool of fd_bank_t structs.  Banks
      69             :   are then accessed via an index into the bank pool (bank index).
      70             : 
      71             :   NOTE: The reason fd_banks_t is keyed by bank index and not by slot is
      72             :   to handle block equivocation: if there are two different blocks for
      73             :   the same slot, we need to be able to differentiate and handle both
      74             :   blocks against different banks.  As mentioned above, the bank index is
      75             :   just an index into the bank pool.  The caller is responsible for
      76             :   establishing a mapping from the bank index (which is managed by
      77             :   fd_banks_t) and runtime state (e.g. slot number).
      78             : 
      79             :   The fields in fd_bank_t can be categorized into two groups:
      80             :   1. Simple fields: these are fields which don't need any special
      81             :      handling and are laid out contiguously in the fd_bank_t struct
      82             :      at bank->f.<field>.
      83             :   2. Complex fields: these are fields which need special handling
      84             :      (e.g. locking, copy on write semantics, delta-based semantics).
      85             :      These types are not templatized and are manually defined below.
      86             : 
      87             :   Each field that is CoW has its own memory pool. The memory
      88             :   corresponding to the field is not located in the fd_bank_t struct and
      89             :   is instead represented by a pool/fork index. When the field is
      90             :   modified, a new element of the pool is acquired and the data is
      91             :   copied over from the parent.
      92             : 
      93             :   Currently, there is a delta-based field, fd_stake_delegations_t.
      94             :   Each bank stores a delta-based representation in the form of an
      95             :   aligned uchar buffer.  The full state is stored in fd_banks_t in
      96             :   out-of-line memory sized using max_stake_accounts, and fd_banks_t
      97             :   also reserves another out-of-line buffer which can store the full
      98             :   state of the stake delegations for frontier queries.
      99             : 
     100             :   The cost tracker is allocated from a pool.  The lifetime of a cost
     101             :   tracker element starts when the bank is linked to a parent with a
     102             :   call to fd_banks_clone_from_parent() which makes the bank replayable.
     103             :   The lifetime of a cost tracker element ends when the bank is marked
     104             :   dead or when the bank is frozen.
     105             : 
     106             :   The lthash is a simple field that is laid out contiguously in the
     107             :   fd_bank_t struct, but is not templatized and it has its own lock.
     108             : 
     109             :   So, when a bank is cloned from a parent, the non CoW fields are copied
     110             :   over and the CoW fields just copy over a pool index. The CoW behavior
     111             :   is completely abstracted away from the caller as callers have to
     112             :   query/modify fields using specific APIs.
     113             : 
     114             :   The memory for the banks is based off of two bounds:
     115             :   1. the max number of unrooted blocks at any given time. Most fields
     116             :      can be bounded by this value.
     117             :   2. the max number of forks that execute through any 1 block.  We bound
     118             :      fields that are only written to at the epoch boundary by
     119             :      the max fork width that can execute through the boundary instead of
     120             :      by the max number of banks.  See fd_banks_footprint() for more
     121             :      details.
     122             : 
     123             :   There are also some important states that a bank can be in:
     124             :   - Initialized: This bank has been created and linked to a parent bank
     125             :     index with a call to fd_banks_new_bank().  However, it is not yet
     126             :     replayable.
     127             :   - Replayable: This bank has inherited state from its parent and now
     128             :     transactions can be executed against it.  For a bank to become
     129             :     replayable, it must've been initialized beforehand.
     130             :   - Dead: This bank has been marked as dead.  This means that the block
     131             :     that this bank is associated with is invalid.  A bank can be marked
     132             :     dead before, during, or after it has finished replaying (i.e. the
     133             :     bank being marked dead just needs to be initialized).  A bank
     134             :     can still be executing transactions while it is marked dead, but it
     135             :     shouldn't be dispatched any more work.  In other words, a key
     136             :     invariant is that a bank's reference count should NEVER be increased
     137             :     after it has been marked dead.
     138             :   - Frozen: This bank has been marked as frozen and no other tasks
     139             :     should be dispatched to it.  Any bank-specific resources will be
     140             :     released (e.g. cost tracker element).  A bank can be marked frozen
     141             :     if the bank has finished executing all of its transactions or if the
     142             :     bank is marked as dead and has no outstanding references.  A bank
     143             :     can only be copied from a parent bank (fd_banks_clone_from_parent)
     144             :     if the parent bank has been frozen.  The program will crash if this
     145             :     invariant is violated.
     146             : 
     147             :   The usage pattern is as follows:
     148             : 
     149             :    To create an initial bank:
     150             :    fd_bank_t * bank_init = fd_banks_init_bank( banks );
     151             : 
     152             :    To create a new bank.  This simply provisions the memory for the bank
     153             :    but it should not be used to execute transactions against.
     154             :    ulong bank_index = fd_banks_new_bank( banks, parent_bank_index )->idx;
     155             : 
     156             :    To clone bank from parent banks.  This makes a bank replayable by
     157             :    copying over the state from the parent bank into the child.  It
     158             :    assumes that the bank index has been previously provisioned by a call
     159             :    to fd_banks_new_bank and that the parent bank index has been frozen.
     160             :    fd_bank_t * bank_clone = fd_banks_clone_from_parent( banks, bank_index );
     161             : 
     162             :    To ensure that the bank index we want to advance our root to is safe
     163             :    and that there are no outstanding references to the banks that are
     164             :    not descendants of the target bank.
     165             :    fd_banks_advance_root_prepare( banks, target_bank_idx, &advanceable_bank_idx_out );
     166             : 
     167             :    To advance the root bank.  This assumes that the bank index is "safe"
     168             :    to advance to.  This means that none of the ancestors of the bank
     169             :    index have a non-zero reference count.
     170             :    fd_banks_advance_root( banks, bank_index );
     171             : 
     172             :    To query some arbitrary bank:
     173             :    fd_bank_t * bank_query = fd_banks_bank_query( banks, bank_index );
     174             : 
     175             :   To access the fields in the bank if they are templatized:
     176             : 
     177             :   fd_struct_t const * field = fd_bank_field_query( bank );
     178             :   OR
     179             :   fd_struct field = fd_bank_field_get( bank );
     180             : 
     181             :   fd_struct_t * field = fd_bank_field_modify( bank );
     182             :   OR
     183             :   fd_bank_field_set( bank, value );
     184             : 
     185             :   If a bank is marked dead, the caller should call
     186             :   fd_banks_mark_bank_dead() to mark the bank and all of its descendants
     187             :   as dead.  This does not actually free the underlying resources that
     188             :   the dead bank has allocated and instead just queues them up for
     189             :   pruning:
     190             :   fd_banks_mark_bank_dead( banks, dead_bank_idx );
     191             : 
     192             :   To actually prune away any dead banks, the caller should call:
     193             :   fd_banks_prune_one_dead_bank( banks, cancel_info )
     194             : 
     195             :   The data used by an fd_bank_t or an fd_banks_t is stored in an
     196             :   fd_banks_t struct.
     197             : 
     198             :   If the fields are not templatized, their accessor and modifier
     199             :   patterns vary and are documented below.
     200             : */
     201             : 
     202             : struct fd_bank_cost_tracker {
     203             :   ulong next;
     204             :   uchar data[FD_COST_TRACKER_FOOTPRINT] __attribute__((aligned(FD_COST_TRACKER_ALIGN)));
     205             : };
     206             : typedef struct fd_bank_cost_tracker fd_bank_cost_tracker_t;
     207             : 
     208             : #define POOL_NAME fd_bank_cost_tracker_pool
     209         999 : #define POOL_T    fd_bank_cost_tracker_t
     210             : #include "../../util/tmpl/fd_pool.c"
     211             : 
     212             : /* The banks follow a state machine that generally transitions forward:
     213             :    All banks start off as INACTIVE.  Once a bank is provisioned (when
     214             :    the first FEC is received from the reassembler), it is in the state
     215             :    INIT; at this point, the bank is not yet replayable but the memory
     216             :    has been reserved.  At this point, it is part of the bank tree and
     217             :    additional children bank can be assigned to the bank.  Once the bank
     218             :    is replayable, it is moved from INIT to REPLAYABLE and any relevant
     219             :    state is copied over from the parent bank.  We know that the parent
     220             :    bank is done executing at this point.  Transactions can now be
     221             :    dispatched and scheduled against the bank.  If the block for the bank
     222             :    is done executing then it transitions to the state FROZEN and the
     223             :    fields in the bank should no longer change.
     224             : 
     225             :    A bank can be marked DEAD even before it enters the replayable or
     226             :    frozen state.  A dead bank can only transition to INACTIVE.
     227             : 
     228             :        INACTIVE -> INIT -> REPLAYABLE -> FROZEN -> INACTIVE
     229             :                         \            \
     230             :                          v            v
     231             :                         DEAD    ->   DEAD -> INACTIVE */
     232             : 
     233        4365 : #define FD_BANK_STATE_INACTIVE   (0UL)
     234         444 : #define FD_BANK_STATE_INIT       (1UL)
     235         423 : #define FD_BANK_STATE_REPLAYABLE (2UL)
     236         708 : #define FD_BANK_STATE_FROZEN     (3UL)
     237          72 : #define FD_BANK_STATE_DEAD       (4UL)
     238             : 
     239             : /* As mentioned above, the overall layout of the bank struct:
     240             :    - Fields used for internal pool/bank management
     241             :    - Non-Cow fields
     242             :    - CoW fields
     243             :    - Locks for CoW fields
     244             : 
     245             :    The CoW fields are laid out contiguously in the bank struct.
     246             :    The locks for the CoW fields are laid out contiguously after the
     247             :    CoW fields.
     248             : 
     249             :    (r) Field is owned by the replay tile, and should be updated only by
     250             :        the replay tile.
     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 state;       /* keeps track of the state of the bank */
     262             :   ulong bank_seq;    /* app-wide bank sequence number */
     263             : 
     264             :   ulong refcnt; /* reference count on the bank, see replay for more details */
     265             : 
     266             :   fd_txncache_fork_id_t txncache_fork_id; /* fork id used by the txn cache */
     267             :   ushort                vote_stakes_fork_id; /* fork id used by the vote stakes */
     268             :   uchar                 stake_rewards_fork_id; /* fork id used by stake rewards */
     269             :   ushort                stake_delegations_fork_id; /* fork id used by stake delegations deltas */
     270             :   ulong                 cost_tracker_pool_idx;
     271             :   ulong                 epoch_leaders_idx; /* always 0 or 1 based on % epoch */
     272             : 
     273             :   ulong banks_data_offset; /* offset from this fd_bank_t back to fd_banks_t */
     274             : 
     275             :   /* Timestamps written and read only by replay */
     276             : 
     277             :   long first_fec_set_received_nanos;
     278             :   long preparation_begin_nanos;
     279             :   long first_transaction_scheduled_nanos;
     280             :   long last_transaction_finished_nanos;
     281             :   long block_completed_nanos;
     282             : 
     283             :   /* This field should only be accessed by the replay and executor
     284             :      tiles. */
     285             :   fd_rwlock_t lthash_lock;
     286             : 
     287             :   struct {
     288             :     fd_lthash_value_t      lthash;
     289             :     fd_blockhashes_t       block_hash_queue;
     290             :     fd_fee_rate_governor_t fee_rate_governor;
     291             :     ulong                  rbh_lamports_per_sig;
     292             :     ulong                  slot;
     293             :     ulong                  parent_slot;
     294             :     ulong                  capitalization;
     295             :     ulong                  transaction_count;
     296             :     ulong                  parent_signature_cnt;
     297             :     ulong                  tick_height;
     298             :     ulong                  max_tick_height;
     299             :     ulong                  hashes_per_tick;
     300             :     fd_w_u128_t            ns_per_slot;
     301             :     ulong                  ticks_per_slot;
     302             :     ulong                  genesis_creation_time;
     303             :     double                 slots_per_year;
     304             :     fd_inflation_t         inflation;
     305             :     ulong                  cluster_type;
     306             :     ulong                  total_epoch_stake;
     307             :     ulong                  total_activating_stake;
     308             :     ulong                  total_deactivating_stake;
     309             :     ulong                  warmup_cooldown_rate_epoch; /* epoch when reduce_stake_warmup_cooldown */
     310             :     ulong                  block_height;
     311             :     ulong                  execution_fees;
     312             :     ulong                  priority_fees;
     313             :     ulong                  tips;
     314             :     ulong                  signature_count;
     315             :     fd_hash_t              poh;
     316             :     ulong                  last_restart_slot;
     317             :     fd_hash_t              bank_hash;
     318             :     fd_hash_t              prev_bank_hash;
     319             :     fd_hash_t              genesis_hash;
     320             :     fd_epoch_schedule_t    epoch_schedule;
     321             :     fd_rent_t              rent;
     322             :     fd_sysvar_cache_t      sysvar_cache;
     323             :     fd_features_t          features;
     324             :     ulong                  txn_count;
     325             :     ulong                  nonvote_txn_count;
     326             :     ulong                  failed_txn_count;
     327             :     ulong                  nonvote_failed_txn_count;
     328             :     ulong                  total_compute_units_used;
     329             :     ulong                  slots_per_epoch;
     330             :     ulong                  shred_cnt;
     331             :     ulong                  epoch;
     332             :     ulong                  identity_vote_idx;
     333             :   } f;
     334             : 
     335             :   uchar top_votes_t_1_mem[FD_TOP_VOTES_MAX_FOOTPRINT] __attribute__((aligned(FD_TOP_VOTES_ALIGN)));
     336             :   uchar top_votes_t_2_mem[FD_TOP_VOTES_MAX_FOOTPRINT] __attribute__((aligned(FD_TOP_VOTES_ALIGN)));
     337             : };
     338             : typedef struct fd_bank fd_bank_t;
     339             : 
     340             : struct fd_banks_prune_cancel_info {
     341             :   fd_txncache_fork_id_t txncache_fork_id;
     342             :   ulong                 slot;
     343             :   ulong                 bank_idx;
     344             : };
     345             : typedef struct fd_banks_prune_cancel_info fd_banks_prune_cancel_info_t;
     346             : 
     347             : fd_vote_stakes_t *
     348             : fd_bank_vote_stakes( fd_bank_t const * bank );
     349             : 
     350             : fd_stake_delegations_t *
     351             : fd_bank_stake_delegations_modify( fd_bank_t * bank );
     352             : 
     353             : /* fd_banks_t is the main struct used to manage the bank state.  It can
     354             :    be used to query/modify/clone/publish the bank state.
     355             : 
     356             :    fd_banks_t contains some metadata to a pool to manage the banks.
     357             :    It also contains pointers to the CoW pools.
     358             : 
     359             :    The data is laid out contiguously in memory starting from fd_banks_t;
     360             :    this can be seen in fd_banks_footprint(). */
     361             : 
     362             : #define POOL_NAME fd_banks_pool
     363         999 : #define POOL_T    fd_bank_t
     364             : #include "../../util/tmpl/fd_pool.c"
     365             : 
     366             : struct fd_bank_idx_seq {
     367             :   ulong idx;
     368             :   ulong seq;
     369             : };
     370             : typedef struct fd_bank_idx_seq fd_bank_idx_seq_t;
     371             : 
     372             : #define DEQUE_NAME fd_banks_dead
     373          27 : #define DEQUE_T    fd_bank_idx_seq_t
     374          87 : #define DEQUE_MAX  FD_BANKS_MAX_BANKS
     375             : #include "../../util/tmpl/fd_deque.c"
     376             : 
     377             : struct fd_banks {
     378             :   ulong magic;              /* ==FD_BANKS_MAGIC */
     379             :   ulong max_total_banks;    /* Maximum number of banks */
     380             :   ulong max_fork_width;     /* Maximum fork width executing through any given slot. */
     381             :   ulong max_stake_accounts; /* Maximum number of stake accounts */
     382             :   ulong max_vote_accounts;  /* Maximum number of vote accounts */
     383             :   ulong root_idx;           /* root idx */
     384             :   ulong bank_seq;           /* app-wide bank sequence number */
     385             : 
     386             :   ulong pool_offset;        /* offset of pool from banks */
     387             : 
     388             :   ulong cost_tracker_pool_offset; /* offset of cost tracker pool from banks */
     389             : 
     390             :   ulong vote_stakes_pool_offset;
     391             : 
     392             :   ulong stake_rewards_offset;
     393             : 
     394             :   ulong dead_banks_deque_offset;
     395             : 
     396             :   ulong epoch_credits_offset;
     397             :   ulong epoch_credits_len;
     398             : 
     399             :   ulong snapshot_commission_t_3_offset;
     400             :   ulong snapshot_commission_t_3_len;
     401             : 
     402             :   /* The set of epoch leaders for the current and previous epochs is
     403             :      allocated out-of-line and tracked by epoch_leaders_offset.  Only
     404             :      two need to be stored because in the worst case we will have a root
     405             :      that sits behind an epoch boundary, with leaf banks executing into
     406             :      the next epoch.  All banks that execute behind the boundary, will
     407             :      use the previous epoch's leader schedule, and all nodes after the
     408             :      epoch boundary are guaranteed to produce identical leader
     409             :      schedules. */
     410             : 
     411             :   ulong epoch_leaders_offset;
     412             :   ulong epoch_leaders_footprint;
     413             : 
     414             :   ulong stake_delegations_offset;
     415             : };
     416             : typedef struct fd_banks fd_banks_t;
     417             : 
     418             : /* Bank accesssors and mutators.  Different accessors are emitted for
     419             :    different types depending on if the field has a lock or not. */
     420             : 
     421             : fd_epoch_credits_t *
     422             : fd_bank_epoch_credits( fd_bank_t * bank );
     423             : 
     424             : ulong *
     425             : fd_bank_epoch_credits_len( fd_bank_t * bank );
     426             : 
     427             : fd_stashed_commission_t *
     428             : fd_bank_snapshot_commission_t_3( fd_bank_t * bank );
     429             : 
     430             : ulong *
     431             : fd_bank_snapshot_commission_t_3_len( fd_bank_t * bank );
     432             : 
     433             : fd_stake_rewards_t const *
     434             : fd_bank_stake_rewards_query( fd_bank_t * bank );
     435             : 
     436             : fd_stake_rewards_t *
     437             : fd_bank_stake_rewards_modify( fd_bank_t * bank );
     438             : 
     439             : fd_epoch_leaders_t const *
     440             : fd_bank_epoch_leaders_query( fd_bank_t const * bank );
     441             : 
     442             : fd_epoch_leaders_t *
     443             : fd_bank_epoch_leaders_modify( fd_bank_t * bank );
     444             : 
     445             : fd_top_votes_t const *
     446             : fd_bank_top_votes_t_1_query( fd_bank_t const * bank );
     447             : 
     448             : fd_top_votes_t *
     449             : fd_bank_top_votes_t_1_modify( fd_bank_t * bank );
     450             : 
     451             : fd_top_votes_t const *
     452             : fd_bank_top_votes_t_2_query( fd_bank_t const * bank );
     453             : 
     454             : fd_top_votes_t *
     455             : fd_bank_top_votes_t_2_modify( fd_bank_t * bank );
     456             : 
     457             : fd_cost_tracker_t *
     458             : fd_bank_cost_tracker_modify( fd_bank_t * bank );
     459             : 
     460             : fd_cost_tracker_t const *
     461             : fd_bank_cost_tracker_query( fd_bank_t * bank );
     462             : 
     463             : fd_lthash_value_t const *
     464             : fd_bank_lthash_locking_query( fd_bank_t * bank );
     465             : 
     466             : void
     467             : fd_bank_lthash_end_locking_query( fd_bank_t * bank );
     468             : 
     469             : fd_lthash_value_t *
     470             : fd_bank_lthash_locking_modify( fd_bank_t * bank );
     471             : 
     472             : void
     473             : fd_bank_lthash_end_locking_modify( fd_bank_t * bank );
     474             : 
     475             : /* fd_bank_stake_delegations_frontier_query() will return a pointer to
     476             :    the full stake delegations for the current frontier. The caller is
     477             :    responsible that there are no concurrent readers or writers to
     478             :    the stake delegations returned by this function.
     479             : 
     480             :    Under the hood, the function applies all of the stake delegation
     481             :    deltas from all banks starting from the root down to the current bank
     482             :    to the rooted version of the stake delegations.  This is done in a
     483             :    reversible way and is unwound with a call to
     484             :    fd_bank_stake_delegations_end_frontier_query(). */
     485             : 
     486             : fd_stake_delegations_t *
     487             : fd_bank_stake_delegations_frontier_query( fd_banks_t * banks,
     488             :                                           fd_bank_t *  bank );
     489             : 
     490             : /* fd_bank_stake_delegations_end_frontier_query() will finish the
     491             :    reversible operation started by
     492             :    fd_bank_stake_delegations_frontier_query().  It is unsafe to call
     493             :    fd_bank_stake_delegations_frontier_query multiple times without
     494             :    calling this function in between.
     495             : 
     496             :    Under the hood, it undoes any references to the stake delegation
     497             :    deltas that were applied. */
     498             : 
     499             : void
     500             : fd_bank_stake_delegations_end_frontier_query( fd_banks_t * banks,
     501             :                                               fd_bank_t *  bank );
     502             : 
     503             : /* fd_banks_stake_delegations_root_query() will return a pointer to the
     504             :    full stake delegations for the current root. This function should
     505             :    only be called on boot. */
     506             : 
     507             : fd_stake_delegations_t *
     508             : fd_banks_stake_delegations_root_query( fd_banks_t * banks );
     509             : 
     510             : /* fd_banks_pool_used_cnt returns the number of bank pool elements
     511             :    currently in use. */
     512             : 
     513             : ulong
     514             : fd_banks_pool_used_cnt( fd_banks_t * banks );
     515             : 
     516             : /* fd_banks_pool_max_cnt returns the max number of bank pool elements. */
     517             : 
     518             : ulong
     519             : fd_banks_pool_max_cnt( fd_banks_t * banks );
     520             : 
     521             : /* fd_banks_stake_delegations_evict_bank_fork evicts the stake
     522             :    delegations fork for the given bank.  This is used to clean up
     523             :    resources during teardown. */
     524             : 
     525             : void
     526             : fd_banks_stake_delegations_evict_bank_fork( fd_banks_t * banks,
     527             :                                             fd_bank_t *  bank );
     528             : 
     529             : /* fd_banks_root() returns a pointer to the root bank respectively. */
     530             : 
     531             : fd_bank_t *
     532             : fd_banks_root( fd_banks_t * banks );
     533             : 
     534             : /* fd_banks_align() returns the alignment of fd_banks_t */
     535             : 
     536             : ulong
     537             : fd_banks_align( void );
     538             : 
     539             : /* fd_banks_footprint() returns the footprint of fd_banks_t.  This
     540             :    includes the struct itself but also the footprint for all of the
     541             :    pools.
     542             : 
     543             :    The footprint of fd_banks_t is determined by the total number
     544             :    of banks that the bank manages.  This is an analog for the max number
     545             :    of unrooted blocks the bank can manage at any given time.
     546             : 
     547             :    We can also further bound the memory footprint of the banks by the
     548             :    max width of forks that can exist at any given time.  The reason for
     549             :    this is that there are several large CoW structs that are only
     550             :    written to during the epoch boundary (e.g. epoch_stakes, etc.).
     551             :    These structs are read-only afterwards.  This
     552             :    means if we also bound the max number of forks that can execute
     553             :    through the epoch boundary, we can bound the memory footprint of
     554             :    the banks. */
     555             : 
     556             : ulong
     557             : fd_banks_footprint( ulong max_total_banks,
     558             :                     ulong max_fork_width,
     559             :                     ulong max_stake_accounts,
     560             :                     ulong max_vote_accounts );
     561             : 
     562             : /* fd_banks_new() creates a new fd_banks_t struct.  This function
     563             :    lays out the memory for all of the constituent fd_bank_t structs
     564             :    and pools depending on the max_total_banks and the max_fork_width for
     565             :    a given block. */
     566             : 
     567             : void *
     568             : fd_banks_new( void * mem,
     569             :               ulong  max_total_banks,
     570             :               ulong  max_fork_width,
     571             :               ulong  max_stake_accounts,
     572             :               ulong  max_vote_accounts,
     573             :               int    larger_max_cost_per_block,
     574             :               ulong  seed );
     575             : 
     576             : /* fd_banks_join() joins an fd_banks_t struct.  It takes in a valid
     577             :    banks_data_mem.  Returns a pointer to the joined fd_banks_t struct
     578             :    on success and NULL on failure (logs details). */
     579             : 
     580             : fd_banks_t *
     581             : fd_banks_join( void * banks_data_mem );
     582             : 
     583             : /* fd_banks_init_bank() initializes a new bank in the bank manager.
     584             :    This should only be used during bootup.  The bank is set to the
     585             :    FROZEN state (skipping INIT/REPLAYABLE since no replay is needed for
     586             :    the initial root) and is established as the root bank. */
     587             : 
     588             : fd_bank_t *
     589             : fd_banks_init_bank( fd_banks_t * banks );
     590             : 
     591             : /* fd_banks_get_bank_idx returns a bank for a given bank index. */
     592             : 
     593             : fd_bank_t *
     594             : fd_banks_bank_query( fd_banks_t * banks,
     595             :                      ulong        bank_idx );
     596             : 
     597             : fd_bank_t *
     598             : fd_banks_get_parent( fd_banks_t * banks,
     599             :                      fd_bank_t *  bank );
     600             : 
     601             : /* fd_banks_clone_from_parent() clones a bank from a parent bank.
     602             :    This function links the child bank to its parent bank and copies
     603             :    over the data from the parent bank to the child.  This function
     604             :    assumes that the child and parent banks both have been allocated.
     605             :    The parent bank must be frozen and the child bank must be initialized
     606             :    but not yet used.  It also assumes that the parent bank is not dead.
     607             : 
     608             :    A more detailed note: not all of the data is copied over and this
     609             :    is a shallow clone.  All of the CoW fields are not copied over and
     610             :    will only be done so if the caller explicitly calls
     611             :    fd_bank_{*}_modify().  This naming was chosen to emulate the
     612             :    semantics of the Agave client. */
     613             : 
     614             : fd_bank_t *
     615             : fd_banks_clone_from_parent( fd_banks_t * banks,
     616             :                             ulong        bank_idx );
     617             : 
     618             : /* fd_banks_advance_root() advances the root bank to the bank manager.
     619             :    This should only be used when a bank is no longer needed and has no
     620             :    active refcnts.  This will prune off the bank from the bank manager.
     621             :    It returns the new root bank.  An invariant of this function is that
     622             :    the new root bank should be a child of the current root bank.
     623             : 
     624             :    All banks that are ancestors or siblings of the new root bank will be
     625             :    cancelled and their resources will be released back to the pool. */
     626             : 
     627             : void
     628             : fd_banks_advance_root( fd_banks_t * banks,
     629             :                        ulong        bank_idx );
     630             : 
     631             : /* fd_bank_clear_bank() clears the contents of a bank. This should ONLY
     632             :    be used with banks that have no children and should only be used in
     633             :    testing and fuzzing.
     634             : 
     635             :    This function will memset all non-CoW fields to 0.
     636             : 
     637             :    For all CoW fields, we will reset the indices to its parent. */
     638             : 
     639             : void
     640             : fd_banks_clear_bank( fd_banks_t * banks,
     641             :                      fd_bank_t *  bank,
     642             :                      ulong        max_vote_accounts );
     643             : 
     644             : /* fd_banks_clear releases all banks back to the pool and resets the
     645             :    banks manager to its post-new state.  Assumes no active references to
     646             :    any bank. */
     647             : 
     648             : void
     649             : fd_banks_clear( fd_banks_t * banks );
     650             : 
     651             : /* fd_banks_advance_root_prepare returns the highest block that can be
     652             :    safely advanced between the current root of the fork tree and the
     653             :    target block.  See the note on safe publishing for more details.  In
     654             :    general, a node in the fork tree can be pruned if:
     655             :    (1) the node itself can be pruned, and
     656             :    (2) all subtrees (except for the one on the rooted fork) forking off
     657             :        of the node can be pruned.
     658             : 
     659             :    This function is read-only: it does not modify any bank state.  It
     660             :    walks from the target bank up to the current root to find the direct
     661             :    child of root on the path, then checks whether all sibling subtrees
     662             :    of that child can be pruned.
     663             : 
     664             :    Highest advanceable block is written to the out pointer.  Returns 1
     665             :    if the advanceable block can be advanced beyond the current root.
     666             :    Returns 0 if no such block can be found (e.g. the root still has a
     667             :    non-zero refcnt, or a sibling subtree cannot be pruned).  We will
     668             :    ONLY advance our advanceable_bank_idx to a child of the current root.
     669             :    In order to advance to the target bank,
     670             :    fd_banks_advance_root_prepare() must be called repeatedly. */
     671             : 
     672             : int
     673             : fd_banks_advance_root_prepare( fd_banks_t * banks,
     674             :                                ulong        target_bank_idx,
     675             :                                ulong *      advanceable_bank_idx_out );
     676             : 
     677             : /* fd_banks_mark_bank_dead marks the current bank (and all of its
     678             :    descendants) as dead.  The caller is still responsible for handling
     679             :    the behavior of the dead bank correctly.  The function should not be
     680             :    called on a bank that is already dead nor on any ancestor of an
     681             :    already dead bank.  After a bank is marked dead, the caller should
     682             :    never increment the reference count on the bank. */
     683             : 
     684             : void
     685             : fd_banks_mark_bank_dead( fd_banks_t * banks,
     686             :                          ulong        bank_idx );
     687             : 
     688             : /* fd_banks_prune_one_dead_bank will try to prune one bank that was
     689             :    marked as dead.  It will not prune a dead bank that has a non-zero
     690             :    reference count.  Returns 0 if nothing was pruned, 1 if a bank was
     691             :    pruned but no accdb/txncache cancellation is needed, or 2 if a bank
     692             :    was pruned and cancellation is needed, in which case opt_cancel will
     693             :    be populated if non-NULL. */
     694             : 
     695             : int
     696             : fd_banks_prune_one_dead_bank( fd_banks_t *                   banks,
     697             :                               fd_banks_prune_cancel_info_t * cancel );
     698             : 
     699             : /* fd_banks_mark_bank_frozen marks the current bank as frozen.  This
     700             :    should be done when the bank is no longer being updated: it should be
     701             :    done at the end of a slot.  This also releases the memory for the
     702             :    cost tracker which only has to be persisted from the start of a slot
     703             :    to the end. */
     704             : 
     705             : void
     706             : fd_banks_mark_bank_frozen( fd_bank_t * bank );
     707             : 
     708             : /* fd_banks_new_bank reserves a bank index for a new bank.  New bank
     709             :    indices should always be available.  After this function is called,
     710             :    the bank will be linked to its parent bank, but not yet replayable.
     711             :    After a call to fd_banks_clone_from_parent, the bank will be
     712             :    replayable.  This assumes that there is a parent bank which exists
     713             :    and that there are available bank indices in the bank pool.  It also
     714             :    assumes that the parent bank is not dead or inactive. */
     715             : 
     716             : fd_bank_t *
     717             : fd_banks_new_bank( fd_banks_t * banks,
     718             :                    ulong        parent_bank_idx,
     719             :                    long         now );
     720             : 
     721             : 
     722             : /* fd_banks_get_frontier returns the frontier set of bank indices in the
     723             :    banks tree.  The frontier is defined as any bank which has no
     724             :    no children and is initialized or replayable but not dead or frozen.
     725             :    The caller is expected to have enough memory to store the bank
     726             :    indices for the frontier.  The bank indices are written to
     727             :    frontier_indices_out in no particular order.  The number of banks in
     728             :    the frontier is written to the frontier_cnt_out pointer. */
     729             : 
     730             : void
     731             : fd_banks_get_frontier( fd_banks_t * banks,
     732             :                        ulong *      frontier_indices_out,
     733             :                        ulong *      frontier_cnt_out );
     734             : 
     735             : /* fd_banks_is_full returns 1 if the banks are full, 0 otherwise.  Banks
     736             :    can be full in two cases:
     737             :    1. All banks in the bank pool have been allocated.
     738             :    2. All cost tracker pool elements have been allocated.  This happens
     739             :       from wide forking across blocks. */
     740             : 
     741             : int
     742             : fd_banks_is_full( fd_banks_t * banks );
     743             : 
     744             : FD_PROTOTYPES_END
     745             : 
     746             : #endif /* HEADER_fd_src_flamenco_runtime_fd_bank_h */

Generated by: LCOV version 1.14