20 #include <ripple/protocol/Feature.h>
22 #include <ripple/basics/Slice.h>
23 #include <ripple/basics/contract.h>
24 #include <ripple/protocol/digest.h>
25 #include <boost/container_hash/hash.hpp>
26 #include <boost/multi_index/hashed_index.hpp>
27 #include <boost/multi_index/key_extractors.hpp>
28 #include <boost/multi_index/random_access_index.hpp>
29 #include <boost/multi_index_container.hpp>
38 using namespace boost;
39 for (
auto const& n : feature)
40 hash_combine(seed, n);
46 enum class Supported : bool { no =
false, yes };
75 class FeatureCollections
84 : name(name_), feature(feature_)
103 template <
class tag,
typename Type, Type Feature::*PtrToMember>
104 using feature_hashed_unique = boost::multi_index::hashed_unique<
105 boost::multi_index::tag<tag>,
106 boost::multi_index::member<Feature, Type, PtrToMember>>;
109 using feature_indexing = boost::multi_index::indexed_by<
110 boost::multi_index::random_access<
111 boost::multi_index::tag<Feature::byIndex>>,
112 feature_hashed_unique<Feature::byFeature, uint256, &Feature::feature>,
113 feature_hashed_unique<Feature::byName, std::string, &Feature::name>>;
117 boost::multi_index::multi_index_container<Feature, feature_indexing>
128 getByIndex(
size_t i)
const
130 if (i >= features.size())
132 const auto& sequence = features.get<Feature::byIndex>();
136 getIndex(Feature
const& feature)
const
138 const auto& sequence = features.get<Feature::byIndex>();
139 auto const it_to = sequence.iterator_to(feature);
140 return it_to - sequence.begin();
143 getByFeature(
uint256 const& feature)
const
145 const auto& feature_index = features.get<Feature::byFeature>();
146 auto const feature_it = feature_index.find(feature);
147 return feature_it == feature_index.end() ? nullptr : &*feature_it;
152 const auto& name_index = features.get<Feature::byName>();
153 auto const name_it = name_index.find(name);
154 return name_it == name_index.end() ? nullptr : &*name_it;
158 FeatureCollections();
208 FeatureCollections::FeatureCollections()
214 FeatureCollections::getRegisteredFeature(
std::string const& name)
const
217 Feature
const* feature = getByName(name);
219 return feature->feature;
224 check(
bool condition,
const char* logicErrorMessage)
231 FeatureCollections::registerFeature(
236 check(!readOnly,
"Attempting to register a feature after startup.");
239 "Invalid feature parameters. Must be supported to be up-voted.");
240 Feature
const* i = getByName(name);
247 "More features defined than allocated. Adjust numFeatures in "
252 features.emplace_back(name, f);
254 if (support == Supported::yes)
256 supported.emplace(name, vote);
264 upVotes + downVotes == supported.size(),
265 "Feature counting logic broke");
267 supported.size() <= features.size(),
268 "More supported features than defined features");
278 FeatureCollections::registrationIsDone()
285 FeatureCollections::featureToBitsetIndex(
uint256 const& f)
const
289 Feature
const* feature = getByFeature(f);
293 return getIndex(*feature);
297 FeatureCollections::bitsetIndexToFeature(
size_t i)
const
300 Feature
const& feature = getByIndex(i);
301 return feature.feature;
305 FeatureCollections::featureToName(
uint256 const& f)
const
308 Feature
const* feature = getByFeature(f);
309 return feature ? feature->name :
to_string(f);
312 static FeatureCollections featureCollections;
322 return featureCollections.supportedAmendments();
329 return featureCollections.numDownVotedAmendments();
336 return featureCollections.numUpVotedAmendments();
344 return featureCollections.getRegisteredFeature(name);
350 return featureCollections.registerFeature(name, support, vote);
365 return featureCollections.registrationIsDone();
371 return featureCollections.featureToBitsetIndex(f);
377 return featureCollections.bitsetIndexToFeature(i);
383 return featureCollections.featureToName(f);
386 #pragma push_macro("REGISTER_FEATURE")
387 #undef REGISTER_FEATURE
394 #define REGISTER_FEATURE(fName, supported, votebehavior) \
395 uint256 const feature##fName = \
396 registerFeature(#fName, supported, votebehavior)
398 #pragma push_macro("REGISTER_FIX")
406 #define REGISTER_FIX(fName, supported, votebehavior) \
407 uint256 const fName = registerFeature(#fName, supported, votebehavior)
476 [[deprecated(
"The referenced amendment has been retired"), maybe_unused]]
497 #pragma pop_macro("REGISTER_FIX")
499 #undef REGISTER_FEATURE
500 #pragma pop_macro("REGISTER_FEATURE")
508 featureCollections.registrationIsDone();