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_user.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 2347941 : #define FD_FEATURE_DISABLED (ULONG_MAX) 17 : 18 : /* Convenience macros for checking features */ 19 : 20 81096 : #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 2898 : #define FD_FEATURE_ACTIVE_OFFSET_(_slot, _features, _offset) ( _slot >= (_features)->f[_offset>>3] ) 23 387 : #define FD_FEATURE_JUST_ACTIVATED_OFFSET_(_slot, _features, _offset) ( _slot == (_features)->f[_offset>>3] ) 24 : 25 600 : #define FD_FEATURE_SET_ACTIVE(_features, _feature_name, _slot) ( (_features)-> _feature_name = _slot ) 26 294 : #define FD_FEATURE_ACTIVE_OFFSET(_slot, _features, _offset) FD_FEATURE_ACTIVE_OFFSET_( _slot, _features, _offset ) 27 387 : #define FD_FEATURE_JUST_ACTIVATED_OFFSET(_bank, _offset) FD_FEATURE_JUST_ACTIVATED_OFFSET_( (_bank)->f.slot, &(_bank)->f.features, _offset ) 28 49530 : #define FD_FEATURE_ACTIVE(_slot, _features, _feature_name) FD_FEATURE_ACTIVE_( _slot, _features, _feature_name ) 29 31536 : #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 enables all manually passed in features. */ 105 : 106 : void 107 : fd_features_enable_one_offs( fd_features_t * features, 108 : char const * * one_offs, 109 : uint one_offs_cnt, 110 : ulong slot ); 111 : 112 : /* fd_feature_iter_{...} is an iterator-style API over all supported 113 : features in this version of Firedancer. Usage: 114 : 115 : for( fd_feature_id_t const * id = fd_feature_iter_init(); 116 : !fd_feature_iter_done( id ); 117 : id = fd_feature_iter_next( id ) ) { 118 : ... 119 : } */ 120 : 121 : static inline fd_feature_id_t const * 122 11208 : fd_feature_iter_init( void ) { 123 11208 : return ids; 124 11208 : } 125 : 126 : static inline int 127 3076464 : fd_feature_iter_done( fd_feature_id_t const * id ) { 128 3076464 : return id->index == ULONG_MAX; 129 3076464 : } 130 : 131 : static inline fd_feature_id_t const * 132 3065256 : fd_feature_iter_next( fd_feature_id_t const * id ) { 133 3065256 : return id+1; 134 3065256 : } 135 : 136 : /* fd_features_set sets the activation slot of the given feature ID. */ 137 : 138 : static inline void 139 : fd_features_set( fd_features_t * features, 140 : fd_feature_id_t const * id, 141 3048948 : ulong slot ) { 142 3048948 : features->f[ id->index ] = slot; 143 3048948 : } 144 : 145 : /* fd_features_get returns the activation slot of the given feature ID. 146 : Returns ULONG_MAX if the feature is not scheduled for activation. */ 147 : 148 : static inline ulong 149 : fd_features_get( fd_features_t const * features, 150 1656 : fd_feature_id_t const * id ) { 151 1656 : return features->f[ id->index ]; 152 1656 : } 153 : 154 : /* fd_feature_id_query queries a feature ID given the first 8 bytes of 155 : the feature address (little-endian order). Returns pointer to ID in 156 : `ids` array on success, or NULL on failure. */ 157 : 158 : FD_FN_PURE fd_feature_id_t const * 159 : fd_feature_id_query( ulong prefix ); 160 : 161 : /* fd_features_restore loads all known feature accounts from the 162 : accounts database and populates the bank's in-memory feature set 163 : with their activation slots. If we're currently at the last slot 164 : before an epoch boundary, any pending features (is_active==0) will 165 : also be populated with slot+1 as their activation slot. */ 166 : 167 : void 168 : fd_features_restore( fd_bank_t * bank, 169 : fd_accdb_user_t * accdb, 170 : fd_funk_txn_xid_t const * xid ); 171 : 172 : FD_PROTOTYPES_END 173 : 174 : #endif /* HEADER_fd_src_flamenco_features_fd_features_h */