LCOV - code coverage report
Current view: top level - flamenco/runtime/sysvar - fd_sysvar_cache.c (source / functions) Hit Total Coverage
Test: cov.lcov Lines: 106 137 77.4 %
Date: 2026-10-22 18:10:43 Functions: 19 21 90.5 %

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

Generated by: LCOV version 1.14