LCOV - code coverage report
Current view: top level - flamenco/runtime/sysvar - fd_sysvar_cache.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 114 136 83.8 %
Date: 2025-08-05 05:04:49 Functions: 16 19 84.2 %

          Line data    Source code
       1             : #include "fd_sysvar_cache.h"
       2             : #include "fd_sysvar_cache_private.h"
       3             : #include "../context/fd_exec_slot_ctx.h"
       4             : #include <errno.h>
       5             : 
       6             : void *
       7         480 : fd_sysvar_cache_new( void * mem ) {
       8             : 
       9         480 :   if( FD_UNLIKELY( !mem ) ) {
      10           3 :     FD_LOG_WARNING(( "NULL mem" ));
      11           3 :     return NULL;
      12           3 :   }
      13         477 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, alignof(fd_sysvar_cache_t) ) ) ) {
      14           3 :     FD_LOG_WARNING(( "misaligned mem" ));
      15           3 :     return NULL;
      16           3 :   }
      17             : 
      18         474 :   fd_sysvar_cache_t * sysvar_cache = mem;
      19         474 :   sysvar_cache->magic = 0UL;
      20         474 :   memset( sysvar_cache->desc, 0, FD_SYSVAR_CACHE_ENTRY_CNT*sizeof(fd_sysvar_desc_t) );
      21             : 
      22         474 :   FD_COMPILER_MFENCE();
      23         474 :   sysvar_cache->magic = FD_SYSVAR_CACHE_MAGIC;
      24         474 :   FD_COMPILER_MFENCE();
      25             : 
      26         474 :   return sysvar_cache;
      27         477 : }
      28             : 
      29             : fd_sysvar_cache_t *
      30         486 : fd_sysvar_cache_join( void * mem ) {
      31             :   /* FIXME This is a good place to ref-count writable joins */
      32         486 :   return (fd_sysvar_cache_t *)fd_sysvar_cache_join_const( mem );
      33         486 : }
      34             : 
      35             : fd_sysvar_cache_t const *
      36         495 : fd_sysvar_cache_join_const( void const * mem ) {
      37             : 
      38         495 :   if( FD_UNLIKELY( !mem ) ) {
      39           6 :     FD_LOG_WARNING(( "NULL mem" ));
      40           6 :     return NULL;
      41           6 :   }
      42         489 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, alignof(fd_sysvar_cache_t) ) ) ) {
      43           6 :     FD_LOG_WARNING(( "misaligned mem" ));
      44           6 :     return NULL;
      45           6 :   }
      46         483 :   fd_sysvar_cache_t const * sysvar_cache = mem;
      47         483 :   if( FD_UNLIKELY( sysvar_cache->magic != FD_SYSVAR_CACHE_MAGIC ) ) {
      48           6 :     FD_LOG_WARNING(( "bad magic" ));
      49           6 :     return NULL;
      50           6 :   }
      51             : 
      52         477 :   return sysvar_cache;
      53         483 : }
      54             : 
      55             : void *
      56         474 : fd_sysvar_cache_leave( fd_sysvar_cache_t * sysvar_cache ) {
      57         474 :   return sysvar_cache;
      58         474 : }
      59             : 
      60             : void const *
      61           3 : fd_sysvar_cache_leave_const( fd_sysvar_cache_t const * sysvar_cache ) {
      62           3 :   return sysvar_cache;
      63           3 : }
      64             : 
      65             : void *
      66          21 : fd_sysvar_cache_delete( void * mem ) {
      67             : 
      68          21 :   if( FD_UNLIKELY( !mem ) ) {
      69           3 :     FD_LOG_WARNING(( "NULL mem" ));
      70           3 :     return NULL;
      71           3 :   }
      72          18 :   fd_sysvar_cache_t * sysvar_cache = mem;
      73          18 :   if( FD_UNLIKELY( sysvar_cache->magic != FD_SYSVAR_CACHE_MAGIC ) ) {
      74           3 :     FD_LOG_WARNING(( "bad magic" ));
      75           3 :     return NULL;
      76           3 :   }
      77             : 
      78          15 :   memset( sysvar_cache, 0, sizeof(fd_sysvar_cache_t) );
      79             : 
      80          15 :   return mem;
      81          18 : }
      82             : 
      83             : uchar const *
      84             : fd_sysvar_cache_data_query(
      85             :     fd_sysvar_cache_t const * sysvar_cache,
      86             :     void const *              address, /* 32 bytes */
      87             :     ulong *                   psz
      88         492 : ) {
      89         492 :   *psz = 0UL;
      90         492 :   fd_pubkey_t const pubkey = FD_LOAD( fd_pubkey_t, address );
      91         492 :   sysvar_tbl_t const * entry = sysvar_map_query( &pubkey, NULL );
      92         492 :   if( FD_UNLIKELY( !entry ) ) return NULL; /* address is not a sysvar */
      93         489 :   fd_sysvar_desc_t const * desc = &sysvar_cache->desc[ entry->desc_idx ];
      94         489 :   fd_sysvar_pos_t const *  pos  = &fd_sysvar_pos_tbl [ entry->desc_idx ];
      95         489 :   if( !( desc->flags & FD_SYSVAR_FLAG_VALID ) ) return NULL; /* sysvar data invalid */
      96         462 :   *psz = desc->data_sz;
      97         462 :   return (uchar const *)sysvar_cache + pos->data_off;
      98         489 : }
      99             : 
     100             : /* Generate accessors for sysvars that are backed by POD structs. */
     101             : 
     102             : #define SIMPLE_SYSVAR_READ( name, name2, typet )                       \
     103             :   typet *                                                              \
     104             :   fd_sysvar_cache_##name##_read( fd_sysvar_cache_t const * cache,      \
     105          18 :                                  typet *                   out ) {     \
     106          18 :     ulong const idx = FD_SYSVAR_##name##_IDX;                          \
     107          18 :     fd_sysvar_desc_t const * desc = &cache->desc[ idx ];               \
     108          18 :     fd_sysvar_pos_t const *  pos  = &fd_sysvar_pos_tbl[ idx ];         \
     109          18 :     if( FD_UNLIKELY( !( desc->flags & FD_SYSVAR_FLAG_VALID ) ) ) return NULL; \
     110          18 :     memcpy( out, (uchar *)cache+pos->obj_off, pos->obj_max );          \
     111           3 :     return out;                                                        \
     112          18 :   }
     113             : 
     114             : #define SIMPLE_SYSVAR( name, name2, type ) \
     115             :   SIMPLE_SYSVAR_READ( name, name2, fd_##type##_t )
     116          15 : FD_SYSVAR_SIMPLE_ITER( SIMPLE_SYSVAR )
     117          15 : #undef SIMPLE_SYSVAR
     118          15 : #undef SIMPLE_SYSVAR_READ
     119          15 : 
     120          15 : fd_slot_hash_t const *
     121          15 : fd_sysvar_cache_slot_hashes_join_const(
     122          15 :     fd_sysvar_cache_t const * cache
     123          15 : ) {
     124           3 :   if( FD_UNLIKELY( !fd_sysvar_cache_slot_hashes_is_valid( cache ) ) ) return NULL;
     125           0 :   fd_slot_hashes_global_t * var = (void *)cache->obj_slot_hashes;
     126           0 :   fd_slot_hash_t * deq = deq_fd_slot_hash_t_join( (uchar *)var+var->hashes_offset );
     127             :   /* If the above is_valid check is passed, then join is guaranteed to succeed */
     128           0 :   if( FD_UNLIKELY( !deq ) ) FD_LOG_CRIT(( "slot hashes sysvar corruption detected" ));
     129           0 :   return deq; /* demote to const ptr */
     130           0 : }
     131             : 
     132             : void
     133             : fd_sysvar_cache_slot_hashes_leave_const(
     134             :     fd_sysvar_cache_t const * sysvar_cache,
     135             :     fd_slot_hash_t const *    slot_hashes
     136           0 : ) {
     137           0 :   (void)sysvar_cache; (void)slot_hashes;
     138           0 : }
     139             : 
     140             : fd_slot_history_global_t const *
     141             : fd_sysvar_cache_slot_history_join_const(
     142             :     fd_sysvar_cache_t const * cache
     143           3 : ) {
     144           3 :   if( FD_UNLIKELY( !fd_sysvar_cache_slot_history_is_valid( cache ) ) ) return NULL;
     145           0 :   return (void const *)( cache->obj_slot_history );
     146           3 : }
     147             : 
     148             : void
     149             : fd_sysvar_slot_history_leave_const(
     150             :     fd_sysvar_cache_t const *        sysvar_cache,
     151             :     fd_slot_history_global_t const * slot_history
     152           0 : ) {
     153           0 :   (void)sysvar_cache; (void)slot_history;
     154           0 : }
     155             : 
     156             : fd_stake_history_t const *
     157             : fd_sysvar_cache_stake_history_join_const(
     158             :     fd_sysvar_cache_t const * cache
     159           3 : ) {
     160           3 :   if( FD_UNLIKELY( !fd_sysvar_cache_stake_history_is_valid( cache ) ) ) return NULL;
     161           0 :   return (void const *)cache->obj_stake_history;
     162           3 : }
     163             : 
     164             : void
     165             : fd_sysvar_cache_stake_history_leave_const(
     166             :     fd_sysvar_cache_t const *  sysvar_cache,
     167             :     fd_stake_history_t const * stake_history
     168           0 : ) {
     169           0 :   (void)sysvar_cache; (void)stake_history;
     170           0 : }
     171             : 
     172             : int
     173             : fd_sysvar_obj_restore( fd_sysvar_cache_t *     cache,
     174             :                        fd_sysvar_desc_t *      desc,
     175             :                        fd_sysvar_pos_t const * pos,
     176         465 :                        int                     log_fails ) {
     177         465 :   desc->flags &= ~FD_SYSVAR_FLAG_VALID;
     178             : 
     179         465 :   uchar const * data    = (uchar const *)cache + pos->data_off;
     180         465 :   ulong const   data_sz = desc->data_sz;
     181             : 
     182         465 :   if( FD_UNLIKELY( !pos->obj_max ) ) {
     183             :     /* Sysvar is directly stored - does not need to be deserialized */
     184         453 :     desc->flags |= FD_SYSVAR_FLAG_VALID;
     185         453 :     FD_LOG_DEBUG(( "Restored sysvar %s (data_sz=%lu)", pos->name, data_sz ));
     186         453 :     return 0;
     187         453 :   }
     188             : 
     189          12 :   fd_bincode_decode_ctx_t ctx = { .data=data, .dataend=data+data_sz };
     190          12 :   ulong obj_sz = 0UL;
     191          12 :   if( FD_UNLIKELY( pos->decode_footprint( &ctx, &obj_sz )!=FD_BINCODE_SUCCESS ) ) {
     192           3 :     if( log_fails ) {
     193           3 :       FD_LOG_DEBUG(( "Failed to decode sysvar %s with data_sz=%lu: decode failed",
     194           3 :                      pos->name, data_sz ));
     195           3 :     }
     196           3 :     return EINVAL;
     197           3 :   }
     198           9 :   if( FD_UNLIKELY( obj_sz > pos->obj_max ) ) {
     199           0 :     if( log_fails ) {
     200           0 :       FD_LOG_WARNING(( "Failed to restore sysvar %s: obj_sz=%lu exceeds max=%u",
     201           0 :                        pos->name, obj_sz, pos->obj_max ));
     202           0 :     }
     203           0 :     return ENOMEM;
     204           0 :   }
     205           9 :   pos->decode( (uchar *)cache+pos->obj_off, &ctx );
     206           9 :   desc->flags |= FD_SYSVAR_FLAG_VALID;
     207             : 
     208           9 :   FD_LOG_DEBUG(( "Restored sysvar %s (data_sz=%lu obj_sz=%lu)",
     209           9 :                  pos->name, data_sz, obj_sz ));
     210           9 :   return 0;
     211           9 : }

Generated by: LCOV version 1.14