Line data Source code
1 : #ifndef HEADER_fd_src_flamenco_features_fd_features_h 2 : #define HEADER_fd_src_flamenco_features_fd_features_h 3 : 4 : #include "../fd_flamenco_base.h" 5 : #include "../types/fd_types.h" 6 : #include "fd_features_generated.h" 7 : #include "../accdb/fd_accdb_user.h" 8 : 9 : /* Macro FEATURE_ID_CNT expands to the number of features in 10 : fd_features_t. */ 11 : 12 : //#define FD_FEATURE_ID_CNT (... see generated.h ...) 13 : 14 : /* FD_FEATURE_DISABLED is the sentinel value of the feature activation 15 : slot when the feature has not yet been activated. */ 16 : 17 101370 : #define FD_FEATURE_DISABLED (ULONG_MAX) 18 : 19 : /* Convenience macros for checking features */ 20 : 21 12411 : #define FD_FEATURE_ACTIVE_(_slot, _features, _feature_name) ( _slot >= (_features)-> _feature_name ) 22 : #define FD_FEATURE_JUST_ACTIVATED_(_slot, _features, _feature_name) ( _slot == (_features)-> _feature_name ) 23 492 : #define FD_FEATURE_ACTIVE_OFFSET_(_slot, _features, _offset) ( _slot >= (_features)->f[_offset>>3] ) 24 180 : #define FD_FEATURE_JUST_ACTIVATED_OFFSET_(_slot, _features, _offset) ( _slot == (_features)->f[_offset>>3] ) 25 : 26 288 : #define FD_FEATURE_SET_ACTIVE(_features, _feature_name, _slot) ( (_features)-> _feature_name = _slot ) 27 396 : #define FD_FEATURE_ACTIVE_OFFSET(_slot, _features, _offset) FD_FEATURE_ACTIVE_OFFSET_( _slot, _features, _offset ) 28 180 : #define FD_FEATURE_JUST_ACTIVATED_OFFSET(_bank, _offset) FD_FEATURE_JUST_ACTIVATED_OFFSET_( fd_bank_slot_get( _bank ), fd_bank_features_query( _bank ), _offset ) 29 6036 : #define FD_FEATURE_ACTIVE(_slot, _features, _feature_name) FD_FEATURE_ACTIVE_( _slot, _features, _feature_name ) 30 1371 : #define FD_FEATURE_ACTIVE_BANK(_bank, _feature_name) FD_FEATURE_ACTIVE_( fd_bank_slot_get( _bank ), fd_bank_features_query( _bank ), _feature_name ) 31 6 : #define FD_FEATURE_ACTIVE_BANK_OFFSET(_bank, _offset) FD_FEATURE_ACTIVE_OFFSET_( fd_bank_slot_get( _bank ), fd_bank_features_query( _bank ), _offset ) 32 : #define FD_FEATURE_JUST_ACTIVATED_BANK(_bank, _feature_name) FD_FEATURE_JUST_ACTIVATED_( fd_bank_slot_get( _bank ), fd_bank_features_query( _bank ), _feature_name ) 33 : 34 : struct __attribute__((packed)) fd_feature { 35 : uchar is_active; /* 0 or 1 */ 36 : ulong activation_slot; 37 : }; 38 : 39 : typedef struct fd_feature fd_feature_t; 40 : 41 : /* fd_features_t is the current set of enabled feature flags. 42 : 43 : Each feature has a corresponding account in the account database, 44 : which are used to control activation. This structure contains an 45 : ulong of the activation slots of each feature for convenience (or 46 : FD_FEATURE_DISABLED if not yet activated). The feature params 47 : contained in this structure change over time, as activated features 48 : become default, and as new pending feature activations get added. 49 : 50 : Usage: 51 : 52 : fd_features_t * features; 53 : 54 : // Direct API 55 : ulong activation_slot = features->FEATURE_NAME; 56 : 57 : // Indirect API 58 : fd_feature_id_t const * id; 59 : ulong activation_slot = fd_features_get( id ); 60 : ... id->index safe in [0,FD_FEATURE_CNT) ... */ 61 : 62 : typedef union fd_features fd_features_t; 63 : 64 : /* fd_feature_id_t maps a feature ID (account address) to the byte 65 : offset in fd_features_t. */ 66 : 67 : struct fd_feature_id { 68 : ulong index; /* index of feature in fd_features_t */ 69 : fd_pubkey_t id; /* pubkey of feature */ 70 : char const * name; /* feature name cstr */ 71 : uchar cleaned_up; /* 1 if feature is cleaned up in firedancer, 0 otherwise */ 72 : uchar reverted; /* if the feature was reverted */ 73 : uchar hardcode_for_fuzzing; /* if the should be treated as hardcoded in the firedancer fuzzing harness */ 74 : }; 75 : typedef struct fd_feature_id fd_feature_id_t; 76 : 77 : FD_PROTOTYPES_BEGIN 78 : 79 : fd_feature_t * 80 : fd_feature_decode( fd_feature_t * feature, 81 : uchar const * data, 82 : ulong data_sz ); 83 : 84 : /* fd_feature_ids is the list of known feature IDs. 85 : The last element has offset==ULONG_MAX. */ 86 : extern fd_feature_id_t const ids[]; 87 : 88 : /* fd_features_disable_all disables all features (cleaned_up or not). */ 89 : 90 : void 91 : fd_features_disable_all( fd_features_t * f ); 92 : 93 : /* fd_features_enable_all enables all features (supported or not). */ 94 : 95 : void 96 : fd_features_enable_all( fd_features_t * ); 97 : 98 : /* fd_features_enable_cleaned_up enables all features marked as "hard 99 : coded". These are features that are baked into the current version 100 : of the Firedancer software and can't be disabled. */ 101 : 102 : void 103 : fd_features_enable_cleaned_up( fd_features_t * ); 104 : 105 : /* fd_features_enable_one_offs enables all manually passed in features. */ 106 : 107 : void 108 : fd_features_enable_one_offs( fd_features_t * features, 109 : char const * * one_offs, 110 : uint one_offs_cnt, 111 : ulong slot ); 112 : 113 : /* fd_feature_iter_{...} is an iterator-style API over all supported 114 : features in this version of Firedancer. Usage: 115 : 116 : for( fd_feature_id_t const * id = fd_feature_iter_init(); 117 : !fd_feature_iter_done( id ); 118 : id = fd_feature_iter_next( id ) ) { 119 : ... 120 : } */ 121 : 122 : static inline fd_feature_id_t const * 123 516 : fd_feature_iter_init( void ) { 124 516 : return ids; 125 516 : } 126 : 127 : static inline int 128 134160 : fd_feature_iter_done( fd_feature_id_t const * id ) { 129 134160 : return id->index == ULONG_MAX; 130 134160 : } 131 : 132 : static inline fd_feature_id_t const * 133 133644 : fd_feature_iter_next( fd_feature_id_t const * id ) { 134 133644 : return id+1; 135 133644 : } 136 : 137 : /* fd_features_set sets the activation slot of the given feature ID. */ 138 : 139 : static inline void 140 : fd_features_set( fd_features_t * features, 141 : fd_feature_id_t const * id, 142 104949 : ulong slot ) { 143 104949 : features->f[ id->index ] = slot; 144 104949 : } 145 : 146 : /* fd_features_get returns the activation slot of the given feature ID. 147 : Returns ULONG_MAX if the feature is not scheduled for activation. */ 148 : 149 : static inline ulong 150 : fd_features_get( fd_features_t const * features, 151 777 : fd_feature_id_t const * id ) { 152 777 : return features->f[ id->index ]; 153 777 : } 154 : 155 : /* fd_feature_id_query queries a feature ID given the first 8 bytes of 156 : the feature address (little-endian order). Returns pointer to ID in 157 : `ids` array on success, or NULL on failure. */ 158 : 159 : FD_FN_PURE fd_feature_id_t const * 160 : fd_feature_id_query( ulong prefix ); 161 : 162 : /* fd_features_restore loads all known feature accounts from the 163 : accounts database. This is used when initializing bank from a 164 : snapshot. */ 165 : 166 : void 167 : fd_features_restore( fd_bank_t * bank, 168 : fd_accdb_user_t * accdb, 169 : fd_funk_txn_xid_t const * xid ); 170 : 171 : FD_PROTOTYPES_END 172 : 173 : #endif /* HEADER_fd_src_flamenco_features_fd_features_h */