1#include <xrpl/basics/Slice.h>
2#include <xrpl/basics/base_uint.h>
3#include <xrpl/basics/contract.h>
4#include <xrpl/beast/utility/instrumentation.h>
5#include <xrpl/protocol/Feature.h>
6#include <xrpl/protocol/digest.h>
8#include <boost/container_hash/hash.hpp>
9#include <boost/multi_index/hashed_index.hpp>
10#include <boost/multi_index/indexed_by.hpp>
11#include <boost/multi_index/member.hpp>
12#include <boost/multi_index/random_access_index.hpp>
13#include <boost/multi_index/tag.hpp>
14#include <boost/multi_index_container.hpp>
28 using namespace boost;
29 for (
auto const& n : feature)
30 hash_combine(seed, n);
65class FeatureCollections
74 : name(name_), feature(feature_)
93 template <
class tag,
typename Type, Type Feature::* PtrToMember>
94 using feature_hashed_unique = boost::multi_index::hashed_unique<
95 boost::multi_index::tag<tag>,
96 boost::multi_index::member<Feature, Type, PtrToMember>>;
99 using feature_indexing = boost::multi_index::indexed_by<
100 boost::multi_index::random_access<boost::multi_index::tag<Feature::byIndex>>,
101 feature_hashed_unique<Feature::byFeature, uint256, &Feature::feature>,
102 feature_hashed_unique<Feature::byName, std::string, &Feature::name>>;
106 boost::multi_index::multi_index_container<Feature, feature_indexing> features;
117 getByIndex(
size_t i)
const
119 if (i >= features.size())
121 auto const& sequence = features.get<Feature::byIndex>();
125 getIndex(Feature
const& feature)
const
127 auto const& sequence = features.get<Feature::byIndex>();
128 auto const it_to = sequence.iterator_to(feature);
129 return it_to - sequence.begin();
132 getByFeature(
uint256 const& feature)
const
134 auto const& feature_index = features.get<Feature::byFeature>();
135 auto const feature_it = feature_index.find(feature);
136 return feature_it == feature_index.end() ? nullptr : &*feature_it;
141 auto const& name_index = features.get<Feature::byName>();
142 auto const name_it = name_index.find(name);
143 return name_it == name_index.end() ? nullptr : &*name_it;
147 FeatureCollections();
201FeatureCollections::FeatureCollections()
207FeatureCollections::getRegisteredFeature(
std::string const& name)
const
210 readOnly.
load(),
"xrpl::FeatureCollections::getRegisteredFeature : startup completed");
211 Feature
const* feature = getByName(name);
212 if (feature !=
nullptr)
213 return feature->feature;
218check(
bool condition,
char const* logicErrorMessage)
227 check(!readOnly,
"Attempting to register a feature after startup.");
230 "Invalid feature parameters. Must be supported to be up-voted.");
231 Feature
const* i = getByName(name);
238 features.emplace_back(name, f);
240 auto const getAmendmentSupport = [=]() {
246 all.emplace(name, getAmendmentSupport());
248 if (support == Supported::yes)
250 supported.emplace(name, vote);
261 check(upVotes + downVotes == supported.size(),
"Feature counting logic broke");
262 check(supported.size() <= features.size(),
"More supported features than defined features");
263 check(features.size() == all.size(),
"The 'all' features list is populated incorrectly");
273FeatureCollections::registrationIsDone()
280FeatureCollections::featureToBitsetIndex(
uint256 const& f)
const
283 readOnly.
load(),
"xrpl::FeatureCollections::featureToBitsetIndex : startup completed");
285 Feature
const* feature = getByFeature(f);
286 if (feature ==
nullptr)
289 return getIndex(*feature);
293FeatureCollections::bitsetIndexToFeature(
size_t i)
const
296 readOnly.
load(),
"xrpl::FeatureCollections::bitsetIndexToFeature : startup completed");
297 Feature
const& feature = getByIndex(i);
298 return feature.feature;
302FeatureCollections::featureToName(
uint256 const& f)
const
304 XRPL_ASSERT(readOnly.
load(),
"xrpl::FeatureCollections::featureToName : startup completed");
305 Feature
const* feature = getByFeature(f);
306 return (feature !=
nullptr) ? feature->name :
to_string(f);
309FeatureCollections featureCollections;
317 return featureCollections.allAmendments();
326 return featureCollections.supportedAmendments();
333 return featureCollections.numDownVotedAmendments();
340 return featureCollections.numUpVotedAmendments();
348 return featureCollections.getRegisteredFeature(name);
354 return featureCollections.registerFeature(name, support, vote);
369 return featureCollections.registrationIsDone();
375 return featureCollections.featureToBitsetIndex(f);
381 return featureCollections.bitsetIndexToFeature(i);
387 return featureCollections.featureToName(f);
393#pragma push_macro("XRPL_FEATURE")
395#pragma push_macro("XRPL_FIX")
397#pragma push_macro("XRPL_RETIRE_FEATURE")
398#undef XRPL_RETIRE_FEATURE
399#pragma push_macro("XRPL_RETIRE_FIX")
400#undef XRPL_RETIRE_FIX
410#define XRPL_FEATURE(name, supported, vote) \
411 uint256 const feature##name = \
412 registerFeature(enforceValidFeatureName([] { return #name; }), supported, vote);
413#define XRPL_FIX(name, supported, vote) \
414 uint256 const fix##name = \
415 registerFeature(enforceValidFeatureName([] { return "fix" #name; }), supported, vote);
418#define XRPL_RETIRE_FEATURE(name) \
419 [[deprecated("The referenced feature amendment has been retired")]] \
421 uint256 const retiredFeature##name = retireFeature(#name);
423#define XRPL_RETIRE_FIX(name) \
424 [[deprecated("The referenced fix amendment has been retired")]] \
426 uint256 const retiredFix##name = retireFeature("fix" #name);
429#include <xrpl/protocol/detail/features.macro>
431#undef XRPL_RETIRE_FEATURE
432#pragma pop_macro("XRPL_RETIRE_FEATURE")
433#undef XRPL_RETIRE_FIX
434#pragma pop_macro("XRPL_RETIRE_FIX")
436#pragma pop_macro("XRPL_FIX")
438#pragma pop_macro("XRPL_FEATURE")
445[[maybe_unused]]
static bool const readOnlySet = featureCollections.registrationIsDone();
void check(bool condition, std::string const &message)
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
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
uint256 registerFeature(std::string const &name, Supported support, VoteBehavior vote)
consteval auto validFeatureNameSize(auto fn) -> bool
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
uint256 retireFeature(std::string const &name)
std::string to_string(base_uint< Bits, Tag > const &a)
static bool const readOnlySet
size_t featureToBitsetIndex(uint256 const &f)
bool registrationIsDone()
Tell FeatureCollections when registration is complete.
consteval auto enforceValidFeatureName(auto fn) -> char const *
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
std::optional< uint256 > getRegisteredFeature(std::string const &name)
std::size_t hash_value(xrpl::uint256 const &feature)