20 #include <ripple/app/main/Application.h>
21 #include <ripple/app/misc/AmendmentTable.h>
22 #include <ripple/protocol/STValidation.h>
23 #include <ripple/core/DatabaseCon.h>
24 #include <ripple/core/ConfigSections.h>
25 #include <ripple/protocol/jss.h>
26 #include <ripple/protocol/TxFlags.h>
27 #include <boost/format.hpp>
28 #include <boost/regex.hpp>
38 static boost::regex
const re1 (
41 "([abcdefABCDEF0-9]{64})"
44 , boost::regex_constants::optimize
49 for (
auto const& line : section.
lines ())
53 if (!boost::regex_match (line, match, re1))
54 Throw<std::runtime_error> (
55 "Invalid entry '" + line +
56 "' in [" + section.
name () +
"]");
60 if (!
id.SetHexExact (match[1]))
61 Throw<std::runtime_error> (
62 "Invalid amendment ID '" + match[1] +
63 "' in [" + section.
name () +
"]");
116 for (
auto const& amendment : amendments)
122 auto const& it =
votes_.find (amendment);
179 int majorityFraction,
197 boost::optional<NetClock::time_point>
229 int majorityFraction,
235 , majorityTime_ (majorityTime)
236 , majorityFraction_ (majorityFraction)
237 , unsupportedEnabled_ (false)
246 if (
auto s =
add (a.first))
249 "Amendment " << a.first <<
" is supported.";
251 if (!a.second.empty ())
260 if (
auto s =
add (a.first))
263 "Amendment " << a.first <<
" is enabled.";
265 if (!a.second.empty ())
276 if (
auto s =
get (a.first))
279 "Amendment " << a.first <<
" is vetoed.";
281 if (!a.second.empty ())
315 if (name == e.second.name)
326 auto s =
add (amendment);
338 auto s =
get (amendment);
340 if (!s || !s->vetoed)
350 auto s =
add (amendment);
360 "Unsupported amendment " << amendment <<
" activated.";
371 auto s =
get (amendment);
373 if (!s || !s->enabled)
384 auto s =
get (amendment);
385 return s && s->enabled;
392 auto s =
get (amendment);
393 return s && s->supported;
403 boost::optional<NetClock::time_point>
423 if (e.second.supported && ! e.second.vetoed &&
424 (enabled.
count (e.first) == 0))
431 if (! amendments.
empty())
453 ": " << enabledAmendments.
size() <<
454 ", " << majorityAmendments.
size() <<
455 ", " << valSet.
size();
457 auto vote = std::make_unique <AmendmentSet> ();
460 for (
auto const& val : valSet)
462 if (val->isTrusted ())
470 ballot.
insert (choices.begin (), choices.end ());
473 vote->tally (ballot);
481 "Received " << vote->mTrustedValidations <<
482 " trusted validations, threshold is: " << vote->mThreshold;
496 bool const hasValMajority =
497 (vote->votes (entry.first) >= vote->mThreshold);
500 auto const it = majorityAmendments.
find (entry.first);
501 if (it != majorityAmendments.
end ())
502 majorityTime = it->second;
505 if (enabledAmendments.
count (entry.first) != 0)
508 entry.first <<
": amendment already enabled";
510 else if (hasValMajority &&
512 ! entry.second.vetoed)
516 entry.first <<
": amendment got majority";
519 else if (! hasValMajority &&
524 entry.first <<
": amendment lost majority";
529 ! entry.second.vetoed)
533 entry.first <<
": amendment majority held";
534 actions[entry.first] = 0;
562 for (
auto& e : enabled)
570 for (
auto const& [ hash, time ] : majority)
579 JLOG(
j_.
info()) <<
"Unsupported amendment " << hash
580 <<
" reached majority at " <<
to_string(time);
593 v[jss::name] = fs.
name;
596 v[jss::vetoed] = fs.
vetoed;
601 auto const votesTotal =
lastVote_->mTrustedValidations;
602 auto const votesNeeded =
lastVote_->mThreshold;
603 auto const votesFor =
lastVote_->votes (
id);
605 v[jss::count] = votesFor;
606 v[jss::validations] = votesTotal;
610 v[jss::vote] = votesFor * 256 / votesNeeded;
611 v[jss::threshold] = votesNeeded;
639 auto a =
add (amendmentID);
640 setJson (jAmendment, amendmentID, *a);
648 int majorityFraction,
654 return std::make_unique<AmendmentTableImpl> (
Holds a collection of configuration values.
bool supported
Indicates an amendment that this server has code support for.
std::uint32_t lastUpdateSeq_
bool disable(uint256 const &amendment) override
bool hasUnsupportedEnabled() override
returns true if one or more amendments on the network have been enabled that this server does not sup...
Current state of an amendment.
boost::optional< NetClock::time_point > firstUnsupportedExpected_
Stream trace() const
Severity stream access functions.
std::unique_ptr< AmendmentTable > make_AmendmentTable(std::chrono::seconds majorityTime, int majorityFraction, Section const &supported, Section const &enabled, Section const &vetoed, beast::Journal journal)
bool isSupported(uint256 const &amendment) override
bool vetoed
If an amendment is vetoed, a server will not support it.
bool unVeto(uint256 const &amendment) override
void tally(std::set< uint256 > const &amendments)
std::string to_string(ListDisposition disposition)
bool isEnabled(uint256 const &amendment) override
const std::uint32_t tfLostMajority
const std::uint32_t tfGotMajority
Track the list of "amendments".
static std::vector< std::pair< uint256, std::string > > parseSection(Section const §ion)
hash_map< uint256, int > votes_
std::string const & name() const
Returns the name of this section.
T time_since_epoch(T... args)
void setJson(Json::Value &v, uint256 const &amendment, const AmendmentState &)
const int majorityFraction_
@ objectValue
object value (collection of name/value pairs).
boost::optional< NetClock::time_point > firstUnsupportedExpected() override
uint256 find(std::string const &name) override
int votes(uint256 const &amendment) const
std::vector< std::string > const & lines() const
Returns all the lines in the section.
A generic endpoint for log messages.
AmendmentTableImpl(std::chrono::seconds majorityTime, int majorityFraction, Section const &supported, Section const &enabled, Section const &vetoed, beast::Journal journal)
bool veto(uint256 const &amendment) override
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Json::Value getJson(int) override
hash_map< uint256, AmendmentState > amendmentMap_
std::vector< uint256 > doValidation(std::set< uint256 > const &enabledAmendments) override
std::unique_ptr< AmendmentSet > lastVote_
const std::chrono::seconds majorityTime_
bool enabled
Indicates that the amendment has been enabled.
std::string name
The name of this amendment, possibly empty.
bool needValidatedLedger(LedgerIndex seq) override
Called to determine whether the amendment logic needs to process a new validated ledger.
const SF_Vec256 sfAmendments(access, STI_VECTOR256, 3, "Amendments")
The status of all amendments requested in a given window.
The amendment table stores the list of enabled and potential amendments.
AmendmentState * get(uint256 const &amendment)
std::map< uint256, std::uint32_t > doVoting(NetClock::time_point closeTime, std::set< uint256 > const &enabledAmendments, majorityAmendments_t const &majorityAmendments, std::vector< STValidation::pointer > const &validations) override
AmendmentState * add(uint256 const &amendment)
std::vector< uint256 > getDesired() override
void doValidatedLedger(LedgerIndex seq, std::set< uint256 > const &enabled, majorityAmendments_t const &majority) override
bool enable(uint256 const &amendment) override