LCOV - code coverage report
Current view: top level - flamenco/runtime/sysvar - fd_sysvar_cache.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 0 152 0.0 %
Date: 2025-06-04 05:03:10 Functions: 0 37 0.0 %

          Line data    Source code
       1             : #include "fd_sysvar_cache.h"
       2             : #include "../fd_acc_mgr.h"
       3             : #include "../fd_executor.h"
       4             : #include "../fd_system_ids.h"
       5             : #include "../context/fd_exec_instr_ctx.h"
       6             : #include "../context/fd_exec_txn_ctx.h"
       7             : 
       8           0 : #define FD_SYSVAR_CACHE_MAGIC (0x195a0e78828cacd5UL)
       9             : 
      10             : ulong
      11           0 : fd_sysvar_cache_align( void ) {
      12           0 :   return alignof(fd_sysvar_cache_t);
      13           0 : }
      14             : 
      15             : ulong
      16           0 : fd_sysvar_cache_footprint( void ) {
      17           0 :   return sizeof(fd_sysvar_cache_t);
      18           0 : }
      19             : 
      20             : fd_sysvar_cache_t *
      21           0 : fd_sysvar_cache_new( void * mem ) {
      22             : 
      23           0 :   if( FD_UNLIKELY( !mem ) ) {
      24           0 :     FD_LOG_WARNING(( "NULL mem" ));
      25           0 :     return NULL;
      26           0 :   }
      27             : 
      28           0 :   fd_sysvar_cache_t * cache = (fd_sysvar_cache_t *)mem;
      29           0 :   fd_memset( cache, 0, sizeof(fd_sysvar_cache_t) );
      30             : 
      31           0 :   FD_COMPILER_MFENCE();
      32           0 :   cache->magic = FD_SYSVAR_CACHE_MAGIC;
      33           0 :   FD_COMPILER_MFENCE();
      34           0 :   return cache;
      35           0 : }
      36             : 
      37             : void *
      38           0 : fd_sysvar_cache_delete( fd_sysvar_cache_t * cache ) {
      39             : 
      40           0 :   if( FD_UNLIKELY( !cache ) ) {
      41           0 :     FD_LOG_WARNING(( "NULL cache" ));
      42           0 :     return NULL;
      43           0 :   }
      44             : 
      45           0 :   if( FD_UNLIKELY( cache->magic != FD_SYSVAR_CACHE_MAGIC ) ) {
      46           0 :     FD_LOG_WARNING(( "bad magic" ));
      47           0 :     return NULL;
      48           0 :   }
      49             : 
      50           0 :   FD_COMPILER_MFENCE();
      51           0 :   cache->magic = 0UL;
      52           0 :   FD_COMPILER_MFENCE();
      53             : 
      54             :   /* Call destroy on all objects.
      55             :      This is safe even if these objects logically don't exist
      56             :      (destroy is safe on zero-initialized values and is idempotent) */
      57           0 : # define X( type, name, is_global ) \
      58             :   //type##_destroy( cache->val_##name );
      59           0 :   FD_SYSVAR_CACHE_ITER(X)
      60           0 : # undef X
      61             : 
      62           0 :   return (void *)cache;
      63           0 : }
      64             : 
      65             : #define HANDLE_GLOBAL_1(type, name, is_global)                                   \
      66             : type##_global_t *                                                                \
      67           0 : fd_sysvar_cache_##name( fd_sysvar_cache_t const * cache, fd_wksp_t * wksp ) {    \
      68           0 :   if( !cache->has_##name ) { return NULL; }                                      \
      69           0 :   type##_global_t * val = fd_wksp_laddr_fast( wksp, cache->gaddr_##name );       \
      70           0 :   return val;                                                                    \
      71           0 : }
      72             : 
      73             : #define HANDLE_GLOBAL_0(type, name, is_global)                                   \
      74             : type##_t *                                                                       \
      75           0 : fd_sysvar_cache_##name( fd_sysvar_cache_t const * cache, fd_wksp_t * wksp ) {    \
      76           0 :   if( !cache->has_##name ) { return NULL; }                                      \
      77           0 :   type##_t * val = fd_wksp_laddr_fast( wksp, cache->gaddr_##name );              \
      78           0 :   return val;                                                                    \
      79           0 : }
      80             : 
      81             : /* Provide accessor methods */
      82             : #define X(type, name, global) \
      83             :   HANDLE_GLOBAL_##global(type, name, global)
      84             : 
      85             : FD_SYSVAR_CACHE_ITER(X)
      86             : #undef X
      87             : #undef HANDLE_GLOBAL_1
      88             : #undef HANDLE_GLOBAL_0
      89             : 
      90             : /* Restore sysvars */
      91             : 
      92           0 : #define HANDLE_GLOBAL_1( type, mem, decode)     type##_decode_global( mem, &decode );
      93           0 : #define HANDLE_GLOBAL_0( type, mem, decode)     type##_decode( mem, &decode );
      94             : 
      95             : # define X( type, name, is_global )                                                       \
      96             : void                                                                                      \
      97             : fd_sysvar_cache_restore_##name(                                                           \
      98             :   fd_sysvar_cache_t * cache,                                                              \
      99             :   fd_funk_t *         funk,                                                               \
     100             :   fd_funk_txn_t *     funk_txn,                                                           \
     101             :   fd_spad_t *         runtime_spad,                                                       \
     102           0 :   fd_wksp_t *         wksp ) {                                                            \
     103           0 :   do {                                                                                    \
     104           0 :     fd_pubkey_t const * pubkey = &fd_sysvar_##name##_id;                                  \
     105           0 :     FD_TXN_ACCOUNT_DECL( account );                                                       \
     106           0 :     int view_err = fd_txn_account_init_from_funk_readonly( account,                       \
     107           0 :                                                            pubkey,                        \
     108           0 :                                                            funk,                          \
     109           0 :                                                            funk_txn );                    \
     110           0 :     if( view_err==FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT ) { break; }                             \
     111           0 :                                                                                           \
     112           0 :     if( view_err!=FD_ACC_MGR_SUCCESS ) {                                                  \
     113           0 :       char pubkey_cstr[ FD_BASE58_ENCODED_32_SZ ];                                        \
     114           0 :       FD_LOG_ERR(( "fd_txn_account_init_from_funk_readonly(%s) failed (%d-%s)",           \
     115           0 :                    fd_acct_addr_cstr( pubkey_cstr, pubkey->key ),                         \
     116           0 :                    view_err, fd_acc_mgr_strerror( view_err ) ));                          \
     117           0 :     }                                                                                     \
     118           0 :                                                                                           \
     119           0 :     if( account->vt->get_lamports( account ) == 0UL ) { break; }                          \
     120           0 :                                                                                           \
     121           0 :     /* Decode new value                                                                   \
     122           0 :       type##_decode() does not do heap allocations on failure */                          \
     123           0 :     fd_bincode_decode_ctx_t decode = {                                                    \
     124           0 :       .data    = account->vt->get_data( account ),                                        \
     125           0 :       .dataend = account->vt->get_data( account ) + account->vt->get_data_len( account )  \
     126           0 :     };                                                                                    \
     127           0 :     ulong total_sz    = 0UL;                                                              \
     128           0 :     int   err         = type##_decode_footprint( &decode, &total_sz );                    \
     129           0 :     cache->has_##name = (err==FD_BINCODE_SUCCESS);                                        \
     130           0 :     if( FD_UNLIKELY( err ) ) break;                                                       \
     131           0 :     type##_t * mem = fd_spad_alloc_check( runtime_spad,  type##_align(),  total_sz );     \
     132           0 :     HANDLE_GLOBAL_##is_global( type, mem, decode )                                        \
     133           0 :     cache->gaddr_##name = fd_wksp_gaddr_fast( wksp, mem );                                \
     134           0 :   } while(0);                                                                             \
     135           0 : }
     136             :   FD_SYSVAR_CACHE_ITER(X)
     137             : # undef X
     138             : 
     139             : #undef HANDLE_GLOBAL_1
     140             : #undef HANDLE_GLOBAL_0
     141             : 
     142             : void
     143             : fd_sysvar_cache_restore( fd_sysvar_cache_t * cache,
     144             :                          fd_funk_t *         funk,
     145             :                          fd_funk_txn_t *     funk_txn,
     146             :                          fd_spad_t *         runtime_spad,
     147           0 :                          fd_wksp_t *         wksp ) {
     148           0 : # define X( type, name, is_global )                                            \
     149           0 :   fd_sysvar_cache_restore_##name( cache, funk, funk_txn, runtime_spad, wksp );
     150           0 :   FD_SYSVAR_CACHE_ITER(X)
     151           0 : # undef X
     152           0 : }
     153             : 
     154             : void
     155           0 : fd_sysvar_cache_invalidate( fd_sysvar_cache_t * cache ) {
     156           0 :   # define X( type, name, is_global ) \
     157           0 :     cache->has_##name = 0;
     158           0 :   FD_SYSVAR_CACHE_ITER(X)
     159           0 :   # undef X
     160           0 : }
     161             : 
     162             : /* Define macros with appropriate parameters */
     163             : #define HANDLE_GLOBAL_1(type, name, is_global)                                                   \
     164             : type##_global_t const *                                                                          \
     165             : fd_sysvar_from_instr_acct_##name( fd_exec_instr_ctx_t const * ctx,                               \
     166             :                                  ulong                       idx,                                \
     167           0 :                                  int *                       err ) {                             \
     168           0 :                                                                                                  \
     169           0 :   if( FD_UNLIKELY( idx >= ctx->instr->acct_cnt ) ) {                                             \
     170           0 :     *err = FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;                                            \
     171           0 :     return NULL;                                                                                 \
     172           0 :   }                                                                                              \
     173           0 :                                                                                                  \
     174           0 :   fd_sysvar_cache_t const * cache = ctx->txn_ctx->sysvar_cache;                                  \
     175           0 :   type##_global_t const * val = fd_sysvar_cache_##name( cache, ctx->txn_ctx->runtime_pub_wksp ); \
     176           0 :                                                                                                  \
     177           0 :   ushort idx_in_txn = ctx->instr->accounts[idx].index_in_transaction;                            \
     178           0 :   fd_pubkey_t const * addr_have = &ctx->txn_ctx->account_keys[ idx_in_txn ];                     \
     179           0 :   fd_pubkey_t const * addr_want = &fd_sysvar_##name##_id;                                        \
     180           0 :   if( 0!=memcmp( addr_have, addr_want, sizeof(fd_pubkey_t) ) ) {                                 \
     181           0 :     *err = FD_EXECUTOR_INSTR_ERR_INVALID_ARG;                                                    \
     182           0 :     return NULL;                                                                                 \
     183           0 :   }                                                                                              \
     184           0 :                                                                                                  \
     185           0 :   *err = val ?                                                                                   \
     186           0 :          FD_EXECUTOR_INSTR_SUCCESS :                                                             \
     187           0 :          FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;                                               \
     188           0 :   return val;                                                                                    \
     189           0 : }
     190             : 
     191             : #define HANDLE_GLOBAL_0(type, name, is_global)                                            \
     192             : type##_t const *                                                                          \
     193             : fd_sysvar_from_instr_acct_##name( fd_exec_instr_ctx_t const * ctx,                        \
     194             :                                  ulong                       idx,                         \
     195           0 :                                  int *                       err ) {                      \
     196           0 :                                                                                           \
     197           0 :   if( FD_UNLIKELY( idx >= ctx->instr->acct_cnt ) ) {                                      \
     198           0 :     *err = FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;                                     \
     199           0 :     return NULL;                                                                          \
     200           0 :   }                                                                                       \
     201           0 :                                                                                           \
     202           0 :   fd_sysvar_cache_t const * cache = ctx->txn_ctx->sysvar_cache;                           \
     203           0 :   type##_t const * val = fd_sysvar_cache_##name( cache, ctx->txn_ctx->runtime_pub_wksp ); \
     204           0 :                                                                                           \
     205           0 :   ushort idx_in_txn = ctx->instr->accounts[idx].index_in_transaction;                     \
     206           0 :   fd_pubkey_t const * addr_have = &ctx->txn_ctx->account_keys[ idx_in_txn ];              \
     207           0 :   fd_pubkey_t const * addr_want = &fd_sysvar_##name##_id;                                 \
     208           0 :   if( 0!=memcmp( addr_have, addr_want, sizeof(fd_pubkey_t) ) ) {                          \
     209           0 :     *err = FD_EXECUTOR_INSTR_ERR_INVALID_ARG;                                             \
     210           0 :     return NULL;                                                                          \
     211           0 :   }                                                                                       \
     212           0 :                                                                                           \
     213           0 :   *err = val ?                                                                            \
     214           0 :          FD_EXECUTOR_INSTR_SUCCESS :                                                      \
     215           0 :          FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;                                        \
     216           0 :   return val;                                                                             \
     217           0 : }
     218             : 
     219             : /* Define the X macro properly */
     220             : #define X(type, name, is_global) \
     221             :   HANDLE_GLOBAL_##is_global(type, name, is_global)
     222             : 
     223             : /* Apply the X macro to iterate through all entries */
     224             : FD_SYSVAR_CACHE_ITER(X)
     225             : 
     226             : /* Clean up macros */
     227             : #undef X
     228             : #undef HANDLE_GLOBAL_0
     229             : #undef HANDLE_GLOBAL_1
     230             : 
     231             : /* https://github.com/anza-xyz/agave/blob/77daab497df191ef485a7ad36ed291c1874596e5/program-runtime/src/sysvar_cache.rs#L223-L234 */
     232             : int
     233             : fd_check_sysvar_account( fd_exec_instr_ctx_t const * ctx,
     234             :                          ulong                       insn_acc_idx,
     235           0 :                          fd_pubkey_t const *         expected_id ) {
     236           0 :   fd_pubkey_t const * txn_accs = ctx->txn_ctx->account_keys;
     237             : 
     238           0 :   if( insn_acc_idx>=ctx->instr->acct_cnt ) {
     239           0 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
     240           0 :   }
     241             : 
     242           0 :   ushort              idx_in_txn   = ctx->instr->accounts[ insn_acc_idx ].index_in_transaction;
     243           0 :   fd_pubkey_t const * insn_acc_key = &txn_accs[ idx_in_txn ];
     244             : 
     245           0 :   if( memcmp( expected_id, insn_acc_key, sizeof(fd_pubkey_t) ) ) {
     246           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
     247           0 :   }
     248           0 :   return FD_EXECUTOR_INSTR_SUCCESS;
     249           0 : }

Generated by: LCOV version 1.14