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