Skip to content

Commit

Permalink
Internal amendment vetoes:
Browse files Browse the repository at this point in the history
* Allows a version to have the code to support a given amendment, but
  not vote for it by default. This allows the amendment to be enabled in
  a future version without necessarily amendment blocking these older
  versions.
* Provides a new configuration file section: [unveto_amendments], which
  can be used to override the hard-coded veto list, and is intended for
  use on test networks (testnet, devnet). Will also override
  [veto_amendments], but since that's in the same configuration file,
  that would be silly.
  • Loading branch information
ximinez committed Jul 1, 2020
1 parent de0c527 commit 87da13c
Show file tree
Hide file tree
Showing 9 changed files with 224 additions and 43 deletions.
41 changes: 27 additions & 14 deletions src/ripple/app/main/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1338,26 +1338,39 @@ ApplicationImp::setup()

// Configure the amendments the server supports
{
auto const& sa = detail::supportedAmendments();
std::vector<std::string> saHashes;
saHashes.reserve(sa.size());
for (auto const& name : sa)
{
auto const f = getRegisteredFeature(name);
BOOST_ASSERT(f);
if (f)
saHashes.push_back(to_string(*f) + " " + name);
}
Section supportedAmendments("Supported Amendments");
supportedAmendments.append(saHashes);
auto buildAmendmentList =
[](Section section, std::vector<std::string> const& amendments) {
std::vector<std::string> hashes;
hashes.reserve(amendments.size());
for (auto const& name : amendments)
{
auto const f = getRegisteredFeature(name);
BOOST_ASSERT(f);
if (f)
hashes.push_back(to_string(*f) + " " + name);
}
section.append(hashes);
return section;
};
Section const supportedAmendments = buildAmendmentList(
Section("Supported Amendments"), detail::supportedAmendments());

Section enabledAmendments = config_->section(SECTION_AMENDMENTS);
Section const enabledAmendments = config_->section(SECTION_AMENDMENTS);

Section const downVotedAmendments = buildAmendmentList(
config_->section(SECTION_VETO_AMENDMENTS),
detail::downVotedAmendments());

// Up votes override down votes!
Section const upVotedAmendments =
config_->section(SECTION_UNVETO_AMENDMENTS);

m_amendmentTable = make_AmendmentTable(
config().AMENDMENT_MAJORITY_TIME,
supportedAmendments,
enabledAmendments,
config_->section(SECTION_VETO_AMENDMENTS),
downVotedAmendments,
upVotedAmendments,
logs_->journal("Amendments"));
}

Expand Down
1 change: 1 addition & 0 deletions src/ripple/app/misc/AmendmentTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ make_AmendmentTable(
Section const& supported,
Section const& enabled,
Section const& vetoed,
Section const& unvetoed,
beast::Journal journal);

} // namespace ripple
Expand Down
40 changes: 36 additions & 4 deletions src/ripple/app/misc/impl/AmendmentTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ class AmendmentTableImpl final : public AmendmentTable
Section const& supported,
Section const& enabled,
Section const& vetoed,
Section const& unvetoed,
beast::Journal journal);

uint256
Expand Down Expand Up @@ -305,6 +306,7 @@ AmendmentTableImpl::AmendmentTableImpl(
Section const& supported,
Section const& enabled,
Section const& vetoed,
Section const& unvetoed,
beast::Journal journal)
: lastUpdateSeq_(0)
, majorityTime_(majorityTime)
Expand All @@ -317,10 +319,13 @@ AmendmentTableImpl::AmendmentTableImpl(
{
if (auto s = add(a.first, sl))
{
JLOG(j_.debug()) << "Amendment " << a.first << " is supported.";
JLOG(j_.debug()) << "Amendment " << a.first << " (" << a.second
<< ") is supported.";

if (!a.second.empty())
s->name = a.second;
else
s->name = featureToName(a.first);

s->supported = true;
}
Expand All @@ -330,10 +335,13 @@ AmendmentTableImpl::AmendmentTableImpl(
{
if (auto s = add(a.first, sl))
{
JLOG(j_.debug()) << "Amendment " << a.first << " is enabled.";
JLOG(j_.debug()) << "Amendment " << a.first << " (" << a.second
<< ") is enabled.";

if (!a.second.empty())
s->name = a.second;
else
s->name = featureToName(a.first);

s->supported = true;
s->enabled = true;
Expand All @@ -345,14 +353,36 @@ AmendmentTableImpl::AmendmentTableImpl(
// Unknown amendments are effectively vetoed already
if (auto s = get(a.first, sl))
{
JLOG(j_.info()) << "Amendment " << a.first << " is vetoed.";
JLOG(j_.debug()) << "Amendment " << a.first << " (" << a.second
<< ") is vetoed.";

if (!a.second.empty())
s->name = a.second;
else
s->name = featureToName(a.first);

s->vetoed = true;
}
}

for (auto const& a : parseSection(unvetoed))
{
// Overrides and removes the veto that may have been set above (by code
// or config, though it wouldn't make much sense to put both in the
// config). May or may not be known, so don't set any other flags.
if (auto s = get(a.first, sl))
{
JLOG(j_.debug()) << "Amendment " << a.first << " (" << a.second
<< ") is unvetoed.";

if (!a.second.empty())
s->name = a.second;
else
s->name = featureToName(a.first);

s->vetoed = false;
}
}
}

AmendmentState*
Expand Down Expand Up @@ -493,6 +523,7 @@ AmendmentTableImpl::doValidation(std::set<uint256> const& enabled) const
(enabled.count(e.first) == 0))
{
amendments.push_back(e.first);
JLOG(j_.info()) << "Voting for amendment " << e.second.name;
}
}
}
Expand Down Expand Up @@ -697,10 +728,11 @@ make_AmendmentTable(
Section const& supported,
Section const& enabled,
Section const& vetoed,
Section const& unvetoed,
beast::Journal journal)
{
return std::make_unique<AmendmentTableImpl>(
majorityTime, supported, enabled, vetoed, journal);
majorityTime, supported, enabled, vetoed, unvetoed, journal);
}

} // namespace ripple
1 change: 1 addition & 0 deletions src/ripple/core/ConfigSections.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ struct ConfigSection
#define SECTION_SSL_VERIFY "ssl_verify"
#define SECTION_SSL_VERIFY_FILE "ssl_verify_file"
#define SECTION_SSL_VERIFY_DIR "ssl_verify_dir"
#define SECTION_UNVETO_AMENDMENTS "unveto_amendments"
#define SECTION_VALIDATORS_FILE "validators_file"
#define SECTION_VALIDATION_SEED "validation_seed"
#define SECTION_WEBSOCKET_PING_FREQ "websocket_ping_frequency"
Expand Down
12 changes: 11 additions & 1 deletion src/ripple/protocol/Feature.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
* 3) add a uint256 definition for the feature to the corresponding source
* file (Feature.cpp)
* 4) if the feature is going to be supported in the near future, add its
* sha512half value and name (matching exactly the featureName here) to
* name (matching exactly the featureName here) to
* the supportedAmendments in Feature.cpp.
*
*/
Expand Down Expand Up @@ -135,12 +135,19 @@ class FeatureCollections

uint256 const&
bitsetIndexToFeature(size_t i) const;

std::string
featureToName(uint256 const& f) const;
};

/** Amendments that this server supports, but doesn't enable by default */
std::vector<std::string> const&
supportedAmendments();

/** Amendments that this server supports, but won't vote for by default */
std::vector<std::string> const&
downVotedAmendments();

} // namespace detail

boost::optional<uint256>
Expand All @@ -152,6 +159,9 @@ featureToBitsetIndex(uint256 const& f);
uint256
bitsetIndexToFeature(size_t i);

std::string
featureToName(uint256 const& f);

class FeatureBitset
: private std::bitset<detail::FeatureCollections::numFeatures()>
{
Expand Down
43 changes: 43 additions & 0 deletions src/ripple/protocol/impl/Feature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,15 @@ detail::FeatureCollections::bitsetIndexToFeature(size_t i) const
return features[i];
}

std::string
detail::FeatureCollections::featureToName(uint256 const& f) const
{
auto const i = featureToIndex.find(f);
return i == featureToIndex.end() || i->second > numFeatures()
? to_string(f)
: featureNames[i->second];
}

static detail::FeatureCollections const featureCollections;

/** Amendments that this server supports, but doesn't enable by default */
Expand Down Expand Up @@ -137,6 +146,34 @@ detail::supportedAmendments()
return supported;
}

/** Amendments that this server supports, but won't vote for by default */
std::vector<std::string> const&
detail::downVotedAmendments()
{
// Amendment names included in this list should also be present and
// uncommented in supportedAmendments above. This allows a particular
// version of rippled to be able to handle if this ledger goes live,
// but never vote for the amendment themselves. Additionally, some tests
// will fail if an entry in this list is not in supportedAmendments.
//
// Note that this list can be overridden by the `[unveto_amendments]` config
// stanza.
//
// For example, if amendment FOO is first complete and released in 2.1, but
// down voted (included in this list) until 2.3, then when it is finally
// enabled in 2.3 (or later), versions 2.1 and later will know how to handle
// the new behavior and will NOT be amendment blocked.
//
// Suggested format for entries in the string vector:
// "AmendmentName", // Added in 2.1, planned to enable in 2.3
//
// To enable automatically voting for the amendment, simply remove it from
// this list. There should never be a need to comment entries out aside from
// testing.
static std::vector<std::string> const vetoed{};
return vetoed;
}

//------------------------------------------------------------------------------

boost::optional<uint256>
Expand All @@ -157,6 +194,12 @@ bitsetIndexToFeature(size_t i)
return featureCollections.bitsetIndexToFeature(i);
}

std::string
featureToName(uint256 const& f)
{
return featureCollections.featureToName(f);
}

// clang-format off

uint256 const
Expand Down
Loading

0 comments on commit 87da13c

Please sign in to comment.