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 : }