1#include <xrpld/app/ledger/LedgerMaster.h>
3#include <xrpld/app/consensus/RCLValidations.h>
4#include <xrpld/app/ledger/InboundLedger.h>
5#include <xrpld/app/ledger/LedgerPersistence.h>
6#include <xrpld/app/ledger/LedgerReplay.h>
7#include <xrpld/app/ledger/LedgerReplayer.h>
8#include <xrpld/app/ledger/OpenLedger.h>
9#include <xrpld/app/main/Application.h>
10#include <xrpld/app/misc/SHAMapStore.h>
11#include <xrpld/app/misc/Transaction.h>
12#include <xrpld/app/misc/TxQ.h>
13#include <xrpld/app/misc/ValidatorList.h>
14#include <xrpld/core/Config.h>
15#include <xrpld/core/TimeKeeper.h>
16#include <xrpld/overlay/Overlay.h>
17#include <xrpld/overlay/Peer.h>
18#include <xrpld/rpc/detail/PathRequestManager.h>
20#include <xrpl/basics/Log.h>
21#include <xrpl/basics/MathUtilities.h>
22#include <xrpl/basics/RangeSet.h>
23#include <xrpl/basics/Slice.h>
24#include <xrpl/basics/UnorderedContainers.h>
25#include <xrpl/basics/UptimeClock.h>
26#include <xrpl/basics/base_uint.h>
27#include <xrpl/basics/chrono.h>
28#include <xrpl/basics/contract.h>
29#include <xrpl/basics/safe_cast.h>
30#include <xrpl/basics/scope.h>
31#include <xrpl/beast/insight/Collector.h>
32#include <xrpl/beast/utility/Journal.h>
33#include <xrpl/beast/utility/Zero.h>
34#include <xrpl/beast/utility/instrumentation.h>
35#include <xrpl/core/Job.h>
36#include <xrpl/json/json_value.h>
37#include <xrpl/ledger/AmendmentTable.h>
38#include <xrpl/ledger/Ledger.h>
39#include <xrpl/ledger/OrderBookDB.h>
40#include <xrpl/ledger/PendingSaves.h>
41#include <xrpl/ledger/View.h>
42#include <xrpl/nodestore/Database.h>
43#include <xrpl/protocol/BuildInfo.h>
44#include <xrpl/protocol/HashPrefix.h>
45#include <xrpl/protocol/LedgerHeader.h>
46#include <xrpl/protocol/Protocol.h>
47#include <xrpl/protocol/RippleLedgerHash.h>
48#include <xrpl/protocol/SField.h>
49#include <xrpl/protocol/Serializer.h>
50#include <xrpl/protocol/digest.h>
51#include <xrpl/rdb/RelationalDatabase.h>
52#include <xrpl/resource/Fees.h>
53#include <xrpl/server/LoadFeeTrack.h>
54#include <xrpl/server/NetworkOPs.h>
55#include <xrpl/shamap/SHAMap.h>
56#include <xrpl/shamap/SHAMapMissingNode.h>
57#include <xrpl/shamap/SHAMapTreeNode.h>
59#include <boost/icl/concept/interval_set.hpp>
102 bool const ret = [&]() {
104 if (candidateLedger >= currentLedger)
108 if (currentLedger - candidateLedger <= ledgerHistory)
113 return minimumOnline.
has_value() && candidateLedger >= *minimumOnline;
116 JLOG(j.
trace()) <<
"Missing ledger " << candidateLedger << (ret ?
" should" :
" should NOT")
136 std::chrono::seconds{45},
138 app_.getJournal(
"TaggedCache"))
146 return app_.getOpenLedger().current()->header().seq;
160 if (validLedger && !
areCompatible(*validLedger, view, s, reason))
181 using namespace std::chrono_literals;
185 JLOG(
journal_.debug()) <<
"No published ledger";
191 ret = (ret > 0s) ? ret : 0s;
196 JLOG(
journal_.trace()) <<
"Published ledger age is " << ret.
count();
205 using namespace std::chrono_literals;
210 JLOG(
journal_.debug()) <<
"No validated ledger";
216 ret = (ret > 0s) ? ret : 0s;
221 JLOG(
journal_.trace()) <<
"Validated ledger age is " << ret.
count();
230 using namespace std::chrono_literals;
234 reason =
"No recently-published ledger";
239 if ((validClose == 0u) || (pubClose == 0u))
241 reason =
"No published ledger";
244 if (validClose > (pubClose + 90))
246 reason =
"Published ledger lags validated ledger";
260 auto validations =
app_.getValidators().negativeUNLFilter(
261 app_.getValidations().getTrustedForLedger(l->header().hash, l->header().seq));
262 times.
reserve(validations.size());
263 for (
auto const& val : validations)
266 if (!validations.empty())
267 consensusHash = validations.front()->getConsensusHash();
272 if (!times.
empty() && times.
size() >=
app_.getValidators().quorum())
276 auto const t0 = times[(times.
size() - 1) / 2];
277 auto const t1 = times[times.
size() / 2];
278 signTime = t0 + (t1 - t0) / 2;
282 signTime = l->header().closeTime;
290 "xrpl::LedgerMaster::setValidLedger : valid ledger sequence");
294 app_.getOPs().updateLocalTx(*l);
297 app_.getAmendmentTable().doValidatedLedger(l);
298 if (!
app_.getOPs().isBlocked())
300 if (
app_.getAmendmentTable().hasUnsupportedEnabled())
302 JLOG(
journal_.error()) <<
"One or more unsupported amendments "
303 "activated: server blocked.";
304 app_.getOPs().setAmendmentBlocked();
306 else if (!
app_.getOPs().isAmendmentWarned() || l->isFlagLedger())
317 if (
auto const first =
app_.getAmendmentTable().firstUnsupportedExpected())
319 JLOG(
journal_.error()) <<
"One or more unsupported amendments "
320 "reached majority. Upgrade before "
322 <<
" to prevent your server from "
323 "becoming amendment blocked.";
324 app_.getOPs().setAmendmentWarned();
328 app_.getOPs().clearAmendmentWarned();
355 XRPL_ASSERT(ledger,
"xrpl::LedgerMaster::canBeCurrent : non-null input");
361 if (validLedger && (ledger->header().seq < validLedger->header().seq))
363 JLOG(
journal_.trace()) <<
"Candidate for current ledger has low seq "
364 << ledger->header().seq <<
" < " << validLedger->header().seq;
373 auto closeTime =
app_.getTimeKeeper().closeTime();
374 auto ledgerClose = ledger->header().parentCloseTime;
376 using namespace std::chrono_literals;
377 if ((validLedger || (ledger->header().seq > 10)) &&
378 ((
std::max(closeTime, ledgerClose) -
std::min(closeTime, ledgerClose)) > 5min))
380 JLOG(
journal_.warn()) <<
"Candidate for current ledger has close time "
381 <<
to_string(ledgerClose) <<
" at network time "
382 <<
to_string(closeTime) <<
" seq " << ledger->header().seq;
393 LedgerIndex maxSeq = validLedger->header().seq + 10;
395 if (closeTime > validLedger->header().parentCloseTime)
398 closeTime - validLedger->header().parentCloseTime)
403 if (ledger->header().seq > maxSeq)
405 JLOG(
journal_.warn()) <<
"Candidate for current ledger has high seq "
406 << ledger->header().seq <<
" > " << maxSeq;
410 JLOG(
journal_.trace()) <<
"Acceptable seq range: " << validLedger->header().seq
411 <<
" <= " << ledger->header().seq <<
" <= " << maxSeq;
420 XRPL_ASSERT(lastClosed,
"xrpl::LedgerMaster::switchLCL : non-null input");
421 if (!lastClosed->isImmutable())
424 if (lastClosed->open())
425 logicError(
"The new last closed ledger is open!");
452 bool const validated = ledger->header().validated;
475 app_.getOPs().processTransactionSet(
set);
528 XRPL_ASSERT(hash->isNonZero(),
"xrpl::LedgerMaster::isValidated : nonzero hash");
529 uint256 const valHash =
app_.getRelationalDatabase().getHashByIndex(seq);
541 JLOG(
journal_.warn()) <<
"Ledger #" << seq <<
": " << mn.
what();
567 if (maybeMin == std::nullopt)
573 minVal = 1 + *maybeMin;
589 auto const pendingSaves =
app_.getPendingSaves().getSnapshot();
591 if (!pendingSaves.empty() && ((minVal != 0) || (maxVal != 0)))
596 while (pendingSaves.contains(maxVal))
598 while (pendingSaves.contains(minVal))
602 for (
auto v : pendingSaves)
604 if ((v.first >= minVal) && (v.first <= maxVal))
606 if (v.first > ((minVal + maxVal) / 2))
608 maxVal = v.first - 1;
612 minVal = v.first + 1;
647 uint256 prevHash = ledger->header().parentHash;
655 while (!
app_.getJobQueue().isStopping() && seq > 0)
666 auto it(ledgerHashes.
find(seq));
668 if (it == ledgerHashes.
end())
670 if (
app_.isStopping())
679 app_.getRelationalDatabase().getHashesByIndex((seq < 500) ? 0 : (seq - 499), seq);
680 it = ledgerHashes.
find(seq);
682 if (it == ledgerHashes.
end())
686 ledgerHashes.
begin()->second.ledgerHash, ledgerHashes.
begin()->first))
690 <<
"SQL DB ledger sequence " << seq <<
" mismatches node store";
695 if (it->second.ledgerHash != prevHash)
698 prevHash = it->second.parentHash;
720 if (!haveHash || haveHash->isZero())
722 JLOG(
journal_.error()) <<
"No hash for fetch pack. Missing Index " << missing;
731 auto peerList =
app_.getOverlay().getActivePeers();
732 for (
auto const& peer : peerList)
734 if (peer->hasRange(missing, missing + 1))
736 int const score = peer->getScore(
true);
737 if (!target || (score > maxScore))
748 protocol::TMGetObjectByHash tmBH;
749 tmBH.set_query(
true);
750 tmBH.set_type(protocol::TMGetObjectByHash::otFETCH_PACK);
751 tmBH.set_ledgerhash(haveHash->begin(), 32);
754 target->send(packet);
755 JLOG(
journal_.trace()) <<
"Requested fetch pack for " << missing;
759 JLOG(
journal_.debug()) <<
"No peer for fetch pack";
780 <<
"fixMismatch encounters partial ledger. Exception: " << ex.
what();
790 if (otherLedger && (otherLedger->header().hash == *hash))
795 JLOG(
journal_.warn()) <<
"Match at " << lSeq <<
", " << invalidate
796 <<
" prior ledgers invalidated";
811 JLOG(
journal_.warn()) <<
"All " << invalidate <<
" prior ledgers invalidated";
822 JLOG(
journal_.debug()) <<
"Ledger " << ledger->header().seq
823 <<
" accepted :" << ledger->header().hash;
825 ledger->stateMap().getHash().isNonZero(),
826 "xrpl::LedgerMaster::setFullLedger : nonzero ledger state hash");
828 ledger->setValidated();
838 app_.getRelationalDatabase().getHashByIndex(ledger->header().seq - 1);
839 if (prevHash.
isNonZero() && prevHash != ledger->header().parentHash)
858 app_.getOrderBookDB().setup(ledger);
861 if (ledger->header().seq != 0 &&
haveLedger(ledger->header().seq - 1))
866 if (!prevLedger || (prevLedger->header().hash != ledger->header().parentHash))
868 JLOG(
journal_.warn()) <<
"Acquired ledger invalidates previous ledger: "
869 << (prevLedger ?
"hashMismatch" :
"missingLedger");
896 auto validations =
app_.getValidators().negativeUNLFilter(
897 app_.getValidations().getTrustedForLedger(hash, seq));
898 valCount = validations.size();
899 if (valCount >=
app_.getValidators().quorum())
921 if (valCount >=
app_.getValidators().quorum())
922 app_.getOverlay().checkTracking(seq);
961 auto validations =
app_.getValidators().negativeUNLFilter(
962 app_.getValidations().getTrustedForLedger(ledger->header().hash, ledger->header().seq));
963 auto const tvc = validations.size();
966 JLOG(
journal_.trace()) <<
"Only " << tvc <<
" validations for " << ledger->header().hash;
970 JLOG(
journal_.info()) <<
"Advancing accepted ledger to " << ledger->header().seq
971 <<
" with >= " << minVal <<
" validations";
973 ledger->setValidated();
980 app_.getOrderBookDB().setup(ledger);
984 auto fees =
app_.getValidations().fees(ledger->header().hash, base);
986 auto fees2 =
app_.getValidations().fees(ledger->header().parentHash, base);
987 fees.reserve(fees.size() + fees2.size());
997 s <<
"Received fees from validations: (" << fees.size() <<
") ";
998 for (
auto const fee1 : fees)
1004 fee = fees[fees.size() / 2];
1011 app_.getFeeTrack().setRemoteFee(fee);
1015 if (ledger->seq() % 256 == 0)
1025 auto currentTime =
app_.getTimeKeeper().now();
1026 bool needPrint =
false;
1033 auto const vals =
app_.getValidations().getTrustedForLedger(
1034 ledger->header().parentHash, ledger->header().seq - 1);
1037 for (
auto const& v : vals)
1039 if (v->isFieldPresent(sfServerVersion))
1041 auto version = v->getFieldU64(sfServerVersion);
1050 if (higherVersionCount > 0 && xrpldCount > 0)
1052 static constexpr std::size_t kReportingPercent = 90;
1054 auto const unlSize{
app_.getValidators().getQuorumKeys().second.size()};
1055 needPrint = unlSize > 0 &&
1073 auto const upgradeMsg =
1074 "Check for upgrade: "
1075 "A majority of trusted validators are "
1076 "running a newer version.";
1078 JLOG(
journal_.error()) << upgradeMsg;
1097 ledgerHistory_.builtLedger(ledger, consensusHash, std::move(consensus));
1101 auto stream =
app_.getJournal(
"LedgerConsensus").info();
1102 JLOG(stream) <<
"Consensus built old ledger: " << ledger->header().seq
1112 auto stream =
app_.getJournal(
"LedgerConsensus").debug();
1113 JLOG(stream) <<
"Consensus ledger fully validated";
1121 app_.getValidators().negativeUNLFilter(
app_.getValidations().currentTrusted());
1145 for (
auto const& v : validations)
1147 ValSeq& vs = count[v->getLedgerHash()];
1148 vs.mergeValidation(v->getFieldU32(sfLedgerSequence));
1153 auto maxLedger = ledger->header().hash;
1157 for (
auto& v : count)
1159 if (v.second.valCount > neededValidations)
1162 if (v.second.ledgerSeq == 0)
1165 v.second.ledgerSeq = l->header().seq;
1168 if (v.second.ledgerSeq > maxSeq)
1170 maxSeq = v.second.ledgerSeq;
1171 maxLedger = v.first;
1178 auto stream =
app_.getJournal(
"LedgerConsensus").debug();
1179 JLOG(stream) <<
"Consensus triggered check of ledger";
1191 if (l && l->header().seq >= index)
1209 JLOG(
journal_.trace()) <<
"findNewLedgersToPublish<";
1214 JLOG(
journal_.trace()) <<
"No valid journal, nothing to publish.";
1232 app_.getOrderBookDB().setup(valLedger);
1239 JLOG(
journal_.trace()) <<
"No valid journal, nothing to publish.";
1254 JLOG(
journal_.trace()) <<
"Trying to fetch/publish valid ledger " << seq;
1262 hash = beast::kZero;
1268 else if (hash->isZero())
1271 JLOG(
journal_.fatal()) <<
"Ledger: " << valSeq <<
" does not have hash for " << seq;
1273 "xrpl::LedgerMaster::findNewLedgersToPublish : ledger "
1282 if (!
app_.config().ledgerReplay)
1287 ledger =
app_.getInboundLedgers().acquire(
1293 if (ledger && (ledger->header().seq == pubSeq))
1295 ledger->setValidated();
1301 JLOG(
journal_.trace()) <<
"ready to publish " << ret.
size() <<
" ledgers.";
1305 JLOG(
journal_.error()) <<
"Exception while trying to find ledgers to publish: "
1309 if (
app_.config().ledgerReplay)
1318 auto finishLedger = valLedger;
1319 while (startLedger->seq() + 1 < finishLedger->seq())
1321 if (
auto const parent =
1322 ledgerHistory_.getLedgerByHash(finishLedger->header().parentHash);
1325 finishLedger = parent;
1329 auto numberLedgers = finishLedger->seq() - startLedger->seq() + 1;
1331 <<
"Publish LedgerReplays " << numberLedgers
1332 <<
" ledgers, from seq=" << startLedger->header().seq <<
", "
1333 << startLedger->header().hash <<
" to seq=" << finishLedger->header().seq
1334 <<
", " << finishLedger->header().hash;
1335 app_.getLedgerReplayer().replay(
1355 app_.getJobQueue().addJob(
JtAdvance,
"AdvanceLedger", [
this]() {
1360 "xrpl::LedgerMaster::tryAdvance : has valid ledger");
1362 JLOG(
journal_.trace()) <<
"advanceThread<";
1370 JLOG(
journal_.fatal()) <<
"doAdvance throws: " << ex.
what();
1374 JLOG(
journal_.trace()) <<
"advanceThread>";
1384 if (
app_.getOPs().isNeedNetworkLedger())
1388 JLOG(
journal_.debug()) <<
"Need network ledger for updating paths";
1393 while (!
app_.getJobQueue().isStopping())
1395 JLOG(
journal_.debug()) <<
"updatePaths running";
1408 lastLedger =
app_.getOpenLedger().current();
1414 JLOG(
journal_.debug()) <<
"Nothing to do for updating paths";
1423 lastLedger->header().closeTime;
1426 JLOG(
journal_.debug()) <<
"Published ledger too old for updating paths";
1436 auto& pathRequests =
app_.getPathRequestManager();
1439 if (!pathRequests.requestsPending())
1443 JLOG(
journal_.debug()) <<
"No path requests found. Nothing to do for updating "
1449 JLOG(
journal_.debug()) <<
"Updating paths";
1450 pathRequests.updateAll(lastLedger);
1453 if (!pathRequests.requestsPending())
1455 JLOG(
journal_.debug()) <<
"No path requests left. No need for further updating "
1464 JLOG(
journal_.info()) <<
"During pathfinding: " << mn.
what();
1465 if (lastLedger->open())
1468 app_.getInboundLedgers().acquire(
1469 lastLedger->header().parentHash,
1470 lastLedger->header().seq - 1,
1476 app_.getInboundLedgers().acquire(
1477 lastLedger->header().hash,
1478 lastLedger->header().seq,
1521 if (
app_.getJobQueue().addJob(
JtUpdatePf, name, [
this]() { updatePaths(); }))
1541 return app_.getOpenLedger().current();
1558 return ledger->rules();
1589 auto nodeObject =
app_.getNodeStore().fetchNodeObject(ledgerHash, index);
1590 if (nodeObject && (nodeObject->getData().size() >= 120))
1592 SerialIter it(nodeObject->getData().data(), nodeObject->getData().size());
1602 return std::nullopt;
1610 if (
hash.isNonZero())
1613 return app_.getRelationalDatabase().getHashByIndex(index);
1633 if (!referenceLedger || (referenceLedger->header().seq < index))
1636 return std::nullopt;
1648 XRPL_ASSERT(refHash,
"xrpl::LedgerMaster::walkHashBySeq : found ledger");
1669 if (
auto const l =
app_.getInboundLedgers().acquire(*refHash, refIndex, reason))
1674 "xrpl::LedgerMaster::walkHashBySeq : has complete "
1690 if (
valid->header().seq == index)
1711 if (ret && (ret->header().seq == index))
1725 if (ret && (ret->header().hash ==
hash))
1787 XRPL_ASSERT(
hash->isNonZero(),
"xrpl::LedgerMaster::fetchForHistory : found ledger");
1791 if (!
app_.getInboundLedgers().isFailure(*
hash))
1793 ledger =
app_.getInboundLedgers().acquire(*
hash, missing, reason);
1795 missing >
app_.getNodeStore().earliestLedgerSeq())
1797 JLOG(
journal_.trace()) <<
"fetchForHistory want fetch pack " << missing;
1803 JLOG(
journal_.trace()) <<
"fetchForHistory no fetch pack for " << missing;
1808 JLOG(
journal_.debug()) <<
"fetchForHistory found failed acquire";
1813 auto seq = ledger->header().seq;
1814 XRPL_ASSERT(seq == missing,
"xrpl::LedgerMaster::fetchForHistory : sequence match");
1815 JLOG(
journal_.trace()) <<
"fetchForHistory acquired " << seq;
1817 int fillInProgress = 0;
1823 if (fillInProgress == 0 &&
1824 app_.getRelationalDatabase().getHashByIndex(seq - 1) == ledger->header().parentHash)
1831 app_.getJobQueue().addJob(
1841 fetchSz =
app_.getNodeStore().earliestLedgerSeq();
1852 "xrpl::LedgerMaster::fetchForHistory : "
1853 "prefetched ledger");
1854 app_.getInboundLedgers().acquire(*h, seq, reason);
1860 JLOG(
journal_.warn()) <<
"Threw while prefetching: " << ex.
what();
1866 JLOG(
journal_.fatal()) <<
"Can't find ledger following prevMissing " << missing;
1868 JLOG(
journal_.fatal()) <<
"Ledgers: " <<
app_.getLedgerMaster().getCompleteLedgers();
1869 JLOG(
journal_.fatal()) <<
"Acquire reason: "
1884 bool progress =
false;
1887 if (pubLedgers.empty())
1903 app_.getNodeStore().earliestLedgerSeq());
1907 JLOG(
journal_.trace()) <<
"tryAdvance discovered missing " << *missing;
1912 app_.getSHAMapStore().minimumOnline(),
1916 JLOG(
journal_.trace()) <<
"advanceThread should acquire";
1920 missing = std::nullopt;
1928 JLOG(
journal_.debug()) <<
"tryAdvance found last valid changed";
1936 JLOG(
journal_.trace()) <<
"tryAdvance not fetching history";
1942 <<
"tryAdvance found " << pubLedgers.size() <<
" ledgers to publish";
1943 for (
auto const& ledger : pubLedgers)
1947 JLOG(
journal_.debug()) <<
"tryAdvance publishing seq " << ledger->header().seq;
1955 app_.getOPs().pubLedger(ledger);
1959 app_.getOPs().clearNeedNetworkLedger();
1960 progress =
newPFWork(
"PthFindNewLed", sl);
1983 return std::nullopt;
1992 app_.getInboundLedgers().gotFetchPack();
2028 protocol::TMGetObjectByHash* into,
2030 bool withLeaves =
true)
2032 XRPL_ASSERT(cnt,
"xrpl::populateFetchPack : nonzero count input");
2037 if (!withLeaves && n.
isLeaf())
2045 protocol::TMIndexedObject* obj = into->add_objects();
2046 obj->set_ledgerseq(seq);
2047 obj->set_hash(
hash.data(),
hash.size());
2061 using namespace std::chrono_literals;
2064 JLOG(
journal_.info()) <<
"Fetch pack request got stale";
2070 JLOG(
journal_.info()) <<
"Too busy to make fetch pack";
2074 auto peer = wPeer.
lock();
2083 JLOG(
journal_.info()) <<
"Peer requests fetch pack for ledger we don't have: " << have;
2090 JLOG(
journal_.warn()) <<
"Peer requests fetch pack from open ledger: " << have;
2097 JLOG(
journal_.debug()) <<
"Peer requests fetch pack that is too early";
2106 JLOG(
journal_.info()) <<
"Peer requests fetch pack for ledger whose predecessor we "
2107 <<
"don't have: " << have;
2116 protocol::TMGetObjectByHash reply;
2117 reply.set_query(
false);
2119 reply.set_ledgerhash(request->ledgerhash());
2120 reply.set_type(protocol::TMGetObjectByHash::otFETCH_PACK);
2139 addRaw(want->header(), hdr);
2142 protocol::TMIndexedObject* obj = reply.add_objects();
2143 obj->set_hash(want->header().hash.data(), want->header().hash.size());
2145 obj->set_ledgerseq(lSeq);
2152 if (want->header().txHash.isNonZero())
2155 if (reply.objects().size() >= 512)
2158 have = std::move(want);
2164 JLOG(
journal_.info()) <<
"Built fetch pack with " << reply.objects().size() <<
" nodes ("
2165 << msg->getBufferSize() <<
" bytes)";
2171 JLOG(
journal_.warn()) <<
"Exception building fetch pack. Exception: " << ex.
what();
2185 return app_.getRelationalDatabase().getMinLedgerSeq();
2197 if (!lgr || lgr->txs.empty())
2200 for (
auto it = lgr->txs.begin(); it != lgr->txs.end(); ++it)
2202 if (it->first && it->second && it->second->isFieldPresent(sfTransactionIndex) &&
2203 it->second->getFieldU32(sfTransactionIndex) == txnIndex)
2204 return it->first->getTransactionID();
T back_inserter(T... args)
NetClock::time_point time_point
Provide a light-weight way to check active() before string formatting.
A generic endpoint for log messages.
Stream trace() const
Severity stream access functions.
std::shared_ptr< Collector > ptr
Holds transactions which were deferred to the next pass of consensus.
std::optional< LedgerIndex > minSqlSeq()
LedgerIndex const maxLedgerDifference_
std::atomic_flag gotFetchPackThread_
bool haveLedger(std::uint32_t seq)
std::size_t getNeededValidations()
Determines how many validations are needed to fully validate a ledger.
bool isCompatible(ReadView const &, beast::Journal::Stream, char const *reason)
std::shared_ptr< STTx const > popAcctTransaction(std::shared_ptr< STTx const > const &tx)
Get the next transaction held for a particular account if any.
void setValidLedger(std::shared_ptr< Ledger const > const &l)
void switchLCL(std::shared_ptr< Ledger const > const &lastClosed)
std::recursive_mutex & peekMutex()
std::chrono::seconds getValidatedLedgerAge()
TimeKeeper::time_point upgradeWarningPrevTime_
std::uint32_t const ledgerFetchSize_
std::atomic< std::uint32_t > pubLedgerClose_
LedgerIndex getCurrentLedgerIndex()
bool fixIndex(LedgerIndex ledgerIndex, LedgerHash const &ledgerHash)
bool getValidatedRange(std::uint32_t &minVal, std::uint32_t &maxVal)
void applyHeldTransactions()
Apply held transactions to the open ledger This is normally called as we close the ledger.
bool storeLedger(std::shared_ptr< Ledger const > ledger)
void gotFetchPack(bool progress, std::uint32_t seq)
void tryFill(std::shared_ptr< Ledger const > ledger)
std::shared_ptr< Ledger const > getLedgerBySeq(std::uint32_t index)
void setPubLedger(std::shared_ptr< Ledger const > const &l)
bool newPFWork(char const *name, std::unique_lock< std::recursive_mutex > &)
A thread needs to be dispatched to handle pathfinding work of some kind.
void setFullLedger(std::shared_ptr< Ledger const > const &ledger, bool isSynchronous, bool isCurrent)
std::atomic< LedgerIndex > pubLedgerSeq_
void clearPriorLedgers(LedgerIndex seq)
void setBuildingLedger(LedgerIndex index)
bool isCaughtUp(std::string &reason)
std::size_t getFetchPackCacheSize() const
std::optional< Blob > getFetchPack(uint256 const &hash) override
std::vector< std::shared_ptr< Ledger const > > findNewLedgersToPublish(std::unique_lock< std::recursive_mutex > &)
std::atomic< LedgerIndex > buildingLedgerSeq_
std::optional< NetClock::time_point > getCloseTimeByHash(LedgerHash const &ledgerHash, LedgerIndex ledgerIndex)
void clearLedger(std::uint32_t seq)
void clearLedgerCachePrior(LedgerIndex seq)
uint256 getHashBySeq(std::uint32_t index)
Get a ledger's hash by sequence number using the cache.
std::unique_ptr< LedgerReplay > replayData_
void consensusBuilt(std::shared_ptr< Ledger const > const &ledger, uint256 const &consensusHash, json::Value consensus)
Report that the consensus process built a particular ledger.
std::atomic< LedgerIndex > validLedgerSeq_
std::shared_ptr< Ledger const > getClosedLedger()
void setLedgerRangePresent(std::uint32_t minV, std::uint32_t maxV)
std::optional< NetClock::time_point > getCloseTimeBySeq(LedgerIndex ledgerIndex)
std::string getCompleteLedgers()
std::shared_ptr< Ledger const > getValidatedLedger()
void fetchForHistory(std::uint32_t missing, bool &progress, InboundLedger::Reason reason, std::unique_lock< std::recursive_mutex > &)
bool isValidated(ReadView const &ledger)
void fixMismatch(ReadView const &ledger)
void makeFetchPack(std::weak_ptr< Peer > const &wPeer, std::shared_ptr< protocol::TMGetObjectByHash > const &request, uint256 haveLedgerHash, UptimeClock::time_point uptime)
LedgerIndex getValidLedgerIndex()
LedgerHolder validLedger_
CanonicalTXSet heldTransactions_
std::shared_ptr< Ledger const > pathLedger_
std::shared_ptr< Ledger const > pubLedger_
std::shared_ptr< ReadView const > getPublishedLedger()
std::uint32_t const fetchDepth_
std::recursive_mutex mutex_
std::pair< uint256, LedgerIndex > lastValidLedger_
Rules getValidatedRules()
LedgerHistory ledgerHistory_
std::optional< LedgerHash > walkHashBySeq(std::uint32_t index, InboundLedger::Reason reason)
Walk to a ledger's hash using the skip list.
LedgerMaster(Application &app, Stopwatch &stopwatch, beast::insight::Collector::ptr const &collector, beast::Journal journal)
std::chrono::seconds getPublishedLedgerAge()
std::optional< uint256 > txnIdFromIndex(uint32_t ledgerSeq, uint32_t txnIndex)
bool canBeCurrent(std::shared_ptr< Ledger const > const &ledger)
Check the sequence number and parent close time of a ledger against our clock and last validated ledg...
LedgerHolder closedLedger_
void addFetchPack(uint256 const &hash, std::shared_ptr< Blob > data)
bool getFullValidatedRange(std::uint32_t &minVal, std::uint32_t &maxVal)
std::optional< LedgerHash > getLedgerHashForHistory(LedgerIndex index, InboundLedger::Reason reason)
RangeSet< std::uint32_t > completeLedgers_
void checkAccept(std::shared_ptr< Ledger const > const &ledger)
std::uint32_t const ledgerHistorySize_
std::atomic< std::uint32_t > validLedgerSign_
void doAdvance(std::unique_lock< std::recursive_mutex > &)
void addHeldTransaction(std::shared_ptr< Transaction > const &trans)
std::shared_ptr< ReadView const > getCurrentLedger()
std::recursive_mutex completeLock_
void takeReplay(std::unique_ptr< LedgerReplay > replay)
std::unique_ptr< LedgerReplay > releaseReplay()
std::shared_ptr< Ledger const > getLedgerByHash(uint256 const &hash)
std::uint32_t getEarliestFetch()
std::shared_ptr< Ledger const > histLedger_
TaggedCache< uint256, Blob > fetchPacks_
void failedSave(std::uint32_t seq, uint256 const &hash)
std::chrono::time_point< NetClock > time_point
std::chrono::duration< rep, period > duration
Persistency layer for NodeObject.
std::shared_ptr< NodeObject > fetchNodeObject(uint256 const &hash, std::uint32_t ledgerSeq=0, FetchType fetchType=FetchType::Synchronous, bool duplicate=false)
Fetch a node object.
virtual LedgerHeader const & header() const =0
Returns information about the ledger.
virtual bool open() const =0
Returns true if this reflects an open ledger.
Rules controlling protocol behavior.
uint256 const & asUInt256() const
SHAMapHash const & getHash() const
Return the hash of this node.
virtual void serializeWithPrefix(Serializer &) const =0
Serialize the node in a format appropriate for hashing.
virtual bool isLeaf() const =0
Determines if this is a leaf node.
A SHAMap is both a radix tree with a fan-out of 16 and a Merkle tree.
void visitDifferences(SHAMap const *have, std::function< bool(SHAMapTreeNode const &)> const &) const
Visit every node in this SHAMap that is not present in the specified SHAMap.
Automatically unlocks and re-locks a unique_lock object.
void const * getDataPtr() const
std::chrono::time_point< UptimeClock > time_point
T duration_cast(T... args)
bool isNewerVersion(std::uint64_t version)
Check if the version is newer than the local node's xrpld software version.
bool isXrpldVersion(std::uint64_t version)
Check if the encoded software version is an xrpld software version.
Charge const kFeeRequestNoReply
Charge const kFeeMalformedRequest
Schedule of fees charged for imposing load on the server.
TER valid(STTx const &tx, ReadView const &view, AccountID const &src, beast::Journal j)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
static constexpr int kMaxLedgerGap
bool set(T &target, std::string const &name, Section const §ion)
Set a value from a configuration Section If the named value is not found or doesn't parse as a T,...
beast::AbstractClock< std::chrono::steady_clock > Stopwatch
A clock for measuring elapsed time.
bool isCurrent(ValidationParms const &p, NetClock::time_point now, NetClock::time_point signTime, NetClock::time_point seenTime)
Whether a validation is still current.
std::optional< T > prevMissing(RangeSet< T > const &rs, T t, T minVal=0)
Find the largest value not in the set that is less than a given value.
bool pendSaveValidated(ServiceRegistry ®istry, std::shared_ptr< Ledger const > const &ledger, bool isSynchronous, bool isCurrent)
Save, or arrange to save, a fully-validated ledger.
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
std::uint32_t LedgerIndex
A ledger index.
Stopwatch & stopwatch()
Returns an instance of a wall clock.
ClosedInterval< T > range(T low, T high)
Create a closed range interval.
constexpr std::enable_if_t< std::is_integral_v< Dest > &&std::is_integral_v< Src >, Dest > safeCast(Src s) noexcept
constexpr std::size_t calculatePercent(std::size_t count, std::size_t total)
Calculate one number divided by another number in percentage.
static void populateFetchPack(SHAMap const &want, SHAMap const *have, std::uint32_t cnt, protocol::TMGetObjectByHash *into, std::uint32_t seq, bool withLeaves=true)
Populate a fetch pack with data from the map the recipient wants.
std::string to_string(BaseUInt< Bits, Tag > const &a)
void logicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
bool areCompatible(ReadView const &validLedger, ReadView const &testLedger, beast::Journal::Stream &s, char const *reason)
Return false if the test ledger is provably incompatible with the valid ledger, that is,...
LedgerIndex getCandidateLedger(LedgerIndex requested)
Find a ledger index from which we could easily get the requested ledger.
std::chrono::duration< int, std::ratio_multiply< days::period, std::ratio< 7 > > > weeks
std::optional< uint256 > hashOfSeq(ReadView const &ledger, LedgerIndex seq, beast::Journal journal)
Return the hash of a ledger by sequence.
void addRaw(LedgerHeader const &, Serializer &, bool includeHash=false)
std::unordered_map< Key, Value, Hash, Pred, Allocator > hash_map
@ LedgerMaster
ledger master data for signing
std::vector< unsigned char > Blob
Storage for linear binary data.
static constexpr int kMaxWriteLoadAcquire
std::enable_if_t< std::is_same_v< T, char >||std::is_same_v< T, unsigned char >, Slice > makeSlice(std::array< T, N > const &a)
static constexpr std::chrono::minutes kMaxLedgerAgeAcquire
static bool shouldAcquire(std::uint32_t const currentLedger, std::uint32_t const ledgerHistory, std::optional< LedgerIndex > const minimumOnline, std::uint32_t const candidateLedger, beast::Journal j)
T time_point_cast(T... args)
T time_since_epoch(T... args)