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 480 : fd_sysvar_cache_new( void * mem ) { 7 : 8 480 : if( FD_UNLIKELY( !mem ) ) { 9 3 : FD_LOG_WARNING(( "NULL mem" )); 10 3 : return NULL; 11 3 : } 12 477 : 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 474 : fd_sysvar_cache_t * sysvar_cache = mem; 18 474 : sysvar_cache->magic = 0UL; 19 474 : memset( sysvar_cache->desc, 0, FD_SYSVAR_CACHE_ENTRY_CNT*sizeof(fd_sysvar_desc_t) ); 20 : 21 474 : FD_COMPILER_MFENCE(); 22 474 : sysvar_cache->magic = FD_SYSVAR_CACHE_MAGIC; 23 474 : FD_COMPILER_MFENCE(); 24 : 25 474 : return sysvar_cache; 26 477 : } 27 : 28 : fd_sysvar_cache_t * 29 486 : fd_sysvar_cache_join( void * mem ) { 30 : /* FIXME This is a good place to ref-count writable joins */ 31 486 : return (fd_sysvar_cache_t *)fd_sysvar_cache_join_const( mem ); 32 486 : } 33 : 34 : fd_sysvar_cache_t const * 35 495 : fd_sysvar_cache_join_const( void const * mem ) { 36 : 37 495 : if( FD_UNLIKELY( !mem ) ) { 38 6 : FD_LOG_WARNING(( "NULL mem" )); 39 6 : return NULL; 40 6 : } 41 489 : 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 483 : fd_sysvar_cache_t const * sysvar_cache = mem; 46 483 : 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 477 : return sysvar_cache; 52 483 : } 53 : 54 : void * 55 474 : fd_sysvar_cache_leave( fd_sysvar_cache_t * sysvar_cache ) { 56 474 : return sysvar_cache; 57 474 : } 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 18 : typet * out ) { \ 105 18 : ulong const idx = FD_SYSVAR_##name##_IDX; \ 106 18 : fd_sysvar_desc_t const * desc = &cache->desc[ idx ]; \ 107 18 : fd_sysvar_pos_t const * pos = &fd_sysvar_pos_tbl[ idx ]; \ 108 18 : if( FD_UNLIKELY( !( desc->flags & FD_SYSVAR_FLAG_VALID ) ) ) return NULL; \ 109 18 : memcpy( out, (uchar *)cache+pos->obj_off, pos->obj_max ); \ 110 3 : return out; \ 111 18 : } 112 : 113 : #define SIMPLE_SYSVAR( name, name2, type ) \ 114 : SIMPLE_SYSVAR_READ( name, name2, fd_##type##_t ) 115 15 : FD_SYSVAR_SIMPLE_ITER( SIMPLE_SYSVAR ) 116 15 : #undef SIMPLE_SYSVAR 117 15 : #undef SIMPLE_SYSVAR_READ 118 15 : 119 15 : fd_block_block_hash_entry_t const * /* deque */ 120 15 : fd_sysvar_cache_recent_hashes_join_const( 121 15 : fd_sysvar_cache_t const * cache 122 15 : ) { 123 0 : if( FD_UNLIKELY( !fd_sysvar_cache_recent_hashes_is_valid( cache ) ) ) return NULL; 124 0 : fd_recent_block_hashes_global_t * var = (void *)cache->obj_recent_hashes; 125 0 : fd_block_block_hash_entry_t * deq = deq_fd_block_block_hash_entry_t_join( (uchar *)var+var->hashes_offset ); 126 0 : if( FD_UNLIKELY( !deq ) ) FD_LOG_CRIT(( "recent blockhashes sysvar corruption detected" )); 127 0 : return deq; /* demote to const ptr */ 128 0 : } 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 0 : ) { 135 0 : (void)sysvar_cache; (void)hashes_deque; 136 0 : } 137 : 138 : fd_slot_hash_t const * 139 : fd_sysvar_cache_slot_hashes_join_const( 140 : fd_sysvar_cache_t const * cache 141 3 : ) { 142 3 : if( FD_UNLIKELY( !fd_sysvar_cache_slot_hashes_is_valid( cache ) ) ) return NULL; 143 0 : fd_slot_hashes_global_t * var = (void *)cache->obj_slot_hashes; 144 0 : 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 0 : if( FD_UNLIKELY( !deq ) ) FD_LOG_CRIT(( "slot hashes sysvar corruption detected" )); 147 0 : return deq; /* demote to const ptr */ 148 0 : } 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 0 : ) { 155 0 : (void)sysvar_cache; (void)slot_hashes; 156 0 : } 157 : 158 : fd_slot_history_global_t const * 159 : fd_sysvar_cache_slot_history_join_const( 160 : fd_sysvar_cache_t const * cache 161 3 : ) { 162 3 : if( FD_UNLIKELY( !fd_sysvar_cache_slot_history_is_valid( cache ) ) ) return NULL; 163 0 : return (void const *)( cache->obj_slot_history ); 164 3 : } 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 3 : ) { 178 3 : if( FD_UNLIKELY( !fd_sysvar_cache_stake_history_is_valid( cache ) ) ) return NULL; 179 0 : return (void const *)cache->obj_stake_history; 180 3 : } 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 465 : fd_sysvar_pos_t const * pos ) { 194 465 : desc->flags &= ~FD_SYSVAR_FLAG_VALID; 195 : 196 465 : uchar const * data = (uchar const *)cache + pos->data_off; 197 465 : ulong const data_sz = desc->data_sz; 198 : 199 465 : 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 465 : fd_bincode_decode_ctx_t ctx = { .data=data, .dataend=data+data_sz }; 207 465 : ulong obj_sz = 0UL; 208 465 : if( FD_UNLIKELY( pos->decode_footprint( &ctx, &obj_sz )!=FD_BINCODE_SUCCESS ) ) { 209 3 : FD_LOG_DEBUG(( "Failed to decode sysvar %s with data_sz=%lu: decode failed", 210 3 : pos->name, data_sz )); 211 3 : return EINVAL; 212 3 : } 213 462 : 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 462 : pos->decode( (uchar *)cache+pos->obj_off, &ctx ); 219 462 : desc->flags |= FD_SYSVAR_FLAG_VALID; 220 : 221 462 : FD_LOG_DEBUG(( "Restored sysvar %s (data_sz=%lu obj_sz=%lu)", 222 462 : pos->name, data_sz, obj_sz )); 223 462 : return 0; 224 462 : }