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