-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Amendment table clean up (Improve amendment processing and activation logic) #3428
Changes from 1 commit
29b74b2
7d90194
492272c
7482d74
5e989ec
63370d1
e0f516f
9f6aefc
f3c752c
2c429dd
69ea2d4
d7cb90c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -27,6 +27,12 @@ | |
|
||
namespace ripple { | ||
|
||
struct MajorityFraction | ||
{ | ||
int old_ = 0; | ||
int new_ = 0; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not keen on the names
Or perhaps you have a better idea for more descriptive names... Also, in general, around this code base, if a member variable is public (like in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's best to use
The nice thing is that Of course, it's important to note that the compiler actually reduces There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
}; | ||
|
||
/** The amendment table stores the list of enabled and potential amendments. | ||
Individuals amendments are voted on by validators during the consensus | ||
process. | ||
|
@@ -99,6 +105,7 @@ class AmendmentTable | |
// inject pseudo-transactions | ||
virtual std::map<uint256, std::uint32_t> | ||
doVoting( | ||
Rules const& rules, | ||
NetClock::time_point closeTime, | ||
std::set<uint256> const& enabledAmendments, | ||
majorityAmendments_t const& majorityAmendments, | ||
|
@@ -130,6 +137,7 @@ class AmendmentTable | |
{ | ||
// Ask implementation what to do | ||
auto actions = doVoting( | ||
lastClosedLedger->rules(), | ||
lastClosedLedger->parentCloseTime(), | ||
getEnabledAmendments(*lastClosedLedger), | ||
getMajorityAmendments(*lastClosedLedger), | ||
|
@@ -164,7 +172,7 @@ class AmendmentTable | |
std::unique_ptr<AmendmentTable> | ||
make_AmendmentTable( | ||
std::chrono::seconds majorityTime, | ||
int majorityFraction, | ||
MajorityFraction const& majorityFraction, | ||
Section const& supported, | ||
Section const& enabled, | ||
Section const& vetoed, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -21,6 +21,7 @@ | |
#include <ripple/app/misc/AmendmentTable.h> | ||
#include <ripple/core/ConfigSections.h> | ||
#include <ripple/core/DatabaseCon.h> | ||
#include <ripple/protocol/Feature.h> | ||
#include <ripple/protocol/STValidation.h> | ||
#include <ripple/protocol/TxFlags.h> | ||
#include <ripple/protocol/jss.h> | ||
|
@@ -148,8 +149,8 @@ class AmendmentTableImpl final : public AmendmentTable | |
std::chrono::seconds const majorityTime_; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I can't comment on a line that hasn't been modified. And I know this is not your doing. I'm looking at the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
|
||
// The amount of support that an amendment must receive | ||
// 0 = 0% and 256 = 100% | ||
int const majorityFraction_; | ||
// 0 = 0% and 256 = 100%(old) 8 = 100%(new) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this comment is wrong? Doesn't the current implementation result in "10 = 100%(new) "? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's right. But I think the comment with the arithmetic is unnecessary here, especially if we use the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Removed the comment |
||
MajorityFraction const majorityFraction_; | ||
|
||
// The results of the last voting round - may be empty if | ||
// we haven't participated in one yet. | ||
|
@@ -187,7 +188,7 @@ class AmendmentTableImpl final : public AmendmentTable | |
public: | ||
AmendmentTableImpl( | ||
std::chrono::seconds majorityTime, | ||
int majorityFraction, | ||
MajorityFraction const& majorityFraction, | ||
Section const& supported, | ||
Section const& enabled, | ||
Section const& vetoed, | ||
|
@@ -237,6 +238,7 @@ class AmendmentTableImpl final : public AmendmentTable | |
|
||
std::map<uint256, std::uint32_t> | ||
doVoting( | ||
Rules const& rules, | ||
NetClock::time_point closeTime, | ||
std::set<uint256> const& enabledAmendments, | ||
majorityAmendments_t const& majorityAmendments, | ||
|
@@ -247,7 +249,7 @@ class AmendmentTableImpl final : public AmendmentTable | |
|
||
AmendmentTableImpl::AmendmentTableImpl( | ||
std::chrono::seconds majorityTime, | ||
int majorityFraction, | ||
MajorityFraction const& majorityFraction, | ||
Section const& supported, | ||
Section const& enabled, | ||
Section const& vetoed, | ||
|
@@ -258,7 +260,7 @@ AmendmentTableImpl::AmendmentTableImpl( | |
, unsupportedEnabled_(false) | ||
, j_(journal) | ||
{ | ||
assert(majorityFraction_ != 0); | ||
assert(majorityFraction_.old_ != 0 && majorityFraction_.new_ != 0); | ||
|
||
std::lock_guard sl(mutex_); | ||
|
||
|
@@ -461,6 +463,7 @@ AmendmentTableImpl::getDesired() const | |
|
||
std::map<uint256, std::uint32_t> | ||
AmendmentTableImpl::doVoting( | ||
Rules const& rules, | ||
NetClock::time_point closeTime, | ||
std::set<uint256> const& enabledAmendments, | ||
majorityAmendments_t const& majorityAmendments, | ||
|
@@ -489,8 +492,10 @@ AmendmentTableImpl::doVoting( | |
} | ||
} | ||
|
||
vote->mThreshold = | ||
std::max(1, (vote->mTrustedValidations * majorityFraction_) / 256); | ||
vote->mThreshold = rules.enabled(ripple::fix3396) | ||
? std::max(1, (vote->mTrustedValidations * majorityFraction_.new_) / 10) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are two different places where I'd like to suggest consolidating those two places into a single place; here. You can do that by rounding up the division instead of doing the usual C/C++ truncate toward zero. It's worth noting that this change, either way it is done, has non-trivial impact on how amendments behave on a network with a small number of validators. It means that with small numbers of trusted validators there must be 100% agreement before any amendment will pass. For example, if we require at least 80% agreement between validators, then with 2, 3, or 4 trusted validators there must be 100% agreement for any amendment to pass. I agree that's the right call to make given the current state of the network. I think by doing the rounding up here, rather than tweaking the comparison on line 515, you'll make the intent easier to understand for future maintainers. There are a couple of different ways to achieve rounding up. Here's one way to do it that avoids floating point:
There are other ways to code it as well. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. While we're here, I have a mild preference for using 100 as the divisor rather than 10. That would allow you to rename amendmentMajorityFraction = 8 to amendmentMajorityPercent = 80; which is way easier to read and understand. I think people accustomed to western math will also recognize percentages much faster than they will recognize fractions of 10. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I appreciate the well-thought out comment (and agree with the 8 -> 80 change), but I find the division code confusing to read. Once I read it carefully, I understand what's happening, but I'm not confident it behaves identically pre-amendment. I am hoping we can do something even better: We should push all this logic into
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
: std::max( | ||
1, (vote->mTrustedValidations * majorityFraction_.old_) / 256); | ||
|
||
JLOG(j_.debug()) << "Received " << vote->mTrustedValidations | ||
<< " trusted validations, threshold is: " | ||
|
@@ -507,8 +512,9 @@ AmendmentTableImpl::doVoting( | |
{ | ||
NetClock::time_point majorityTime = {}; | ||
|
||
bool const hasValMajority = | ||
(vote->votes(entry.first) >= vote->mThreshold); | ||
bool const hasValMajority = rules.enabled(ripple::fix3396) | ||
? (vote->votes(entry.first) > vote->mThreshold) | ||
: (vote->votes(entry.first) >= vote->mThreshold); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you go with rounding up when calculating the threshold, then this change should be reverted. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated per Nik's suggestion of pushing the logic into AmendmentSet. |
||
|
||
{ | ||
auto const it = majorityAmendments.find(entry.first); | ||
|
@@ -666,7 +672,7 @@ AmendmentTableImpl::getJson(uint256 const& amendmentID) const | |
std::unique_ptr<AmendmentTable> | ||
make_AmendmentTable( | ||
std::chrono::seconds majorityTime, | ||
int majorityFraction, | ||
MajorityFraction const& majorityFraction, | ||
Section const& supported, | ||
Section const& enabled, | ||
Section const& vetoed, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -480,6 +480,31 @@ Config::loadFromString(std::string const& fileContents) | |
if (getSingleSection(secConfig, SECTION_COMPRESSION, strTemp, j_)) | ||
COMPRESSION = beast::lexicalCastThrow<bool>(strTemp); | ||
|
||
if (getSingleSection( | ||
secConfig, SECTION_AMENDMENT_MAJORITY_TIME, strTemp, j_)) | ||
{ | ||
using namespace std::chrono; | ||
boost::regex const re( | ||
"^\\s*(\\d+)\\s*(seconds|minutes|hours|days|weeks)\\s*(\\s+.*)?$"); | ||
boost::smatch match; | ||
if (!boost::regex_match(strTemp, match, re)) | ||
Throw<std::runtime_error>( | ||
"Invalid " SECTION_AMENDMENT_MAJORITY_TIME | ||
", must be: [0-9]+ [seconds|minutes|hours|days|weeks]"); | ||
std::uint32_t duration = | ||
beast::lexicalCastThrow<std::uint32_t>(match[1].str()); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would not allow There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
if (boost::iequals(match[2], "seconds")) | ||
AMENDMENT_MAJORITY_TIME = seconds(duration); | ||
else if (boost::iequals(match[2], "minutes")) | ||
AMENDMENT_MAJORITY_TIME = minutes(duration); | ||
else if (boost::iequals(match[2], "hours")) | ||
AMENDMENT_MAJORITY_TIME = hours(duration); | ||
else if (boost::iequals(match[2], "days")) | ||
AMENDMENT_MAJORITY_TIME = days(duration); | ||
else if (boost::iequals(match[2], "weeks")) | ||
AMENDMENT_MAJORITY_TIME = weeks(duration); | ||
} | ||
|
||
// Do not load trusted validator configuration for standalone mode | ||
if (!RUN_STANDALONE) | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -111,7 +111,8 @@ class FeatureCollections | |
"RequireFullyCanonicalSig", | ||
"fix1781", // XRPEndpointSteps should be included in the circular | ||
// payment check | ||
"HardenedValidations"}; | ||
"HardenedValidations", | ||
"fix3396"}; // Fix Amendment majority calculation | ||
|
||
std::vector<uint256> features; | ||
boost::container::flat_map<uint256, std::size_t> featureToIndex; | ||
|
@@ -367,6 +368,7 @@ extern uint256 const fixQualityUpperBound; | |
extern uint256 const featureRequireFullyCanonicalSig; | ||
extern uint256 const fix1781; | ||
extern uint256 const featureHardenedValidations; | ||
extern uint256 const fix3396; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I suggest renaming this to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done |
||
|
||
} // namespace ripple | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These values, along with the default value for the majority time should probably migrate into
SystemParametersInfo.h
:There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done, except for
amendmentMajorityPercent
, which is currently not used. Added insteadamendmentMajorityFraction
.