LCOV - code coverage report
Current view: top level - flamenco/runtime/sysvar - fd_sysvar_cache.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 140 141 99.3 %
Date: 2026-11-12 04:25:03 Functions: 21 21 100.0 %

          Line data    Source code
       1             : #include "fd_sysvar_cache.h"
       2             : #include "fd_sysvar_cache_private.h"
       3             : #include "fd_sysvar_recent_hashes.h"
       4             : #include "fd_sysvar_slot_hashes.h"
       5             : #include "fd_sysvar_stake_history.h"
       6             : 
       7             : #include <errno.h>
       8             : 
       9             : void *
      10        1194 : fd_sysvar_cache_new( void * mem ) {
      11             : 
      12        1194 :   if( FD_UNLIKELY( !mem ) ) {
      13           3 :     FD_LOG_WARNING(( "NULL mem" ));
      14           3 :     return NULL;
      15           3 :   }
      16        1191 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, alignof(fd_sysvar_cache_t) ) ) ) {
      17           3 :     FD_LOG_WARNING(( "misaligned mem" ));
      18           3 :     return NULL;
      19           3 :   }
      20             : 
      21        1188 :   fd_sysvar_cache_t * sysvar_cache = mem;
      22        1188 :   sysvar_cache->magic = 0UL;
      23        1188 :   memset( sysvar_cache->desc, 0, FD_SYSVAR_CACHE_ENTRY_CNT*sizeof(fd_sysvar_desc_t) );
      24             : 
      25        1188 :   FD_COMPILER_MFENCE();
      26        1188 :   sysvar_cache->magic = FD_SYSVAR_CACHE_MAGIC;
      27        1188 :   FD_COMPILER_MFENCE();
      28             : 
      29        1188 :   return sysvar_cache;
      30        1191 : }
      31             : 
      32             : fd_sysvar_cache_t *
      33        1197 : fd_sysvar_cache_join( void * mem ) {
      34             :   /* FIXME This is a good place to ref-count writable joins */
      35        1197 :   return (fd_sysvar_cache_t *)fd_sysvar_cache_join_const( mem );
      36        1197 : }
      37             : 
      38             : fd_sysvar_cache_t const *
      39        1206 : fd_sysvar_cache_join_const( void const * mem ) {
      40             : 
      41        1206 :   if( FD_UNLIKELY( !mem ) ) {
      42           6 :     FD_LOG_WARNING(( "NULL mem" ));
      43           6 :     return NULL;
      44           6 :   }
      45        1200 :   if( FD_UNLIKELY( !fd_ulong_is_aligned( (ulong)mem, alignof(fd_sysvar_cache_t) ) ) ) {
      46           6 :     FD_LOG_WARNING(( "misaligned mem" ));
      47           6 :     return NULL;
      48           6 :   }
      49        1194 :   fd_sysvar_cache_t const * sysvar_cache = mem;
      50        1194 :   if( FD_UNLIKELY( sysvar_cache->magic != FD_SYSVAR_CACHE_MAGIC ) ) {
      51           6 :     FD_LOG_WARNING(( "bad magic" ));
      52           6 :     return NULL;
      53           6 :   }
      54             : 
      55        1188 :   return sysvar_cache;
      56        1194 : }
      57             : 
      58             : void *
      59         993 : fd_sysvar_cache_leave( fd_sysvar_cache_t * sysvar_cache ) {
      60         993 :   return sysvar_cache;
      61         993 : }
      62             : 
      63             : void const *
      64           3 : fd_sysvar_cache_leave_const( fd_sysvar_cache_t const * sysvar_cache ) {
      65           3 :   return sysvar_cache;
      66           3 : }
      67             : 
      68             : void *
      69          90 : fd_sysvar_cache_delete( void * mem ) {
      70             : 
      71          90 :   if( FD_UNLIKELY( !mem ) ) {
      72           3 :     FD_LOG_WARNING(( "NULL mem" ));
      73           3 :     return NULL;
      74           3 :   }
      75          87 :   fd_sysvar_cache_t * sysvar_cache = mem;
      76          87 :   if( FD_UNLIKELY( sysvar_cache->magic != FD_SYSVAR_CACHE_MAGIC ) ) {
      77           3 :     FD_LOG_WARNING(( "bad magic" ));
      78           3 :     return NULL;
      79           3 :   }
      80             : 
      81          84 :   memset( sysvar_cache, 0, sizeof(fd_sysvar_cache_t) );
      82             : 
      83          84 :   return mem;
      84          87 : }
      85             : 
      86             : uchar const *
      87             : fd_sysvar_cache_data_query(
      88             :     fd_sysvar_cache_t const * sysvar_cache,
      89             :     void const *              address, /* 32 bytes */
      90             :     ulong *                   psz
      91        1755 : ) {
      92        1755 :   *psz = 0UL;
      93        1755 :   fd_pubkey_t const pubkey = FD_LOAD( fd_pubkey_t, address );
      94        1755 :   sysvar_tbl_t const * entry = sysvar_map_query( &pubkey, NULL );
      95        1755 :   if( FD_UNLIKELY( !entry ) ) return NULL; /* address is not a sysvar */
      96        1752 :   fd_sysvar_desc_t const * desc = &sysvar_cache->desc[ entry->desc_idx ];
      97        1752 :   fd_sysvar_pos_t const *  pos  = &fd_sysvar_pos_tbl [ entry->desc_idx ];
      98        1752 :   if( !( desc->flags & FD_SYSVAR_FLAG_VALID ) ) return NULL; /* sysvar data invalid */
      99        1701 :   *psz = desc->data_sz;
     100        1701 :   return (uchar const *)sysvar_cache + pos->data_off;
     101        1752 : }
     102             : 
     103             : /* Generate accessors for sysvars that are backed by POD structs. */
     104             : 
     105             : #define SIMPLE_SYSVAR_READ( name, name2, typet )                       \
     106             :   typet *                                                              \
     107             :   fd_sysvar_cache_##name##_read( fd_sysvar_cache_t const * cache,      \
     108         573 :                                  typet *                   out ) {     \
     109         573 :     ulong const idx = FD_SYSVAR_##name##_IDX;                          \
     110         573 :     fd_sysvar_desc_t const * desc = &cache->desc[ idx ];               \
     111         573 :     fd_sysvar_pos_t const *  pos  = &fd_sysvar_pos_tbl[ idx ];         \
     112         573 :     if( FD_UNLIKELY( !( desc->flags & FD_SYSVAR_FLAG_VALID ) ) ) return NULL; \
     113         573 :     memcpy( out, (uchar *)cache+pos->data_off, pos->data_max );        \
     114         546 :     return out;                                                        \
     115         573 :   }
     116             : 
     117             : #define SIMPLE_SYSVAR( name, name2, type ) \
     118             :   SIMPLE_SYSVAR_READ( name, name2, fd_##type##_t )
     119          27 : FD_SYSVAR_SIMPLE_ITER( SIMPLE_SYSVAR )
     120          27 : #undef SIMPLE_SYSVAR
     121          27 : #undef SIMPLE_SYSVAR_READ
     122          27 : 
     123          27 : ulong const *
     124          27 : fd_sysvar_cache_last_restart_slot_read( fd_sysvar_cache_t const * cache ) {
     125           6 :   ulong const idx = FD_SYSVAR_last_restart_slot_IDX;
     126           6 :   fd_sysvar_desc_t const * desc = &cache->desc[ idx ];
     127           6 :   fd_sysvar_pos_t const *  pos  = &fd_sysvar_pos_tbl[ idx ];
     128           6 :   if( FD_UNLIKELY( !( desc->flags & FD_SYSVAR_FLAG_VALID ) ) ) return NULL;
     129           0 :   return fd_type_pun_const( (uchar const *)cache + pos->data_off );
     130           6 : }
     131             : 
     132             : int
     133          15 : fd_sysvar_cache_recent_hashes_is_empty( fd_sysvar_cache_t const * sysvar_cache ) {
     134          15 :   fd_sysvar_desc_t const * desc = &sysvar_cache->desc[ FD_SYSVAR_recent_hashes_IDX ];
     135          15 :   if( FD_UNLIKELY( !( desc->flags & FD_SYSVAR_FLAG_VALID ) ) ) return 1;
     136          15 :   FD_TEST( desc->data_sz >= sizeof(ulong) );
     137          15 :   ulong len = FD_LOAD( ulong, sysvar_cache->bin_recent_hashes );
     138          15 :   return len == 0UL;
     139          15 : }
     140             : 
     141             : int
     142             : fd_sysvar_obj_restore( fd_sysvar_cache_t *     cache,
     143             :                        fd_sysvar_desc_t *      desc,
     144        4740 :                        fd_sysvar_pos_t const * pos ) {
     145        4740 :   desc->flags &= ~FD_SYSVAR_FLAG_VALID;
     146             : 
     147        4740 :   uchar const * data    = (uchar const *)cache + pos->data_off;
     148        4740 :   ulong const   data_sz = desc->data_sz;
     149             : 
     150        4740 :   if( FD_UNLIKELY( !pos->validate( data, data_sz ) ) ) {
     151          36 :     FD_LOG_DEBUG(( "Failed to validate sysvar %s with data_sz=%lu",
     152          36 :                     pos->name, data_sz ));
     153          36 :     return EINVAL;
     154          36 :   }
     155        4704 :   desc->flags |= FD_SYSVAR_FLAG_VALID;
     156        4704 :   return 0;
     157        4740 : }
     158             : 
     159             : static int
     160       12996 : fd_sysvar_validate_clock( uchar const * data, ulong data_sz ) {
     161       12996 :   (void)data;
     162       12996 :   return data_sz >= sizeof(fd_sol_sysvar_clock_t );
     163       12996 : }
     164             : 
     165             : static int
     166       12945 : fd_sysvar_validate_rent( uchar const * data, ulong data_sz ) {
     167       12945 :   (void)data;
     168       12945 :   return data_sz >= sizeof(fd_rent_t );
     169       12945 : }
     170             : 
     171             : static int
     172       12960 : fd_sysvar_validate_last_restart_slot( uchar const * data, ulong data_sz ) {
     173       12960 :   (void)data;
     174       12960 :   return data_sz >= sizeof(ulong);
     175       12960 : }
     176             : 
     177             : static int
     178        1053 : fd_sysvar_validate_epoch_rewards( uchar const * data, ulong data_sz ) {
     179        1053 :   if( FD_UNLIKELY( data_sz < sizeof(fd_sysvar_epoch_rewards_t) ) ) return 0;
     180        1050 :   fd_sysvar_epoch_rewards_t ew = FD_LOAD( fd_sysvar_epoch_rewards_t, data );
     181        1050 :   uchar active = ew.active;
     182        1050 :   if( FD_UNLIKELY( active!=0 && active!=1 ) ) return 0;
     183        1047 :   return 1;
     184        1050 : }
     185             : 
     186             : static int
     187       12978 : fd_sysvar_validate_epoch_schedule( uchar const * data, ulong data_sz ) {
     188       12978 :   if( FD_UNLIKELY( data_sz < sizeof(fd_epoch_schedule_t) ) ) return 0;
     189       12975 :   fd_epoch_schedule_t es = FD_LOAD( fd_epoch_schedule_t, data );
     190       12975 :   uchar warmup = es.warmup;
     191       12975 :   if( FD_UNLIKELY( warmup!=0 && warmup!=1 ) ) return 0;
     192       12969 :   return 1;
     193       12975 : }
     194             : 
     195             : fd_sysvar_pos_t const fd_sysvar_pos_tbl[ FD_SYSVAR_CACHE_ENTRY_CNT ] = {
     196             :   [FD_SYSVAR_clock_IDX] =
     197             :     { .name="clock",
     198             :       .data_off=offsetof(fd_sysvar_cache_t, bin_clock            ), .data_max=FD_SYSVAR_CLOCK_BINCODE_SZ,
     199             :       .validate=fd_sysvar_validate_clock },
     200             :   [FD_SYSVAR_epoch_rewards_IDX] =
     201             :     { .name="epoch rewards",
     202             :       .data_off=offsetof(fd_sysvar_cache_t, bin_epoch_rewards    ), .data_max=FD_SYSVAR_EPOCH_REWARDS_BINCODE_SZ,
     203             :       .validate=fd_sysvar_validate_epoch_rewards },
     204             :   [FD_SYSVAR_epoch_schedule_IDX] =
     205             :     { .name="epoch schedule",
     206             :       .data_off=offsetof(fd_sysvar_cache_t, bin_epoch_schedule   ), .data_max=FD_SYSVAR_EPOCH_SCHEDULE_BINCODE_SZ,
     207             :       .validate=fd_sysvar_validate_epoch_schedule },
     208             :   [FD_SYSVAR_last_restart_slot_IDX] =
     209             :     { .name="last restart slot",
     210             :       .data_off=offsetof(fd_sysvar_cache_t, bin_last_restart_slot), .data_max=FD_SYSVAR_LAST_RESTART_SLOT_BINCODE_SZ,
     211             :       .validate=fd_sysvar_validate_last_restart_slot },
     212             :   [FD_SYSVAR_recent_hashes_IDX] =
     213             :     { .name="recent blockhashes",
     214             :       .data_off=offsetof(fd_sysvar_cache_t, bin_recent_hashes    ), .data_max=FD_SYSVAR_RECENT_HASHES_BINCODE_SZ,
     215             :       .validate=fd_sysvar_recent_hashes_validate },
     216             :   [FD_SYSVAR_rent_IDX] =
     217             :     { .name="rent",
     218             :       .data_off=offsetof(fd_sysvar_cache_t, bin_rent             ), .data_max=FD_SYSVAR_RENT_BINCODE_SZ,
     219             :       .validate=fd_sysvar_validate_rent },
     220             :   [FD_SYSVAR_slot_hashes_IDX] =
     221             :     { .name="slot hashes",
     222             :       .data_off=offsetof(fd_sysvar_cache_t, bin_slot_hashes      ), .data_max=FD_SYSVAR_SLOT_HASHES_BINCODE_SZ,
     223             :       .validate=fd_sysvar_slot_hashes_validate },
     224             :   [FD_SYSVAR_stake_history_IDX] =
     225             :     { .name="stake history",
     226             :       .data_off=offsetof(fd_sysvar_cache_t, bin_stake_history    ), .data_max=FD_SYSVAR_STAKE_HISTORY_BINCODE_SZ,
     227             :       .validate=fd_sysvar_stake_history_validate },
     228             : };
     229             : 
     230             : fd_slot_hashes_t *
     231             : fd_sysvar_cache_slot_hashes_view( fd_sysvar_cache_t const * cache,
     232         312 :                                   fd_slot_hashes_t *        view ) {
     233         312 :   fd_sysvar_desc_t const * desc = &cache->desc[ FD_SYSVAR_slot_hashes_IDX ];
     234         312 :   if( FD_UNLIKELY( !( desc->flags & FD_SYSVAR_FLAG_VALID ) ) ) return NULL;
     235         312 :   return fd_sysvar_slot_hashes_view( view, cache->bin_slot_hashes, desc->data_sz );
     236         312 : }
     237             : 
     238             : fd_stake_history_t *
     239             : fd_sysvar_cache_stake_history_view( fd_sysvar_cache_t const * cache,
     240           6 :                                     fd_stake_history_t *      view ) {
     241           6 :   fd_sysvar_desc_t const * desc = &cache->desc[ FD_SYSVAR_stake_history_IDX ];
     242           6 :   if( FD_UNLIKELY( !( desc->flags & FD_SYSVAR_FLAG_VALID ) ) ) return NULL;
     243           6 :   return fd_sysvar_stake_history_view( view, cache->bin_stake_history, desc->data_sz );
     244           6 : }

Generated by: LCOV version 1.14