rippled
Loading...
Searching...
No Matches
Feature.h
1#pragma once
2
3#include <xrpl/basics/base_uint.h>
4
5#include <boost/container/flat_map.hpp>
6
7#include <bitset>
8#include <map>
9#include <optional>
10#include <string>
11
65namespace xrpl {
66
67// Feature names must not exceed this length (in characters, excluding the null terminator).
68static constexpr std::size_t maxFeatureNameSize = 63;
69// Reserve this exact feature-name length (in characters/bytes, excluding the null terminator)
70// so that a 32-byte uint256 (for example, in WASM or other interop contexts) can be used
71// as a compact, fixed-size feature selector without conflicting with human-readable names.
73
74// Both validFeatureNameSize and validFeatureName are consteval functions that can be used in
75// static_asserts to validate feature names at compile time. They are only used inside
76// enforceValidFeatureName in Feature.cpp, but are exposed here for testing. The expected
77// parameter `auto fn` is a constexpr lambda which returns a const char*, making it available
78// for compile-time evaluation. Read more in https://accu.org/journals/overload/30/172/wu/
79consteval auto
80validFeatureNameSize(auto fn) -> bool
81{
82 constexpr char const* n = fn();
83 // Note, std::strlen is not constexpr, we need to implement our own here.
84 constexpr std::size_t N = [](auto n) {
85 std::size_t ret = 0;
86 for (auto ptr = n; *ptr != '\0'; ret++, ++ptr)
87 ;
88 return ret;
89 }(n);
90 return N != reservedFeatureNameSize && //
92}
93
94consteval auto
95validFeatureName(auto fn) -> bool
96{
97 constexpr char const* n = fn();
98 // Prevent the use of visually confusable characters and enforce that feature names
99 // are always valid ASCII. This is needed because C++ allows Unicode identifiers.
100 // Characters below 0x20 are nonprintable control characters, and characters with the 0x80 bit
101 // set are non-ASCII (e.g. UTF-8 encoding of Unicode), so both are disallowed.
102 for (auto ptr = n; *ptr != '\0'; ++ptr)
103 {
104 if (*ptr & 0x80 || *ptr < 0x20)
105 return false;
106 }
107 return true;
108}
109
110enum class VoteBehavior : int { Obsolete = -1, DefaultNo = 0, DefaultYes };
111enum class AmendmentSupport : int { Retired = -1, Supported = 0, Unsupported };
112
116
117namespace detail {
118
119#pragma push_macro("XRPL_FEATURE")
120#undef XRPL_FEATURE
121#pragma push_macro("XRPL_FIX")
122#undef XRPL_FIX
123#pragma push_macro("XRPL_RETIRE_FEATURE")
124#undef XRPL_RETIRE_FEATURE
125#pragma push_macro("XRPL_RETIRE_FIX")
126#undef XRPL_RETIRE_FIX
127
128#define XRPL_FEATURE(name, supported, vote) +1
129#define XRPL_FIX(name, supported, vote) +1
130#define XRPL_RETIRE_FEATURE(name) +1
131#define XRPL_RETIRE_FIX(name) +1
132
133// This value SHOULD be equal to the number of amendments registered in
134// Feature.cpp. Because it's only used to reserve storage, and determine how
135// large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than
136// the actual number of amendments. A LogicError on startup will verify this.
137static constexpr std::size_t numFeatures =
138 (0 +
139#include <xrpl/protocol/detail/features.macro>
140 );
141
142#undef XRPL_RETIRE_FEATURE
143#pragma pop_macro("XRPL_RETIRE_FEATURE")
144#undef XRPL_RETIRE_FIX
145#pragma pop_macro("XRPL_RETIRE_FIX")
146#undef XRPL_FIX
147#pragma pop_macro("XRPL_FIX")
148#undef XRPL_FEATURE
149#pragma pop_macro("XRPL_FEATURE")
150
156
163
170
171} // namespace detail
172
175
176size_t
178
180bitsetIndexToFeature(size_t i);
181
183featureToName(uint256 const& f);
184
185class FeatureBitset : private std::bitset<detail::numFeatures>
186{
188
189 template <class... Fs>
190 void
191 initFromFeatures(uint256 const& f, Fs&&... fs)
192 {
193 set(f);
194 if constexpr (sizeof...(fs) > 0)
196 }
197
198public:
199 using base::bitset;
200 using base::operator==;
201
202 using base::all;
203 using base::any;
204 using base::count;
205 using base::flip;
206 using base::none;
207 using base::reset;
208 using base::set;
209 using base::size;
210 using base::test;
211 using base::operator[];
212 using base::to_string;
213 using base::to_ullong;
214 using base::to_ulong;
215
216 FeatureBitset() = default;
217
218 explicit FeatureBitset(base const& b) : base(b)
219 {
220 XRPL_ASSERT(b.count() == count(), "xrpl::FeatureBitset::FeatureBitset(base) : count match");
221 }
222
223 template <class... Fs>
224 explicit FeatureBitset(uint256 const& f, Fs&&... fs)
225 {
227 XRPL_ASSERT(
228 count() == (sizeof...(fs) + 1),
229 "xrpl::FeatureBitset::FeatureBitset(uint256) : count and "
230 "sizeof... do match");
231 }
232
233 template <class Col>
234 explicit FeatureBitset(Col const& fs)
235 {
236 for (auto const& f : fs)
238 XRPL_ASSERT(
239 fs.size() == count(),
240 "xrpl::FeatureBitset::FeatureBitset(Container auto) : count and "
241 "size do match");
242 }
243
244 auto
246 {
248 }
249
250 auto
251 operator[](uint256 const& f) const
252 {
254 }
255
257 set(uint256 const& f, bool value = true)
258 {
260 return *this;
261 }
262
264 reset(uint256 const& f)
265 {
267 return *this;
268 }
269
271 flip(uint256 const& f)
272 {
274 return *this;
275 }
276
279 {
280 base::operator&=(rhs);
281 return *this;
282 }
283
286 {
287 base::operator|=(rhs);
288 return *this;
289 }
290
292 operator~() const
293 {
295 }
296
297 friend FeatureBitset
298 operator&(FeatureBitset const& lhs, FeatureBitset const& rhs)
299 {
300 return FeatureBitset{static_cast<base const&>(lhs) & static_cast<base const&>(rhs)};
301 }
302
303 friend FeatureBitset
304 operator&(FeatureBitset const& lhs, uint256 const& rhs)
305 {
306 return lhs & FeatureBitset{rhs};
307 }
308
309 friend FeatureBitset
310 operator&(uint256 const& lhs, FeatureBitset const& rhs)
311 {
312 return FeatureBitset{lhs} & rhs;
313 }
314
315 friend FeatureBitset
316 operator|(FeatureBitset const& lhs, FeatureBitset const& rhs)
317 {
318 return FeatureBitset{static_cast<base const&>(lhs) | static_cast<base const&>(rhs)};
319 }
320
321 friend FeatureBitset
322 operator|(FeatureBitset const& lhs, uint256 const& rhs)
323 {
324 return lhs | FeatureBitset{rhs};
325 }
326
327 friend FeatureBitset
328 operator|(uint256 const& lhs, FeatureBitset const& rhs)
329 {
330 return FeatureBitset{lhs} | rhs;
331 }
332
333 friend FeatureBitset
334 operator^(FeatureBitset const& lhs, FeatureBitset const& rhs)
335 {
336 return FeatureBitset{static_cast<base const&>(lhs) ^ static_cast<base const&>(rhs)};
337 }
338
339 friend FeatureBitset
340 operator^(FeatureBitset const& lhs, uint256 const& rhs)
341 {
342 return lhs ^ FeatureBitset{rhs};
343 }
344
345 friend FeatureBitset
346 operator^(uint256 const& lhs, FeatureBitset const& rhs)
347 {
348 return FeatureBitset{lhs} ^ rhs;
349 }
350
351 // set difference
352 friend FeatureBitset
353 operator-(FeatureBitset const& lhs, FeatureBitset const& rhs)
354 {
355 return lhs & ~rhs;
356 }
357
358 friend FeatureBitset
359 operator-(FeatureBitset const& lhs, uint256 const& rhs)
360 {
361 return lhs - FeatureBitset{rhs};
362 }
363
364 friend FeatureBitset
365 operator-(uint256 const& lhs, FeatureBitset const& rhs)
366 {
367 return FeatureBitset{lhs} - rhs;
368 }
369};
370
371template <class F>
372void
374{
375 for (size_t i = 0; i < bs.size(); ++i)
376 if (bs[i])
378}
379
380#pragma push_macro("XRPL_FEATURE")
381#undef XRPL_FEATURE
382#pragma push_macro("XRPL_FIX")
383#undef XRPL_FIX
384#pragma push_macro("XRPL_RETIRE_FEATURE")
385#undef XRPL_RETIRE_FEATURE
386#pragma push_macro("XRPL_RETIRE_FIX")
387#undef XRPL_RETIRE_FIX
388
389#define XRPL_FEATURE(name, supported, vote) extern uint256 const feature##name;
390#define XRPL_FIX(name, supported, vote) extern uint256 const fix##name;
391#define XRPL_RETIRE_FEATURE(name)
392#define XRPL_RETIRE_FIX(name)
393
394#include <xrpl/protocol/detail/features.macro>
395
396#undef XRPL_RETIRE_FEATURE
397#pragma pop_macro("XRPL_RETIRE_FEATURE")
398#undef XRPL_RETIRE_FIX
399#pragma pop_macro("XRPL_RETIRE_FIX")
400#undef XRPL_FIX
401#pragma pop_macro("XRPL_FIX")
402#undef XRPL_FEATURE
403#pragma pop_macro("XRPL_FEATURE")
404
405} // namespace xrpl
friend FeatureBitset operator|(FeatureBitset const &lhs, FeatureBitset const &rhs)
Definition Feature.h:316
friend FeatureBitset operator&(FeatureBitset const &lhs, uint256 const &rhs)
Definition Feature.h:304
friend FeatureBitset operator-(FeatureBitset const &lhs, uint256 const &rhs)
Definition Feature.h:359
FeatureBitset(base const &b)
Definition Feature.h:218
friend FeatureBitset operator|(uint256 const &lhs, FeatureBitset const &rhs)
Definition Feature.h:328
FeatureBitset(Col const &fs)
Definition Feature.h:234
friend FeatureBitset operator^(FeatureBitset const &lhs, uint256 const &rhs)
Definition Feature.h:340
FeatureBitset & operator&=(FeatureBitset const &rhs)
Definition Feature.h:278
FeatureBitset operator~() const
Definition Feature.h:292
FeatureBitset(uint256 const &f, Fs &&... fs)
Definition Feature.h:224
FeatureBitset & flip(uint256 const &f)
Definition Feature.h:271
FeatureBitset()=default
friend FeatureBitset operator|(FeatureBitset const &lhs, uint256 const &rhs)
Definition Feature.h:322
friend FeatureBitset operator&(uint256 const &lhs, FeatureBitset const &rhs)
Definition Feature.h:310
friend FeatureBitset operator^(FeatureBitset const &lhs, FeatureBitset const &rhs)
Definition Feature.h:334
FeatureBitset & reset(uint256 const &f)
Definition Feature.h:264
friend FeatureBitset operator^(uint256 const &lhs, FeatureBitset const &rhs)
Definition Feature.h:346
auto operator[](uint256 const &f) const
Definition Feature.h:251
void initFromFeatures(uint256 const &f, Fs &&... fs)
Definition Feature.h:191
friend FeatureBitset operator&(FeatureBitset const &lhs, FeatureBitset const &rhs)
Definition Feature.h:298
FeatureBitset & set(uint256 const &f, bool value=true)
Definition Feature.h:257
friend FeatureBitset operator-(uint256 const &lhs, FeatureBitset const &rhs)
Definition Feature.h:365
FeatureBitset & operator|=(FeatureBitset const &rhs)
Definition Feature.h:285
friend FeatureBitset operator-(FeatureBitset const &lhs, FeatureBitset const &rhs)
Definition Feature.h:353
auto operator[](uint256 const &f)
Definition Feature.h:245
T is_same_v
std::size_t numDownVotedAmendments()
Amendments that this server won't vote for by default.
std::map< std::string, VoteBehavior > const & supportedAmendments()
Amendments that this server supports and the default voting behavior.
std::size_t numUpVotedAmendments()
Amendments that this server will vote for by default.
static constexpr std::size_t numFeatures
Definition Feature.h:137
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
consteval auto validFeatureNameSize(auto fn) -> bool
Definition Feature.h:80
AmendmentSupport
Definition Feature.h:111
VoteBehavior
Definition Feature.h:110
static constexpr std::size_t reservedFeatureNameSize
Definition Feature.h:72
size_t featureToBitsetIndex(uint256 const &f)
void foreachFeature(FeatureBitset bs, F &&f)
Definition Feature.h:373
static constexpr std::size_t maxFeatureNameSize
Definition Feature.h:68
std::map< std::string, AmendmentSupport > const & allAmendments()
All amendments libxrpl knows about.
std::string featureToName(uint256 const &f)
uint256 bitsetIndexToFeature(size_t i)
consteval auto validFeatureName(auto fn) -> bool
Definition Feature.h:95
std::optional< uint256 > getRegisteredFeature(std::string const &name)