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 2682318 : #define FD_FEATURE_DISABLED (ULONG_MAX)
17 :
18 : /* Convenience macros for checking features */
19 :
20 4635277 : #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 3351 : #define FD_FEATURE_ACTIVE_OFFSET_(_slot, _features, _offset) ( _slot >= (_features)->f[_offset>>3] )
23 846 : #define FD_FEATURE_JUST_ACTIVATED_OFFSET_(_slot, _features, _offset) ( _slot == (_features)->f[_offset>>3] )
24 :
25 402 : #define FD_FEATURE_SET_ACTIVE(_features, _feature_name, _slot) ( (_features)-> _feature_name = _slot )
26 564 : #define FD_FEATURE_ACTIVE_OFFSET(_slot, _features, _offset) FD_FEATURE_ACTIVE_OFFSET_( _slot, _features, _offset )
27 846 : #define FD_FEATURE_JUST_ACTIVATED_OFFSET(_bank, _offset) FD_FEATURE_JUST_ACTIVATED_OFFSET_( (_bank)->f.slot, &(_bank)->f.features, _offset )
28 4612840 : #define FD_FEATURE_ACTIVE(_slot, _features, _feature_name) FD_FEATURE_ACTIVE_( _slot, _features, _feature_name )
29 21855 : #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 12030 : fd_feature_iter_init( void ) {
124 12030 : return ids;
125 12030 : }
126 :
127 : static inline int
128 3564471 : fd_feature_iter_done( fd_feature_id_t const * id ) {
129 3564471 : return id->index == ULONG_MAX;
130 3564471 : }
131 :
132 : static inline fd_feature_id_t const *
133 3552441 : fd_feature_iter_next( fd_feature_id_t const * id ) {
134 3552441 : return id+1;
135 3552441 : }
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 3618180 : ulong slot ) {
143 3618180 : features->f[ id->index ] = slot;
144 3618180 : }
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 5382 : fd_feature_id_t const * id ) {
152 5382 : return features->f[ id->index ];
153 5382 : }
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 72858 : ulong offset ) {
164 72858 : return features->f[ offset>>3 ];
165 72858 : }
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 given
175 : accounts database fork and populates the in-memory feature set with
176 : their activation slots. If slot is the last slot before an epoch
177 : boundary, any pending features (is_active==0) will also be populated
178 : with slot+1 as their activation slot. Features forced on by
179 : fd_features_enable_one_offs stay activated. */
180 :
181 : void
182 : fd_features_restore( fd_features_t * features,
183 : fd_accdb_t * accdb,
184 : fd_accdb_fork_id_t fork_id,
185 : ulong slot,
186 : fd_epoch_schedule_t const * epoch_schedule );
187 :
188 : /* fd_features_restore_chunk behaves like fd_features_restore but only
189 : restores one balanced, contiguous chunk of the known feature IDs.
190 : Assumes chunk_cnt>0 and chunk_idx<chunk_cnt. */
191 :
192 : void
193 : fd_features_restore_chunk( fd_features_t * features,
194 : fd_accdb_t * accdb,
195 : fd_accdb_fork_id_t fork_id,
196 : ulong slot,
197 : fd_epoch_schedule_t const * epoch_schedule,
198 : ulong chunk_idx,
199 : ulong chunk_cnt );
200 :
201 : FD_PROTOTYPES_END
202 :
203 : #endif /* HEADER_fd_src_flamenco_features_fd_features_h */
|