LCOV - code coverage report
Current view: top level - flamenco/runtime/sysvar - fd_sysvar_cache.h (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 9 9 100.0 %
Date: 2024-11-13 11:58:15 Functions: 0 0 -

          Line data    Source code
       1             : #ifndef HEADER_fd_src_flamenco_runtime_sysvar_fd_sysvar_cache_h
       2             : #define HEADER_fd_src_flamenco_runtime_sysvar_fd_sysvar_cache_h
       3             : 
       4             : /* fd_sysvar_cache reproduces the behavior of
       5             :    solana_program_runtime::sysvar_cache::SysvarCache.
       6             : 
       7             :    Firedancer provides this sysvar cache to be compatible with the Agave
       8             :    validator.  Otherwise, it serves no purpose other than to make the
       9             :    runtime more complicated.  The sysvar cache keeps a copy of various
      10             :    sysvar accounts.  It is part of the implicit state of the runtime.
      11             : 
      12             :    Note that not all sysvars are in this cache.
      13             : 
      14             :    ### Cache state
      15             : 
      16             :    The sysvar cache is not a pure cache.  For every supported sysvar, it
      17             :    may store NULL or a parsed version of the sysvar account.  It is
      18             :    populated from the accounts DB.  After parsing, the contents of the
      19             :    cache are not identical to the original account content anymore.  If
      20             :    a sysvar account fails to parse, the corresponding cache entry will
      21             :    be NULL.
      22             : 
      23             :    ### Write back
      24             : 
      25             :    The sysvar cache can be modified directly by native programs.  There
      26             :    is no standard pattern to how these changes get written back to the
      27             :    accounts DB.  Currently, the write back happens at arbitrary stages
      28             :    in the slot boundary logic and is different for every sysvar.
      29             : 
      30             :    ### Memory Management
      31             : 
      32             :    fd_sysvar_cache_t is contained by a continuous memory region and
      33             :    embeds a heap allocator. */
      34             : 
      35             : #include "../fd_acc_mgr.h"
      36             : 
      37             : /* Reuse this table to avoid code duplication */
      38             : #define FD_SYSVAR_CACHE_ITER(X) \
      39      228942 :   X( fd_sol_sysvar_clock,             clock               ) \
      40      228942 :   X( fd_epoch_schedule,               epoch_schedule      ) \
      41      228942 :   X( fd_sysvar_epoch_rewards,         epoch_rewards       ) \
      42      228942 :   X( fd_sysvar_fees,                  fees                ) \
      43      228942 :   X( fd_rent,                         rent                ) \
      44      228942 :   X( fd_slot_hashes,                  slot_hashes         ) \
      45      228942 :   X( fd_recent_block_hashes,          recent_block_hashes ) \
      46      228942 :   X( fd_stake_history,                stake_history       ) \
      47      228942 :   X( fd_sol_sysvar_last_restart_slot, last_restart_slot   )
      48             : 
      49             : /* The memory of fd_sysvar_cache_t fits as much sysvar information into
      50             :    the struct as possible.  Unfortunately some parts of the sysvar
      51             :    spill out onto the heap due to how the type generator works.
      52             : 
      53             :    The has_{...} bits specify whether a sysvar logically exists.
      54             :    The val_{...} structs contain the top-level struct of each sysvar.
      55             :    If has_{...}==0 then any heap pointers in val_{...} are NULL,
      56             :    allowing for safe idempotent calls to fd_sol_sysvar_{...}_destroy() */
      57             : 
      58             : struct __attribute__((aligned(16UL))) fd_sysvar_cache_private {
      59             :   ulong       magic;  /* ==FD_SYSVAR_CACHE_MAGIC */
      60             :   fd_valloc_t valloc;
      61             : 
      62             :   /* Declare the val_{...} values */
      63             : # define X( type, name ) \
      64             :   type##_t val_##name[1];
      65             :   FD_SYSVAR_CACHE_ITER(X)
      66             : # undef X
      67             : 
      68             :   /* Declare the has_{...} bits */
      69             : # define X( _type, name ) \
      70             :   ulong has_##name : 1;
      71             :   FD_SYSVAR_CACHE_ITER(X)
      72             : # undef X
      73             : };
      74             : 
      75             : struct fd_sysvar_cache_private;
      76             : typedef struct fd_sysvar_cache_private fd_sysvar_cache_t;
      77             : 
      78             : FD_PROTOTYPES_BEGIN
      79             : 
      80             : /* fd_sysvar_cache_{align,footprint} return the memory region params of
      81             :    an fd_sysvar_cache_t. */
      82             : 
      83             : ulong
      84             : fd_sysvar_cache_align( void );
      85             : 
      86             : ulong
      87             : fd_sysvar_cache_footprint( void );
      88             : 
      89             : /* fd_sysvar_cache_new creates a new sysvar cache object.  mem is the
      90             :    memory region that will back the fd_sysvar_cache_t.  Attaches to the
      91             :    given valloc for use as a heap allocator for sysvar data.  Returns
      92             :    object (in mem) on success and NULL on failure.  Logs reasons for
      93             :    failure. */
      94             : 
      95             : fd_sysvar_cache_t *
      96             : fd_sysvar_cache_new( void *      mem,
      97             :                      fd_valloc_t valloc );
      98             : 
      99             : /* fd_sysvar_cache_delete destroys a given sysvar cache object and any
     100             :    heap allocations made.  Detaches from the valloc provided in
     101             :    fd_sysvar_cache_new.  Returns the memory region that previously
     102             :    backed cache back to the caller. */
     103             : 
     104             : void *
     105             : fd_sysvar_cache_delete( fd_sysvar_cache_t * cache );
     106             : 
     107             : /* fd_sysvar_cache_restore restores all sysvars from the given slot
     108             :    context.
     109             : 
     110             :    Roughly compatible with Agave's
     111             :    solana_program_runtime::sysvar_cache::SysvarCache::fill_missing_entries
     112             :    https://github.com/solana-labs/solana/blob/v1.17.23/program-runtime/src/sysvar_cache.rs#L137-L208 */
     113             : 
     114             : void
     115             : fd_sysvar_cache_restore( fd_sysvar_cache_t * cache,
     116             :                          fd_acc_mgr_t *      acc_mgr,
     117             :                          fd_funk_txn_t *     funk_txn );
     118             : 
     119             : /* fd_sysvar_cache_restore_{name} restores only the given sysvar object from the given slot context */
     120             : 
     121             : # define X( type, name )                                               \
     122             : void                                                                   \
     123             : fd_sysvar_cache_restore_##name( fd_sysvar_cache_t * cache,             \
     124             :                          fd_acc_mgr_t *      acc_mgr,                  \
     125             :                          fd_funk_txn_t *     funk_txn ); 
     126             :   FD_SYSVAR_CACHE_ITER(X)
     127             : # undef X
     128             : 
     129             : /* Accessors for sysvars.  May return NULL. */
     130             : 
     131             : FD_FN_PURE fd_sol_sysvar_clock_t             const * fd_sysvar_cache_clock              ( fd_sysvar_cache_t const * cache );
     132             : FD_FN_PURE fd_epoch_schedule_t               const * fd_sysvar_cache_epoch_schedule     ( fd_sysvar_cache_t const * cache );
     133             : FD_FN_PURE fd_sysvar_epoch_rewards_t         const * fd_sysvar_cache_epoch_rewards      ( fd_sysvar_cache_t const * cache );
     134             : FD_FN_PURE fd_sysvar_fees_t                  const * fd_sysvar_cache_fees               ( fd_sysvar_cache_t const * cache );
     135             : FD_FN_PURE fd_rent_t                         const * fd_sysvar_cache_rent               ( fd_sysvar_cache_t const * cache );
     136             : FD_FN_PURE fd_slot_hashes_t                  const * fd_sysvar_cache_slot_hashes        ( fd_sysvar_cache_t const * cache );
     137             : FD_FN_PURE fd_recent_block_hashes_t          const * fd_sysvar_cache_recent_block_hashes( fd_sysvar_cache_t const * cache );
     138             : FD_FN_PURE fd_stake_history_t                const * fd_sysvar_cache_stake_history      ( fd_sysvar_cache_t const * cache );
     139             : FD_FN_PURE fd_sol_sysvar_last_restart_slot_t const * fd_sysvar_cache_last_restart_slot  ( fd_sysvar_cache_t const * cache );
     140             : 
     141             : /* fd_sysvar_from_instr_acct_{...} pretends to read a sysvar from an
     142             :    instruction account.  Checks that a given instruction account has
     143             :    an address matching the sysvar.  Returns the sysvar from the sysvar
     144             :    cache.  On return, *err is in FD_EXECUTOR_INSTR_{SUCCESS,ERR_{...}}.
     145             : 
     146             :    Matches Agave's
     147             :    solana_program_runtime::sysvar_cache::get_sysvar_with_account_check
     148             :    https://github.com/solana-labs/solana/blob/v1.18.8/program-runtime/src/sysvar_cache.rs#L215-L314
     149             : 
     150             :    Equivalent to:
     151             : 
     152             :      fd_sysvar_FOO_t const *
     153             :      fd_sysvar_from_instr_acct_FOO( fd_exec_instr_ctx_t const * ctx,
     154             :                                     ulong                       acct_idx ) {
     155             :        if( FD_UNLIKELY( idx >= ctx->instr->acct_cnt ) ) {
     156             :           *err = FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
     157             :           return NULL;
     158             :        }
     159             :        if( ctx->instr->acct_pubkeys[ acct_idx ] != FOO_addr ) {
     160             :          *err = FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
     161             :          return NULL;
     162             :        }
     163             :        FOO_t const * value = fd_sysvar_cache_FOO( ctx->slot_ctx->sysvar_cache );
     164             :        *err = value ? 0 : FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;
     165             :        return value;
     166             :      } */
     167             : 
     168             : fd_sol_sysvar_clock_t             const * fd_sysvar_from_instr_acct_clock              ( fd_exec_instr_ctx_t const * ctx, ulong acct_idx, int * err );
     169             : fd_epoch_schedule_t               const * fd_sysvar_from_instr_acct_epoch_schedule     ( fd_exec_instr_ctx_t const * ctx, ulong acct_idx, int * err );
     170             : fd_sysvar_epoch_rewards_t         const * fd_sysvar_from_instr_acct_epoch_rewards      ( fd_exec_instr_ctx_t const * ctx, ulong acct_idx, int * err );
     171             : fd_sysvar_fees_t                  const * fd_sysvar_from_instr_acct_fees               ( fd_exec_instr_ctx_t const * ctx, ulong acct_idx, int * err );
     172             : fd_rent_t                         const * fd_sysvar_from_instr_acct_rent               ( fd_exec_instr_ctx_t const * ctx, ulong acct_idx, int * err );
     173             : fd_slot_hashes_t                  const * fd_sysvar_from_instr_acct_slot_hashes        ( fd_exec_instr_ctx_t const * ctx, ulong acct_idx, int * err );
     174             : fd_recent_block_hashes_t          const * fd_sysvar_from_instr_acct_recent_block_hashes( fd_exec_instr_ctx_t const * ctx, ulong acct_idx, int * err );
     175             : fd_stake_history_t                const * fd_sysvar_from_instr_acct_stake_history      ( fd_exec_instr_ctx_t const * ctx, ulong acct_idx, int * err );
     176             : fd_sol_sysvar_last_restart_slot_t const * fd_sysvar_from_instr_acct_last_restart_slot  ( fd_exec_instr_ctx_t const * ctx, ulong acct_idx, int * err );
     177             : 
     178             : /* fd_check_sysvar_account does a check on if an instruction account index
     179             :    matches the expected pubkey of a specific sysvar. */
     180             :    
     181             : int
     182             : fd_check_sysvar_account( fd_exec_instr_ctx_t const * ctx,
     183             :                          ulong                       insn_acc_idx,
     184             :                          fd_pubkey_t const *         expected_id );
     185             : 
     186             : FD_PROTOTYPES_END
     187             : 
     188             : #endif /* HEADER_fd_src_flamenco_runtime_sysvar_fd_sysvar_cache_h */

Generated by: LCOV version 1.14