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/InboundLedgers.h>
6#include <xrpld/app/ledger/LedgerPersistence.h>
7#include <xrpld/app/ledger/LedgerReplay.h>
8#include <xrpld/app/ledger/LedgerReplayer.h>
9#include <xrpld/app/ledger/OpenLedger.h>
10#include <xrpld/app/main/Application.h>
11#include <xrpld/app/misc/SHAMapStore.h>
12#include <xrpld/app/misc/Transaction.h>
13#include <xrpld/app/misc/TxQ.h>
14#include <xrpld/app/misc/ValidatorList.h>
15#include <xrpld/core/Config.h>
16#include <xrpld/core/TimeKeeper.h>
17#include <xrpld/overlay/Overlay.h>
18#include <xrpld/overlay/Peer.h>
19#include <xrpld/rpc/detail/PathRequestManager.h>
21#include <xrpl/basics/Log.h>
22#include <xrpl/basics/MathUtilities.h>
23#include <xrpl/basics/RangeSet.h>
24#include <xrpl/basics/Slice.h>
25#include <xrpl/basics/UnorderedContainers.h>
26#include <xrpl/basics/UptimeClock.h>
27#include <xrpl/basics/base_uint.h>
28#include <xrpl/basics/chrono.h>
29#include <xrpl/basics/contract.h>
30#include <xrpl/basics/safe_cast.h>
31#include <xrpl/basics/scope.h>
32#include <xrpl/beast/insight/Collector.h>
33#include <xrpl/beast/utility/Journal.h>
34#include <xrpl/beast/utility/Zero.h>
35#include <xrpl/beast/utility/instrumentation.h>
36#include <xrpl/core/Job.h>
37#include <xrpl/json/json_value.h>
38#include <xrpl/ledger/AmendmentTable.h>
39#include <xrpl/ledger/Ledger.h>
40#include <xrpl/ledger/OrderBookDB.h>
41#include <xrpl/ledger/PendingSaves.h>
42#include <xrpl/ledger/View.h>
43#include <xrpl/nodestore/Database.h>
44#include <xrpl/protocol/BuildInfo.h>
45#include <xrpl/protocol/HashPrefix.h>
46#include <xrpl/protocol/LedgerHeader.h>
47#include <xrpl/protocol/Protocol.h>
48#include <xrpl/protocol/RippleLedgerHash.h>
49#include <xrpl/protocol/SField.h>
50#include <xrpl/protocol/Serializer.h>
51#include <xrpl/protocol/digest.h>
52#include <xrpl/rdb/RelationalDatabase.h>
53#include <xrpl/resource/Fees.h>
54#include <xrpl/server/LoadFeeTrack.h>
55#include <xrpl/server/NetworkOPs.h>
56#include <xrpl/shamap/SHAMap.h>
57#include <xrpl/shamap/SHAMapMissingNode.h>
58#include <xrpl/shamap/SHAMapTreeNode.h>
60#include <boost/icl/concept/interval_set.hpp>
103 bool const ret = [&]() {
105 if (candidateLedger >= currentLedger)
109 if (currentLedger - candidateLedger <= ledgerHistory)
114 return minimumOnline.
has_value() && candidateLedger >= *minimumOnline;
117 JLOG(j.
trace()) <<
"Missing ledger " << candidateLedger << (ret ?
" should" :
" should NOT")
137 std::chrono::seconds{45},
139 app_.getJournal(
"TaggedCache"))
147 return app_.getOpenLedger().current()->header().seq;
161 if (validLedger && !
areCompatible(*validLedger, view, s, reason))
182 using namespace std::chrono_literals;
186 JLOG(
journal_.debug()) <<
"No published ledger";
192 ret = (ret > 0s) ? ret : 0s;
197 JLOG(
journal_.trace()) <<
"Published ledger age is " << ret.
count();
206 using namespace std::chrono_literals;
211 JLOG(
journal_.debug()) <<
"No validated ledger";
217 ret = (ret > 0s) ? ret : 0s;
222 JLOG(
journal_.trace()) <<
"Validated ledger age is " << ret.
count();
231 using namespace std::chrono_literals;
235 reason =
"No recently-published ledger";
240 if ((validClose == 0u) || (pubClose == 0u))
242 reason =
"No published ledger";
245 if (validClose > (pubClose + 90))
247 reason =
"Published ledger lags validated ledger";
261 auto validations =
app_.getValidators().negativeUNLFilter(
262 app_.getValidations().getTrustedForLedger(l->header().hash, l->header().seq));
263 times.
reserve(validations.size());
264 for (
auto const& val : validations)
267 if (!validations.empty())
268 consensusHash = validations.front()->getConsensusHash();
273 if (!times.
empty() && times.
size() >=
app_.getValidators().quorum())
277 auto const t0 = times[(times.
size() - 1) / 2];
278 auto const t1 = times[times.
size() / 2];
279 signTime = t0 + (t1 - t0) / 2;
283 signTime = l->header().closeTime;
291 "xrpl::LedgerMaster::setValidLedger : valid ledger sequence");
295 app_.getOPs().updateLocalTx(*l);
298 app_.getAmendmentTable().doValidatedLedger(l);
299 if (!
app_.getOPs().isBlocked())
301 if (
app_.getAmendmentTable().hasUnsupportedEnabled())
303 JLOG(
journal_.error()) <<
"One or more unsupported amendments "
304 "activated: server blocked.";
305 app_.getOPs().setAmendmentBlocked();
307 else if (!
app_.getOPs().isAmendmentWarned() || l->isFlagLedger())
318 if (
auto const first =
app_.getAmendmentTable().firstUnsupportedExpected())
320 JLOG(
journal_.error()) <<
"One or more unsupported amendments "
321 "reached majority. Upgrade before "
323 <<
" to prevent your server from "
324 "becoming amendment blocked.";
325 app_.getOPs().setAmendmentWarned();
329 app_.getOPs().clearAmendmentWarned();
356 XRPL_ASSERT(ledger,
"xrpl::LedgerMaster::canBeCurrent : non-null input");
362 if (validLedger && (ledger->header().seq < validLedger->header().seq))
364 JLOG(
journal_.trace()) <<
"Candidate for current ledger has low seq "
365 << ledger->header().seq <<
" < " << validLedger->header().seq;
374 auto closeTime =
app_.getTimeKeeper().closeTime();
375 auto ledgerClose = ledger->header().parentCloseTime;
377 using namespace std::chrono_literals;
378 if ((validLedger || (ledger->header().seq > 10)) &&
379 ((
std::max(closeTime, ledgerClose) -
std::min(closeTime, ledgerClose)) > 5min))
381 JLOG(
journal_.warn()) <<
"Candidate for current ledger has close time "
382 <<
to_string(ledgerClose) <<
" at network time "
383 <<
to_string(closeTime) <<
" seq " << ledger->header().seq;
394 LedgerIndex maxSeq = validLedger->header().seq + 10;
396 if (closeTime > validLedger->header().parentCloseTime)
399 closeTime - validLedger->header().parentCloseTime)
404 if (ledger->header().seq > maxSeq)
406 JLOG(
journal_.warn()) <<
"Candidate for current ledger has high seq "
407 << ledger->header().seq <<
" > " << maxSeq;
411 JLOG(
journal_.trace()) <<
"Acceptable seq range: " << validLedger->header().seq
412 <<
" <= " << ledger->header().seq <<
" <= " << maxSeq;
421 XRPL_ASSERT(lastClosed,
"xrpl::LedgerMaster::switchLCL : non-null input");
422 if (!lastClosed->isImmutable())
425 if (lastClosed->open())
426 logicError(
"The new last closed ledger is open!");
453 bool const validated = ledger->header().validated;
477 app_.getOPs().processTransactionSet(
set);
530 XRPL_ASSERT(hash->isNonZero(),
"xrpl::LedgerMaster::isValidated : nonzero hash");
531 uint256 const valHash =
app_.getRelationalDatabase().getHashByIndex(seq);
543 JLOG(
journal_.warn()) <<
"Ledger #" << seq <<
": " << mn.
what();
569 if (maybeMin == std::nullopt)
575 minVal = 1 + *maybeMin;
591 auto const pendingSaves =
app_.getPendingSaves().getSnapshot();
593 if (!pendingSaves.empty() && ((minVal != 0) || (maxVal != 0)))
598 while (pendingSaves.contains(maxVal))
600 while (pendingSaves.contains(minVal))
604 for (
auto v : pendingSaves)
606 if ((v.first >= minVal) && (v.first <= maxVal))
608 if (v.first > ((minVal + maxVal) / 2))
610 maxVal = v.first - 1;
614 minVal = v.first + 1;
649 uint256 prevHash = ledger->header().parentHash;
657 while (!
app_.getJobQueue().isStopping() && seq > 0)
668 auto it(ledgerHashes.
find(seq));
670 if (it == ledgerHashes.
end())
672 if (
app_.isStopping())
681 app_.getRelationalDatabase().getHashesByIndex((seq < 500) ? 0 : (seq - 499), seq);
682 it = ledgerHashes.
find(seq);
684 if (it == ledgerHashes.
end())
688 ledgerHashes.
begin()->second.ledgerHash, ledgerHashes.
begin()->first))
692 <<
"SQL DB ledger sequence " << seq <<
" mismatches node store";
697 if (it->second.ledgerHash != prevHash)
700 prevHash = it->second.parentHash;
723 if (!haveHash || haveHash->isZero())
725 JLOG(
journal_.error()) <<
"No hash for fetch pack. Missing Index " << missing;
734 auto peerList =
app_.getOverlay().getActivePeers();
735 for (
auto const& peer : peerList)
737 if (peer->hasRange(missing, missing + 1))
739 int const score = peer->getScore(
true);
740 if (!target || (score > maxScore))
751 protocol::TMGetObjectByHash tmBH;
752 tmBH.set_query(
true);
753 tmBH.set_type(protocol::TMGetObjectByHash::otFETCH_PACK);
754 tmBH.set_ledgerhash(haveHash->begin(), 32);
757 target->send(packet);
758 JLOG(
journal_.trace()) <<
"Requested fetch pack for " << missing;
762 JLOG(
journal_.debug()) <<
"No peer for fetch pack";
783 <<
"fixMismatch encounters partial ledger. Exception: " << ex.
what();
793 if (otherLedger && (otherLedger->header().hash == *hash))
798 JLOG(
journal_.warn()) <<
"Match at " << lSeq <<
", " << invalidate
799 <<
" prior ledgers invalidated";
814 JLOG(
journal_.warn()) <<
"All " << invalidate <<
" prior ledgers invalidated";
825 JLOG(
journal_.debug()) <<
"Ledger " << ledger->header().seq
826 <<
" accepted :" << ledger->header().hash;
828 ledger->stateMap().getHash().isNonZero(),
829 "xrpl::LedgerMaster::setFullLedger : nonzero ledger state hash");
831 ledger->setValidated();
841 app_.getRelationalDatabase().getHashByIndex(ledger->header().seq - 1);
842 if (prevHash.
isNonZero() && prevHash != ledger->header().parentHash)
861 app_.getOrderBookDB().setup(ledger);
864 if (ledger->header().seq != 0 &&
haveLedger(ledger->header().seq - 1))
869 if (!prevLedger || (prevLedger->header().hash != ledger->header().parentHash))
871 JLOG(
journal_.warn()) <<
"Acquired ledger invalidates previous ledger: "
872 << (prevLedger ?
"hashMismatch" :
"missingLedger");
899 auto validations =
app_.getValidators().negativeUNLFilter(
900 app_.getValidations().getTrustedForLedger(hash, seq));
901 valCount = validations.size();
902 if (valCount >=
app_.getValidators().quorum())
924 if (valCount >=
app_.getValidators().quorum())
925 app_.getOverlay().checkTracking(seq);
964 auto validations =
app_.getValidators().negativeUNLFilter(
965 app_.getValidations().getTrustedForLedger(ledger->header().hash, ledger->header().seq));
966 auto const tvc = validations.size();
969 JLOG(
journal_.trace()) <<
"Only " << tvc <<
" validations for " << ledger->header().hash;
973 JLOG(
journal_.info()) <<
"Advancing accepted ledger to " << ledger->header().seq
974 <<
" with >= " << minVal <<
" validations";
976 ledger->setValidated();
983 app_.getOrderBookDB().setup(ledger);
987 auto fees =
app_.getValidations().fees(ledger->header().hash, base);
989 auto fees2 =
app_.getValidations().fees(ledger->header().parentHash, base);
990 fees.reserve(fees.size() + fees2.size());
1000 s <<
"Received fees from validations: (" << fees.size() <<
") ";
1001 for (
auto const fee1 : fees)
1007 fee = fees[fees.size() / 2];
1014 app_.getFeeTrack().setRemoteFee(fee);
1018 if (ledger->seq() % 256 == 0)
1028 auto currentTime =
app_.getTimeKeeper().now();
1029 bool needPrint =
false;
1036 auto const vals =
app_.getValidations().getTrustedForLedger(
1037 ledger->header().parentHash, ledger->header().seq - 1);
1040 for (
auto const& v : vals)
1042 if (v->isFieldPresent(sfServerVersion))
1044 auto version = v->getFieldU64(sfServerVersion);
1053 if (higherVersionCount > 0 && xrpldCount > 0)
1055 static constexpr std::size_t kReportingPercent = 90;
1057 auto const unlSize{
app_.getValidators().getQuorumKeys().second.size()};
1058 needPrint = unlSize > 0 &&
1076 auto const upgradeMsg =
1077 "Check for upgrade: "
1078 "A majority of trusted validators are "
1079 "running a newer version.";
1081 JLOG(
journal_.error()) << upgradeMsg;
1102 ledgerHistory_.builtLedger(ledger, consensusHash, std::move(consensus));
1106 auto stream =
app_.getJournal(
"LedgerConsensus").info();
1107 JLOG(stream) <<
"Consensus built old ledger: " << ledger->header().seq
1117 auto stream =
app_.getJournal(
"LedgerConsensus").debug();
1118 JLOG(stream) <<
"Consensus ledger fully validated";
1126 app_.getValidators().negativeUNLFilter(
app_.getValidations().currentTrusted());
1150 for (
auto const& v : validations)
1152 ValSeq& vs = count[v->getLedgerHash()];
1153 vs.mergeValidation(v->getFieldU32(sfLedgerSequence));
1158 auto maxLedger = ledger->header().hash;
1162 for (
auto& v : count)
1164 if (v.second.valCount > neededValidations)
1167 if (v.second.ledgerSeq == 0)
1170 v.second.ledgerSeq = l->header().seq;
1173 if (v.second.ledgerSeq > maxSeq)
1175 maxSeq = v.second.ledgerSeq;
1176 maxLedger = v.first;
1183 auto stream =
app_.getJournal(
"LedgerConsensus").debug();
1184 JLOG(stream) <<
"Consensus triggered check of ledger";
1196 if (l && l->header().seq >= index)
1214 JLOG(
journal_.trace()) <<
"findNewLedgersToPublish<";
1219 JLOG(
journal_.trace()) <<
"No valid journal, nothing to publish.";
1237 app_.getOrderBookDB().setup(valLedger);
1244 JLOG(
journal_.trace()) <<
"No valid journal, nothing to publish.";
1259 JLOG(
journal_.trace()) <<
"Trying to fetch/publish valid ledger " << seq;
1273 else if (hash->isZero())
1276 JLOG(
journal_.fatal()) <<
"Ledger: " << valSeq <<
" does not have hash for " << seq;
1278 "xrpl::LedgerMaster::findNewLedgersToPublish : ledger "
1287 if (!
app_.config().ledgerReplay)
1292 ledger =
app_.getInboundLedgers().acquire(
1298 if (ledger && (ledger->header().seq == pubSeq))
1300 ledger->setValidated();
1306 JLOG(
journal_.trace()) <<
"ready to publish " << ret.
size() <<
" ledgers.";
1310 JLOG(
journal_.error()) <<
"Exception while trying to find ledgers to publish: "
1314 if (
app_.config().ledgerReplay)
1323 auto finishLedger = valLedger;
1324 while (startLedger->seq() + 1 < finishLedger->seq())
1326 if (
auto const parent =
1327 ledgerHistory_.getLedgerByHash(finishLedger->header().parentHash);
1330 finishLedger = parent;
1334 auto numberLedgers = finishLedger->seq() - startLedger->seq() + 1;
1336 <<
"Publish LedgerReplays " << numberLedgers
1337 <<
" ledgers, from seq=" << startLedger->header().seq <<
", "
1338 << startLedger->header().hash <<
" to seq=" << finishLedger->header().seq
1339 <<
", " << finishLedger->header().hash;
1340 app_.getLedgerReplayer().replay(
1360 app_.getJobQueue().addJob(
JtAdvance,
"AdvanceLedger", [
this]() {
1365 "xrpl::LedgerMaster::tryAdvance : has valid ledger");
1367 JLOG(
journal_.trace()) <<
"advanceThread<";
1375 JLOG(
journal_.fatal()) <<
"doAdvance throws: " << ex.
what();
1379 JLOG(
journal_.trace()) <<
"advanceThread>";
1389 if (
app_.getOPs().isNeedNetworkLedger())
1393 JLOG(
journal_.debug()) <<
"Need network ledger for updating paths";
1398 while (!
app_.getJobQueue().isStopping())
1400 JLOG(
journal_.debug()) <<
"updatePaths running";
1413 lastLedger =
app_.getOpenLedger().current();
1419 JLOG(
journal_.debug()) <<
"Nothing to do for updating paths";
1428 lastLedger->header().closeTime;
1431 JLOG(
journal_.debug()) <<
"Published ledger too old for updating paths";
1441 auto& pathRequests =
app_.getPathRequestManager();
1444 if (!pathRequests.requestsPending())
1448 JLOG(
journal_.debug()) <<
"No path requests found. Nothing to do for updating "
1454 JLOG(
journal_.debug()) <<
"Updating paths";
1455 pathRequests.updateAll(lastLedger);
1458 if (!pathRequests.requestsPending())
1460 JLOG(
journal_.debug()) <<
"No path requests left. No need for further updating "
1469 JLOG(
journal_.info()) <<
"During pathfinding: " << mn.
what();
1470 if (lastLedger->open())
1473 app_.getInboundLedgers().acquire(
1474 lastLedger->header().parentHash,
1475 lastLedger->header().seq - 1,
1481 app_.getInboundLedgers().acquire(
1482 lastLedger->header().hash,
1483 lastLedger->header().seq,
1527 if (
app_.getJobQueue().addJob(
JtUpdatePf, name, [
this]() { updatePaths(); }))
1547 return app_.getOpenLedger().current();
1564 return ledger->rules();
1595 auto nodeObject =
app_.getNodeStore().fetchNodeObject(ledgerHash, index);
1596 if (nodeObject && (nodeObject->getData().size() >= 120))
1598 SerialIter it(nodeObject->getData().data(), nodeObject->getData().size());
1608 return std::nullopt;
1616 if (
hash.isNonZero())
1619 return app_.getRelationalDatabase().getHashByIndex(index);
1639 if (!referenceLedger || (referenceLedger->header().seq < index))
1642 return std::nullopt;
1654 XRPL_ASSERT(refHash,
"xrpl::LedgerMaster::walkHashBySeq : found ledger");
1675 if (
auto const l =
app_.getInboundLedgers().acquire(*refHash, refIndex, reason))
1680 "xrpl::LedgerMaster::walkHashBySeq : has complete "
1696 if (
valid->header().seq == index)
1717 if (ret && (ret->header().seq == index))
1731 if (ret && (ret->header().hash ==
hash))
1793 XRPL_ASSERT(
hash->isNonZero(),
"xrpl::LedgerMaster::fetchForHistory : found ledger");
1797 if (!
app_.getInboundLedgers().isFailure(*
hash))
1799 ledger =
app_.getInboundLedgers().acquire(*
hash, missing, reason);
1801 missing >
app_.getNodeStore().earliestLedgerSeq())
1803 JLOG(
journal_.trace()) <<
"fetchForHistory want fetch pack " << missing;
1809 JLOG(
journal_.trace()) <<
"fetchForHistory no fetch pack for " << missing;
1814 JLOG(
journal_.debug()) <<
"fetchForHistory found failed acquire";
1819 auto seq = ledger->header().seq;
1820 XRPL_ASSERT(seq == missing,
"xrpl::LedgerMaster::fetchForHistory : sequence match");
1821 JLOG(
journal_.trace()) <<
"fetchForHistory acquired " << seq;
1823 int fillInProgress = 0;
1829 if (fillInProgress == 0 &&
1830 app_.getRelationalDatabase().getHashByIndex(seq - 1) == ledger->header().parentHash)
1837 app_.getJobQueue().addJob(
1847 fetchSz =
app_.getNodeStore().earliestLedgerSeq();
1858 "xrpl::LedgerMaster::fetchForHistory : "
1859 "prefetched ledger");
1860 app_.getInboundLedgers().acquire(*h, seq, reason);
1866 JLOG(
journal_.warn()) <<
"Threw while prefetching: " << ex.
what();
1872 JLOG(
journal_.fatal()) <<
"Can't find ledger following prevMissing " << missing;
1874 JLOG(
journal_.fatal()) <<
"Ledgers: " <<
app_.getLedgerMaster().getCompleteLedgers();
1875 JLOG(
journal_.fatal()) <<
"Acquire reason: "
1890 bool progress =
false;
1893 if (pubLedgers.empty())
1909 app_.getNodeStore().earliestLedgerSeq());
1913 JLOG(
journal_.trace()) <<
"tryAdvance discovered missing " << *missing;
1918 app_.getSHAMapStore().minimumOnline(),
1922 JLOG(
journal_.trace()) <<
"advanceThread should acquire";
1926 missing = std::nullopt;
1934 JLOG(
journal_.debug()) <<
"tryAdvance found last valid changed";
1942 JLOG(
journal_.trace()) <<
"tryAdvance not fetching history";
1948 <<
"tryAdvance found " << pubLedgers.size() <<
" ledgers to publish";
1949 for (
auto const& ledger : pubLedgers)
1953 JLOG(
journal_.debug()) <<
"tryAdvance publishing seq " << ledger->header().seq;
1961 app_.getOPs().pubLedger(ledger);
1965 app_.getOPs().clearNeedNetworkLedger();
1966 progress =
newPFWork(
"PthFindNewLed", sl);
1989 return std::nullopt;
1998 app_.getInboundLedgers().gotFetchPack();
2035 protocol::TMGetObjectByHash* into,
2037 bool withLeaves =
true)
2039 XRPL_ASSERT(cnt,
"xrpl::populateFetchPack : nonzero count input");
2044 if (!withLeaves && n.
isLeaf())
2052 protocol::TMIndexedObject* obj = into->add_objects();
2053 obj->set_ledgerseq(seq);
2054 obj->set_hash(
hash.data(),
hash.size());
2068 using namespace std::chrono_literals;
2071 JLOG(
journal_.info()) <<
"Fetch pack request got stale";
2077 JLOG(
journal_.info()) <<
"Too busy to make fetch pack";
2081 auto peer = wPeer.
lock();
2090 JLOG(
journal_.info()) <<
"Peer requests fetch pack for ledger we don't have: " << have;
2097 JLOG(
journal_.warn()) <<
"Peer requests fetch pack from open ledger: " << have;
2104 JLOG(
journal_.debug()) <<
"Peer requests fetch pack that is too early";
2113 JLOG(
journal_.info()) <<
"Peer requests fetch pack for ledger whose predecessor we "
2114 <<
"don't have: " << have;
2123 protocol::TMGetObjectByHash reply;
2124 reply.set_query(
false);
2126 reply.set_ledgerhash(request->ledgerhash());
2127 reply.set_type(protocol::TMGetObjectByHash::otFETCH_PACK);
2146 addRaw(want->header(), hdr);
2149 protocol::TMIndexedObject* obj = reply.add_objects();
2150 obj->set_hash(want->header().hash.data(), want->header().hash.size());
2152 obj->set_ledgerseq(lSeq);
2159 if (want->header().txHash.isNonZero())
2162 if (reply.objects().size() >= 512)
2165 have = std::move(want);
2171 JLOG(
journal_.info()) <<
"Built fetch pack with " << reply.objects().size() <<
" nodes ("
2172 << msg->getBufferSize() <<
" bytes)";
2178 JLOG(
journal_.warn()) <<
"Exception building fetch pack. Exception: " << ex.
what();
2192 return app_.getRelationalDatabase().getMinLedgerSeq();
2204 if (!lgr || lgr->txs.empty())
2207 for (
auto it = lgr->txs.begin(); it != lgr->txs.end(); ++it)
2209 if (it->first && it->second && it->second->isFieldPresent(sfTransactionIndex) &&
2210 it->second->getFieldU32(sfTransactionIndex) == txnIndex)
2211 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
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.
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
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.
T duration_cast(T... args)
bool isXrpldVersion(std::uint64_t version)
Check if the encoded software version is an xrpld software version.
bool isNewerVersion(std::uint64_t version)
Check if the version is newer than the local node's xrpld software version.
TER valid(STTx const &tx, ReadView const &view, AccountID const &src, beast::Journal j)
Charge const kFeeRequestNoReply
Charge const kFeeMalformedRequest
Schedule of fees charged for imposing load on the server.
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::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.
constexpr Dest safeCast(Src s) noexcept
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.
Slice makeSlice(std::array< T, N > const &a)
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
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)