rippled
LedgerMaster.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/app/consensus/RCLValidations.h>
21 #include <ripple/app/ledger/Ledger.h>
22 #include <ripple/app/ledger/LedgerMaster.h>
23 #include <ripple/app/ledger/LedgerReplayer.h>
24 #include <ripple/app/ledger/OpenLedger.h>
25 #include <ripple/app/ledger/OrderBookDB.h>
26 #include <ripple/app/ledger/PendingSaves.h>
27 #include <ripple/app/main/Application.h>
28 #include <ripple/app/misc/AmendmentTable.h>
29 #include <ripple/app/misc/HashRouter.h>
30 #include <ripple/app/misc/LoadFeeTrack.h>
31 #include <ripple/app/misc/NetworkOPs.h>
32 #include <ripple/app/misc/SHAMapStore.h>
33 #include <ripple/app/misc/Transaction.h>
34 #include <ripple/app/misc/TxQ.h>
35 #include <ripple/app/misc/ValidatorList.h>
36 #include <ripple/app/paths/PathRequests.h>
37 #include <ripple/app/rdb/backend/PostgresDatabase.h>
38 #include <ripple/app/tx/apply.h>
39 #include <ripple/basics/Log.h>
40 #include <ripple/basics/MathUtilities.h>
41 #include <ripple/basics/TaggedCache.h>
42 #include <ripple/basics/UptimeClock.h>
43 #include <ripple/basics/contract.h>
44 #include <ripple/basics/safe_cast.h>
45 #include <ripple/core/DatabaseCon.h>
46 #include <ripple/core/Pg.h>
47 #include <ripple/core/TimeKeeper.h>
48 #include <ripple/nodestore/DatabaseShard.h>
49 #include <ripple/overlay/Overlay.h>
50 #include <ripple/overlay/Peer.h>
51 #include <ripple/protocol/BuildInfo.h>
52 #include <ripple/protocol/HashPrefix.h>
53 #include <ripple/protocol/digest.h>
54 #include <ripple/resource/Fees.h>
55 #include <algorithm>
56 #include <cassert>
57 #include <chrono>
58 #include <cstdlib>
59 #include <limits>
60 #include <memory>
61 #include <vector>
62 
63 namespace ripple {
64 
65 namespace {
66 
67 //==============================================================================
104 template <class MutexType>
105 class ScopedUnlock
106 {
108 
109 public:
120  explicit ScopedUnlock(std::unique_lock<MutexType>& lock) : lock_(lock)
121  {
122  assert(lock_.owns_lock());
123  lock_.unlock();
124  }
125 
126  ScopedUnlock(ScopedUnlock const&) = delete;
127  ScopedUnlock&
128  operator=(ScopedUnlock const&) = delete;
129 
137  ~ScopedUnlock() noexcept(false)
138  {
139  lock_.lock();
140  }
141 };
142 
143 } // namespace
144 
145 // Don't catch up more than 100 ledgers (cannot exceed 256)
146 static constexpr int MAX_LEDGER_GAP{100};
147 
148 // Don't acquire history if ledger is too old
150 
151 // Don't acquire history if write load is too high
152 static constexpr int MAX_WRITE_LOAD_ACQUIRE{8192};
153 
154 // Helper function for LedgerMaster::doAdvance()
155 // Return true if candidateLedger should be fetched from the network.
156 static bool
158  std::uint32_t const currentLedger,
159  std::uint32_t const ledgerHistory,
160  std::optional<LedgerIndex> const minimumOnline,
161  std::uint32_t const candidateLedger,
162  beast::Journal j)
163 {
164  bool const ret = [&]() {
165  // Fetch ledger if it may be the current ledger
166  if (candidateLedger >= currentLedger)
167  return true;
168 
169  // Or if it is within our configured history range:
170  if (currentLedger - candidateLedger <= ledgerHistory)
171  return true;
172 
173  // Or if greater than or equal to a specific minimum ledger.
174  // Do nothing if the minimum ledger to keep online is unknown.
175  return minimumOnline.has_value() && candidateLedger >= *minimumOnline;
176  }();
177 
178  JLOG(j.trace()) << "Missing ledger " << candidateLedger
179  << (ret ? " should" : " should NOT") << " be acquired";
180  return ret;
181 }
182 
184  Application& app,
186  beast::insight::Collector::ptr const& collector,
187  beast::Journal journal)
188  : app_(app)
189  , m_journal(journal)
190  , mLedgerHistory(collector, app)
191  , standalone_(app_.config().standalone())
192  , fetch_depth_(
193  app_.getSHAMapStore().clampFetchDepth(app_.config().FETCH_DEPTH))
194  , ledger_history_(app_.config().LEDGER_HISTORY)
195  , ledger_fetch_size_(app_.config().getValueFor(SizedItem::ledgerFetch))
196  , fetch_packs_(
197  "FetchPack",
198  65536,
199  std::chrono::seconds{45},
200  stopwatch,
201  app_.journal("TaggedCache"))
202  , m_stats(std::bind(&LedgerMaster::collect_metrics, this), collector)
203 {
204 }
205 
208 {
209  return app_.openLedger().current()->info().seq;
210 }
211 
214 {
215  return mValidLedgerSeq;
216 }
217 
218 bool
220  ReadView const& view,
222  char const* reason)
223 {
224  auto validLedger = getValidatedLedger();
225 
226  if (validLedger && !areCompatible(*validLedger, view, s, reason))
227  {
228  return false;
229  }
230 
231  {
233 
234  if ((mLastValidLedger.second != 0) &&
235  !areCompatible(
236  mLastValidLedger.first,
237  mLastValidLedger.second,
238  view,
239  s,
240  reason))
241  {
242  return false;
243  }
244  }
245 
246  return true;
247 }
248 
251 {
252  using namespace std::chrono_literals;
254  if (pubClose == 0s)
255  {
256  JLOG(m_journal.debug()) << "No published ledger";
257  return weeks{2};
258  }
259 
260  std::chrono::seconds ret = app_.timeKeeper().closeTime().time_since_epoch();
261  ret -= pubClose;
262  ret = (ret > 0s) ? ret : 0s;
263  static std::chrono::seconds lastRet = -1s;
264 
265  if (ret != lastRet)
266  {
267  JLOG(m_journal.trace()) << "Published ledger age is " << ret.count();
268  lastRet = ret;
269  }
270  return ret;
271 }
272 
275 {
276  using namespace std::chrono_literals;
277 
278 #ifdef RIPPLED_REPORTING
279  if (app_.config().reporting())
280  return static_cast<PostgresDatabase*>(&app_.getRelationalDatabase())
282 #endif
283 
285  if (valClose == 0s)
286  {
287  JLOG(m_journal.debug()) << "No validated ledger";
288  return weeks{2};
289  }
290 
291  std::chrono::seconds ret = app_.timeKeeper().closeTime().time_since_epoch();
292  ret -= valClose;
293  ret = (ret > 0s) ? ret : 0s;
294  static std::chrono::seconds lastRet = -1s;
295 
296  if (ret != lastRet)
297  {
298  JLOG(m_journal.trace()) << "Validated ledger age is " << ret.count();
299  lastRet = ret;
300  }
301  return ret;
302 }
303 
304 bool
306 {
307  using namespace std::chrono_literals;
308 
309 #ifdef RIPPLED_REPORTING
310  if (app_.config().reporting())
311  return static_cast<PostgresDatabase*>(&app_.getRelationalDatabase())
312  ->isCaughtUp(reason);
313 #endif
314 
315  if (getPublishedLedgerAge() > 3min)
316  {
317  reason = "No recently-published ledger";
318  return false;
319  }
320  std::uint32_t validClose = mValidLedgerSign.load();
321  std::uint32_t pubClose = mPubLedgerClose.load();
322  if (!validClose || !pubClose)
323  {
324  reason = "No published ledger";
325  return false;
326  }
327  if (validClose > (pubClose + 90))
328  {
329  reason = "Published ledger lags validated ledger";
330  return false;
331  }
332  return true;
333 }
334 
335 void
337 {
339  std::optional<uint256> consensusHash;
340 
341  if (!standalone_)
342  {
343  auto validations = app_.validators().negativeUNLFilter(
345  l->info().hash, l->info().seq));
346  times.reserve(validations.size());
347  for (auto const& val : validations)
348  times.push_back(val->getSignTime());
349 
350  if (!validations.empty())
351  consensusHash = validations.front()->getConsensusHash();
352  }
353 
354  NetClock::time_point signTime;
355 
356  if (!times.empty() && times.size() >= app_.validators().quorum())
357  {
358  // Calculate the sample median
359  std::sort(times.begin(), times.end());
360  auto const t0 = times[(times.size() - 1) / 2];
361  auto const t1 = times[times.size() / 2];
362  signTime = t0 + (t1 - t0) / 2;
363  }
364  else
365  {
366  signTime = l->info().closeTime;
367  }
368 
369  mValidLedger.set(l);
370  // In case we're waiting for a valid before proceeding with Consensus.
372  mValidLedgerSign = signTime.time_since_epoch().count();
373  assert(
377  mValidLedgerSeq = l->info().seq;
378 
379  app_.getOPs().updateLocalTx(*l);
381  mLedgerHistory.validatedLedger(l, consensusHash);
383  if (!app_.getOPs().isBlocked())
384  {
386  {
387  JLOG(m_journal.error()) << "One or more unsupported amendments "
388  "activated: server blocked.";
390  }
391  else if (!app_.getOPs().isAmendmentWarned() || l->isFlagLedger())
392  {
393  // Amendments can lose majority, so re-check periodically (every
394  // flag ledger), and clear the flag if appropriate. If an unknown
395  // amendment gains majority log a warning as soon as it's
396  // discovered, then again every flag ledger until the operator
397  // upgrades, the amendment loses majority, or the amendment goes
398  // live and the node gets blocked. Unlike being amendment blocked,
399  // this message may be logged more than once per session, because
400  // the node will otherwise function normally, and this gives
401  // operators an opportunity to see and resolve the warning.
402  if (auto const first =
404  {
405  JLOG(m_journal.error()) << "One or more unsupported amendments "
406  "reached majority. Upgrade before "
407  << to_string(*first)
408  << " to prevent your server from "
409  "becoming amendment blocked.";
411  }
412  else
414  }
415  }
416 }
417 
418 void
420 {
421  mPubLedger = l;
422  mPubLedgerClose = l->info().closeTime.time_since_epoch().count();
423  mPubLedgerSeq = l->info().seq;
424 }
425 
426 void
428  std::shared_ptr<Transaction> const& transaction)
429 {
431  mHeldTransactions.insert(transaction->getSTransaction());
432 }
433 
434 // Validate a ledger's close time and sequence number if we're considering
435 // jumping to that ledger. This helps defend against some rare hostile or
436 // diverged majority scenarios.
437 bool
439 {
440  assert(ledger);
441 
442  // Never jump to a candidate ledger that precedes our
443  // last validated ledger
444 
445  auto validLedger = getValidatedLedger();
446  if (validLedger && (ledger->info().seq < validLedger->info().seq))
447  {
448  JLOG(m_journal.trace())
449  << "Candidate for current ledger has low seq " << ledger->info().seq
450  << " < " << validLedger->info().seq;
451  return false;
452  }
453 
454  // Ensure this ledger's parent close time is within five minutes of
455  // our current time. If we already have a known fully-valid ledger
456  // we perform this check. Otherwise, we only do it if we've built a
457  // few ledgers as our clock can be off when we first start up
458 
459  auto closeTime = app_.timeKeeper().closeTime();
460  auto ledgerClose = ledger->info().parentCloseTime;
461 
462  using namespace std::chrono_literals;
463  if ((validLedger || (ledger->info().seq > 10)) &&
464  ((std::max(closeTime, ledgerClose) - std::min(closeTime, ledgerClose)) >
465  5min))
466  {
467  JLOG(m_journal.warn())
468  << "Candidate for current ledger has close time "
469  << to_string(ledgerClose) << " at network time "
470  << to_string(closeTime) << " seq " << ledger->info().seq;
471  return false;
472  }
473 
474  if (validLedger)
475  {
476  // Sequence number must not be too high. We allow ten ledgers
477  // for time inaccuracies plus a maximum run rate of one ledger
478  // every two seconds. The goal is to prevent a malicious ledger
479  // from increasing our sequence unreasonably high
480 
481  LedgerIndex maxSeq = validLedger->info().seq + 10;
482 
483  if (closeTime > validLedger->info().parentCloseTime)
484  maxSeq += std::chrono::duration_cast<std::chrono::seconds>(
485  closeTime - validLedger->info().parentCloseTime)
486  .count() /
487  2;
488 
489  if (ledger->info().seq > maxSeq)
490  {
491  JLOG(m_journal.warn())
492  << "Candidate for current ledger has high seq "
493  << ledger->info().seq << " > " << maxSeq;
494  return false;
495  }
496 
497  JLOG(m_journal.trace())
498  << "Acceptable seq range: " << validLedger->info().seq
499  << " <= " << ledger->info().seq << " <= " << maxSeq;
500  }
501 
502  return true;
503 }
504 
505 void
507 {
508  assert(lastClosed);
509  if (!lastClosed->isImmutable())
510  LogicError("mutable ledger in switchLCL");
511 
512  if (lastClosed->open())
513  LogicError("The new last closed ledger is open!");
514 
515  {
517  mClosedLedger.set(lastClosed);
518  }
519 
520  if (standalone_)
521  {
522  setFullLedger(lastClosed, true, false);
523  tryAdvance();
524  }
525  else
526  {
527  checkAccept(lastClosed);
528  }
529 }
530 
531 bool
532 LedgerMaster::fixIndex(LedgerIndex ledgerIndex, LedgerHash const& ledgerHash)
533 {
534  return mLedgerHistory.fixIndex(ledgerIndex, ledgerHash);
535 }
536 
537 bool
539 {
540  bool validated = ledger->info().validated;
541  // Returns true if we already had the ledger
542  return mLedgerHistory.insert(std::move(ledger), validated);
543 }
544 
550 void
552 {
554  // It can be expensive to modify the open ledger even with no transactions
555  // to process. Regardless, make sure to reset held transactions with
556  // the parent.
557  if (mHeldTransactions.size())
558  {
559  app_.openLedger().modify([&](OpenView& view, beast::Journal j) {
560  bool any = false;
561  for (auto const& it : mHeldTransactions)
562  {
563  ApplyFlags flags = tapNONE;
564  auto const result =
565  app_.getTxQ().apply(app_, view, it.second, flags, j);
566  if (result.second)
567  any = true;
568  }
569  return any;
570  });
571  }
572 
573  // VFALCO NOTE The hash for an open ledger is undefined so we use
574  // something that is a reasonable substitute.
575  mHeldTransactions.reset(app_.openLedger().current()->info().parentHash);
576 }
577 
580 {
582 
584 }
585 
586 void
588 {
589  mBuildingLedgerSeq.store(i);
590 }
591 
592 bool
594 {
596  return boost::icl::contains(mCompleteLedgers, seq);
597 }
598 
599 void
601 {
603  mCompleteLedgers.erase(seq);
604 }
605 
606 // returns Ledgers we have all the nodes for
607 bool
609  std::uint32_t& minVal,
610  std::uint32_t& maxVal)
611 {
612  // Validated ledger is likely not stored in the DB yet so we use the
613  // published ledger which is.
614  maxVal = mPubLedgerSeq.load();
615 
616  if (!maxVal)
617  return false;
618 
620  {
622  maybeMin = prevMissing(mCompleteLedgers, maxVal);
623  }
624 
625  if (maybeMin == std::nullopt)
626  minVal = maxVal;
627  else
628  minVal = 1 + *maybeMin;
629 
630  return true;
631 }
632 
633 // Returns Ledgers we have all the nodes for and are indexed
634 bool
636 {
637  if (app_.config().reporting())
638  {
640  try
641  {
642  if (res == "empty" || res == "error" || res.empty())
643  return false;
644  else if (size_t delim = res.find('-'); delim != std::string::npos)
645  {
646  minVal = std::stol(res.substr(0, delim));
647  maxVal = std::stol(res.substr(delim + 1));
648  }
649  else
650  {
651  minVal = maxVal = std::stol(res);
652  }
653  return true;
654  }
655  catch (std::exception const& e)
656  {
657  JLOG(m_journal.error()) << "LedgerMaster::getValidatedRange: "
658  "exception parsing complete ledgers: "
659  << e.what();
660  return false;
661  }
662  }
663  if (!getFullValidatedRange(minVal, maxVal))
664  return false;
665 
666  // Remove from the validated range any ledger sequences that may not be
667  // fully updated in the database yet
668 
669  auto const pendingSaves = app_.pendingSaves().getSnapshot();
670 
671  if (!pendingSaves.empty() && ((minVal != 0) || (maxVal != 0)))
672  {
673  // Ensure we shrink the tips as much as possible. If we have 7-9 and
674  // 8,9 are invalid, we don't want to see the 8 and shrink to just 9
675  // because then we'll have nothing when we could have 7.
676  while (pendingSaves.count(maxVal) > 0)
677  --maxVal;
678  while (pendingSaves.count(minVal) > 0)
679  ++minVal;
680 
681  // Best effort for remaining exclusions
682  for (auto v : pendingSaves)
683  {
684  if ((v.first >= minVal) && (v.first <= maxVal))
685  {
686  if (v.first > ((minVal + maxVal) / 2))
687  maxVal = v.first - 1;
688  else
689  minVal = v.first + 1;
690  }
691  }
692 
693  if (minVal > maxVal)
694  minVal = maxVal = 0;
695  }
696 
697  return true;
698 }
699 
700 // Get the earliest ledger we will let peers fetch
703 {
704  // The earliest ledger we will let people fetch is ledger zero,
705  // unless that creates a larger range than allowed
706  std::uint32_t e = getClosedLedger()->info().seq;
707 
708  if (e > fetch_depth_)
709  e -= fetch_depth_;
710  else
711  e = 0;
712  return e;
713 }
714 
715 void
717 {
718  std::uint32_t seq = ledger->info().seq;
719  uint256 prevHash = ledger->info().parentHash;
720 
722 
723  std::uint32_t minHas = seq;
724  std::uint32_t maxHas = seq;
725 
726  NodeStore::Database& nodeStore{app_.getNodeStore()};
727  while (!app_.getJobQueue().isStopping() && seq > 0)
728  {
729  {
731  minHas = seq;
732  --seq;
733 
734  if (haveLedger(seq))
735  break;
736  }
737 
738  auto it(ledgerHashes.find(seq));
739 
740  if (it == ledgerHashes.end())
741  {
742  if (app_.isStopping())
743  return;
744 
745  {
747  mCompleteLedgers.insert(range(minHas, maxHas));
748  }
749  maxHas = minHas;
751  (seq < 500) ? 0 : (seq - 499), seq);
752  it = ledgerHashes.find(seq);
753 
754  if (it == ledgerHashes.end())
755  break;
756 
757  if (!nodeStore.fetchNodeObject(
758  ledgerHashes.begin()->second.ledgerHash,
759  ledgerHashes.begin()->first))
760  {
761  // The ledger is not backed by the node store
762  JLOG(m_journal.warn()) << "SQL DB ledger sequence " << seq
763  << " mismatches node store";
764  break;
765  }
766  }
767 
768  if (it->second.ledgerHash != prevHash)
769  break;
770 
771  prevHash = it->second.parentHash;
772  }
773 
774  {
776  mCompleteLedgers.insert(range(minHas, maxHas));
777  }
778  {
780  mFillInProgress = 0;
781  tryAdvance();
782  }
783 }
784 
787 void
789 {
790  LedgerIndex const ledgerIndex([&]() {
791  if (reason == InboundLedger::Reason::SHARD)
792  {
793  // Do not acquire a ledger sequence greater
794  // than the last ledger in the shard
795  auto const shardStore{app_.getShardStore()};
796  auto const shardIndex{shardStore->seqToShardIndex(missing)};
797  return std::min(missing + 1, shardStore->lastLedgerSeq(shardIndex));
798  }
799  return missing + 1;
800  }());
801 
802  auto const haveHash{getLedgerHashForHistory(ledgerIndex, reason)};
803  if (!haveHash || haveHash->isZero())
804  {
805  if (reason == InboundLedger::Reason::SHARD)
806  {
807  auto const shardStore{app_.getShardStore()};
808  auto const shardIndex{shardStore->seqToShardIndex(missing)};
809  if (missing < shardStore->lastLedgerSeq(shardIndex))
810  {
811  JLOG(m_journal.error())
812  << "No hash for fetch pack. "
813  << "Missing ledger sequence " << missing
814  << " while acquiring shard " << shardIndex;
815  }
816  }
817  else
818  {
819  JLOG(m_journal.error())
820  << "No hash for fetch pack. Missing Index " << missing;
821  }
822  return;
823  }
824 
825  // Select target Peer based on highest score. The score is randomized
826  // but biased in favor of Peers with low latency.
827  std::shared_ptr<Peer> target;
828  {
829  int maxScore = 0;
830  auto peerList = app_.overlay().getActivePeers();
831  for (auto const& peer : peerList)
832  {
833  if (peer->hasRange(missing, missing + 1))
834  {
835  int score = peer->getScore(true);
836  if (!target || (score > maxScore))
837  {
838  target = peer;
839  maxScore = score;
840  }
841  }
842  }
843  }
844 
845  if (target)
846  {
847  protocol::TMGetObjectByHash tmBH;
848  tmBH.set_query(true);
849  tmBH.set_type(protocol::TMGetObjectByHash::otFETCH_PACK);
850  tmBH.set_ledgerhash(haveHash->begin(), 32);
851  auto packet = std::make_shared<Message>(tmBH, protocol::mtGET_OBJECTS);
852 
853  target->send(packet);
854  JLOG(m_journal.trace()) << "Requested fetch pack for " << missing;
855  }
856  else
857  JLOG(m_journal.debug()) << "No peer for fetch pack";
858 }
859 
860 void
862 {
863  int invalidate = 0;
865 
866  for (std::uint32_t lSeq = ledger.info().seq - 1; lSeq > 0; --lSeq)
867  {
868  if (haveLedger(lSeq))
869  {
870  try
871  {
872  hash = hashOfSeq(ledger, lSeq, m_journal);
873  }
874  catch (std::exception const& ex)
875  {
876  JLOG(m_journal.warn())
877  << "fixMismatch encounters partial ledger. Exception: "
878  << ex.what();
879  clearLedger(lSeq);
880  return;
881  }
882 
883  if (hash)
884  {
885  // try to close the seam
886  auto otherLedger = getLedgerBySeq(lSeq);
887 
888  if (otherLedger && (otherLedger->info().hash == *hash))
889  {
890  // we closed the seam
891  if (invalidate != 0)
892  {
893  JLOG(m_journal.warn())
894  << "Match at " << lSeq << ", " << invalidate
895  << " prior ledgers invalidated";
896  }
897 
898  return;
899  }
900  }
901 
902  clearLedger(lSeq);
903  ++invalidate;
904  }
905  }
906 
907  // all prior ledgers invalidated
908  if (invalidate != 0)
909  {
910  JLOG(m_journal.warn())
911  << "All " << invalidate << " prior ledgers invalidated";
912  }
913 }
914 
915 void
917  std::shared_ptr<Ledger const> const& ledger,
918  bool isSynchronous,
919  bool isCurrent)
920 {
921  // A new ledger has been accepted as part of the trusted chain
922  JLOG(m_journal.debug()) << "Ledger " << ledger->info().seq
923  << " accepted :" << ledger->info().hash;
924  assert(ledger->stateMap().getHash().isNonZero());
925 
926  ledger->setValidated();
927  ledger->setFull();
928 
929  if (isCurrent)
930  mLedgerHistory.insert(ledger, true);
931 
932  {
933  // Check the SQL database's entry for the sequence before this
934  // ledger, if it's not this ledger's parent, invalidate it
935  uint256 prevHash =
936  app_.getRelationalDatabase().getHashByIndex(ledger->info().seq - 1);
937  if (prevHash.isNonZero() && prevHash != ledger->info().parentHash)
938  clearLedger(ledger->info().seq - 1);
939  }
940 
941  pendSaveValidated(app_, ledger, isSynchronous, isCurrent);
942 
943  {
945  mCompleteLedgers.insert(ledger->info().seq);
946  }
947 
948  {
950 
951  if (ledger->info().seq > mValidLedgerSeq)
952  setValidLedger(ledger);
953  if (!mPubLedger)
954  {
955  setPubLedger(ledger);
956  app_.getOrderBookDB().setup(ledger);
957  }
958 
959  if (ledger->info().seq != 0 && haveLedger(ledger->info().seq - 1))
960  {
961  // we think we have the previous ledger, double check
962  auto prevLedger = getLedgerBySeq(ledger->info().seq - 1);
963 
964  if (!prevLedger ||
965  (prevLedger->info().hash != ledger->info().parentHash))
966  {
967  JLOG(m_journal.warn())
968  << "Acquired ledger invalidates previous ledger: "
969  << (prevLedger ? "hashMismatch" : "missingLedger");
970  fixMismatch(*ledger);
971  }
972  }
973  }
974 }
975 
976 void
978 {
979  clearLedger(seq);
981 }
982 
983 // Check if the specified ledger can become the new last fully-validated
984 // ledger.
985 void
987 {
988  std::size_t valCount = 0;
989 
990  if (seq != 0)
991  {
992  // Ledger is too old
993  if (seq < mValidLedgerSeq)
994  return;
995 
996  auto validations = app_.validators().negativeUNLFilter(
998  valCount = validations.size();
999  if (valCount >= app_.validators().quorum())
1000  {
1002  if (seq > mLastValidLedger.second)
1003  mLastValidLedger = std::make_pair(hash, seq);
1004  }
1005 
1006  if (seq == mValidLedgerSeq)
1007  return;
1008 
1009  // Ledger could match the ledger we're already building
1010  if (seq == mBuildingLedgerSeq)
1011  return;
1012  }
1013 
1014  auto ledger = mLedgerHistory.getLedgerByHash(hash);
1015 
1016  if (!ledger)
1017  {
1018  if ((seq != 0) && (getValidLedgerIndex() == 0))
1019  {
1020  // Set peers converged early if we can
1021  if (valCount >= app_.validators().quorum())
1022  app_.overlay().checkTracking(seq);
1023  }
1024 
1025  // FIXME: We may not want to fetch a ledger with just one
1026  // trusted validation
1027  ledger = app_.getInboundLedgers().acquire(
1028  hash, seq, InboundLedger::Reason::GENERIC);
1029  }
1030 
1031  if (ledger)
1032  checkAccept(ledger);
1033 }
1034 
1042 {
1043  return standalone_ ? 0 : app_.validators().quorum();
1044 }
1045 
1046 void
1048 {
1049  // Can we accept this ledger as our new last fully-validated ledger
1050 
1051  if (!canBeCurrent(ledger))
1052  return;
1053 
1054  // Can we advance the last fully-validated ledger? If so, can we
1055  // publish?
1057 
1058  if (ledger->info().seq <= mValidLedgerSeq)
1059  return;
1060 
1061  auto const minVal = getNeededValidations();
1062  auto validations = app_.validators().negativeUNLFilter(
1064  ledger->info().hash, ledger->info().seq));
1065  auto const tvc = validations.size();
1066  if (tvc < minVal) // nothing we can do
1067  {
1068  JLOG(m_journal.trace())
1069  << "Only " << tvc << " validations for " << ledger->info().hash;
1070  return;
1071  }
1072 
1073  JLOG(m_journal.info()) << "Advancing accepted ledger to "
1074  << ledger->info().seq << " with >= " << minVal
1075  << " validations";
1076 
1077  ledger->setValidated();
1078  ledger->setFull();
1079  setValidLedger(ledger);
1080  if (!mPubLedger)
1081  {
1082  pendSaveValidated(app_, ledger, true, true);
1083  setPubLedger(ledger);
1084  app_.getOrderBookDB().setup(ledger);
1085  }
1086 
1087  std::uint32_t const base = app_.getFeeTrack().getLoadBase();
1088  auto fees = app_.getValidations().fees(ledger->info().hash, base);
1089  {
1090  auto fees2 =
1091  app_.getValidations().fees(ledger->info().parentHash, base);
1092  fees.reserve(fees.size() + fees2.size());
1093  std::copy(fees2.begin(), fees2.end(), std::back_inserter(fees));
1094  }
1095  std::uint32_t fee;
1096  if (!fees.empty())
1097  {
1098  std::sort(fees.begin(), fees.end());
1099  if (auto stream = m_journal.debug())
1100  {
1102  s << "Received fees from validations: (" << fees.size() << ") ";
1103  for (auto const fee1 : fees)
1104  {
1105  s << " " << fee1;
1106  }
1107  stream << s.str();
1108  }
1109  fee = fees[fees.size() / 2]; // median
1110  }
1111  else
1112  {
1113  fee = base;
1114  }
1115 
1116  app_.getFeeTrack().setRemoteFee(fee);
1117 
1118  tryAdvance();
1119 
1120  if (ledger->seq() % 256 == 0)
1121  {
1122  // Check if the majority of validators run a higher version rippled
1123  // software. If so print a warning.
1124  //
1125  // Once the HardenedValidations amendment is enabled, validators include
1126  // their rippled software version in the validation messages of every
1127  // (flag - 1) ledger. We wait for one ledger time before checking the
1128  // version information to accumulate more validation messages.
1129 
1130  auto currentTime = app_.timeKeeper().now();
1131  bool needPrint = false;
1132 
1133  // The variable upgradeWarningPrevTime_ will be set when and only when
1134  // the warning is printed.
1136  {
1137  // Have not printed the warning before, check if need to print.
1138  auto const vals = app_.getValidations().getTrustedForLedger(
1139  ledger->info().parentHash, ledger->info().seq - 1);
1140  std::size_t higherVersionCount = 0;
1141  std::size_t rippledCount = 0;
1142  for (auto const& v : vals)
1143  {
1144  if (v->isFieldPresent(sfServerVersion))
1145  {
1146  auto version = v->getFieldU64(sfServerVersion);
1147  higherVersionCount +=
1148  BuildInfo::isNewerVersion(version) ? 1 : 0;
1149  rippledCount +=
1150  BuildInfo::isRippledVersion(version) ? 1 : 0;
1151  }
1152  }
1153  // We report only if (1) we have accumulated validation messages
1154  // from 90% validators from the UNL, (2) 60% of validators
1155  // running the rippled implementation have higher version numbers,
1156  // and (3) the calculation won't cause divide-by-zero.
1157  if (higherVersionCount > 0 && rippledCount > 0)
1158  {
1159  constexpr std::size_t reportingPercent = 90;
1160  constexpr std::size_t cutoffPercent = 60;
1161  auto const unlSize{
1162  app_.validators().getQuorumKeys().second.size()};
1163  needPrint = unlSize > 0 &&
1164  calculatePercent(vals.size(), unlSize) >=
1165  reportingPercent &&
1166  calculatePercent(higherVersionCount, rippledCount) >=
1167  cutoffPercent;
1168  }
1169  }
1170  // To throttle the warning messages, instead of printing a warning
1171  // every flag ledger, we print every week.
1172  else if (currentTime - upgradeWarningPrevTime_ >= weeks{1})
1173  {
1174  // Printed the warning before, and assuming most validators
1175  // do not downgrade, we keep printing the warning
1176  // until the local server is restarted.
1177  needPrint = true;
1178  }
1179 
1180  if (needPrint)
1181  {
1182  upgradeWarningPrevTime_ = currentTime;
1183  auto const upgradeMsg =
1184  "Check for upgrade: "
1185  "A majority of trusted validators are "
1186  "running a newer version.";
1187  std::cerr << upgradeMsg << std::endl;
1188  JLOG(m_journal.error()) << upgradeMsg;
1189  }
1190  }
1191 }
1192 
1194 void
1196  std::shared_ptr<Ledger const> const& ledger,
1197  uint256 const& consensusHash,
1198  Json::Value consensus)
1199 {
1200  // Because we just built a ledger, we are no longer building one
1201  setBuildingLedger(0);
1202 
1203  // No need to process validations in standalone mode
1204  if (standalone_)
1205  return;
1206 
1207  mLedgerHistory.builtLedger(ledger, consensusHash, std::move(consensus));
1208 
1209  if (ledger->info().seq <= mValidLedgerSeq)
1210  {
1211  auto stream = app_.journal("LedgerConsensus").info();
1212  JLOG(stream) << "Consensus built old ledger: " << ledger->info().seq
1213  << " <= " << mValidLedgerSeq;
1214  return;
1215  }
1216 
1217  // See if this ledger can be the new fully-validated ledger
1218  checkAccept(ledger);
1219 
1220  if (ledger->info().seq <= mValidLedgerSeq)
1221  {
1222  auto stream = app_.journal("LedgerConsensus").debug();
1223  JLOG(stream) << "Consensus ledger fully validated";
1224  return;
1225  }
1226 
1227  // This ledger cannot be the new fully-validated ledger, but
1228  // maybe we saved up validations for some other ledger that can be
1229 
1230  auto validations = app_.validators().negativeUNLFilter(
1232 
1233  // Track validation counts with sequence numbers
1234  class valSeq
1235  {
1236  public:
1237  valSeq() : valCount_(0), ledgerSeq_(0)
1238  {
1239  ;
1240  }
1241 
1242  void
1243  mergeValidation(LedgerIndex seq)
1244  {
1245  valCount_++;
1246 
1247  // If we didn't already know the sequence, now we do
1248  if (ledgerSeq_ == 0)
1249  ledgerSeq_ = seq;
1250  }
1251 
1252  std::size_t valCount_;
1253  LedgerIndex ledgerSeq_;
1254  };
1255 
1256  // Count the number of current, trusted validations
1258  for (auto const& v : validations)
1259  {
1260  valSeq& vs = count[v->getLedgerHash()];
1261  vs.mergeValidation(v->getFieldU32(sfLedgerSequence));
1262  }
1263 
1264  auto const neededValidations = getNeededValidations();
1265  auto maxSeq = mValidLedgerSeq.load();
1266  auto maxLedger = ledger->info().hash;
1267 
1268  // Of the ledgers with sufficient validations,
1269  // find the one with the highest sequence
1270  for (auto& v : count)
1271  if (v.second.valCount_ > neededValidations)
1272  {
1273  // If we still don't know the sequence, get it
1274  if (v.second.ledgerSeq_ == 0)
1275  {
1276  if (auto l = getLedgerByHash(v.first))
1277  v.second.ledgerSeq_ = l->info().seq;
1278  }
1279 
1280  if (v.second.ledgerSeq_ > maxSeq)
1281  {
1282  maxSeq = v.second.ledgerSeq_;
1283  maxLedger = v.first;
1284  }
1285  }
1286 
1287  if (maxSeq > mValidLedgerSeq)
1288  {
1289  auto stream = app_.journal("LedgerConsensus").debug();
1290  JLOG(stream) << "Consensus triggered check of ledger";
1291  checkAccept(maxLedger, maxSeq);
1292  }
1293 }
1294 
1297  LedgerIndex index,
1298  InboundLedger::Reason reason)
1299 {
1300  // Try to get the hash of a ledger we need to fetch for history
1302  auto const& l{
1304 
1305  if (l && l->info().seq >= index)
1306  {
1307  ret = hashOfSeq(*l, index, m_journal);
1308  if (!ret)
1309  ret = walkHashBySeq(index, l, reason);
1310  }
1311 
1312  if (!ret)
1313  ret = walkHashBySeq(index, reason);
1314 
1315  return ret;
1316 }
1317 
1321 {
1323 
1324  JLOG(m_journal.trace()) << "findNewLedgersToPublish<";
1325 
1326  // No valid ledger, nothing to do
1327  if (mValidLedger.empty())
1328  {
1329  JLOG(m_journal.trace()) << "No valid journal, nothing to publish.";
1330  return {};
1331  }
1332 
1333  if (!mPubLedger)
1334  {
1335  JLOG(m_journal.info())
1336  << "First published ledger will be " << mValidLedgerSeq;
1337  return {mValidLedger.get()};
1338  }
1339 
1341  {
1342  JLOG(m_journal.warn()) << "Gap in validated ledger stream "
1343  << mPubLedgerSeq << " - " << mValidLedgerSeq - 1;
1344 
1345  auto valLedger = mValidLedger.get();
1346  ret.push_back(valLedger);
1347  setPubLedger(valLedger);
1348  app_.getOrderBookDB().setup(valLedger);
1349 
1350  return {valLedger};
1351  }
1352 
1354  {
1355  JLOG(m_journal.trace()) << "No valid journal, nothing to publish.";
1356  return {};
1357  }
1358 
1359  int acqCount = 0;
1360 
1361  auto pubSeq = mPubLedgerSeq + 1; // Next sequence to publish
1362  auto valLedger = mValidLedger.get();
1363  std::uint32_t valSeq = valLedger->info().seq;
1364 
1365  ScopedUnlock sul{sl};
1366  try
1367  {
1368  for (std::uint32_t seq = pubSeq; seq <= valSeq; ++seq)
1369  {
1370  JLOG(m_journal.trace())
1371  << "Trying to fetch/publish valid ledger " << seq;
1372 
1374  // This can throw
1375  auto hash = hashOfSeq(*valLedger, seq, m_journal);
1376  // VFALCO TODO Restructure this code so that zero is not
1377  // used.
1378  if (!hash)
1379  hash = beast::zero; // kludge
1380  if (seq == valSeq)
1381  {
1382  // We need to publish the ledger we just fully validated
1383  ledger = valLedger;
1384  }
1385  else if (hash->isZero())
1386  {
1387  JLOG(m_journal.fatal()) << "Ledger: " << valSeq
1388  << " does not have hash for " << seq;
1389  assert(false);
1390  }
1391  else
1392  {
1393  ledger = mLedgerHistory.getLedgerByHash(*hash);
1394  }
1395 
1396  if (!app_.config().LEDGER_REPLAY)
1397  {
1398  // Can we try to acquire the ledger we need?
1399  if (!ledger && (++acqCount < ledger_fetch_size_))
1400  ledger = app_.getInboundLedgers().acquire(
1401  *hash, seq, InboundLedger::Reason::GENERIC);
1402  }
1403 
1404  // Did we acquire the next ledger we need to publish?
1405  if (ledger && (ledger->info().seq == pubSeq))
1406  {
1407  ledger->setValidated();
1408  ret.push_back(ledger);
1409  ++pubSeq;
1410  }
1411  }
1412 
1413  JLOG(m_journal.trace())
1414  << "ready to publish " << ret.size() << " ledgers.";
1415  }
1416  catch (std::exception const& ex)
1417  {
1418  JLOG(m_journal.error())
1419  << "Exception while trying to find ledgers to publish: "
1420  << ex.what();
1421  }
1422 
1423  if (app_.config().LEDGER_REPLAY)
1424  {
1425  /* Narrow down the gap of ledgers, and try to replay them.
1426  * When replaying a ledger gap, if the local node has
1427  * the start ledger, it saves an expensive InboundLedger
1428  * acquire. If the local node has the finish ledger, it
1429  * saves a skip list acquire.
1430  */
1431  auto const& startLedger = ret.empty() ? mPubLedger : ret.back();
1432  auto finishLedger = valLedger;
1433  while (startLedger->seq() + 1 < finishLedger->seq())
1434  {
1435  if (auto const parent = mLedgerHistory.getLedgerByHash(
1436  finishLedger->info().parentHash);
1437  parent)
1438  {
1439  finishLedger = parent;
1440  }
1441  else
1442  {
1443  auto numberLedgers =
1444  finishLedger->seq() - startLedger->seq() + 1;
1445  JLOG(m_journal.debug())
1446  << "Publish LedgerReplays " << numberLedgers
1447  << " ledgers, from seq=" << startLedger->info().seq << ", "
1448  << startLedger->info().hash
1449  << " to seq=" << finishLedger->info().seq << ", "
1450  << finishLedger->info().hash;
1453  finishLedger->info().hash,
1454  numberLedgers);
1455  break;
1456  }
1457  }
1458  }
1459 
1460  return ret;
1461 }
1462 
1463 void
1465 {
1467 
1468  // Can't advance without at least one fully-valid ledger
1469  mAdvanceWork = true;
1470  if (!mAdvanceThread && !mValidLedger.empty())
1471  {
1472  mAdvanceThread = true;
1473  app_.getJobQueue().addJob(jtADVANCE, "advanceLedger", [this]() {
1475 
1476  assert(!mValidLedger.empty() && mAdvanceThread);
1477 
1478  JLOG(m_journal.trace()) << "advanceThread<";
1479 
1480  try
1481  {
1482  doAdvance(sl);
1483  }
1484  catch (std::exception const& ex)
1485  {
1486  JLOG(m_journal.fatal()) << "doAdvance throws: " << ex.what();
1487  }
1488 
1489  mAdvanceThread = false;
1490  JLOG(m_journal.trace()) << "advanceThread>";
1491  });
1492  }
1493 }
1494 
1495 void
1497 {
1498  {
1501  {
1502  --mPathFindThread;
1503  JLOG(m_journal.debug()) << "Need network ledger for updating paths";
1504  return;
1505  }
1506  }
1507 
1508  while (!app_.getJobQueue().isStopping())
1509  {
1510  JLOG(m_journal.debug()) << "updatePaths running";
1512  {
1514 
1515  if (!mValidLedger.empty() &&
1516  (!mPathLedger || (mPathLedger->info().seq != mValidLedgerSeq)))
1517  { // We have a new valid ledger since the last full pathfinding
1519  lastLedger = mPathLedger;
1520  }
1521  else if (mPathFindNewRequest)
1522  { // We have a new request but no new ledger
1523  lastLedger = app_.openLedger().current();
1524  }
1525  else
1526  { // Nothing to do
1527  --mPathFindThread;
1528  JLOG(m_journal.debug()) << "Nothing to do for updating paths";
1529  return;
1530  }
1531  }
1532 
1533  if (!standalone_)
1534  { // don't pathfind with a ledger that's more than 60 seconds old
1535  using namespace std::chrono;
1536  auto age = time_point_cast<seconds>(app_.timeKeeper().closeTime()) -
1537  lastLedger->info().closeTime;
1538  if (age > 1min)
1539  {
1540  JLOG(m_journal.debug())
1541  << "Published ledger too old for updating paths";
1543  --mPathFindThread;
1544  return;
1545  }
1546  }
1547 
1548  try
1549  {
1550  auto& pathRequests = app_.getPathRequests();
1551  {
1553  if (!pathRequests.requestsPending())
1554  {
1555  --mPathFindThread;
1556  JLOG(m_journal.debug())
1557  << "No path requests found. Nothing to do for updating "
1558  "paths. "
1559  << mPathFindThread << " jobs remaining";
1560  return;
1561  }
1562  }
1563  JLOG(m_journal.debug()) << "Updating paths";
1564  pathRequests.updateAll(lastLedger);
1565 
1567  if (!pathRequests.requestsPending())
1568  {
1569  JLOG(m_journal.debug())
1570  << "No path requests left. No need for further updating "
1571  "paths";
1572  --mPathFindThread;
1573  return;
1574  }
1575  }
1576  catch (SHAMapMissingNode const& mn)
1577  {
1578  JLOG(m_journal.info()) << "During pathfinding: " << mn.what();
1579  if (lastLedger->open())
1580  {
1581  // our parent is the problem
1583  lastLedger->info().parentHash,
1584  lastLedger->info().seq - 1,
1586  }
1587  else
1588  {
1589  // this ledger is the problem
1591  lastLedger->info().hash,
1592  lastLedger->info().seq,
1594  }
1595  }
1596  }
1597 }
1598 
1599 bool
1601 {
1603  mPathFindNewRequest = newPFWork("pf:newRequest", ml);
1604  return mPathFindNewRequest;
1605 }
1606 
1607 bool
1609 {
1611  bool const ret = mPathFindNewRequest;
1612  mPathFindNewRequest = false;
1613  return ret;
1614 }
1615 
1616 // If the order book is radically updated, we need to reprocess all
1617 // pathfinding requests.
1618 bool
1620 {
1622  mPathLedger.reset();
1623 
1624  return newPFWork("pf:newOBDB", ml);
1625 }
1626 
1629 bool
1631  const char* name,
1633 {
1634  if (!app_.isStopping() && mPathFindThread < 2 &&
1636  {
1637  JLOG(m_journal.debug())
1638  << "newPFWork: Creating job. path find threads: "
1639  << mPathFindThread;
1640  if (app_.getJobQueue().addJob(
1641  jtUPDATE_PF, name, [this]() { updatePaths(); }))
1642  {
1643  ++mPathFindThread;
1644  }
1645  }
1646  // If we're stopping don't give callers the expectation that their
1647  // request will be fulfilled, even if it may be serviced.
1648  return mPathFindThread > 0 && !app_.isStopping();
1649 }
1650 
1653 {
1654  return m_mutex;
1655 }
1656 
1657 // The current ledger is the ledger we believe new transactions should go in
1660 {
1661  if (app_.config().reporting())
1662  {
1663  Throw<ReportingShouldProxy>();
1664  }
1665  return app_.openLedger().current();
1666 }
1667 
1670 {
1671 #ifdef RIPPLED_REPORTING
1672  if (app_.config().reporting())
1673  {
1675  if (!seq)
1676  return {};
1677  return getLedgerBySeq(*seq);
1678  }
1679 #endif
1680  return mValidLedger.get();
1681 }
1682 
1683 Rules
1685 {
1686  // Once we have a guarantee that there's always a last validated
1687  // ledger then we can dispense with the if.
1688 
1689  // Return the Rules from the last validated ledger.
1690  if (auto const ledger = getValidatedLedger())
1691  return ledger->rules();
1692 
1693  return Rules(app_.config().features);
1694 }
1695 
1696 // This is the last ledger we published to clients and can lag the validated
1697 // ledger.
1700 {
1701  std::lock_guard lock(m_mutex);
1702  return mPubLedger;
1703 }
1704 
1707 {
1708 #ifdef RIPPLED_REPORTING
1709  if (app_.config().reporting())
1710  return static_cast<PostgresDatabase*>(&app_.getRelationalDatabase())
1711  ->getCompleteLedgers();
1712 #endif
1714  return to_string(mCompleteLedgers);
1715 }
1716 
1719 {
1720  uint256 hash = getHashBySeq(ledgerIndex);
1721  return hash.isNonZero() ? getCloseTimeByHash(hash, ledgerIndex)
1722  : std::nullopt;
1723 }
1724 
1727  LedgerHash const& ledgerHash,
1728  std::uint32_t index)
1729 {
1730  auto nodeObject = app_.getNodeStore().fetchNodeObject(ledgerHash, index);
1731  if (nodeObject && (nodeObject->getData().size() >= 120))
1732  {
1733  SerialIter it(
1734  nodeObject->getData().data(), nodeObject->getData().size());
1735  if (safe_cast<HashPrefix>(it.get32()) == HashPrefix::ledgerMaster)
1736  {
1737  it.skip(
1738  4 + 8 + 32 + // seq drops parentHash
1739  32 + 32 + 4); // txHash acctHash parentClose
1741  }
1742  }
1743 
1744  return std::nullopt;
1745 }
1746 
1747 uint256
1749 {
1750  uint256 hash = mLedgerHistory.getLedgerHash(index);
1751 
1752  if (hash.isNonZero())
1753  return hash;
1754 
1755  return app_.getRelationalDatabase().getHashByIndex(index);
1756 }
1757 
1760 {
1761  std::optional<LedgerHash> ledgerHash;
1762 
1763  if (auto referenceLedger = mValidLedger.get())
1764  ledgerHash = walkHashBySeq(index, referenceLedger, reason);
1765 
1766  return ledgerHash;
1767 }
1768 
1771  std::uint32_t index,
1772  std::shared_ptr<ReadView const> const& referenceLedger,
1773  InboundLedger::Reason reason)
1774 {
1775  if (!referenceLedger || (referenceLedger->info().seq < index))
1776  {
1777  // Nothing we can do. No validated ledger.
1778  return std::nullopt;
1779  }
1780 
1781  // See if the hash for the ledger we need is in the reference ledger
1782  auto ledgerHash = hashOfSeq(*referenceLedger, index, m_journal);
1783  if (ledgerHash)
1784  return ledgerHash;
1785 
1786  // The hash is not in the reference ledger. Get another ledger which can
1787  // be located easily and should contain the hash.
1788  LedgerIndex refIndex = getCandidateLedger(index);
1789  auto const refHash = hashOfSeq(*referenceLedger, refIndex, m_journal);
1790  assert(refHash);
1791  if (refHash)
1792  {
1793  // Try the hash and sequence of a better reference ledger just found
1794  auto ledger = mLedgerHistory.getLedgerByHash(*refHash);
1795 
1796  if (ledger)
1797  {
1798  try
1799  {
1800  ledgerHash = hashOfSeq(*ledger, index, m_journal);
1801  }
1802  catch (SHAMapMissingNode const&)
1803  {
1804  ledger.reset();
1805  }
1806  }
1807 
1808  // Try to acquire the complete ledger
1809  if (!ledger)
1810  {
1811  if (auto const l = app_.getInboundLedgers().acquire(
1812  *refHash, refIndex, reason))
1813  {
1814  ledgerHash = hashOfSeq(*l, index, m_journal);
1815  assert(ledgerHash);
1816  }
1817  }
1818  }
1819  return ledgerHash;
1820 }
1821 
1824 {
1825  if (index <= mValidLedgerSeq)
1826  {
1827  // Always prefer a validated ledger
1828  if (auto valid = mValidLedger.get())
1829  {
1830  if (valid->info().seq == index)
1831  return valid;
1832 
1833  try
1834  {
1835  auto const hash = hashOfSeq(*valid, index, m_journal);
1836 
1837  if (hash)
1838  return mLedgerHistory.getLedgerByHash(*hash);
1839  }
1840  catch (std::exception const&)
1841  {
1842  // Missing nodes are already handled
1843  }
1844  }
1845  }
1846 
1847  if (auto ret = mLedgerHistory.getLedgerBySeq(index))
1848  return ret;
1849 
1850  auto ret = mClosedLedger.get();
1851  if (ret && (ret->info().seq == index))
1852  return ret;
1853 
1854  clearLedger(index);
1855  return {};
1856 }
1857 
1860 {
1861  if (auto ret = mLedgerHistory.getLedgerByHash(hash))
1862  return ret;
1863 
1864  auto ret = mClosedLedger.get();
1865  if (ret && (ret->info().hash == hash))
1866  return ret;
1867 
1868  return {};
1869 }
1870 
1871 void
1873 {
1875  mCompleteLedgers.insert(range(minV, maxV));
1876 }
1877 
1878 void
1880 {
1882  fetch_packs_.sweep();
1883 }
1884 
1885 float
1887 {
1889 }
1890 
1891 void
1893 {
1895  if (seq > 0)
1896  mCompleteLedgers.erase(range(0u, seq - 1));
1897 }
1898 
1899 void
1901 {
1903 }
1904 
1905 void
1907 {
1908  replayData = std::move(replay);
1909 }
1910 
1913 {
1914  return std::move(replayData);
1915 }
1916 
1917 void
1919  std::uint32_t missing,
1920  bool& progress,
1921  InboundLedger::Reason reason,
1923 {
1924  ScopedUnlock sul{sl};
1925  if (auto hash = getLedgerHashForHistory(missing, reason))
1926  {
1927  assert(hash->isNonZero());
1928  auto ledger = getLedgerByHash(*hash);
1929  if (!ledger)
1930  {
1931  if (!app_.getInboundLedgers().isFailure(*hash))
1932  {
1933  ledger =
1934  app_.getInboundLedgers().acquire(*hash, missing, reason);
1935  if (!ledger && missing != fetch_seq_ &&
1936  missing > app_.getNodeStore().earliestLedgerSeq())
1937  {
1938  JLOG(m_journal.trace())
1939  << "fetchForHistory want fetch pack " << missing;
1940  fetch_seq_ = missing;
1941  getFetchPack(missing, reason);
1942  }
1943  else
1944  JLOG(m_journal.trace())
1945  << "fetchForHistory no fetch pack for " << missing;
1946  }
1947  else
1948  JLOG(m_journal.debug())
1949  << "fetchForHistory found failed acquire";
1950  }
1951  if (ledger)
1952  {
1953  auto seq = ledger->info().seq;
1954  assert(seq == missing);
1955  JLOG(m_journal.trace()) << "fetchForHistory acquired " << seq;
1956  if (reason == InboundLedger::Reason::SHARD)
1957  {
1958  ledger->setFull();
1959  {
1960  std::lock_guard lock(m_mutex);
1961  mShardLedger = ledger;
1962  }
1963  if (!ledger->stateMap().family().isShardBacked())
1964  app_.getShardStore()->storeLedger(ledger);
1965  }
1966  else
1967  {
1968  setFullLedger(ledger, false, false);
1969  int fillInProgress;
1970  {
1971  std::lock_guard lock(m_mutex);
1972  mHistLedger = ledger;
1973  fillInProgress = mFillInProgress;
1974  }
1975  if (fillInProgress == 0 &&
1977  ledger->info().parentHash)
1978  {
1979  {
1980  // Previous ledger is in DB
1981  std::lock_guard lock(m_mutex);
1982  mFillInProgress = seq;
1983  }
1985  jtADVANCE, "tryFill", [this, ledger]() {
1986  tryFill(ledger);
1987  });
1988  }
1989  }
1990  progress = true;
1991  }
1992  else
1993  {
1994  std::uint32_t fetchSz;
1995  if (reason == InboundLedger::Reason::SHARD)
1996  // Do not fetch ledger sequences lower
1997  // than the shard's first ledger sequence
1998  fetchSz = app_.getShardStore()->firstLedgerSeq(
1999  app_.getShardStore()->seqToShardIndex(missing));
2000  else
2001  // Do not fetch ledger sequences lower
2002  // than the earliest ledger sequence
2003  fetchSz = app_.getNodeStore().earliestLedgerSeq();
2004  fetchSz = missing >= fetchSz
2005  ? std::min(ledger_fetch_size_, (missing - fetchSz) + 1)
2006  : 0;
2007  try
2008  {
2009  for (std::uint32_t i = 0; i < fetchSz; ++i)
2010  {
2011  std::uint32_t seq = missing - i;
2012  if (auto h = getLedgerHashForHistory(seq, reason))
2013  {
2014  assert(h->isNonZero());
2015  app_.getInboundLedgers().acquire(*h, seq, reason);
2016  }
2017  }
2018  }
2019  catch (std::exception const& ex)
2020  {
2021  JLOG(m_journal.warn())
2022  << "Threw while prefetching: " << ex.what();
2023  }
2024  }
2025  }
2026  else
2027  {
2028  JLOG(m_journal.fatal())
2029  << "Can't find ledger following prevMissing " << missing;
2030  JLOG(m_journal.fatal())
2031  << "Pub:" << mPubLedgerSeq << " Val:" << mValidLedgerSeq;
2032  JLOG(m_journal.fatal())
2033  << "Ledgers: " << app_.getLedgerMaster().getCompleteLedgers();
2034  JLOG(m_journal.fatal())
2035  << "Acquire reason: "
2036  << (reason == InboundLedger::Reason::HISTORY ? "HISTORY" : "SHARD");
2037  clearLedger(missing + 1);
2038  progress = true;
2039  }
2040 }
2041 
2042 // Try to publish ledgers, acquire missing ledgers
2043 void
2045 {
2046  do
2047  {
2048  mAdvanceWork = false; // If there's work to do, we'll make progress
2049  bool progress = false;
2050 
2051  auto const pubLedgers = findNewLedgersToPublish(sl);
2052  if (pubLedgers.empty())
2053  {
2054  if (!standalone_ && !app_.getFeeTrack().isLoadedLocal() &&
2059  {
2060  // We are in sync, so can acquire
2063  {
2065  missing = prevMissing(
2067  mPubLedger->info().seq,
2069  }
2070  if (missing)
2071  {
2072  JLOG(m_journal.trace())
2073  << "tryAdvance discovered missing " << *missing;
2074  if ((mFillInProgress == 0 || *missing > mFillInProgress) &&
2075  shouldAcquire(
2079  *missing,
2080  m_journal))
2081  {
2082  JLOG(m_journal.trace())
2083  << "advanceThread should acquire";
2084  }
2085  else
2086  missing = std::nullopt;
2087  }
2088  if (!missing && mFillInProgress == 0)
2089  {
2090  if (auto shardStore = app_.getShardStore())
2091  {
2092  missing = shardStore->prepareLedger(mValidLedgerSeq);
2093  if (missing)
2095  }
2096  }
2097  if (missing)
2098  {
2099  fetchForHistory(*missing, progress, reason, sl);
2101  {
2102  JLOG(m_journal.debug())
2103  << "tryAdvance found last valid changed";
2104  progress = true;
2105  }
2106  }
2107  }
2108  else
2109  {
2110  mHistLedger.reset();
2111  mShardLedger.reset();
2112  JLOG(m_journal.trace()) << "tryAdvance not fetching history";
2113  }
2114  }
2115  else
2116  {
2117  JLOG(m_journal.trace()) << "tryAdvance found " << pubLedgers.size()
2118  << " ledgers to publish";
2119  for (auto const& ledger : pubLedgers)
2120  {
2121  {
2122  ScopedUnlock sul{sl};
2123  JLOG(m_journal.debug())
2124  << "tryAdvance publishing seq " << ledger->info().seq;
2125  setFullLedger(ledger, true, true);
2126  }
2127 
2128  setPubLedger(ledger);
2129 
2130  {
2131  ScopedUnlock sul{sl};
2132  app_.getOPs().pubLedger(ledger);
2133  }
2134  }
2135 
2137  progress = newPFWork("pf:newLedger", sl);
2138  }
2139  if (progress)
2140  mAdvanceWork = true;
2141  } while (mAdvanceWork);
2142 }
2143 
2144 void
2146 {
2147  fetch_packs_.canonicalize_replace_client(hash, data);
2148 }
2149 
2152 {
2153  Blob data;
2154  if (fetch_packs_.retrieve(hash, data))
2155  {
2156  fetch_packs_.del(hash, false);
2157  if (hash == sha512Half(makeSlice(data)))
2158  return data;
2159  }
2160  return std::nullopt;
2161 }
2162 
2163 void
2165 {
2166  if (!mGotFetchPackThread.test_and_set(std::memory_order_acquire))
2167  {
2168  app_.getJobQueue().addJob(jtLEDGER_DATA, "gotFetchPack", [&]() {
2170  mGotFetchPackThread.clear(std::memory_order_release);
2171  });
2172  }
2173 }
2174 
2200 static void
2202  SHAMap const& want,
2203  SHAMap const* have,
2204  std::uint32_t cnt,
2205  protocol::TMGetObjectByHash* into,
2206  std::uint32_t seq,
2207  bool withLeaves = true)
2208 {
2209  assert(cnt != 0);
2210 
2211  Serializer s(1024);
2212 
2213  want.visitDifferences(
2214  have,
2215  [&s, withLeaves, &cnt, into, seq](SHAMapTreeNode const& n) -> bool {
2216  if (!withLeaves && n.isLeaf())
2217  return true;
2218 
2219  s.erase();
2220  n.serializeWithPrefix(s);
2221 
2222  auto const& hash = n.getHash().as_uint256();
2223 
2224  protocol::TMIndexedObject* obj = into->add_objects();
2225  obj->set_ledgerseq(seq);
2226  obj->set_hash(hash.data(), hash.size());
2227  obj->set_data(s.getDataPtr(), s.getLength());
2228 
2229  return --cnt != 0;
2230  });
2231 }
2232 
2233 void
2235  std::weak_ptr<Peer> const& wPeer,
2237  uint256 haveLedgerHash,
2238  UptimeClock::time_point uptime)
2239 {
2240  using namespace std::chrono_literals;
2241  if (UptimeClock::now() > uptime + 1s)
2242  {
2243  JLOG(m_journal.info()) << "Fetch pack request got stale";
2244  return;
2245  }
2246 
2247  if (app_.getFeeTrack().isLoadedLocal() || (getValidatedLedgerAge() > 40s))
2248  {
2249  JLOG(m_journal.info()) << "Too busy to make fetch pack";
2250  return;
2251  }
2252 
2253  auto peer = wPeer.lock();
2254 
2255  if (!peer)
2256  return;
2257 
2258  auto have = getLedgerByHash(haveLedgerHash);
2259 
2260  if (!have)
2261  {
2262  JLOG(m_journal.info())
2263  << "Peer requests fetch pack for ledger we don't have: " << have;
2264  peer->charge(Resource::feeRequestNoReply);
2265  return;
2266  }
2267 
2268  if (have->open())
2269  {
2270  JLOG(m_journal.warn())
2271  << "Peer requests fetch pack from open ledger: " << have;
2272  peer->charge(Resource::feeInvalidRequest);
2273  return;
2274  }
2275 
2276  if (have->info().seq < getEarliestFetch())
2277  {
2278  JLOG(m_journal.debug()) << "Peer requests fetch pack that is too early";
2279  peer->charge(Resource::feeInvalidRequest);
2280  return;
2281  }
2282 
2283  auto want = getLedgerByHash(have->info().parentHash);
2284 
2285  if (!want)
2286  {
2287  JLOG(m_journal.info())
2288  << "Peer requests fetch pack for ledger whose predecessor we "
2289  << "don't have: " << have;
2290  peer->charge(Resource::feeRequestNoReply);
2291  return;
2292  }
2293 
2294  try
2295  {
2296  Serializer hdr(128);
2297 
2298  protocol::TMGetObjectByHash reply;
2299  reply.set_query(false);
2300 
2301  if (request->has_seq())
2302  reply.set_seq(request->seq());
2303 
2304  reply.set_ledgerhash(request->ledgerhash());
2305  reply.set_type(protocol::TMGetObjectByHash::otFETCH_PACK);
2306 
2307  // Building a fetch pack:
2308  // 1. Add the header for the requested ledger.
2309  // 2. Add the nodes for the AccountStateMap of that ledger.
2310  // 3. If there are transactions, add the nodes for the
2311  // transactions of the ledger.
2312  // 4. If the FetchPack now contains at least 512 entries then stop.
2313  // 5. If not very much time has elapsed, then loop back and repeat
2314  // the same process adding the previous ledger to the FetchPack.
2315  do
2316  {
2317  std::uint32_t lSeq = want->info().seq;
2318 
2319  {
2320  // Serialize the ledger header:
2321  hdr.erase();
2322 
2324  addRaw(want->info(), hdr);
2325 
2326  // Add the data
2327  protocol::TMIndexedObject* obj = reply.add_objects();
2328  obj->set_hash(
2329  want->info().hash.data(), want->info().hash.size());
2330  obj->set_data(hdr.getDataPtr(), hdr.getLength());
2331  obj->set_ledgerseq(lSeq);
2332  }
2333 
2335  want->stateMap(), &have->stateMap(), 16384, &reply, lSeq);
2336 
2337  // We use nullptr here because transaction maps are per ledger
2338  // and so the requestor is unlikely to already have it.
2339  if (want->info().txHash.isNonZero())
2340  populateFetchPack(want->txMap(), nullptr, 512, &reply, lSeq);
2341 
2342  if (reply.objects().size() >= 512)
2343  break;
2344 
2345  have = std::move(want);
2346  want = getLedgerByHash(have->info().parentHash);
2347  } while (want && UptimeClock::now() <= uptime + 1s);
2348 
2349  auto msg = std::make_shared<Message>(reply, protocol::mtGET_OBJECTS);
2350 
2351  JLOG(m_journal.info())
2352  << "Built fetch pack with " << reply.objects().size() << " nodes ("
2353  << msg->getBufferSize() << " bytes)";
2354 
2355  peer->send(msg);
2356  }
2357  catch (std::exception const& ex)
2358  {
2359  JLOG(m_journal.warn())
2360  << "Exception building fetch pach. Exception: " << ex.what();
2361  }
2362 }
2363 
2366 {
2367  return fetch_packs_.getCacheSize();
2368 }
2369 
2370 // Returns the minimum ledger sequence in SQL database, if any.
2373 {
2375 }
2376 
2378 LedgerMaster::txnIdFromIndex(uint32_t ledgerSeq, uint32_t txnIndex)
2379 {
2380  uint32_t first = 0, last = 0;
2381 
2382  if (!getValidatedRange(first, last) || last < ledgerSeq)
2383  return {};
2384 
2385  auto const lgr = getLedgerBySeq(ledgerSeq);
2386  if (!lgr || lgr->txs.empty())
2387  return {};
2388 
2389  for (auto it = lgr->txs.begin(); it != lgr->txs.end(); ++it)
2390  if (it->first && it->second &&
2391  it->second->isFieldPresent(sfTransactionIndex) &&
2392  it->second->getFieldU32(sfTransactionIndex) == txnIndex)
2393  return it->first->getTransactionID();
2394 
2395  return {};
2396 }
2397 
2398 } // namespace ripple
ripple::NetworkOPs::pubLedger
virtual void pubLedger(std::shared_ptr< ReadView const > const &lpAccepted)=0
beast::Journal::fatal
Stream fatal() const
Definition: Journal.h:338
ripple::ReadView::info
virtual LedgerInfo const & info() const =0
Returns information about the ledger.
ripple::LedgerMaster::getValidatedRange
bool getValidatedRange(std::uint32_t &minVal, std::uint32_t &maxVal)
Definition: LedgerMaster.cpp:635
ripple::LedgerMaster::mPubLedger
std::shared_ptr< Ledger const > mPubLedger
Definition: LedgerMaster.h:371
ripple::LedgerMaster::validCond_
std::condition_variable validCond_
Definition: LedgerMaster.h:438
ripple::Resource::feeInvalidRequest
const Charge feeInvalidRequest
Schedule of fees charged for imposing load on the server.
ripple::RelationalDatabase::getMaxLedgerSeq
virtual std::optional< LedgerIndex > getMaxLedgerSeq()=0
getMaxLedgerSeq Returns the maximum ledger sequence in the Ledgers table.
ripple::Application
Definition: Application.h:116
ripple::LedgerMaster::mClosedLedger
LedgerHolder mClosedLedger
Definition: LedgerMaster.h:365
ripple::Application::getOrderBookDB
virtual OrderBookDB & getOrderBookDB()=0
ripple::InboundLedger::Reason::HISTORY
@ HISTORY
std::optional::has_value
T has_value(T... args)
ripple::HashPrefix::ledgerMaster
@ ledgerMaster
ledger master data for signing
std::lock
T lock(T... args)
ripple::makeSlice
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
Definition: Slice.h:241
ripple::NodeStore::Database::getWriteLoad
virtual std::int32_t getWriteLoad() const =0
Retrieve the estimated number of pending write operations.
ripple::LedgerMaster::getPublishedLedger
std::shared_ptr< ReadView const > getPublishedLedger()
Definition: LedgerMaster.cpp:1699
ripple::LedgerIndex
std::uint32_t LedgerIndex
A ledger index.
Definition: Protocol.h:90
std::bind
T bind(T... args)
ripple::LedgerMaster::fetch_packs_
TaggedCache< uint256, Blob > fetch_packs_
Definition: LedgerMaster.h:425
ripple::OpenLedger::current
std::shared_ptr< OpenView const > current() const
Returns a view to the current open ledger.
Definition: OpenLedger.cpp:50
ripple::NodeStore::Database
Persistency layer for NodeObject.
Definition: Database.h:51
ripple::LedgerMaster::makeFetchPack
void makeFetchPack(std::weak_ptr< Peer > const &wPeer, std::shared_ptr< protocol::TMGetObjectByHash > const &request, uint256 haveLedgerHash, UptimeClock::time_point uptime)
Definition: LedgerMaster.cpp:2234
ripple::LedgerMaster::clearLedgerCachePrior
void clearLedgerCachePrior(LedgerIndex seq)
Definition: LedgerMaster.cpp:1900
std::string
STL class.
std::shared_ptr< Collector >
ripple::shouldAcquire
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)
Definition: LedgerMaster.cpp:157
ripple::LedgerMaster::sweep
void sweep()
Definition: LedgerMaster.cpp:1879
ripple::SizedItem
SizedItem
Definition: Config.h:51
std::exception
STL class.
ripple::base_uint::isNonZero
bool isNonZero() const
Definition: base_uint.h:537
beast::Journal::trace
Stream trace() const
Severity stream access functions.
Definition: Journal.h:308
ripple::LedgerMaster::mBuildingLedgerSeq
std::atomic< LedgerIndex > mBuildingLedgerSeq
Definition: LedgerMaster.h:412
ripple::LedgerMaster::app_
Application & app_
Definition: LedgerMaster.h:359
ripple::sfLedgerSequence
const SF_UINT32 sfLedgerSequence
ripple::SHAMapStore::minimumOnline
virtual std::optional< LedgerIndex > minimumOnline() const =0
The minimum ledger to try and maintain in our database.
ripple::apply
std::pair< TER, bool > apply(Application &app, OpenView &view, STTx const &tx, ApplyFlags flags, beast::Journal journal)
Apply a transaction to an OpenView.
Definition: apply.cpp:109
ripple::LedgerMaster::mLedgerHistory
LedgerHistory mLedgerHistory
Definition: LedgerMaster.h:385
std::atomic_flag::test_and_set
T test_and_set(T... args)
ripple::LedgerMaster::mHeldTransactions
CanonicalTXSet mHeldTransactions
Definition: LedgerMaster.h:387
ripple::Serializer::erase
void erase()
Definition: Serializer.h:210
ripple::Config::LEDGER_REPLAY
bool LEDGER_REPLAY
Definition: Config.h:231
std::pair::second
T second
std::vector::reserve
T reserve(T... args)
ripple::CanonicalTXSet::popAcctTransaction
std::shared_ptr< STTx const > popAcctTransaction(std::shared_ptr< STTx const > const &tx)
Definition: CanonicalTXSet.cpp:62
ripple::LedgerHistory::fixIndex
bool fixIndex(LedgerIndex ledgerIndex, LedgerHash const &ledgerHash)
Repair a hash to index mapping.
Definition: LedgerHistory.cpp:508
ripple::Validations::fees
std::vector< std::uint32_t > fees(ID const &ledgerID, std::uint32_t baseFee)
Returns fees reported by trusted full validators in the given ledger.
Definition: Validations.h:1079
ripple::LedgerHolder::set
void set(std::shared_ptr< Ledger const > ledger)
Definition: LedgerHolder.h:44
ripple::LedgerMaster::getValidLedgerIndex
LedgerIndex getValidLedgerIndex()
Definition: LedgerMaster.cpp:213
ripple::Application::getAmendmentTable
virtual AmendmentTable & getAmendmentTable()=0
ripple::OpenView
Writable ledger view that accumulates state and tx changes.
Definition: OpenView.h:55
ripple::InboundLedger::Reason::GENERIC
@ GENERIC
vector
std::string::find
T find(T... args)
std::vector::size
T size(T... args)
ripple::LedgerMaster::mHistLedger
std::shared_ptr< Ledger const > mHistLedger
Definition: LedgerMaster.h:377
ripple::LedgerMaster::getPublishedLedgerAge
std::chrono::seconds getPublishedLedgerAge()
Definition: LedgerMaster.cpp:250
std::back_inserter
T back_inserter(T... args)
ripple::LedgerMaster::upgradeWarningPrevTime_
TimeKeeper::time_point upgradeWarningPrevTime_
Definition: LedgerMaster.h:434
ripple::SHAMapTreeNode::serializeWithPrefix
virtual void serializeWithPrefix(Serializer &) const =0
Serialize the node in a format appropriate for hashing.
ripple::ValidatorList::getQuorumKeys
QuorumKeys getQuorumKeys() const
Get the quorum and all of the trusted keys.
Definition: ValidatorList.h:658
ripple::LedgerMaster::releaseReplay
std::unique_ptr< LedgerReplay > releaseReplay()
Definition: LedgerMaster.cpp:1912
std::chrono::minutes
ripple::ApplyFlags
ApplyFlags
Definition: ApplyView.h:29
ripple::SHAMapStore::onLedgerClosed
virtual void onLedgerClosed(std::shared_ptr< Ledger const > const &ledger)=0
Called by LedgerMaster every time a ledger validates.
ripple::LedgerMaster::getValidatedRules
Rules getValidatedRules()
Definition: LedgerMaster.cpp:1684
ripple::AmendmentTable::doValidatedLedger
void doValidatedLedger(std::shared_ptr< ReadView const > const &lastValidatedLedger)
Called when a new fully-validated ledger is accepted.
Definition: AmendmentTable.h:92
ripple::LedgerHeader::seq
LedgerIndex seq
Definition: LedgerHeader.h:41
ripple::LedgerMaster::mCompleteLock
std::recursive_mutex mCompleteLock
Definition: LedgerMaster.h:392
ripple::LedgerMaster::applyHeldTransactions
void applyHeldTransactions()
Apply held transactions to the open ledger This is normally called as we close the ledger.
Definition: LedgerMaster.cpp:551
ripple::LedgerMaster::switchLCL
void switchLCL(std::shared_ptr< Ledger const > const &lastClosed)
Definition: LedgerMaster.cpp:506
std::stringstream
STL class.
beast::Journal::warn
Stream warn() const
Definition: Journal.h:326
std::recursive_mutex
STL class.
ripple::LedgerMaster::newPFWork
bool newPFWork(const char *name, std::unique_lock< std::recursive_mutex > &)
A thread needs to be dispatched to handle pathfinding work of some kind.
Definition: LedgerMaster.cpp:1630
std::lock_guard
STL class.
ripple::NetworkOPs::setAmendmentBlocked
virtual void setAmendmentBlocked()=0
ripple::Application::getShardStore
virtual NodeStore::DatabaseShard * getShardStore()=0
ripple::NetworkOPs::isAmendmentWarned
virtual bool isAmendmentWarned()=0
ripple::LedgerMaster::getLedgerByHash
std::shared_ptr< Ledger const > getLedgerByHash(uint256 const &hash)
Definition: LedgerMaster.cpp:1859
std::cerr
ripple::Application::isStopping
virtual bool isStopping() const =0
ripple::LedgerMaster::isNewPathRequest
bool isNewPathRequest()
Definition: LedgerMaster.cpp:1608
ripple::JobQueue::addJob
bool addJob(JobType type, std::string const &name, JobHandler &&jobHandler)
Adds a job to the JobQueue.
Definition: JobQueue.h:166
ripple::SHAMap::visitDifferences
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.
Definition: SHAMapSync.cpp:100
ripple::stopwatch
Stopwatch & stopwatch()
Returns an instance of a wall clock.
Definition: chrono.h:88
std::vector::back
T back(T... args)
ripple::LoadFeeTrack::getLoadBase
std::uint32_t getLoadBase() const
Definition: LoadFeeTrack.h:89
ripple::jtUPDATE_PF
@ jtUPDATE_PF
Definition: Job.h:57
ripple::Application::timeKeeper
virtual TimeKeeper & timeKeeper()=0
ripple::LedgerMaster::getEarliestFetch
std::uint32_t getEarliestFetch()
Definition: LedgerMaster.cpp:702
ripple::Application::openLedger
virtual OpenLedger & openLedger()=0
ripple::LedgerMaster::walkHashBySeq
std::optional< LedgerHash > walkHashBySeq(std::uint32_t index, InboundLedger::Reason reason)
Walk to a ledger's hash using the skip list.
Definition: LedgerMaster.cpp:1759
ripple::tapNONE
@ tapNONE
Definition: ApplyView.h:30
ripple::SizedItem::ledgerFetch
@ ledgerFetch
ripple::LedgerHistory::sweep
void sweep()
Remove stale cache entries.
Definition: LedgerHistory.h:76
ripple::Resource::feeRequestNoReply
const Charge feeRequestNoReply
ripple::LedgerHistory::getLedgerHash
LedgerHash getLedgerHash(LedgerIndex ledgerIndex)
Get a ledger's hash given its sequence number.
Definition: LedgerHistory.cpp:74
ripple::LedgerHistory::insert
bool insert(std::shared_ptr< Ledger const > const &ledger, bool validated)
Track a ledger.
Definition: LedgerHistory.cpp:54
ripple::LedgerMaster::setFullLedger
void setFullLedger(std::shared_ptr< Ledger const > const &ledger, bool isSynchronous, bool isCurrent)
Definition: LedgerMaster.cpp:916
std::sort
T sort(T... args)
algorithm
ripple::Application::getOPs
virtual NetworkOPs & getOPs()=0
ripple::PathRequests::requestsPending
bool requestsPending() const
Definition: PathRequests.cpp:219
ripple::jtLEDGER_DATA
@ jtLEDGER_DATA
Definition: Job.h:67
ripple::LedgerMaster::fixMismatch
void fixMismatch(ReadView const &ledger)
Definition: LedgerMaster.cpp:861
std::atomic_flag::clear
T clear(T... args)
ripple::LedgerMaster::fetch_depth_
const std::uint32_t fetch_depth_
Definition: LedgerMaster.h:418
ripple::Application::getInboundLedgers
virtual InboundLedgers & getInboundLedgers()=0
ripple::LedgerHistory::builtLedger
void builtLedger(std::shared_ptr< Ledger const > const &, uint256 const &consensusHash, Json::Value)
Report that we have locally built a particular ledger.
Definition: LedgerHistory.cpp:426
ripple::Application::getFeeTrack
virtual LoadFeeTrack & getFeeTrack()=0
ripple::LedgerMaster::getCompleteLedgers
std::string getCompleteLedgers()
Definition: LedgerMaster.cpp:1706
ripple::LedgerMaster::ledger_fetch_size_
const std::uint32_t ledger_fetch_size_
Definition: LedgerMaster.h:423
ripple::BuildInfo::isRippledVersion
bool isRippledVersion(std::uint64_t version)
Check if the encoded software version is a rippled software version.
Definition: BuildInfo.cpp:162
ripple::SHAMapMissingNode
Definition: SHAMapMissingNode.h:55
ripple::JobQueue::getJobCount
int getJobCount(JobType t) const
Jobs waiting at this priority.
Definition: JobQueue.cpp:128
std::vector::push_back
T push_back(T... args)
ripple::LedgerMaster::peekMutex
std::recursive_mutex & peekMutex()
Definition: LedgerMaster.cpp:1652
ripple::LedgerMaster::mGotFetchPackThread
std::atomic_flag mGotFetchPackThread
Definition: LedgerMaster.h:405
ripple::base_uint< 256 >
ripple::LoadFeeTrack::isLoadedLocal
bool isLoadedLocal() const
Definition: LoadFeeTrack.h:126
ripple::jtPUBOLDLEDGER
@ jtPUBOLDLEDGER
Definition: Job.h:44
std::chrono::time_point::time_since_epoch
T time_since_epoch(T... args)
ripple::LedgerMaster::mCompleteLedgers
RangeSet< std::uint32_t > mCompleteLedgers
Definition: LedgerMaster.h:393
std::stol
T stol(T... args)
ripple::NodeStore::Database::firstLedgerSeq
std::uint32_t firstLedgerSeq(std::uint32_t shardIndex) const noexcept
Calculates the first ledger sequence for a given shard index.
Definition: Database.h:257
ripple::Config::reporting
bool reporting() const
Definition: Config.h:349
ripple::UptimeClock::now
static time_point now()
Definition: UptimeClock.cpp:63
ripple::LedgerMaster::mFillInProgress
int mFillInProgress
Definition: LedgerMaster.h:400
ripple::NetworkOPs::isNeedNetworkLedger
virtual bool isNeedNetworkLedger()=0
ripple::sfServerVersion
const SF_UINT64 sfServerVersion
ripple::LedgerMaster::replayData
std::unique_ptr< LedgerReplay > replayData
Definition: LedgerMaster.h:390
ripple::LedgerMaster::gotFetchPack
void gotFetchPack(bool progress, std::uint32_t seq)
Definition: LedgerMaster.cpp:2164
ripple::LedgerMaster::fetchForHistory
void fetchForHistory(std::uint32_t missing, bool &progress, InboundLedger::Reason reason, std::unique_lock< std::recursive_mutex > &)
Definition: LedgerMaster.cpp:1918
ripple::LedgerMaster::getFetchPack
std::optional< Blob > getFetchPack(uint256 const &hash) override
Retrieves partial ledger data of the coresponding hash from peers.
Definition: LedgerMaster.cpp:2151
ripple::LedgerMaster::failedSave
void failedSave(std::uint32_t seq, uint256 const &hash)
Definition: LedgerMaster.cpp:977
ripple::Application::getLedgerMaster
virtual LedgerMaster & getLedgerMaster()=0
ripple::InboundLedgers::acquire
virtual std::shared_ptr< Ledger const > acquire(uint256 const &hash, std::uint32_t seq, InboundLedger::Reason)=0
std::atomic::load
T load(T... args)
ripple::NetworkOPs::setAmendmentWarned
virtual void setAmendmentWarned()=0
ripple::Application::pendingSaves
virtual PendingSaves & pendingSaves()=0
ripple::LedgerHolder::empty
bool empty()
Definition: LedgerHolder.h:63
ripple::LedgerHistory::getLedgerByHash
std::shared_ptr< Ledger const > getLedgerByHash(LedgerHash const &ledgerHash)
Retrieve a ledger given its hash.
Definition: LedgerHistory.cpp:116
ripple::Serializer::getDataPtr
const void * getDataPtr() const
Definition: Serializer.h:190
ripple::MAX_LEDGER_GAP
static constexpr int MAX_LEDGER_GAP
Definition: LedgerMaster.cpp:146
ripple::RelationalDatabase::getHashByIndex
virtual uint256 getHashByIndex(LedgerIndex ledgerIndex)=0
getHashByIndex Returns the hash of the ledger with the given sequence.
chrono
ripple::LedgerMaster::getFullValidatedRange
bool getFullValidatedRange(std::uint32_t &minVal, std::uint32_t &maxVal)
Definition: LedgerMaster.cpp:608
ripple::NetworkOPs::updateLocalTx
virtual void updateLocalTx(ReadView const &newValidLedger)=0
ripple::Application::config
virtual Config & config()=0
ripple::LedgerMaster::fixIndex
bool fixIndex(LedgerIndex ledgerIndex, LedgerHash const &ledgerHash)
Definition: LedgerMaster.cpp:532
ripple::isCurrent
bool isCurrent(ValidationParms const &p, NetClock::time_point now, NetClock::time_point signTime, NetClock::time_point seenTime)
Whether a validation is still current.
Definition: Validations.h:148
std::unique_lock
STL class.
ripple::SHAMap
A SHAMap is both a radix tree with a fan-out of 16 and a Merkle tree.
Definition: SHAMap.h:95
ripple::populateFetchPack
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.
Definition: LedgerMaster.cpp:2201
ripple::Application::getRelationalDatabase
virtual RelationalDatabase & getRelationalDatabase()=0
ripple::LedgerHistory::validatedLedger
void validatedLedger(std::shared_ptr< Ledger const > const &, std::optional< uint256 > const &consensusHash)
Report that we have validated a particular ledger.
Definition: LedgerHistory.cpp:467
ripple::LedgerMaster::canBeCurrent
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...
Definition: LedgerMaster.cpp:438
ripple::Application::getTxQ
virtual TxQ & getTxQ()=0
ripple::SHAMapTreeNode
Definition: SHAMapTreeNode.h:53
ripple::Application::getJobQueue
virtual JobQueue & getJobQueue()=0
ripple::LedgerMaster::haveLedger
bool haveLedger(std::uint32_t seq)
Definition: LedgerMaster.cpp:593
ripple::AmendmentTable::firstUnsupportedExpected
virtual std::optional< NetClock::time_point > firstUnsupportedExpected() const =0
ripple::JobQueue::isStopping
bool isStopping() const
Definition: JobQueue.h:230
ripple::calculatePercent
constexpr std::size_t calculatePercent(std::size_t count, std::size_t total)
Calculate one number divided by another number in percentage.
Definition: MathUtilities.h:44
beast::Journal::Stream
Provide a light-weight way to check active() before string formatting.
Definition: Journal.h:193
ripple::RelationalDatabase::getMinLedgerSeq
virtual std::optional< LedgerIndex > getMinLedgerSeq()=0
getMinLedgerSeq Returns the minimum ledger sequence in the Ledgers table.
beast::Journal::error
Stream error() const
Definition: Journal.h:332
beast::Journal::info
Stream info() const
Definition: Journal.h:320
ripple::LedgerMaster::isCompatible
bool isCompatible(ReadView const &, beast::Journal::Stream, char const *reason)
Definition: LedgerMaster.cpp:219
std::chrono::time_point
ripple::LedgerMaster::minSqlSeq
std::optional< LedgerIndex > minSqlSeq()
Definition: LedgerMaster.cpp:2372
ripple::LedgerMaster::updatePaths
void updatePaths()
Definition: LedgerMaster.cpp:1496
ripple::SHAMapTreeNode::isLeaf
virtual bool isLeaf() const =0
Determines if this is a leaf node.
ripple::hashOfSeq
std::optional< uint256 > hashOfSeq(ReadView const &ledger, LedgerIndex seq, beast::Journal journal)
Return the hash of a ledger by sequence.
Definition: View.cpp:661
ripple::OrderBookDB::setup
void setup(std::shared_ptr< ReadView const > const &ledger)
Definition: OrderBookDB.cpp:38
std::copy
T copy(T... args)
ripple::LedgerMaster::getLedgerBySeq
std::shared_ptr< Ledger const > getLedgerBySeq(std::uint32_t index)
Definition: LedgerMaster.cpp:1823
ripple::LedgerMaster::txnIdFromIndex
std::optional< uint256 > txnIdFromIndex(uint32_t ledgerSeq, uint32_t txnIndex)
Definition: LedgerMaster.cpp:2378
ripple::Overlay::getActivePeers
virtual PeerSequence getActivePeers() const =0
Returns a sequence representing the current list of peers.
ripple::TimeKeeper::closeTime
virtual time_point closeTime() const =0
Returns the close time, in network time.
ripple::LedgerMaster::newPathRequest
bool newPathRequest()
Definition: LedgerMaster.cpp:1600
ripple::SerialIter
Definition: Serializer.h:311
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::Application::getValidations
virtual RCLValidations & getValidations()=0
std::uint32_t
ripple::LedgerReplayer::replay
void replay(InboundLedger::Reason r, uint256 const &finishLedgerHash, std::uint32_t totalNumLedgers)
Replay a range of ledgers.
Definition: LedgerReplayer.cpp:45
ripple::LedgerMaster::addHeldTransaction
void addHeldTransaction(std::shared_ptr< Transaction > const &trans)
Definition: LedgerMaster.cpp:427
ripple::SerialIter::skip
void skip(int num)
Definition: Serializer.cpp:352
ripple::LedgerMaster::setValidLedger
void setValidLedger(std::shared_ptr< Ledger const > const &l)
Definition: LedgerMaster.cpp:336
ripple::NetworkOPs::clearNeedNetworkLedger
virtual void clearNeedNetworkLedger()=0
std::map
STL class.
ripple::LedgerHistory::getLedgerBySeq
std::shared_ptr< Ledger const > getLedgerBySeq(LedgerIndex ledgerIndex)
Get a ledger given its sequence number.
Definition: LedgerHistory.cpp:83
ripple::LedgerMaster::mPathFindNewRequest
bool mPathFindNewRequest
Definition: LedgerMaster.h:403
ripple::range
ClosedInterval< T > range(T low, T high)
Create a closed range interval.
Definition: RangeSet.h:54
ripple::Application::getPathRequests
virtual PathRequests & getPathRequests()=0
ripple::LedgerHolder::get
std::shared_ptr< Ledger const > get()
Definition: LedgerHolder.h:56
ripple::CanonicalTXSet::insert
void insert(std::shared_ptr< STTx const > const &txn)
Definition: CanonicalTXSet.cpp:52
ripple::prevMissing
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.
Definition: RangeSet.h:183
ripple::LedgerMaster::getCurrentLedger
std::shared_ptr< ReadView const > getCurrentLedger()
Definition: LedgerMaster.cpp:1659
ripple::PendingSaves::getSnapshot
std::map< LedgerIndex, bool > getSnapshot() const
Get a snapshot of the pending saves.
Definition: PendingSaves.h:137
ripple::LedgerMaster::newOrderBookDB
bool newOrderBookDB()
Definition: LedgerMaster.cpp:1619
ripple::LedgerMaster::getNeededValidations
std::size_t getNeededValidations()
Determines how many validations are needed to fully validate a ledger.
Definition: LedgerMaster.cpp:1041
beast::abstract_clock< std::chrono::steady_clock >
memory
ripple::ValidatorList::negativeUNLFilter
std::vector< std::shared_ptr< STValidation > > negativeUNLFilter(std::vector< std::shared_ptr< STValidation >> &&validations) const
Remove validations that are from validators on the negative UNL.
Definition: ValidatorList.cpp:1957
ripple::areCompatible
bool areCompatible(ReadView const &validLedger, ReadView const &testLedger, beast::Journal::Stream &s, const char *reason)
Return false if the test ledger is provably incompatible with the valid ledger, that is,...
Definition: View.cpp:499
ripple::LedgerMaster::mAdvanceThread
bool mAdvanceThread
Definition: LedgerMaster.h:396
ripple::LedgerMaster::checkAccept
void checkAccept(std::shared_ptr< Ledger const > const &ledger)
Definition: LedgerMaster.cpp:1047
ripple::Application::validators
virtual ValidatorList & validators()=0
ripple::AmendmentTable::hasUnsupportedEnabled
virtual bool hasUnsupportedEnabled() const =0
returns true if one or more amendments on the network have been enabled that this server does not sup...
std::weak_ptr< Peer >
ripple::sfTransactionIndex
const SF_UINT32 sfTransactionIndex
std::min
T min(T... args)
ripple::SHAMapTreeNode::getHash
SHAMapHash const & getHash() const
Return the hash of this node.
Definition: SHAMapTreeNode.h:143
std::condition_variable::notify_one
T notify_one(T... args)
ripple::LedgerMaster::max_ledger_difference_
const LedgerIndex max_ledger_difference_
Definition: LedgerMaster.h:431
ripple::Serializer
Definition: Serializer.h:40
ripple::LedgerMaster::getFetchPackCacheSize
std::size_t getFetchPackCacheSize() const
Definition: LedgerMaster.cpp:2365
std::string::substr
T substr(T... args)
ripple::BuildInfo::isNewerVersion
bool isNewerVersion(std::uint64_t version)
Check if the version is newer than the local node's rippled software version.
Definition: BuildInfo.cpp:169
ripple::LedgerMaster::mPathLedger
std::shared_ptr< Ledger const > mPathLedger
Definition: LedgerMaster.h:374
ripple::LedgerMaster::getValidatedLedgerAge
std::chrono::seconds getValidatedLedgerAge()
Definition: LedgerMaster.cpp:274
ripple::LedgerMaster::getClosedLedger
std::shared_ptr< Ledger const > getClosedLedger()
Definition: LedgerMaster.h:98
ripple::LedgerMaster::mAdvanceWork
bool mAdvanceWork
Definition: LedgerMaster.h:399
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:54
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::NetworkOPs::isBlocked
virtual bool isBlocked()=0
ripple::Config::features
std::unordered_set< uint256, beast::uhash<> > features
Definition: Config.h:286
ripple::NodeStore::Database::storeLedger
virtual bool storeLedger(std::shared_ptr< Ledger const > const &srcLedger)=0
Store a ledger from a different database.
ripple::LedgerMaster::mPubLedgerClose
std::atomic< std::uint32_t > mPubLedgerClose
Definition: LedgerMaster.h:408
ripple::Application::getNodeStore
virtual NodeStore::Database & getNodeStore()=0
ripple::Application::journal
virtual beast::Journal journal(std::string const &name)=0
ripple::addRaw
void addRaw(LedgerHeader const &info, Serializer &s, bool includeHash)
Definition: protocol/impl/LedgerHeader.cpp:25
ripple::LedgerMaster::ledger_history_
const std::uint32_t ledger_history_
Definition: LedgerMaster.h:421
ripple::LedgerMaster::mPubLedgerSeq
std::atomic< LedgerIndex > mPubLedgerSeq
Definition: LedgerMaster.h:409
cstdlib
std::endl
T endl(T... args)
ripple::LedgerHistory::getCacheHitRate
float getCacheHitRate()
Get the ledgers_by_hash cache hit rate.
Definition: LedgerHistory.h:53
ripple::CanonicalTXSet::size
size_t size() const
Definition: CanonicalTXSet.h:155
ripple::LedgerMaster::getCloseTimeBySeq
std::optional< NetClock::time_point > getCloseTimeBySeq(LedgerIndex ledgerIndex)
Definition: LedgerMaster.cpp:1718
limits
ripple::LedgerMaster::addFetchPack
void addFetchPack(uint256 const &hash, std::shared_ptr< Blob > data)
Definition: LedgerMaster.cpp:2145
ripple::LedgerMaster::clearLedger
void clearLedger(std::uint32_t seq)
Definition: LedgerMaster.cpp:600
std::vector::begin
T begin(T... args)
ripple::NodeStore::Database::seqToShardIndex
std::uint32_t seqToShardIndex(std::uint32_t ledgerSeq) const noexcept
Calculates the shard index for a given ledger sequence.
Definition: Database.h:283
ripple::NetworkOPs::clearAmendmentWarned
virtual void clearAmendmentWarned()=0
ripple::LedgerMaster::getLedgerHashForHistory
std::optional< LedgerHash > getLedgerHashForHistory(LedgerIndex index, InboundLedger::Reason reason)
Definition: LedgerMaster.cpp:1296
ripple::LedgerMaster::m_journal
beast::Journal m_journal
Definition: LedgerMaster.h:360
std
STL namespace.
ripple::LogicError
void LogicError(std::string const &how) noexcept
Called when faulty logic causes a broken invariant.
Definition: contract.cpp:48
ripple::sha512Half
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition: digest.h:216
cassert
ripple::MAX_LEDGER_AGE_ACQUIRE
static constexpr std::chrono::minutes MAX_LEDGER_AGE_ACQUIRE
Definition: LedgerMaster.cpp:149
ripple::LedgerMaster::mValidLedgerSeq
std::atomic< LedgerIndex > mValidLedgerSeq
Definition: LedgerMaster.h:411
ripple::PostgresDatabase
Definition: PostgresDatabase.h:27
ripple::LedgerMaster::getCurrentLedgerIndex
LedgerIndex getCurrentLedgerIndex()
Definition: LedgerMaster.cpp:207
ripple::TimeKeeper::now
virtual time_point now() const override=0
Returns the estimate of wall time, in network time.
ripple::Application::overlay
virtual Overlay & overlay()=0
std::chrono::seconds::count
T count(T... args)
ripple::LedgerMaster::takeReplay
void takeReplay(std::unique_ptr< LedgerReplay > replay)
Definition: LedgerMaster.cpp:1906
ripple::LedgerMaster::getValidatedLedger
std::shared_ptr< Ledger const > getValidatedLedger()
Definition: LedgerMaster.cpp:1669
ripple::LedgerMaster::mLastValidLedger
std::pair< uint256, LedgerIndex > mLastValidLedger
Definition: LedgerMaster.h:383
std::vector::empty
T empty(T... args)
ripple::Rules
Rules controlling protocol behavior.
Definition: Rules.h:33
ripple::LedgerHistory::clearLedgerCachePrior
void clearLedgerCachePrior(LedgerIndex seq)
Definition: LedgerHistory.cpp:522
std::optional< LedgerIndex >
ripple::Overlay::checkTracking
virtual void checkTracking(std::uint32_t index)=0
Calls the checkTracking function on each peer.
std::stringstream::str
T str(T... args)
ripple::LedgerMaster::mShardLedger
std::shared_ptr< Ledger const > mShardLedger
Definition: LedgerMaster.h:380
beast::Journal::debug
Stream debug() const
Definition: Journal.h:314
std::size_t
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
std::make_pair
T make_pair(T... args)
ripple::Serializer::add32
int add32(std::uint32_t i)
Definition: Serializer.cpp:38
ripple::LedgerMaster::storeLedger
bool storeLedger(std::shared_ptr< Ledger const > ledger)
Definition: LedgerMaster.cpp:538
std::vector::end
T end(T... args)
ripple::InboundLedger::Reason
Reason
Definition: InboundLedger.h:43
ripple::NodeStore::Database::fetchNodeObject
std::shared_ptr< NodeObject > fetchNodeObject(uint256 const &hash, std::uint32_t ledgerSeq=0, FetchType fetchType=FetchType::synchronous, bool duplicate=false)
Fetch a node object.
Definition: Database.cpp:252
ripple::Application::getLedgerReplayer
virtual LedgerReplayer & getLedgerReplayer()=0
ripple::SHAMapHash::as_uint256
uint256 const & as_uint256() const
Definition: SHAMapHash.h:43
ripple::Application::getSHAMapStore
virtual SHAMapStore & getSHAMapStore()=0
ripple::LedgerMaster::setLedgerRangePresent
void setLedgerRangePresent(std::uint32_t minV, std::uint32_t maxV)
Definition: LedgerMaster.cpp:1872
ripple::NodeStore::Database::earliestLedgerSeq
std::uint32_t earliestLedgerSeq() const noexcept
Definition: Database.h:238
ripple::jtADVANCE
@ jtADVANCE
Definition: Job.h:68
std::max
T max(T... args)
ripple::Serializer::getLength
int getLength() const
Definition: Serializer.h:200
ripple::getCandidateLedger
LedgerIndex getCandidateLedger(LedgerIndex requested)
Find a ledger index from which we could easily get the requested ledger.
Definition: View.h:252
ripple::LedgerMaster::consensusBuilt
void consensusBuilt(std::shared_ptr< Ledger const > const &ledger, uint256 const &consensusHash, Json::Value consensus)
Report that the consensus process built a particular ledger.
Definition: LedgerMaster.cpp:1195
ripple::LedgerMaster::tryFill
void tryFill(std::shared_ptr< Ledger const > ledger)
Definition: LedgerMaster.cpp:716
ripple::SerialIter::get32
std::uint32_t get32()
Definition: Serializer.cpp:386
ripple::LedgerMaster::mValidLedger
LedgerHolder mValidLedger
Definition: LedgerMaster.h:368
ripple::LedgerMaster::fetch_seq_
std::uint32_t fetch_seq_
Definition: LedgerMaster.h:427
ripple::LoadFeeTrack::setRemoteFee
void setRemoteFee(std::uint32_t f)
Definition: LoadFeeTrack.h:60
ripple::LedgerMaster::getHashBySeq
uint256 getHashBySeq(std::uint32_t index)
Get a ledger's hash by sequence number using the cache.
Definition: LedgerMaster.cpp:1748
ripple::LedgerMaster::findNewLedgersToPublish
std::vector< std::shared_ptr< Ledger const > > findNewLedgersToPublish(std::unique_lock< std::recursive_mutex > &)
Definition: LedgerMaster.cpp:1319
ripple::pendSaveValidated
bool pendSaveValidated(Application &app, std::shared_ptr< Ledger const > const &ledger, bool isSynchronous, bool isCurrent)
Save, or arrange to save, a fully-validated ledger Returns false on error.
Definition: Ledger.cpp:1005
ripple::LedgerMaster::isCaughtUp
bool isCaughtUp(std::string &reason)
Definition: LedgerMaster.cpp:305
std::unique_ptr
STL class.
ripple::LedgerMaster::getCloseTimeByHash
std::optional< NetClock::time_point > getCloseTimeByHash(LedgerHash const &ledgerHash, LedgerIndex ledgerIndex)
Definition: LedgerMaster.cpp:1726
ripple::LedgerMaster::mPathFindThread
int mPathFindThread
Definition: LedgerMaster.h:402
ripple::Validations::getTrustedForLedger
std::vector< WrappedValidationType > getTrustedForLedger(ID const &ledgerID, Seq const &seq)
Get trusted full validations for a specific ledger.
Definition: Validations.h:1056
ripple::InboundLedger::Reason::SHARD
@ SHARD
ripple::LedgerMaster::mValidLedgerSign
std::atomic< std::uint32_t > mValidLedgerSign
Definition: LedgerMaster.h:410
ripple::LedgerMaster::setBuildingLedger
void setBuildingLedger(LedgerIndex index)
Definition: LedgerMaster.cpp:587
ripple::LedgerMaster::doAdvance
void doAdvance(std::unique_lock< std::recursive_mutex > &)
Definition: LedgerMaster.cpp:2044
std::unordered_map
STL class.
ripple::LedgerMaster::tryAdvance
void tryAdvance()
Definition: LedgerMaster.cpp:1464
ripple::LedgerMaster::clearPriorLedgers
void clearPriorLedgers(LedgerIndex seq)
Definition: LedgerMaster.cpp:1892
ripple::LedgerMaster::setPubLedger
void setPubLedger(std::shared_ptr< Ledger const > const &l)
Definition: LedgerMaster.cpp:419
ripple::RelationalDatabase::getHashesByIndex
virtual std::optional< LedgerHashPair > getHashesByIndex(LedgerIndex ledgerIndex)=0
getHashesByIndex Returns the hashes of the ledger and its parent as specified by the ledgerIndex.
beast::abstract_clock< NetClock >::time_point
typename NetClock ::time_point time_point
Definition: abstract_clock.h:63
ripple::LedgerMaster::popAcctTransaction
std::shared_ptr< STTx const > popAcctTransaction(std::shared_ptr< STTx const > const &tx)
Get the next transaction held for a particular account if any.
Definition: LedgerMaster.cpp:579
ripple::OpenLedger::modify
bool modify(modify_type const &f)
Modify the open ledger.
Definition: OpenLedger.cpp:57
ripple::LedgerMaster::LedgerMaster
LedgerMaster(Application &app, Stopwatch &stopwatch, beast::insight::Collector::ptr const &collector, beast::Journal journal)
Definition: LedgerMaster.cpp:183
ripple::InboundLedgers::isFailure
virtual bool isFailure(uint256 const &h)=0
std::exception::what
T what(T... args)
ripple::LedgerMaster::getCacheHitRate
float getCacheHitRate()
Definition: LedgerMaster.cpp:1886
ripple::CanonicalTXSet::reset
void reset(LedgerHash const &salt)
Definition: CanonicalTXSet.h:130
ripple::MAX_WRITE_LOAD_ACQUIRE
static constexpr int MAX_WRITE_LOAD_ACQUIRE
Definition: LedgerMaster.cpp:152
ripple::ValidatorList::quorum
std::size_t quorum() const
Get quorum value for current trusted key set.
Definition: ValidatorList.h:492
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::Application::getMaxDisallowedLedger
virtual LedgerIndex getMaxDisallowedLedger()=0
Ensure that a newly-started validator does not sign proposals older than the last ledger it persisted...
ripple::LedgerMaster::m_mutex
std::recursive_mutex m_mutex
Definition: LedgerMaster.h:362
ripple::Validations::currentTrusted
std::vector< WrappedValidationType > currentTrusted()
Get the currently trusted full validations.
Definition: Validations.h:997
ripple::LedgerMaster::collect_metrics
void collect_metrics()
Definition: LedgerMaster.h:462
ripple::LedgerMaster::standalone_
const bool standalone_
Definition: LedgerMaster.h:415
std::chrono