mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-24 21:15:58 +00:00
Support UNLs with future effective dates:
* Creates a version 2 of the UNL file format allowing publishers to pre-publish the next UNL while the current one is still valid. * Version 1 of the UNL file format is still valid and backward compatible. * Also causes rippled to lock down if it has no valid UNLs, similar to being amendment blocked, except reversible. * Resolves #3548 * Resolves #3470
This commit is contained in:
@@ -261,19 +261,13 @@ public:
|
||||
|
||||
public:
|
||||
OperatingMode
|
||||
getOperatingMode() const override
|
||||
{
|
||||
return mMode;
|
||||
}
|
||||
getOperatingMode() const override;
|
||||
|
||||
std::string
|
||||
strOperatingMode(OperatingMode const mode, bool const admin) const override;
|
||||
|
||||
std::string
|
||||
strOperatingMode(bool const admin = false) const override
|
||||
{
|
||||
return strOperatingMode(mMode, admin);
|
||||
}
|
||||
strOperatingMode(bool const admin = false) const override;
|
||||
|
||||
//
|
||||
// Transaction operations.
|
||||
@@ -391,10 +385,7 @@ public:
|
||||
void
|
||||
endConsensus() override;
|
||||
void
|
||||
setStandAlone() override
|
||||
{
|
||||
setMode(OperatingMode::FULL);
|
||||
}
|
||||
setStandAlone() override;
|
||||
|
||||
/** Called to initially start our timers.
|
||||
Not called for stand-alone mode.
|
||||
@@ -403,51 +394,35 @@ public:
|
||||
setStateTimer() override;
|
||||
|
||||
void
|
||||
setNeedNetworkLedger() override
|
||||
{
|
||||
needNetworkLedger_ = true;
|
||||
}
|
||||
setNeedNetworkLedger() override;
|
||||
void
|
||||
clearNeedNetworkLedger() override
|
||||
{
|
||||
needNetworkLedger_ = false;
|
||||
}
|
||||
clearNeedNetworkLedger() override;
|
||||
bool
|
||||
isNeedNetworkLedger() override
|
||||
{
|
||||
return needNetworkLedger_;
|
||||
}
|
||||
isNeedNetworkLedger() override;
|
||||
bool
|
||||
isFull() override
|
||||
{
|
||||
return !needNetworkLedger_ && (mMode == OperatingMode::FULL);
|
||||
}
|
||||
isFull() override;
|
||||
|
||||
void
|
||||
setMode(OperatingMode om) override;
|
||||
|
||||
bool
|
||||
isAmendmentBlocked() override
|
||||
{
|
||||
return amendmentBlocked_;
|
||||
}
|
||||
isBlocked() override;
|
||||
bool
|
||||
isAmendmentBlocked() override;
|
||||
void
|
||||
setAmendmentBlocked() override;
|
||||
bool
|
||||
isAmendmentWarned() override
|
||||
{
|
||||
return !amendmentBlocked_ && amendmentWarned_;
|
||||
}
|
||||
isAmendmentWarned() override;
|
||||
void
|
||||
setAmendmentWarned() override
|
||||
{
|
||||
amendmentWarned_ = true;
|
||||
}
|
||||
setAmendmentWarned() override;
|
||||
void
|
||||
clearAmendmentWarned() override
|
||||
{
|
||||
amendmentWarned_ = false;
|
||||
}
|
||||
clearAmendmentWarned() override;
|
||||
bool
|
||||
isUNLBlocked() override;
|
||||
void
|
||||
setUNLBlocked() override;
|
||||
void
|
||||
clearUNLBlocked() override;
|
||||
void
|
||||
consensusViewChange() override;
|
||||
|
||||
@@ -470,15 +445,9 @@ public:
|
||||
reportConsensusStateChange(ConsensusPhase phase);
|
||||
|
||||
void
|
||||
updateLocalTx(ReadView const& view) override
|
||||
{
|
||||
m_localTX->sweep(view);
|
||||
}
|
||||
updateLocalTx(ReadView const& view) override;
|
||||
std::size_t
|
||||
getLocalTxCount() override
|
||||
{
|
||||
return m_localTX->size();
|
||||
}
|
||||
getLocalTxCount() override;
|
||||
|
||||
// Helper function to generate SQL query to get transactions.
|
||||
std::string
|
||||
@@ -638,34 +607,7 @@ public:
|
||||
// Stoppable.
|
||||
|
||||
void
|
||||
onStop() override
|
||||
{
|
||||
mAcquiringLedger.reset();
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
heartbeatTimer_.cancel(ec);
|
||||
if (ec)
|
||||
{
|
||||
JLOG(m_journal.error())
|
||||
<< "NetworkOPs: heartbeatTimer cancel error: "
|
||||
<< ec.message();
|
||||
}
|
||||
|
||||
ec.clear();
|
||||
clusterTimer_.cancel(ec);
|
||||
if (ec)
|
||||
{
|
||||
JLOG(m_journal.error())
|
||||
<< "NetworkOPs: clusterTimer cancel error: "
|
||||
<< ec.message();
|
||||
}
|
||||
}
|
||||
// Make sure that any waitHandlers pending in our timers are done
|
||||
// before we declare ourselves stopped.
|
||||
using namespace std::chrono_literals;
|
||||
waitHandlerCounter_.join("NetworkOPs", 1s, m_journal);
|
||||
stopped();
|
||||
}
|
||||
onStop() override;
|
||||
|
||||
private:
|
||||
void
|
||||
@@ -720,6 +662,7 @@ private:
|
||||
std::atomic<bool> needNetworkLedger_{false};
|
||||
std::atomic<bool> amendmentBlocked_{false};
|
||||
std::atomic<bool> amendmentWarned_{false};
|
||||
std::atomic<bool> unlBlocked_{false};
|
||||
|
||||
ClosureCounter<void, boost::system::error_code const&> waitHandlerCounter_;
|
||||
boost::asio::steady_timer heartbeatTimer_;
|
||||
@@ -827,47 +770,7 @@ private:
|
||||
|
||||
private:
|
||||
void
|
||||
collect_metrics()
|
||||
{
|
||||
auto [counters, mode, start] = accounting_.getCounterData();
|
||||
auto const current =
|
||||
std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::system_clock::now() - start);
|
||||
counters[static_cast<std::size_t>(mode)].dur += current;
|
||||
|
||||
std::lock_guard lock(m_statsMutex);
|
||||
m_stats.disconnected_duration.set(
|
||||
counters[static_cast<std::size_t>(OperatingMode::DISCONNECTED)]
|
||||
.dur.count());
|
||||
m_stats.connected_duration.set(
|
||||
counters[static_cast<std::size_t>(OperatingMode::CONNECTED)]
|
||||
.dur.count());
|
||||
m_stats.syncing_duration.set(
|
||||
counters[static_cast<std::size_t>(OperatingMode::SYNCING)]
|
||||
.dur.count());
|
||||
m_stats.tracking_duration.set(
|
||||
counters[static_cast<std::size_t>(OperatingMode::TRACKING)]
|
||||
.dur.count());
|
||||
m_stats.full_duration.set(
|
||||
counters[static_cast<std::size_t>(OperatingMode::FULL)]
|
||||
.dur.count());
|
||||
|
||||
m_stats.disconnected_transitions.set(
|
||||
counters[static_cast<std::size_t>(OperatingMode::DISCONNECTED)]
|
||||
.transitions);
|
||||
m_stats.connected_transitions.set(
|
||||
counters[static_cast<std::size_t>(OperatingMode::CONNECTED)]
|
||||
.transitions);
|
||||
m_stats.syncing_transitions.set(
|
||||
counters[static_cast<std::size_t>(OperatingMode::SYNCING)]
|
||||
.transitions);
|
||||
m_stats.tracking_transitions.set(
|
||||
counters[static_cast<std::size_t>(OperatingMode::TRACKING)]
|
||||
.transitions);
|
||||
m_stats.full_transitions.set(
|
||||
counters[static_cast<std::size_t>(OperatingMode::FULL)]
|
||||
.transitions);
|
||||
}
|
||||
collect_metrics();
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
@@ -886,6 +789,48 @@ std::array<Json::StaticString const, 5> const
|
||||
Json::StaticString(stateNames[4])}};
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
inline OperatingMode
|
||||
NetworkOPsImp::getOperatingMode() const
|
||||
{
|
||||
return mMode;
|
||||
}
|
||||
|
||||
inline std::string
|
||||
NetworkOPsImp::strOperatingMode(bool const admin /* = false */) const
|
||||
{
|
||||
return strOperatingMode(mMode, admin);
|
||||
}
|
||||
|
||||
inline void
|
||||
NetworkOPsImp::setStandAlone()
|
||||
{
|
||||
setMode(OperatingMode::FULL);
|
||||
}
|
||||
|
||||
inline void
|
||||
NetworkOPsImp::setNeedNetworkLedger()
|
||||
{
|
||||
needNetworkLedger_ = true;
|
||||
}
|
||||
|
||||
inline void
|
||||
NetworkOPsImp::clearNeedNetworkLedger()
|
||||
{
|
||||
needNetworkLedger_ = false;
|
||||
}
|
||||
|
||||
inline bool
|
||||
NetworkOPsImp::isNeedNetworkLedger()
|
||||
{
|
||||
return needNetworkLedger_;
|
||||
}
|
||||
|
||||
inline bool
|
||||
NetworkOPsImp::isFull()
|
||||
{
|
||||
return !needNetworkLedger_ && (mMode == OperatingMode::FULL);
|
||||
}
|
||||
|
||||
std::string
|
||||
NetworkOPsImp::getHostId(bool forAdmin)
|
||||
{
|
||||
@@ -1554,11 +1499,60 @@ NetworkOPsImp::getOwnerInfo(
|
||||
// Other
|
||||
//
|
||||
|
||||
inline bool
|
||||
NetworkOPsImp::isBlocked()
|
||||
{
|
||||
return isAmendmentBlocked() || isUNLBlocked();
|
||||
}
|
||||
|
||||
inline bool
|
||||
NetworkOPsImp::isAmendmentBlocked()
|
||||
{
|
||||
return amendmentBlocked_;
|
||||
}
|
||||
|
||||
void
|
||||
NetworkOPsImp::setAmendmentBlocked()
|
||||
{
|
||||
amendmentBlocked_ = true;
|
||||
setMode(OperatingMode::TRACKING);
|
||||
setMode(OperatingMode::CONNECTED);
|
||||
}
|
||||
|
||||
inline bool
|
||||
NetworkOPsImp::isAmendmentWarned()
|
||||
{
|
||||
return !amendmentBlocked_ && amendmentWarned_;
|
||||
}
|
||||
|
||||
inline void
|
||||
NetworkOPsImp::setAmendmentWarned()
|
||||
{
|
||||
amendmentWarned_ = true;
|
||||
}
|
||||
|
||||
inline void
|
||||
NetworkOPsImp::clearAmendmentWarned()
|
||||
{
|
||||
amendmentWarned_ = false;
|
||||
}
|
||||
|
||||
inline bool
|
||||
NetworkOPsImp::isUNLBlocked()
|
||||
{
|
||||
return unlBlocked_;
|
||||
}
|
||||
|
||||
void
|
||||
NetworkOPsImp::setUNLBlocked()
|
||||
{
|
||||
unlBlocked_ = true;
|
||||
setMode(OperatingMode::CONNECTED);
|
||||
}
|
||||
|
||||
inline void
|
||||
NetworkOPsImp::clearUNLBlocked()
|
||||
{
|
||||
unlBlocked_ = false;
|
||||
}
|
||||
|
||||
bool
|
||||
@@ -1752,7 +1746,11 @@ NetworkOPsImp::beginConsensus(uint256 const& networkClosed)
|
||||
if (prevLedger->rules().enabled(featureNegativeUNL))
|
||||
app_.validators().setNegativeUNL(prevLedger->negativeUNL());
|
||||
TrustChanges const changes = app_.validators().updateTrusted(
|
||||
app_.getValidations().getCurrentNodeIDs());
|
||||
app_.getValidations().getCurrentNodeIDs(),
|
||||
closingInfo.parentCloseTime,
|
||||
*this,
|
||||
app_.overlay(),
|
||||
app_.getHashRouter());
|
||||
|
||||
if (!changes.added.empty() || !changes.removed.empty())
|
||||
app_.getValidations().trustChanged(changes.added, changes.removed);
|
||||
@@ -2154,8 +2152,8 @@ NetworkOPsImp::setMode(OperatingMode om)
|
||||
om = OperatingMode::CONNECTED;
|
||||
}
|
||||
|
||||
if ((om > OperatingMode::TRACKING) && amendmentBlocked_)
|
||||
om = OperatingMode::TRACKING;
|
||||
if ((om > OperatingMode::CONNECTED) && isBlocked())
|
||||
om = OperatingMode::CONNECTED;
|
||||
|
||||
if (mMode == om)
|
||||
return;
|
||||
@@ -2505,6 +2503,15 @@ NetworkOPsImp::getServerInfo(bool human, bool admin, bool counters)
|
||||
"This server is amendment blocked, and must be updated to be "
|
||||
"able to stay in sync with the network.";
|
||||
}
|
||||
if (isUNLBlocked())
|
||||
{
|
||||
Json::Value& w = warnings.append(Json::objectValue);
|
||||
w[jss::id] = warnRPC_EXPIRED_VALIDATOR_LIST;
|
||||
w[jss::message] =
|
||||
"This server has an expired validator list. validators.txt "
|
||||
"may be incorrectly configured or some [validator_list_sites] "
|
||||
"may be unreachable.";
|
||||
}
|
||||
if (admin && isAmendmentWarned())
|
||||
{
|
||||
Json::Value& w = warnings.append(Json::objectValue);
|
||||
@@ -2948,6 +2955,17 @@ NetworkOPsImp::reportConsensusStateChange(ConsensusPhase phase)
|
||||
[this, phase](Job&) { pubConsensus(phase); });
|
||||
}
|
||||
|
||||
inline void
|
||||
NetworkOPsImp::updateLocalTx(ReadView const& view)
|
||||
{
|
||||
m_localTX->sweep(view);
|
||||
}
|
||||
inline std::size_t
|
||||
NetworkOPsImp::getLocalTxCount()
|
||||
{
|
||||
return m_localTX->size();
|
||||
}
|
||||
|
||||
// This routine should only be used to publish accepted or validated
|
||||
// transactions.
|
||||
Json::Value
|
||||
@@ -3498,6 +3516,34 @@ NetworkOPsImp::tryRemoveRpcSub(std::string const& strUrl)
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
NetworkOPsImp::onStop()
|
||||
{
|
||||
mAcquiringLedger.reset();
|
||||
{
|
||||
boost::system::error_code ec;
|
||||
heartbeatTimer_.cancel(ec);
|
||||
if (ec)
|
||||
{
|
||||
JLOG(m_journal.error())
|
||||
<< "NetworkOPs: heartbeatTimer cancel error: " << ec.message();
|
||||
}
|
||||
|
||||
ec.clear();
|
||||
clusterTimer_.cancel(ec);
|
||||
if (ec)
|
||||
{
|
||||
JLOG(m_journal.error())
|
||||
<< "NetworkOPs: clusterTimer cancel error: " << ec.message();
|
||||
}
|
||||
}
|
||||
// Make sure that any waitHandlers pending in our timers are done
|
||||
// before we declare ourselves stopped.
|
||||
using namespace std::chrono_literals;
|
||||
waitHandlerCounter_.join("NetworkOPs", 1s, m_journal);
|
||||
stopped();
|
||||
}
|
||||
|
||||
#ifndef USE_NEW_BOOK_PAGE
|
||||
|
||||
// NIKB FIXME this should be looked at. There's no reason why this shouldn't
|
||||
@@ -3855,6 +3901,44 @@ NetworkOPsImp::getBookPage(
|
||||
|
||||
#endif
|
||||
|
||||
inline void
|
||||
NetworkOPsImp::collect_metrics()
|
||||
{
|
||||
auto [counters, mode, start] = accounting_.getCounterData();
|
||||
auto const current = std::chrono::duration_cast<std::chrono::microseconds>(
|
||||
std::chrono::system_clock::now() - start);
|
||||
counters[static_cast<std::size_t>(mode)].dur += current;
|
||||
|
||||
std::lock_guard lock(m_statsMutex);
|
||||
m_stats.disconnected_duration.set(
|
||||
counters[static_cast<std::size_t>(OperatingMode::DISCONNECTED)]
|
||||
.dur.count());
|
||||
m_stats.connected_duration.set(
|
||||
counters[static_cast<std::size_t>(OperatingMode::CONNECTED)]
|
||||
.dur.count());
|
||||
m_stats.syncing_duration.set(
|
||||
counters[static_cast<std::size_t>(OperatingMode::SYNCING)].dur.count());
|
||||
m_stats.tracking_duration.set(
|
||||
counters[static_cast<std::size_t>(OperatingMode::TRACKING)]
|
||||
.dur.count());
|
||||
m_stats.full_duration.set(
|
||||
counters[static_cast<std::size_t>(OperatingMode::FULL)].dur.count());
|
||||
|
||||
m_stats.disconnected_transitions.set(
|
||||
counters[static_cast<std::size_t>(OperatingMode::DISCONNECTED)]
|
||||
.transitions);
|
||||
m_stats.connected_transitions.set(
|
||||
counters[static_cast<std::size_t>(OperatingMode::CONNECTED)]
|
||||
.transitions);
|
||||
m_stats.syncing_transitions.set(
|
||||
counters[static_cast<std::size_t>(OperatingMode::SYNCING)].transitions);
|
||||
m_stats.tracking_transitions.set(
|
||||
counters[static_cast<std::size_t>(OperatingMode::TRACKING)]
|
||||
.transitions);
|
||||
m_stats.full_transitions.set(
|
||||
counters[static_cast<std::size_t>(OperatingMode::FULL)].transitions);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
NetworkOPs::NetworkOPs(Stoppable& parent)
|
||||
|
||||
Reference in New Issue
Block a user