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 "fd_features_generated.h" 6 : #include "../accdb/fd_accdb.h" 7 : 8 : /* Macro FEATURE_ID_CNT expands to the number of features in 9 : fd_features_t. */ 10 : 11 : //#define FD_FEATURE_ID_CNT (... see generated.h ...) 12 : 13 : /* FD_FEATURE_DISABLED is the sentinel value of the feature activation 14 : slot when the feature has not yet been activated. */ 15 : 16 3351459 : #define FD_FEATURE_DISABLED (ULONG_MAX) 17 : 18 : /* Convenience macros for checking features */ 19 : 20 61608 : #define FD_FEATURE_ACTIVE_(_slot, _features, _feature_name) ( _slot >= (_features)-> _feature_name ) 21 : #define FD_FEATURE_JUST_ACTIVATED_(_slot, _features, _feature_name) ( _slot == (_features)-> _feature_name ) 22 3315 : #define FD_FEATURE_ACTIVE_OFFSET_(_slot, _features, _offset) ( _slot >= (_features)->f[_offset>>3] ) 23 792 : #define FD_FEATURE_JUST_ACTIVATED_OFFSET_(_slot, _features, _offset) ( _slot == (_features)->f[_offset>>3] ) 24 : 25 387 : #define FD_FEATURE_SET_ACTIVE(_features, _feature_name, _slot) ( (_features)-> _feature_name = _slot ) 26 528 : #define FD_FEATURE_ACTIVE_OFFSET(_slot, _features, _offset) FD_FEATURE_ACTIVE_OFFSET_( _slot, _features, _offset ) 27 792 : #define FD_FEATURE_JUST_ACTIVATED_OFFSET(_bank, _offset) FD_FEATURE_JUST_ACTIVATED_OFFSET_( (_bank)->f.slot, &(_bank)->f.features, _offset ) 28 39915 : #define FD_FEATURE_ACTIVE(_slot, _features, _feature_name) FD_FEATURE_ACTIVE_( _slot, _features, _feature_name ) 29 21111 : #define FD_FEATURE_ACTIVE_BANK(_bank, _feature_name) FD_FEATURE_ACTIVE_( (_bank)->f.slot, &(_bank)->f.features, _feature_name ) 30 0 : #define FD_FEATURE_ACTIVE_BANK_OFFSET(_bank, _offset) FD_FEATURE_ACTIVE_OFFSET_( (_bank)->f.slot, &(_bank)->f.features, _offset ) 31 : #define FD_FEATURE_JUST_ACTIVATED_BANK(_bank, _feature_name) FD_FEATURE_JUST_ACTIVATED_( (_bank)->f.slot, &(_bank)->f.features, _feature_name ) 32 : 33 : struct __attribute__((packed)) fd_feature { 34 : uchar is_active; /* 0 or 1 */ 35 : ulong activation_slot; 36 : }; 37 : 38 : typedef struct fd_feature fd_feature_t; 39 : 40 : /* fd_features_t is the current set of enabled feature flags. 41 : 42 : Each feature has a corresponding account in the account database, 43 : which are used to control activation. This structure contains an 44 : ulong of the activation slots of each feature for convenience (or 45 : FD_FEATURE_DISABLED if not yet activated). The feature params 46 : contained in this structure change over time, as activated features 47 : become default, and as new pending feature activations get added. 48 : 49 : Usage: 50 : 51 : fd_features_t * features; 52 : 53 : // Direct API 54 : ulong activation_slot = features->FEATURE_NAME; 55 : 56 : // Indirect API 57 : fd_feature_id_t const * id; 58 : ulong activation_slot = fd_features_get( id ); 59 : ... id->index safe in [0,FD_FEATURE_CNT) ... */ 60 : 61 : typedef union fd_features fd_features_t; 62 : 63 : /* fd_feature_id_t maps a feature ID (account address) to the byte 64 : offset in fd_features_t. */ 65 : 66 : struct fd_feature_id { 67 : ulong index; /* index of feature in fd_features_t */ 68 : fd_pubkey_t id; /* pubkey of feature */ 69 : char const * name; /* feature name cstr */ 70 : uchar cleaned_up; /* 1 if feature is cleaned up in firedancer, 0 otherwise */ 71 : uchar reverted; /* if the feature was reverted */ 72 : uchar hardcode_for_fuzzing; /* if the should be treated as hardcoded in the firedancer fuzzing harness */ 73 : }; 74 : typedef struct fd_feature_id fd_feature_id_t; 75 : 76 : FD_PROTOTYPES_BEGIN 77 : 78 : fd_feature_t * 79 : fd_feature_decode( fd_feature_t * feature, 80 : uchar const * data, 81 : ulong data_sz ); 82 : 83 : /* fd_feature_ids is the list of known feature IDs. 84 : The last element has offset==ULONG_MAX. */ 85 : extern fd_feature_id_t const ids[]; 86 : 87 : /* fd_features_disable_all disables all features (cleaned_up or not). */ 88 : 89 : void 90 : fd_features_disable_all( fd_features_t * f ); 91 : 92 : /* fd_features_enable_all enables all features (supported or not). */ 93 : 94 : void 95 : fd_features_enable_all( fd_features_t * ); 96 : 97 : /* fd_features_enable_cleaned_up enables all features marked as "hard 98 : coded". These are features that are baked into the current version 99 : of the Firedancer software and can't be disabled. */ 100 : 101 : void 102 : fd_features_enable_cleaned_up( fd_features_t * ); 103 : 104 : /* fd_features_enable_one_offs forces all manually passed in features to 105 : activate at slot. The feature will always stay activated. */ 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 12165 : fd_feature_iter_init( void ) { 124 12165 : return ids; 125 12165 : } 126 : 127 : static inline int 128 3545376 : fd_feature_iter_done( fd_feature_id_t const * id ) { 129 3545376 : return id->index == ULONG_MAX; 130 3545376 : } 131 : 132 : static inline fd_feature_id_t const * 133 3533211 : fd_feature_iter_next( fd_feature_id_t const * id ) { 134 3533211 : return id+1; 135 3533211 : } 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 3495060 : ulong slot ) { 143 3495060 : features->f[ id->index ] = slot; 144 3495060 : } 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 1794 : fd_feature_id_t const * id ) { 152 1794 : return features->f[ id->index ]; 153 1794 : } 154 : 155 : /* fd_features_get_activation_slot_from_offset returns the 156 : activation slot of the feature at byte offset `offset` within 157 : fd_features_t. 158 : 159 : Returns ULONG_MAX if the feature is not scheduled for activation. */ 160 : 161 : static inline ulong 162 : fd_features_get_activation_slot_from_offset( fd_features_t const * features, 163 71514 : ulong offset ) { 164 71514 : return features->f[ offset>>3 ]; 165 71514 : } 166 : 167 : /* fd_feature_id_query queries a feature ID given the first 8 bytes of 168 : the feature address (little-endian order). Returns pointer to ID in 169 : `ids` array on success, or NULL on failure. */ 170 : 171 : FD_FN_PURE fd_feature_id_t const * 172 : fd_feature_id_query( ulong prefix ); 173 : 174 : /* fd_features_restore loads all known feature accounts from the 175 : accounts database and populates the bank's in-memory feature set 176 : with their activation slots. If we're currently at the last slot 177 : before an epoch boundary, any pending features (is_active==0) will 178 : also be populated with slot+1 as their activation slot. Features 179 : forced on by fd_features_enable_one_offs stay activated. */ 180 : 181 : void 182 : fd_features_restore( fd_bank_t * bank, 183 : fd_accdb_t * accdb ); 184 : 185 : FD_PROTOTYPES_END 186 : 187 : #endif /* HEADER_fd_src_flamenco_features_fd_features_h */