LCOV - code coverage report
Current view: top level - flamenco/runtime/sysvar - fd_sysvar_cache.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 135 151 89.4 %
Date: 2026-04-13 06:42:39 Functions: 19 21 90.5 %

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

Generated by: LCOV version 1.14