mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-24 13:05:53 +00:00
AmendmentTable improvements
This commit is contained in:
committed by
manojsdoshi
parent
16f79d160a
commit
68494a308e
@@ -139,7 +139,7 @@ public:
|
||||
class AmendmentTableImpl final : public AmendmentTable
|
||||
{
|
||||
protected:
|
||||
std::mutex mutex_;
|
||||
mutable std::mutex mutex_;
|
||||
|
||||
hash_map<uint256, AmendmentState> amendmentMap_;
|
||||
std::uint32_t lastUpdateSeq_;
|
||||
@@ -157,6 +157,7 @@ protected:
|
||||
|
||||
// True if an unsupported amendment is enabled
|
||||
bool unsupportedEnabled_;
|
||||
|
||||
// Unset if no unsupported amendments reach majority,
|
||||
// else set to the earliest time an unsupported amendment
|
||||
// will be enabled.
|
||||
@@ -164,16 +165,24 @@ protected:
|
||||
|
||||
beast::Journal const j_;
|
||||
|
||||
// Finds or creates state
|
||||
// Finds or creates state. Must be called with mutex_ locked.
|
||||
AmendmentState*
|
||||
add(uint256 const& amendment);
|
||||
add(uint256 const& amendment, std::lock_guard<std::mutex> const& sl);
|
||||
|
||||
// Finds existing state
|
||||
// Finds existing state. Must be called with mutex_ locked.
|
||||
AmendmentState*
|
||||
get(uint256 const& amendment);
|
||||
get(uint256 const& amendment, std::lock_guard<std::mutex> const& sl);
|
||||
|
||||
AmendmentState const*
|
||||
get(uint256 const& amendment, std::lock_guard<std::mutex> const& sl) const;
|
||||
|
||||
// Injects amendment json into v. Must be called with mutex_ locked.
|
||||
void
|
||||
setJson(Json::Value& v, uint256 const& amendment, const AmendmentState&);
|
||||
injectJson(
|
||||
Json::Value& v,
|
||||
uint256 const& amendment,
|
||||
AmendmentState const& state,
|
||||
std::lock_guard<std::mutex> const& sl) const;
|
||||
|
||||
public:
|
||||
AmendmentTableImpl(
|
||||
@@ -185,7 +194,7 @@ public:
|
||||
beast::Journal journal);
|
||||
|
||||
uint256
|
||||
find(std::string const& name) override;
|
||||
find(std::string const& name) const override;
|
||||
|
||||
bool
|
||||
veto(uint256 const& amendment) override;
|
||||
@@ -194,26 +203,25 @@ public:
|
||||
|
||||
bool
|
||||
enable(uint256 const& amendment) override;
|
||||
bool
|
||||
disable(uint256 const& amendment) override;
|
||||
|
||||
bool
|
||||
isEnabled(uint256 const& amendment) override;
|
||||
isEnabled(uint256 const& amendment) const override;
|
||||
bool
|
||||
isSupported(uint256 const& amendment) override;
|
||||
isSupported(uint256 const& amendment) const override;
|
||||
|
||||
bool
|
||||
hasUnsupportedEnabled() override;
|
||||
hasUnsupportedEnabled() const override;
|
||||
|
||||
boost::optional<NetClock::time_point>
|
||||
firstUnsupportedExpected() override;
|
||||
firstUnsupportedExpected() const override;
|
||||
|
||||
Json::Value
|
||||
getJson(int) override;
|
||||
getJson() const override;
|
||||
Json::Value
|
||||
getJson(uint256 const&) override;
|
||||
getJson(uint256 const&) const override;
|
||||
|
||||
bool
|
||||
needValidatedLedger(LedgerIndex seq) override;
|
||||
needValidatedLedger(LedgerIndex seq) const override;
|
||||
|
||||
void
|
||||
doValidatedLedger(
|
||||
@@ -222,10 +230,10 @@ public:
|
||||
majorityAmendments_t const& majority) override;
|
||||
|
||||
std::vector<uint256>
|
||||
doValidation(std::set<uint256> const& enabledAmendments) override;
|
||||
doValidation(std::set<uint256> const& enabledAmendments) const override;
|
||||
|
||||
std::vector<uint256>
|
||||
getDesired() override;
|
||||
getDesired() const override;
|
||||
|
||||
std::map<uint256, std::uint32_t>
|
||||
doVoting(
|
||||
@@ -256,7 +264,7 @@ AmendmentTableImpl::AmendmentTableImpl(
|
||||
|
||||
for (auto const& a : parseSection(supported))
|
||||
{
|
||||
if (auto s = add(a.first))
|
||||
if (auto s = add(a.first, sl))
|
||||
{
|
||||
JLOG(j_.debug()) << "Amendment " << a.first << " is supported.";
|
||||
|
||||
@@ -269,7 +277,7 @@ AmendmentTableImpl::AmendmentTableImpl(
|
||||
|
||||
for (auto const& a : parseSection(enabled))
|
||||
{
|
||||
if (auto s = add(a.first))
|
||||
if (auto s = add(a.first, sl))
|
||||
{
|
||||
JLOG(j_.debug()) << "Amendment " << a.first << " is enabled.";
|
||||
|
||||
@@ -284,7 +292,7 @@ AmendmentTableImpl::AmendmentTableImpl(
|
||||
for (auto const& a : parseSection(vetoed))
|
||||
{
|
||||
// Unknown amendments are effectively vetoed already
|
||||
if (auto s = get(a.first))
|
||||
if (auto s = get(a.first, sl))
|
||||
{
|
||||
JLOG(j_.info()) << "Amendment " << a.first << " is vetoed.";
|
||||
|
||||
@@ -297,14 +305,28 @@ AmendmentTableImpl::AmendmentTableImpl(
|
||||
}
|
||||
|
||||
AmendmentState*
|
||||
AmendmentTableImpl::add(uint256 const& amendmentHash)
|
||||
AmendmentTableImpl::add(
|
||||
uint256 const& amendmentHash,
|
||||
std::lock_guard<std::mutex> const&)
|
||||
{
|
||||
// call with the mutex held
|
||||
return &amendmentMap_[amendmentHash];
|
||||
}
|
||||
|
||||
AmendmentState*
|
||||
AmendmentTableImpl::get(uint256 const& amendmentHash)
|
||||
AmendmentTableImpl::get(
|
||||
uint256 const& amendmentHash,
|
||||
std::lock_guard<std::mutex> const& sl)
|
||||
{
|
||||
// Forward to the const version of get.
|
||||
return const_cast<AmendmentState*>(
|
||||
std::as_const(*this).get(amendmentHash, sl));
|
||||
}
|
||||
|
||||
AmendmentState const*
|
||||
AmendmentTableImpl::get(
|
||||
uint256 const& amendmentHash,
|
||||
std::lock_guard<std::mutex> const&) const
|
||||
{
|
||||
// call with the mutex held
|
||||
auto ret = amendmentMap_.find(amendmentHash);
|
||||
@@ -316,7 +338,7 @@ AmendmentTableImpl::get(uint256 const& amendmentHash)
|
||||
}
|
||||
|
||||
uint256
|
||||
AmendmentTableImpl::find(std::string const& name)
|
||||
AmendmentTableImpl::find(std::string const& name) const
|
||||
{
|
||||
std::lock_guard sl(mutex_);
|
||||
|
||||
@@ -333,7 +355,7 @@ bool
|
||||
AmendmentTableImpl::veto(uint256 const& amendment)
|
||||
{
|
||||
std::lock_guard sl(mutex_);
|
||||
auto s = add(amendment);
|
||||
auto s = add(amendment, sl);
|
||||
|
||||
if (s->vetoed)
|
||||
return false;
|
||||
@@ -345,7 +367,7 @@ bool
|
||||
AmendmentTableImpl::unVeto(uint256 const& amendment)
|
||||
{
|
||||
std::lock_guard sl(mutex_);
|
||||
auto s = get(amendment);
|
||||
auto s = get(amendment, sl);
|
||||
|
||||
if (!s || !s->vetoed)
|
||||
return false;
|
||||
@@ -357,7 +379,7 @@ bool
|
||||
AmendmentTableImpl::enable(uint256 const& amendment)
|
||||
{
|
||||
std::lock_guard sl(mutex_);
|
||||
auto s = add(amendment);
|
||||
auto s = add(amendment, sl);
|
||||
|
||||
if (s->enabled)
|
||||
return false;
|
||||
@@ -375,58 +397,45 @@ AmendmentTableImpl::enable(uint256 const& amendment)
|
||||
}
|
||||
|
||||
bool
|
||||
AmendmentTableImpl::disable(uint256 const& amendment)
|
||||
AmendmentTableImpl::isEnabled(uint256 const& amendment) const
|
||||
{
|
||||
std::lock_guard sl(mutex_);
|
||||
auto s = get(amendment);
|
||||
|
||||
if (!s || !s->enabled)
|
||||
return false;
|
||||
|
||||
s->enabled = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
AmendmentTableImpl::isEnabled(uint256 const& amendment)
|
||||
{
|
||||
std::lock_guard sl(mutex_);
|
||||
auto s = get(amendment);
|
||||
auto s = get(amendment, sl);
|
||||
return s && s->enabled;
|
||||
}
|
||||
|
||||
bool
|
||||
AmendmentTableImpl::isSupported(uint256 const& amendment)
|
||||
AmendmentTableImpl::isSupported(uint256 const& amendment) const
|
||||
{
|
||||
std::lock_guard sl(mutex_);
|
||||
auto s = get(amendment);
|
||||
auto s = get(amendment, sl);
|
||||
return s && s->supported;
|
||||
}
|
||||
|
||||
bool
|
||||
AmendmentTableImpl::hasUnsupportedEnabled()
|
||||
AmendmentTableImpl::hasUnsupportedEnabled() const
|
||||
{
|
||||
std::lock_guard sl(mutex_);
|
||||
return unsupportedEnabled_;
|
||||
}
|
||||
|
||||
boost::optional<NetClock::time_point>
|
||||
AmendmentTableImpl::firstUnsupportedExpected()
|
||||
AmendmentTableImpl::firstUnsupportedExpected() const
|
||||
{
|
||||
std::lock_guard sl(mutex_);
|
||||
return firstUnsupportedExpected_;
|
||||
}
|
||||
|
||||
std::vector<uint256>
|
||||
AmendmentTableImpl::doValidation(std::set<uint256> const& enabled)
|
||||
AmendmentTableImpl::doValidation(std::set<uint256> const& enabled) const
|
||||
{
|
||||
// Get the list of amendments we support and do not
|
||||
// veto, but that are not already enabled
|
||||
std::vector<uint256> amendments;
|
||||
amendments.reserve(amendmentMap_.size());
|
||||
|
||||
{
|
||||
std::lock_guard sl(mutex_);
|
||||
amendments.reserve(amendmentMap_.size());
|
||||
for (auto const& e : amendmentMap_)
|
||||
{
|
||||
if (e.second.supported && !e.second.vetoed &&
|
||||
@@ -444,7 +453,7 @@ AmendmentTableImpl::doValidation(std::set<uint256> const& enabled)
|
||||
}
|
||||
|
||||
std::vector<uint256>
|
||||
AmendmentTableImpl::getDesired()
|
||||
AmendmentTableImpl::getDesired() const
|
||||
{
|
||||
// Get the list of amendments we support and do not veto
|
||||
return doValidation({});
|
||||
@@ -491,63 +500,58 @@ AmendmentTableImpl::doVoting(
|
||||
// the value of the flags in the pseudo-transaction
|
||||
std::map<uint256, std::uint32_t> actions;
|
||||
|
||||
std::lock_guard sl(mutex_);
|
||||
|
||||
// process all amendments we know of
|
||||
for (auto const& entry : amendmentMap_)
|
||||
{
|
||||
std::lock_guard sl(mutex_);
|
||||
NetClock::time_point majorityTime = {};
|
||||
|
||||
bool const hasValMajority =
|
||||
(vote->votes(entry.first) >= vote->mThreshold);
|
||||
|
||||
// process all amendments we know of
|
||||
for (auto const& entry : amendmentMap_)
|
||||
{
|
||||
NetClock::time_point majorityTime = {};
|
||||
|
||||
bool const hasValMajority =
|
||||
(vote->votes(entry.first) >= vote->mThreshold);
|
||||
|
||||
{
|
||||
auto const it = majorityAmendments.find(entry.first);
|
||||
if (it != majorityAmendments.end())
|
||||
majorityTime = it->second;
|
||||
}
|
||||
|
||||
if (enabledAmendments.count(entry.first) != 0)
|
||||
{
|
||||
JLOG(j_.debug())
|
||||
<< entry.first << ": amendment already enabled";
|
||||
}
|
||||
else if (
|
||||
hasValMajority && (majorityTime == NetClock::time_point{}) &&
|
||||
!entry.second.vetoed)
|
||||
{
|
||||
// Ledger says no majority, validators say yes
|
||||
JLOG(j_.debug()) << entry.first << ": amendment got majority";
|
||||
actions[entry.first] = tfGotMajority;
|
||||
}
|
||||
else if (
|
||||
!hasValMajority && (majorityTime != NetClock::time_point{}))
|
||||
{
|
||||
// Ledger says majority, validators say no
|
||||
JLOG(j_.debug()) << entry.first << ": amendment lost majority";
|
||||
actions[entry.first] = tfLostMajority;
|
||||
}
|
||||
else if (
|
||||
(majorityTime != NetClock::time_point{}) &&
|
||||
((majorityTime + majorityTime_) <= closeTime) &&
|
||||
!entry.second.vetoed)
|
||||
{
|
||||
// Ledger says majority held
|
||||
JLOG(j_.debug()) << entry.first << ": amendment majority held";
|
||||
actions[entry.first] = 0;
|
||||
}
|
||||
auto const it = majorityAmendments.find(entry.first);
|
||||
if (it != majorityAmendments.end())
|
||||
majorityTime = it->second;
|
||||
}
|
||||
|
||||
// Stash for reporting
|
||||
lastVote_ = std::move(vote);
|
||||
if (enabledAmendments.count(entry.first) != 0)
|
||||
{
|
||||
JLOG(j_.debug()) << entry.first << ": amendment already enabled";
|
||||
}
|
||||
else if (
|
||||
hasValMajority && (majorityTime == NetClock::time_point{}) &&
|
||||
!entry.second.vetoed)
|
||||
{
|
||||
// Ledger says no majority, validators say yes
|
||||
JLOG(j_.debug()) << entry.first << ": amendment got majority";
|
||||
actions[entry.first] = tfGotMajority;
|
||||
}
|
||||
else if (!hasValMajority && (majorityTime != NetClock::time_point{}))
|
||||
{
|
||||
// Ledger says majority, validators say no
|
||||
JLOG(j_.debug()) << entry.first << ": amendment lost majority";
|
||||
actions[entry.first] = tfLostMajority;
|
||||
}
|
||||
else if (
|
||||
(majorityTime != NetClock::time_point{}) &&
|
||||
((majorityTime + majorityTime_) <= closeTime) &&
|
||||
!entry.second.vetoed)
|
||||
{
|
||||
// Ledger says majority held
|
||||
JLOG(j_.debug()) << entry.first << ": amendment majority held";
|
||||
actions[entry.first] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Stash for reporting
|
||||
lastVote_ = std::move(vote);
|
||||
return actions;
|
||||
}
|
||||
|
||||
bool
|
||||
AmendmentTableImpl::needValidatedLedger(LedgerIndex ledgerSeq)
|
||||
AmendmentTableImpl::needValidatedLedger(LedgerIndex ledgerSeq) const
|
||||
{
|
||||
std::lock_guard sl(mutex_);
|
||||
|
||||
@@ -567,13 +571,17 @@ AmendmentTableImpl::doValidatedLedger(
|
||||
enable(e);
|
||||
|
||||
std::lock_guard sl(mutex_);
|
||||
// Since we have the whole list in `majority`, reset the time flag, even if
|
||||
// it's currently set. If it's not set when the loop is done, then any
|
||||
|
||||
// Remember the ledger sequence of this update.
|
||||
lastUpdateSeq_ = ledgerSeq;
|
||||
|
||||
// Since we have the whole list in `majority`, reset the time flag, even
|
||||
// if it's currently set. If it's not set when the loop is done, then any
|
||||
// prior unknown amendments have lost majority.
|
||||
firstUnsupportedExpected_.reset();
|
||||
for (auto const& [hash, time] : majority)
|
||||
{
|
||||
auto s = add(hash);
|
||||
auto s = add(hash, sl);
|
||||
|
||||
if (s->enabled)
|
||||
continue;
|
||||
@@ -591,10 +599,11 @@ AmendmentTableImpl::doValidatedLedger(
|
||||
}
|
||||
|
||||
void
|
||||
AmendmentTableImpl::setJson(
|
||||
AmendmentTableImpl::injectJson(
|
||||
Json::Value& v,
|
||||
const uint256& id,
|
||||
const AmendmentState& fs)
|
||||
const AmendmentState& fs,
|
||||
std::lock_guard<std::mutex> const&) const
|
||||
{
|
||||
if (!fs.name.empty())
|
||||
v[jss::name] = fs.name;
|
||||
@@ -621,30 +630,34 @@ AmendmentTableImpl::setJson(
|
||||
}
|
||||
|
||||
Json::Value
|
||||
AmendmentTableImpl::getJson(int)
|
||||
AmendmentTableImpl::getJson() const
|
||||
{
|
||||
Json::Value ret(Json::objectValue);
|
||||
{
|
||||
std::lock_guard sl(mutex_);
|
||||
for (auto const& e : amendmentMap_)
|
||||
{
|
||||
setJson(
|
||||
ret[to_string(e.first)] = Json::objectValue, e.first, e.second);
|
||||
injectJson(
|
||||
ret[to_string(e.first)] = Json::objectValue,
|
||||
e.first,
|
||||
e.second,
|
||||
sl);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
Json::Value
|
||||
AmendmentTableImpl::getJson(uint256 const& amendmentID)
|
||||
AmendmentTableImpl::getJson(uint256 const& amendmentID) const
|
||||
{
|
||||
Json::Value ret = Json::objectValue;
|
||||
Json::Value& jAmendment = (ret[to_string(amendmentID)] = Json::objectValue);
|
||||
|
||||
{
|
||||
std::lock_guard sl(mutex_);
|
||||
auto a = add(amendmentID);
|
||||
setJson(jAmendment, amendmentID, *a);
|
||||
auto a = get(amendmentID, sl);
|
||||
if (a)
|
||||
injectJson(jAmendment, amendmentID, *a, sl);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
Reference in New Issue
Block a user