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