diff --git a/include/xrpl/protocol/Feature.h b/include/xrpl/protocol/Feature.h index c55776a5ce..5844a70eb0 100644 --- a/include/xrpl/protocol/Feature.h +++ b/include/xrpl/protocol/Feature.h @@ -53,19 +53,19 @@ * then change the macro parameter in features.macro to * `VoteBehavior::DefaultYes`. The communication process is beyond * the scope of these instructions. + + * 5) If a supported feature (`Supported::yes`) was _ever_ in a released + * version, it can never be changed back to `Supported::no`, because + * it _may_ still become enabled at any time. This would cause newer + * versions of `rippled` to become amendment blocked. + * Instead, to prevent newer versions from voting on the feature, use + * `VoteBehavior::Obsolete`. Obsolete features can not be voted for + * by any versions of `rippled` built with that setting, but will still + * work correctly if they get enabled. If a feature remains obsolete + * for long enough that _all_ clients that could vote for it are + * amendment blocked, the feature can be removed from the code + * as if it was unsupported. * - * 5) A feature marked as Obsolete can mean either: - * 1) It is in the ledger (marked as Supported::yes) and it is on its way to - * become Retired - * 2) The feature is not in the ledger (has always been marked as - * Supported::no) and the code to support it has been removed - * - * If we want to discontinue a feature that we've never fully supported and - * the feature has never been enabled, we should remove all the related - * code, and mark the feature as "abandoned". To do this: - * - * 1) Open features.macro, move the feature to the abandoned section and - * change the macro to XRPL_ABANDON * * When a feature has been enabled for several years, the conditional code * may be removed, and the feature "retired". To retire a feature: @@ -99,13 +99,10 @@ namespace detail { #undef XRPL_FIX #pragma push_macro("XRPL_RETIRE") #undef XRPL_RETIRE -#pragma push_macro("XRPL_ABANDON") -#undef XRPL_ABANDON #define XRPL_FEATURE(name, supported, vote) +1 #define XRPL_FIX(name, supported, vote) +1 #define XRPL_RETIRE(name) +1 -#define XRPL_ABANDON(name) +1 // This value SHOULD be equal to the number of amendments registered in // Feature.cpp. Because it's only used to reserve storage, and determine how @@ -122,8 +119,6 @@ static constexpr std::size_t numFeatures = #pragma pop_macro("XRPL_FIX") #undef XRPL_FEATURE #pragma pop_macro("XRPL_FEATURE") -#undef XRPL_ABANDON -#pragma pop_macro("XRPL_ABANDON") /** Amendments that this server supports and the default voting behavior. Whether they are enabled depends on the Rules defined in the validated @@ -365,13 +360,10 @@ foreachFeature(FeatureBitset bs, F&& f) #undef XRPL_FIX #pragma push_macro("XRPL_RETIRE") #undef XRPL_RETIRE -#pragma push_macro("XRPL_ABANDON") -#undef XRPL_ABANDON #define XRPL_FEATURE(name, supported, vote) extern uint256 const feature##name; #define XRPL_FIX(name, supported, vote) extern uint256 const fix##name; #define XRPL_RETIRE(name) -#define XRPL_ABANDON(name) #include @@ -381,8 +373,6 @@ foreachFeature(FeatureBitset bs, F&& f) #pragma pop_macro("XRPL_FIX") #undef XRPL_FEATURE #pragma pop_macro("XRPL_FEATURE") -#undef XRPL_ABANDON -#pragma pop_macro("XRPL_ABANDON") } // namespace ripple diff --git a/include/xrpl/protocol/detail/features.macro b/include/xrpl/protocol/detail/features.macro index 63c1b2258b..c83dacfa73 100644 --- a/include/xrpl/protocol/detail/features.macro +++ b/include/xrpl/protocol/detail/features.macro @@ -26,9 +26,6 @@ #if !defined(XRPL_RETIRE) #error "undefined macro: XRPL_RETIRE" #endif -#if !defined(XRPL_ABANDON) -#error "undefined macro: XRPL_ABANDON" -#endif // Add new amendments to the top of this list. // Keep it sorted in reverse chronological order. @@ -133,11 +130,6 @@ XRPL_FIX (NFTokenDirV1, Supported::yes, VoteBehavior::Obsolete) XRPL_FEATURE(NonFungibleTokensV1, Supported::yes, VoteBehavior::Obsolete) XRPL_FEATURE(CryptoConditionsSuite, Supported::yes, VoteBehavior::Obsolete) -// The following amendments were never supported, never enabled, and -// we've abanded them. These features should never be in the ledger, -// and we've removed all the related code. -XRPL_ABANDON(OwnerPaysFee) - // The following amendments have been active for at least two years. Their // pre-amendment code has been removed and the identifiers are deprecated. // All known amendments and amendments that may appear in a validated diff --git a/src/libxrpl/protocol/Feature.cpp b/src/libxrpl/protocol/Feature.cpp index 478b155387..eeeee1c185 100644 --- a/src/libxrpl/protocol/Feature.cpp +++ b/src/libxrpl/protocol/Feature.cpp @@ -254,7 +254,7 @@ FeatureCollections::registerFeature( { check(!readOnly, "Attempting to register a feature after startup."); check( - support == Supported::yes || vote != VoteBehavior::DefaultYes, + support == Supported::yes || vote == VoteBehavior::DefaultNo, "Invalid feature parameters. Must be supported to be up-voted."); Feature const* i = getByName(name); if (!i) @@ -268,7 +268,7 @@ FeatureCollections::registerFeature( features.emplace_back(name, f); auto const getAmendmentSupport = [=]() { - if (vote == VoteBehavior::Obsolete && support == Supported::yes) + if (vote == VoteBehavior::Obsolete) return AmendmentSupport::Retired; return support == Supported::yes ? AmendmentSupport::Supported : AmendmentSupport::Unsupported; @@ -398,14 +398,6 @@ retireFeature(std::string const& name) return registerFeature(name, Supported::yes, VoteBehavior::Obsolete); } -// Abandoned features are not in the ledger and have no code controlled by the -// feature. They were never supported, and cannot be voted on. -uint256 -abandonFeature(std::string const& name) -{ - return registerFeature(name, Supported::no, VoteBehavior::Obsolete); -} - /** Tell FeatureCollections when registration is complete. */ bool registrationIsDone() @@ -440,8 +432,6 @@ featureToName(uint256 const& f) #undef XRPL_FIX #pragma push_macro("XRPL_RETIRE") #undef XRPL_RETIRE -#pragma push_macro("XRPL_ABANDON") -#undef XRPL_ABANDON #define XRPL_FEATURE(name, supported, vote) \ uint256 const feature##name = registerFeature(#name, supported, vote); @@ -453,11 +443,6 @@ featureToName(uint256 const& f) [[deprecated("The referenced amendment has been retired")]] \ [[maybe_unused]] \ uint256 const retired##name = retireFeature(#name); - -#define XRPL_ABANDON(name) \ - [[deprecated("The referenced amendment has been abandoned")]] \ - [[maybe_unused]] \ - uint256 const abandoned##name = abandonFeature(#name); // clang-format on #include @@ -468,8 +453,6 @@ featureToName(uint256 const& f) #pragma pop_macro("XRPL_FIX") #undef XRPL_FEATURE #pragma pop_macro("XRPL_FEATURE") -#undef XRPL_ABANDON -#pragma pop_macro("XRPL_ABANDON") // All of the features should now be registered, since variables in a cpp file // are initialized from top to bottom.