LCOV - code coverage report
Current view: top level - flamenco/runtime/sysvar - fd_sysvar_cache.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 99 120 82.5 %
Date: 2024-11-13 11:58:15 Functions: 27 33 81.8 %

          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             : #include "../context/fd_exec_slot_ctx.h"
       8             : 
       9      108786 : #define FD_SYSVAR_CACHE_MAGIC (0x195a0e78828cacd5UL)
      10             : 
      11             : ulong
      12      108786 : fd_sysvar_cache_align( void ) {
      13      108786 :   return alignof(fd_sysvar_cache_t);
      14      108786 : }
      15             : 
      16             : ulong
      17      108786 : fd_sysvar_cache_footprint( void ) {
      18      108786 :   return sizeof(fd_sysvar_cache_t);
      19      108786 : }
      20             : 
      21             : fd_sysvar_cache_t *
      22             : fd_sysvar_cache_new( void *      mem,
      23      108786 :                      fd_valloc_t valloc ) {
      24             : 
      25      108786 :   if( FD_UNLIKELY( !mem ) ) {
      26           0 :     FD_LOG_WARNING(( "NULL mem" ));
      27           0 :     return NULL;
      28           0 :   }
      29             : 
      30      108786 :   fd_sysvar_cache_t * cache = (fd_sysvar_cache_t *)mem;
      31      108786 :   fd_memset( cache, 0, sizeof(fd_sysvar_cache_t) );
      32             : 
      33      108786 :   cache->valloc = valloc;
      34             : 
      35      108786 :   FD_COMPILER_MFENCE();
      36      108786 :   cache->magic = FD_SYSVAR_CACHE_MAGIC;
      37      108786 :   FD_COMPILER_MFENCE();
      38      108786 :   return cache;
      39      108786 : }
      40             : 
      41             : void *
      42      108786 : fd_sysvar_cache_delete( fd_sysvar_cache_t * cache ) {
      43             : 
      44      108786 :   if( FD_UNLIKELY( !cache ) ) {
      45           0 :     FD_LOG_WARNING(( "NULL cache" ));
      46           0 :     return NULL;
      47           0 :   }
      48             : 
      49      108786 :   if( FD_UNLIKELY( cache->magic != FD_SYSVAR_CACHE_MAGIC ) ) {
      50           0 :     FD_LOG_WARNING(( "bad magic" ));
      51           0 :     return NULL;
      52           0 :   }
      53             : 
      54      108786 :   if( FD_UNLIKELY( !cache->valloc.vt ) ) {
      55           0 :     FD_LOG_WARNING(( "NULL alloc" ));
      56           0 :     return NULL;
      57           0 :   }
      58             : 
      59      108786 :   FD_COMPILER_MFENCE();
      60      108786 :   cache->magic = 0UL;
      61      108786 :   FD_COMPILER_MFENCE();
      62             : 
      63      108786 :   fd_bincode_destroy_ctx_t ctx = { .valloc = cache->valloc };
      64             : 
      65             :   /* Call destroy on all objects.
      66             :      This is safe even if these objects logically don't exist
      67             :      (destory is safe on zero-initialized values and is idempotent) */
      68      108786 : # define X( type, name ) \
      69      979074 :   type##_destroy( cache->val_##name, &ctx );
      70      979074 :   FD_SYSVAR_CACHE_ITER(X)
      71      108786 : # undef X
      72             : 
      73      108786 :   return (void *)cache;
      74      108786 : }
      75             : 
      76             : /* Provide accessor methods */
      77             : 
      78             : #define X( type, name )                                                \
      79             :   type##_t const *                                                     \
      80      408984 :   fd_sysvar_cache_##name( fd_sysvar_cache_t const * cache ) {          \
      81      408984 :     type##_t const * val = cache->val_##name;                          \
      82      408984 :     return (cache->has_##name) ? val : NULL;                           \
      83      408984 :   }
      84             : FD_SYSVAR_CACHE_ITER(X)
      85             : #undef X
      86             : 
      87             : /* Restore sysvars */
      88             : 
      89             : # define X( type, name )                                                  \
      90             : void                                                                      \
      91             : fd_sysvar_cache_restore_##name(                                           \
      92             :   fd_sysvar_cache_t * cache,                                              \
      93             :   fd_acc_mgr_t *      acc_mgr,                                            \
      94     1081404 :   fd_funk_txn_t *     funk_txn) {                                         \
      95     1081404 :   do {                                                                    \
      96     1081404 :     fd_pubkey_t const * pubkey = &fd_sysvar_##name##_id;                  \
      97     1081404 :     FD_BORROWED_ACCOUNT_DECL( account );                                  \
      98     1081404 :     int view_err = fd_acc_mgr_view( acc_mgr, funk_txn, pubkey, account ); \
      99     1081404 :     if( view_err==FD_ACC_MGR_ERR_UNKNOWN_ACCOUNT ) break;                 \
     100     1081404 :                                                                           \
     101     1081404 :     if( view_err!=FD_ACC_MGR_SUCCESS ) {                                  \
     102           0 :       char pubkey_cstr[ FD_BASE58_ENCODED_32_SZ ];                        \
     103           0 :       FD_LOG_ERR(( "fd_acc_mgr_view(%s) failed (%d-%s)",                  \
     104           0 :                   fd_acct_addr_cstr( pubkey_cstr, pubkey->key ),          \
     105           0 :                   view_err, fd_acc_mgr_strerror( view_err ) ));           \
     106           0 :     }                                                                     \
     107      188892 :                                                                           \
     108      188892 :     if( account->const_meta->info.lamports == 0UL ) break;                \
     109      188892 :                                                                           \
     110      188892 :     /* Destroy previous value */                                          \
     111      188892 :                                                                           \
     112      188892 :     fd_bincode_destroy_ctx_t destroy = { .valloc = cache->valloc };       \
     113      187620 :     type##_destroy( cache->val_##name, &destroy );                        \
     114      187620 :                                                                           \
     115      187620 :     /* Decode new value                                                   \
     116      187620 :       type##_decode() does not do heap allocations on failure */          \
     117      187620 :                                                                           \
     118      187620 :     fd_bincode_decode_ctx_t decode =                                      \
     119      187620 :       { .data    = account->const_data,                                   \
     120      187620 :         .dataend = account->const_data + account->const_meta->dlen,       \
     121      187620 :         .valloc  = cache->valloc };                                       \
     122      187620 :     int err = type##_decode( cache->val_##name, &decode );                \
     123      187620 :     cache->has_##name = (err==FD_BINCODE_SUCCESS);                        \
     124      187620 :   } while(0);                                                             \
     125     1081404 : }
     126             :   FD_SYSVAR_CACHE_ITER(X)
     127             : # undef X
     128             : 
     129             : void
     130             : fd_sysvar_cache_restore( fd_sysvar_cache_t * cache,
     131             :                          fd_acc_mgr_t *      acc_mgr,
     132      120156 :                          fd_funk_txn_t *     funk_txn ) {
     133     1081404 : # define X( type, name )                                               \
     134     1081404 : fd_sysvar_cache_restore_##name( cache, acc_mgr, funk_txn );
     135     1081404 :   FD_SYSVAR_CACHE_ITER(X)
     136      120156 : # undef X
     137      120156 : }
     138             : 
     139             : # define X( type, name )                                               \
     140             :   type##_t const *                                                     \
     141             :   fd_sysvar_from_instr_acct_##name( fd_exec_instr_ctx_t const * ctx,   \
     142             :                                     ulong                       idx,   \
     143       15237 :                                     int *                       err ) {\
     144       15237 :                                                                        \
     145       15237 :     if( FD_UNLIKELY( idx >= ctx->instr->acct_cnt ) ) {                 \
     146          45 :       *err = FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;                \
     147          45 :       return NULL;                                                     \
     148          45 :     }                                                                  \
     149       15237 :                                                                        \
     150       15237 :     fd_sysvar_cache_t const * cache = ctx->slot_ctx->sysvar_cache;     \
     151       15192 :     type##_t const * val = fd_sysvar_cache_##name ( cache );           \
     152       15192 :                                                                        \
     153       15192 :     fd_pubkey_t const * addr_have = &ctx->instr->acct_pubkeys[idx];    \
     154       15192 :     fd_pubkey_t const * addr_want = &fd_sysvar_##name##_id;            \
     155       15192 :     if( 0!=memcmp( addr_have, addr_want, sizeof(fd_pubkey_t) ) ) {     \
     156        1170 :       *err = FD_EXECUTOR_INSTR_ERR_INVALID_ARG;                        \
     157        1170 :       return NULL;                                                     \
     158        1170 :     }                                                                  \
     159       15192 :                                                                        \
     160       15192 :     *err = val ?                                                       \
     161       14022 :            FD_EXECUTOR_INSTR_SUCCESS :                                 \
     162       14022 :            FD_EXECUTOR_INSTR_ERR_UNSUPPORTED_SYSVAR;                   \
     163       14022 :     return val;                                                        \
     164       15192 :                                                                        \
     165       15192 :   }
     166             :   FD_SYSVAR_CACHE_ITER(X)
     167             : # undef X
     168             : 
     169             : /* https://github.com/anza-xyz/agave/blob/77daab497df191ef485a7ad36ed291c1874596e5/program-runtime/src/sysvar_cache.rs#L223-L234 */
     170             : int
     171             : fd_check_sysvar_account( fd_exec_instr_ctx_t const * ctx,
     172             :                          ulong                       insn_acc_idx,
     173        1740 :                          fd_pubkey_t const *         expected_id ) {
     174        1740 :   uchar const *       instr_acc_idxs = ctx->instr->acct_txn_idxs;
     175        1740 :   fd_pubkey_t const * txn_accs       = ctx->txn_ctx->accounts;
     176             : 
     177        1740 :   if( insn_acc_idx>=ctx->instr->acct_cnt ) {
     178           0 :     return FD_EXECUTOR_INSTR_ERR_NOT_ENOUGH_ACC_KEYS;
     179           0 :   }
     180             : 
     181        1740 :   fd_pubkey_t const * insn_acc_key = &txn_accs[ instr_acc_idxs[ insn_acc_idx ] ];
     182             : 
     183        1740 :   if( memcmp( expected_id, insn_acc_key, sizeof(fd_pubkey_t) ) ) {
     184           0 :     return FD_EXECUTOR_INSTR_ERR_INVALID_ARG;
     185           0 :   }
     186        1740 :   return FD_EXECUTOR_INSTR_SUCCESS;
     187        1740 : }

Generated by: LCOV version 1.14