xrpld
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
64
65namespace xrpl {
66
67// Feature names must not exceed this length (in characters, excluding the null terminator).
68static constexpr std::size_t kMaxFeatureNameSize = 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* kN = fn();
83 // Note, std::strlen is not constexpr, we need to implement our own here.
84 constexpr std::size_t kLen = [](auto n) {
85 std::size_t ret = 0;
86 for (auto ptr = n; *ptr != '\0'; ret++, ++ptr)
87 ;
88 return ret;
89 }(kN);
90 return kLen != kReservedFeatureNameSize && //
91 kLen <= kMaxFeatureNameSize;
92}
93
94consteval auto
95validFeatureName(auto fn) -> bool
96{
97 constexpr char const* kN = 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 = kN; *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 = 1 };
111enum class AmendmentSupport : int { Retired = -1, Supported = 0, Unsupported = 1 };
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// NOLINTBEGIN(bugprone-macro-parentheses)
129#define XRPL_FEATURE(name, supported, vote) +1
130#define XRPL_FIX(name, supported, vote) +1
131#define XRPL_RETIRE_FEATURE(name) +1
132#define XRPL_RETIRE_FIX(name) +1
133// NOLINTEND(bugprone-macro-parentheses)
134
135// This value SHOULD be equal to the number of amendments registered in
136// Feature.cpp. Because it's only used to reserve storage, and determine how
137// large to make the FeatureBitset, it MAY be larger. It MUST NOT be less than
138// the actual number of amendments. A LogicError on startup will verify this.
139static constexpr std::size_t kNumFeatures =
140 (0 +
141#include <xrpl/protocol/detail/features.macro>
142 );
143
144#undef XRPL_RETIRE_FEATURE
145#pragma pop_macro("XRPL_RETIRE_FEATURE")
146#undef XRPL_RETIRE_FIX
147#pragma pop_macro("XRPL_RETIRE_FIX")
148#undef XRPL_FIX
149#pragma pop_macro("XRPL_FIX")
150#undef XRPL_FEATURE
151#pragma pop_macro("XRPL_FEATURE")
152
158
165
172
173} // namespace detail
174
177
178size_t
180
182bitsetIndexToFeature(size_t i);
183
185featureToName(uint256 const& f);
186
187class FeatureBitset : private std::bitset<detail::kNumFeatures>
188{
190
191 template <class... Fs>
192 void
193 initFromFeatures(uint256 const& f, Fs&&... fs)
194 {
195 set(f);
196 if constexpr (sizeof...(fs) > 0)
198 }
199
200public:
201 using base::bitset;
202 using base::operator==;
203
204 using base::all;
205 using base::any;
206 using base::count;
207 using base::flip;
208 using base::none;
209 using base::reset;
210 using base::set;
211 using base::size;
212 using base::test;
213 using base::operator[];
214 using base::to_string;
215 using base::to_ullong;
216 using base::to_ulong;
217
218 FeatureBitset() = default;
219
220 explicit FeatureBitset(base const& b) : base(b)
221 {
222 XRPL_ASSERT(b.count() == count(), "xrpl::FeatureBitset::FeatureBitset(base) : count match");
223 }
224
225 template <class... Fs>
226 explicit FeatureBitset(uint256 const& f, Fs&&... fs)
227 {
229 XRPL_ASSERT(
230 count() == (sizeof...(fs) + 1),
231 "xrpl::FeatureBitset::FeatureBitset(uint256) : count and "
232 "sizeof... do match");
233 }
234
235 template <class Col>
236 explicit FeatureBitset(Col const& fs)
237 {
238 for (auto const& f : fs)
240 XRPL_ASSERT(
241 fs.size() == count(),
242 "xrpl::FeatureBitset::FeatureBitset(Container auto) : count and "
243 "size do match");
244 }
245
246 auto
248 {
250 }
251
252 auto
253 operator[](uint256 const& f) const
254 {
256 }
257
259 set(uint256 const& f, bool value = true)
260 {
262 return *this;
263 }
264
266 reset(uint256 const& f)
267 {
269 return *this;
270 }
271
273 flip(uint256 const& f)
274 {
276 return *this;
277 }
278
281 {
282 base::operator&=(rhs);
283 return *this;
284 }
285
288 {
289 base::operator|=(rhs);
290 return *this;
291 }
292
294 operator~() const
295 {
297 }
298
299 friend FeatureBitset
300 operator&(FeatureBitset const& lhs, FeatureBitset const& rhs)
301 {
302 return FeatureBitset{static_cast<base const&>(lhs) & static_cast<base const&>(rhs)};
303 }
304
305 friend FeatureBitset
306 operator&(FeatureBitset const& lhs, uint256 const& rhs)
307 {
308 return lhs & FeatureBitset{rhs};
309 }
310
311 friend FeatureBitset
312 operator&(uint256 const& lhs, FeatureBitset const& rhs)
313 {
314 return FeatureBitset{lhs} & rhs;
315 }
316
317 friend FeatureBitset
318 operator|(FeatureBitset const& lhs, FeatureBitset const& rhs)
319 {
320 return FeatureBitset{static_cast<base const&>(lhs) | static_cast<base const&>(rhs)};
321 }
322
323 friend FeatureBitset
324 operator|(FeatureBitset const& lhs, uint256 const& rhs)
325 {
326 return lhs | FeatureBitset{rhs};
327 }
328
329 friend FeatureBitset
330 operator|(uint256 const& lhs, FeatureBitset const& rhs)
331 {
332 return FeatureBitset{lhs} | rhs;
333 }
334
335 friend FeatureBitset
336 operator^(FeatureBitset const& lhs, FeatureBitset const& rhs)
337 {
338 return FeatureBitset{static_cast<base const&>(lhs) ^ static_cast<base const&>(rhs)};
339 }
340
341 friend FeatureBitset
342 operator^(FeatureBitset const& lhs, uint256 const& rhs)
343 {
344 return lhs ^ FeatureBitset{rhs};
345 }
346
347 friend FeatureBitset
348 operator^(uint256 const& lhs, FeatureBitset const& rhs)
349 {
350 return FeatureBitset{lhs} ^ rhs;
351 }
352
353 // set difference
354 friend FeatureBitset
355 operator-(FeatureBitset const& lhs, FeatureBitset const& rhs)
356 {
357 return lhs & ~rhs;
358 }
359
360 friend FeatureBitset
361 operator-(FeatureBitset const& lhs, uint256 const& rhs)
362 {
363 return lhs - FeatureBitset{rhs};
364 }
365
366 friend FeatureBitset
367 operator-(uint256 const& lhs, FeatureBitset const& rhs)
368 {
369 return FeatureBitset{lhs} - rhs;
370 }
371};
372
373template <class F>
374void
376{
377 for (size_t i = 0; i < bs.size(); ++i)
378 {
379 if (bs[i])
381 }
382}
383
384#pragma push_macro("XRPL_FEATURE")
385#undef XRPL_FEATURE
386#pragma push_macro("XRPL_FIX")
387#undef XRPL_FIX
388#pragma push_macro("XRPL_RETIRE_FEATURE")
389#undef XRPL_RETIRE_FEATURE
390#pragma push_macro("XRPL_RETIRE_FIX")
391#undef XRPL_RETIRE_FIX
392
393#define XRPL_FEATURE(name, supported, vote) extern uint256 const feature##name;
394#define XRPL_FIX(name, supported, vote) extern uint256 const fix##name;
395#define XRPL_RETIRE_FEATURE(name)
396#define XRPL_RETIRE_FIX(name)
397
398#include <xrpl/protocol/detail/features.macro>
399
400#undef XRPL_RETIRE_FEATURE
401#pragma pop_macro("XRPL_RETIRE_FEATURE")
402#undef XRPL_RETIRE_FIX
403#pragma pop_macro("XRPL_RETIRE_FIX")
404#undef XRPL_FIX
405#pragma pop_macro("XRPL_FIX")
406#undef XRPL_FEATURE
407#pragma pop_macro("XRPL_FEATURE")
408
409} // namespace xrpl
friend FeatureBitset operator|(FeatureBitset const &lhs, FeatureBitset const &rhs)
Definition Feature.h:318
friend FeatureBitset operator&(FeatureBitset const &lhs, uint256 const &rhs)
Definition Feature.h:306
friend FeatureBitset operator-(FeatureBitset const &lhs, uint256 const &rhs)
Definition Feature.h:361
FeatureBitset(base const &b)
Definition Feature.h:220
friend FeatureBitset operator|(uint256 const &lhs, FeatureBitset const &rhs)
Definition Feature.h:330
T count(T... args)
FeatureBitset(Col const &fs)
Definition Feature.h:236
friend FeatureBitset operator^(FeatureBitset const &lhs, uint256 const &rhs)
Definition Feature.h:342
std::bitset< detail::kNumFeatures > base
Definition Feature.h:189
FeatureBitset & operator&=(FeatureBitset const &rhs)
Definition Feature.h:280
FeatureBitset operator~() const
Definition Feature.h:294
FeatureBitset(uint256 const &f, Fs &&... fs)
Definition Feature.h:226
FeatureBitset & flip(uint256 const &f)
Definition Feature.h:273
FeatureBitset()=default
T size(T... args)
friend FeatureBitset operator|(FeatureBitset const &lhs, uint256 const &rhs)
Definition Feature.h:324
friend FeatureBitset operator&(uint256 const &lhs, FeatureBitset const &rhs)
Definition Feature.h:312
friend FeatureBitset operator^(FeatureBitset const &lhs, FeatureBitset const &rhs)
Definition Feature.h:336
FeatureBitset & reset(uint256 const &f)
Definition Feature.h:266
friend FeatureBitset operator^(uint256 const &lhs, FeatureBitset const &rhs)
Definition Feature.h:348
auto operator[](uint256 const &f) const
Definition Feature.h:253
void initFromFeatures(uint256 const &f, Fs &&... fs)
Definition Feature.h:193
friend FeatureBitset operator&(FeatureBitset const &lhs, FeatureBitset const &rhs)
Definition Feature.h:300
FeatureBitset & set(uint256 const &f, bool value=true)
Definition Feature.h:259
friend FeatureBitset operator-(uint256 const &lhs, FeatureBitset const &rhs)
Definition Feature.h:367
FeatureBitset & operator|=(FeatureBitset const &rhs)
Definition Feature.h:287
friend FeatureBitset operator-(FeatureBitset const &lhs, FeatureBitset const &rhs)
Definition Feature.h:355
auto operator[](uint256 const &f)
Definition Feature.h:247
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:139
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:80
AmendmentSupport
Definition Feature.h:111
VoteBehavior
Definition Feature.h:110
size_t featureToBitsetIndex(uint256 const &f)
static constexpr std::size_t kReservedFeatureNameSize
Definition Feature.h:72
void foreachFeature(FeatureBitset bs, F &&f)
Definition Feature.h:375
static constexpr std::size_t kMaxFeatureNameSize
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)
BaseUInt< 256 > uint256
Definition base_uint.h:562