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