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  mValidLedgerSign = signTime.time_since_epoch().count();
371  assert(
375  mValidLedgerSeq = l->info().seq;
376 
377  app_.getOPs().updateLocalTx(*l);
379  mLedgerHistory.validatedLedger(l, consensusHash);
381  if (!app_.getOPs().isBlocked())
382  {
384  {
385  JLOG(m_journal.error()) << "One or more unsupported amendments "
386  "activated: server blocked.";
388  }
389  else if (!app_.getOPs().isAmendmentWarned() || l->isFlagLedger())
390  {
391  // Amendments can lose majority, so re-check periodically (every
392  // flag ledger), and clear the flag if appropriate. If an unknown
393  // amendment gains majority log a warning as soon as it's
394  // discovered, then again every flag ledger until the operator
395  // upgrades, the amendment loses majority, or the amendment goes
396  // live and the node gets blocked. Unlike being amendment blocked,
397  // this message may be logged more than once per session, because
398  // the node will otherwise function normally, and this gives
399  // operators an opportunity to see and resolve the warning.
400  if (auto const first =
402  {
403  JLOG(m_journal.error()) << "One or more unsupported amendments "
404  "reached majority. Upgrade before "
405  << to_string(*first)
406  << " to prevent your server from "
407  "becoming amendment blocked.";
409  }
410  else
412  }
413  }
414 }
415 
416 void
418 {
419  mPubLedger = l;
420  mPubLedgerClose = l->info().closeTime.time_since_epoch().count();
421  mPubLedgerSeq = l->info().seq;
422 }
423 
424 void
426  std::shared_ptr<Transaction> const& transaction)
427 {
429  mHeldTransactions.insert(transaction->getSTransaction());
430 }
431 
432 // Validate a ledger's close time and sequence number if we're considering
433 // jumping to that ledger. This helps defend against some rare hostile or
434 // diverged majority scenarios.
435 bool
437 {
438  assert(ledger);
439 
440  // Never jump to a candidate ledger that precedes our
441  // last validated ledger
442 
443  auto validLedger = getValidatedLedger();
444  if (validLedger && (ledger->info().seq < validLedger->info().seq))
445  {
446  JLOG(m_journal.trace())
447  << "Candidate for current ledger has low seq " << ledger->info().seq
448  << " < " << validLedger->info().seq;
449  return false;
450  }
451 
452  // Ensure this ledger's parent close time is within five minutes of
453  // our current time. If we already have a known fully-valid ledger
454  // we perform this check. Otherwise, we only do it if we've built a
455  // few ledgers as our clock can be off when we first start up
456 
457  auto closeTime = app_.timeKeeper().closeTime();
458  auto ledgerClose = ledger->info().parentCloseTime;
459 
460  using namespace std::chrono_literals;
461  if ((validLedger || (ledger->info().seq > 10)) &&
462  ((std::max(closeTime, ledgerClose) - std::min(closeTime, ledgerClose)) >
463  5min))
464  {
465  JLOG(m_journal.warn())
466  << "Candidate for current ledger has close time "
467  << to_string(ledgerClose) << " at network time "
468  << to_string(closeTime) << " seq " << ledger->info().seq;
469  return false;
470  }
471 
472  if (validLedger)
473  {
474  // Sequence number must not be too high. We allow ten ledgers
475  // for time inaccuracies plus a maximum run rate of one ledger
476  // every two seconds. The goal is to prevent a malicious ledger
477  // from increasing our sequence unreasonably high
478 
479  LedgerIndex maxSeq = validLedger->info().seq + 10;
480 
481  if (closeTime > validLedger->info().parentCloseTime)
482  maxSeq += std::chrono::duration_cast<std::chrono::seconds>(
483  closeTime - validLedger->info().parentCloseTime)
484  .count() /
485  2;
486 
487  if (ledger->info().seq > maxSeq)
488  {
489  JLOG(m_journal.warn())
490  << "Candidate for current ledger has high seq "
491  << ledger->info().seq << " > " << maxSeq;
492  return false;
493  }
494 
495  JLOG(m_journal.trace())
496  << "Acceptable seq range: " << validLedger->info().seq
497  << " <= " << ledger->info().seq << " <= " << maxSeq;
498  }
499 
500  return true;
501 }
502 
503 void
505 {
506  assert(lastClosed);
507  if (!lastClosed->isImmutable())
508  LogicError("mutable ledger in switchLCL");
509 
510  if (lastClosed->open())
511  LogicError("The new last closed ledger is open!");
512 
513  {
515  mClosedLedger.set(lastClosed);
516  }
517 
518  if (standalone_)
519  {
520  setFullLedger(lastClosed, true, false);
521  tryAdvance();
522  }
523  else
524  {
525  checkAccept(lastClosed);
526  }
527 }
528 
529 bool
530 LedgerMaster::fixIndex(LedgerIndex ledgerIndex, LedgerHash const& ledgerHash)
531 {
532  return mLedgerHistory.fixIndex(ledgerIndex, ledgerHash);
533 }
534 
535 bool
537 {
538  bool validated = ledger->info().validated;
539  // Returns true if we already had the ledger
540  return mLedgerHistory.insert(std::move(ledger), validated);
541 }
542 
548 void
550 {
552 
553  app_.openLedger().modify([&](OpenView& view, beast::Journal j) {
554  bool any = false;
555  for (auto const& it : mHeldTransactions)
556  {
557  ApplyFlags flags = tapNONE;
558  auto const result =
559  app_.getTxQ().apply(app_, view, it.second, flags, j);
560  if (result.second)
561  any = true;
562  }
563  return any;
564  });
565 
566  // VFALCO TODO recreate the CanonicalTxSet object instead of resetting
567  // it.
568  // VFALCO NOTE The hash for an open ledger is undefined so we use
569  // something that is a reasonable substitute.
570  mHeldTransactions.reset(app_.openLedger().current()->info().parentHash);
571 }
572 
575 {
577 
579 }
580 
581 void
583 {
584  mBuildingLedgerSeq.store(i);
585 }
586 
587 bool
589 {
591  return boost::icl::contains(mCompleteLedgers, seq);
592 }
593 
594 void
596 {
598  mCompleteLedgers.erase(seq);
599 }
600 
601 // returns Ledgers we have all the nodes for
602 bool
604  std::uint32_t& minVal,
605  std::uint32_t& maxVal)
606 {
607  // Validated ledger is likely not stored in the DB yet so we use the
608  // published ledger which is.
609  maxVal = mPubLedgerSeq.load();
610 
611  if (!maxVal)
612  return false;
613 
615  {
617  maybeMin = prevMissing(mCompleteLedgers, maxVal);
618  }
619 
620  if (maybeMin == std::nullopt)
621  minVal = maxVal;
622  else
623  minVal = 1 + *maybeMin;
624 
625  return true;
626 }
627 
628 // Returns Ledgers we have all the nodes for and are indexed
629 bool
631 {
632  if (app_.config().reporting())
633  {
635  try
636  {
637  if (res == "empty" || res == "error" || res.empty())
638  return false;
639  else if (size_t delim = res.find('-'); delim != std::string::npos)
640  {
641  minVal = std::stol(res.substr(0, delim));
642  maxVal = std::stol(res.substr(delim + 1));
643  }
644  else
645  {
646  minVal = maxVal = std::stol(res);
647  }
648  return true;
649  }
650  catch (std::exception const& e)
651  {
652  JLOG(m_journal.error()) << "LedgerMaster::getValidatedRange: "
653  "exception parsing complete ledgers: "
654  << e.what();
655  return false;
656  }
657  }
658  if (!getFullValidatedRange(minVal, maxVal))
659  return false;
660 
661  // Remove from the validated range any ledger sequences that may not be
662  // fully updated in the database yet
663 
664  auto const pendingSaves = app_.pendingSaves().getSnapshot();
665 
666  if (!pendingSaves.empty() && ((minVal != 0) || (maxVal != 0)))
667  {
668  // Ensure we shrink the tips as much as possible. If we have 7-9 and
669  // 8,9 are invalid, we don't want to see the 8 and shrink to just 9
670  // because then we'll have nothing when we could have 7.
671  while (pendingSaves.count(maxVal) > 0)
672  --maxVal;
673  while (pendingSaves.count(minVal) > 0)
674  ++minVal;
675 
676  // Best effort for remaining exclusions
677  for (auto v : pendingSaves)
678  {
679  if ((v.first >= minVal) && (v.first <= maxVal))
680  {
681  if (v.first > ((minVal + maxVal) / 2))
682  maxVal = v.first - 1;
683  else
684  minVal = v.first + 1;
685  }
686  }
687 
688  if (minVal > maxVal)
689  minVal = maxVal = 0;
690  }
691 
692  return true;
693 }
694 
695 // Get the earliest ledger we will let peers fetch
698 {
699  // The earliest ledger we will let people fetch is ledger zero,
700  // unless that creates a larger range than allowed
701  std::uint32_t e = getClosedLedger()->info().seq;
702 
703  if (e > fetch_depth_)
704  e -= fetch_depth_;
705  else
706  e = 0;
707  return e;
708 }
709 
710 void
712 {
713  std::uint32_t seq = ledger->info().seq;
714  uint256 prevHash = ledger->info().parentHash;
715 
717 
718  std::uint32_t minHas = seq;
719  std::uint32_t maxHas = seq;
720 
721  NodeStore::Database& nodeStore{app_.getNodeStore()};
722  while (!app_.getJobQueue().isStopping() && seq > 0)
723  {
724  {
726  minHas = seq;
727  --seq;
728 
729  if (haveLedger(seq))
730  break;
731  }
732 
733  auto it(ledgerHashes.find(seq));
734 
735  if (it == ledgerHashes.end())
736  {
737  if (app_.isStopping())
738  return;
739 
740  {
742  mCompleteLedgers.insert(range(minHas, maxHas));
743  }
744  maxHas = minHas;
746  (seq < 500) ? 0 : (seq - 499), seq);
747  it = ledgerHashes.find(seq);
748 
749  if (it == ledgerHashes.end())
750  break;
751 
752  if (!nodeStore.fetchNodeObject(
753  ledgerHashes.begin()->second.ledgerHash,
754  ledgerHashes.begin()->first))
755  {
756  // The ledger is not backed by the node store
757  JLOG(m_journal.warn()) << "SQL DB ledger sequence " << seq
758  << " mismatches node store";
759  break;
760  }
761  }
762 
763  if (it->second.ledgerHash != prevHash)
764  break;
765 
766  prevHash = it->second.parentHash;
767  }
768 
769  {
771  mCompleteLedgers.insert(range(minHas, maxHas));
772  }
773  {
775  mFillInProgress = 0;
776  tryAdvance();
777  }
778 }
779 
782 void
784 {
785  LedgerIndex const ledgerIndex([&]() {
786  if (reason == InboundLedger::Reason::SHARD)
787  {
788  // Do not acquire a ledger sequence greater
789  // than the last ledger in the shard
790  auto const shardStore{app_.getShardStore()};
791  auto const shardIndex{shardStore->seqToShardIndex(missing)};
792  return std::min(missing + 1, shardStore->lastLedgerSeq(shardIndex));
793  }
794  return missing + 1;
795  }());
796 
797  auto const haveHash{getLedgerHashForHistory(ledgerIndex, reason)};
798  if (!haveHash || haveHash->isZero())
799  {
800  if (reason == InboundLedger::Reason::SHARD)
801  {
802  auto const shardStore{app_.getShardStore()};
803  auto const shardIndex{shardStore->seqToShardIndex(missing)};
804  if (missing < shardStore->lastLedgerSeq(shardIndex))
805  {
806  JLOG(m_journal.error())
807  << "No hash for fetch pack. "
808  << "Missing ledger sequence " << missing
809  << " while acquiring shard " << shardIndex;
810  }
811  }
812  else
813  {
814  JLOG(m_journal.error())
815  << "No hash for fetch pack. Missing Index " << missing;
816  }
817  return;
818  }
819 
820  // Select target Peer based on highest score. The score is randomized
821  // but biased in favor of Peers with low latency.
822  std::shared_ptr<Peer> target;
823  {
824  int maxScore = 0;
825  auto peerList = app_.overlay().getActivePeers();
826  for (auto const& peer : peerList)
827  {
828  if (peer->hasRange(missing, missing + 1))
829  {
830  int score = peer->getScore(true);
831  if (!target || (score > maxScore))
832  {
833  target = peer;
834  maxScore = score;
835  }
836  }
837  }
838  }
839 
840  if (target)
841  {
842  protocol::TMGetObjectByHash tmBH;
843  tmBH.set_query(true);
844  tmBH.set_type(protocol::TMGetObjectByHash::otFETCH_PACK);
845  tmBH.set_ledgerhash(haveHash->begin(), 32);
846  auto packet = std::make_shared<Message>(tmBH, protocol::mtGET_OBJECTS);
847 
848  target->send(packet);
849  JLOG(m_journal.trace()) << "Requested fetch pack for " << missing;
850  }
851  else
852  JLOG(m_journal.debug()) << "No peer for fetch pack";
853 }
854 
855 void
857 {
858  int invalidate = 0;
860 
861  for (std::uint32_t lSeq = ledger.info().seq - 1; lSeq > 0; --lSeq)
862  {
863  if (haveLedger(lSeq))
864  {
865  try
866  {
867  hash = hashOfSeq(ledger, lSeq, m_journal);
868  }
869  catch (std::exception const& ex)
870  {
871  JLOG(m_journal.warn())
872  << "fixMismatch encounters partial ledger. Exception: "
873  << ex.what();
874  clearLedger(lSeq);
875  return;
876  }
877 
878  if (hash)
879  {
880  // try to close the seam
881  auto otherLedger = getLedgerBySeq(lSeq);
882 
883  if (otherLedger && (otherLedger->info().hash == *hash))
884  {
885  // we closed the seam
886  if (invalidate != 0)
887  {
888  JLOG(m_journal.warn())
889  << "Match at " << lSeq << ", " << invalidate
890  << " prior ledgers invalidated";
891  }
892 
893  return;
894  }
895  }
896 
897  clearLedger(lSeq);
898  ++invalidate;
899  }
900  }
901 
902  // all prior ledgers invalidated
903  if (invalidate != 0)
904  {
905  JLOG(m_journal.warn())
906  << "All " << invalidate << " prior ledgers invalidated";
907  }
908 }
909 
910 void
912  std::shared_ptr<Ledger const> const& ledger,
913  bool isSynchronous,
914  bool isCurrent)
915 {
916  // A new ledger has been accepted as part of the trusted chain
917  JLOG(m_journal.debug()) << "Ledger " << ledger->info().seq
918  << " accepted :" << ledger->info().hash;
919  assert(ledger->stateMap().getHash().isNonZero());
920 
921  ledger->setValidated();
922  ledger->setFull();
923 
924  if (isCurrent)
925  mLedgerHistory.insert(ledger, true);
926 
927  {
928  // Check the SQL database's entry for the sequence before this
929  // ledger, if it's not this ledger's parent, invalidate it
930  uint256 prevHash =
931  app_.getRelationalDatabase().getHashByIndex(ledger->info().seq - 1);
932  if (prevHash.isNonZero() && prevHash != ledger->info().parentHash)
933  clearLedger(ledger->info().seq - 1);
934  }
935 
936  pendSaveValidated(app_, ledger, isSynchronous, isCurrent);
937 
938  {
940  mCompleteLedgers.insert(ledger->info().seq);
941  }
942 
943  {
945 
946  if (ledger->info().seq > mValidLedgerSeq)
947  setValidLedger(ledger);
948  if (!mPubLedger)
949  {
950  setPubLedger(ledger);
951  app_.getOrderBookDB().setup(ledger);
952  }
953 
954  if (ledger->info().seq != 0 && haveLedger(ledger->info().seq - 1))
955  {
956  // we think we have the previous ledger, double check
957  auto prevLedger = getLedgerBySeq(ledger->info().seq - 1);
958 
959  if (!prevLedger ||
960  (prevLedger->info().hash != ledger->info().parentHash))
961  {
962  JLOG(m_journal.warn())
963  << "Acquired ledger invalidates previous ledger: "
964  << (prevLedger ? "hashMismatch" : "missingLedger");
965  fixMismatch(*ledger);
966  }
967  }
968  }
969 }
970 
971 void
973 {
974  clearLedger(seq);
976 }
977 
978 // Check if the specified ledger can become the new last fully-validated
979 // ledger.
980 void
982 {
983  std::size_t valCount = 0;
984 
985  if (seq != 0)
986  {
987  // Ledger is too old
988  if (seq < mValidLedgerSeq)
989  return;
990 
991  auto validations = app_.validators().negativeUNLFilter(
993  valCount = validations.size();
994  if (valCount >= app_.validators().quorum())
995  {
997  if (seq > mLastValidLedger.second)
998  mLastValidLedger = std::make_pair(hash, seq);
999  }
1000 
1001  if (seq == mValidLedgerSeq)
1002  return;
1003 
1004  // Ledger could match the ledger we're already building
1005  if (seq == mBuildingLedgerSeq)
1006  return;
1007  }
1008 
1009  auto ledger = mLedgerHistory.getLedgerByHash(hash);
1010 
1011  if (!ledger)
1012  {
1013  if ((seq != 0) && (getValidLedgerIndex() == 0))
1014  {
1015  // Set peers converged early if we can
1016  if (valCount >= app_.validators().quorum())
1017  app_.overlay().checkTracking(seq);
1018  }
1019 
1020  // FIXME: We may not want to fetch a ledger with just one
1021  // trusted validation
1022  ledger = app_.getInboundLedgers().acquire(
1023  hash, seq, InboundLedger::Reason::GENERIC);
1024  }
1025 
1026  if (ledger)
1027  checkAccept(ledger);
1028 }
1029 
1037 {
1038  return standalone_ ? 0 : app_.validators().quorum();
1039 }
1040 
1041 void
1043 {
1044  // Can we accept this ledger as our new last fully-validated ledger
1045 
1046  if (!canBeCurrent(ledger))
1047  return;
1048 
1049  // Can we advance the last fully-validated ledger? If so, can we
1050  // publish?
1052 
1053  if (ledger->info().seq <= mValidLedgerSeq)
1054  return;
1055 
1056  auto const minVal = getNeededValidations();
1057  auto validations = app_.validators().negativeUNLFilter(
1059  ledger->info().hash, ledger->info().seq));
1060  auto const tvc = validations.size();
1061  if (tvc < minVal) // nothing we can do
1062  {
1063  JLOG(m_journal.trace())
1064  << "Only " << tvc << " validations for " << ledger->info().hash;
1065  return;
1066  }
1067 
1068  JLOG(m_journal.info()) << "Advancing accepted ledger to "
1069  << ledger->info().seq << " with >= " << minVal
1070  << " validations";
1071 
1072  ledger->setValidated();
1073  ledger->setFull();
1074  setValidLedger(ledger);
1075  if (!mPubLedger)
1076  {
1077  pendSaveValidated(app_, ledger, true, true);
1078  setPubLedger(ledger);
1079  app_.getOrderBookDB().setup(ledger);
1080  }
1081 
1082  std::uint32_t const base = app_.getFeeTrack().getLoadBase();
1083  auto fees = app_.getValidations().fees(ledger->info().hash, base);
1084  {
1085  auto fees2 =
1086  app_.getValidations().fees(ledger->info().parentHash, base);
1087  fees.reserve(fees.size() + fees2.size());
1088  std::copy(fees2.begin(), fees2.end(), std::back_inserter(fees));
1089  }
1090  std::uint32_t fee;
1091  if (!fees.empty())
1092  {
1093  std::sort(fees.begin(), fees.end());
1094  if (auto stream = m_journal.debug())
1095  {
1097  s << "Received fees from validations: (" << fees.size() << ") ";
1098  for (auto const fee1 : fees)
1099  {
1100  s << " " << fee1;
1101  }
1102  stream << s.str();
1103  }
1104  fee = fees[fees.size() / 2]; // median
1105  }
1106  else
1107  {
1108  fee = base;
1109  }
1110 
1111  app_.getFeeTrack().setRemoteFee(fee);
1112 
1113  tryAdvance();
1114 
1115  if (ledger->seq() % 256 == 0)
1116  {
1117  // Check if the majority of validators run a higher version rippled
1118  // software. If so print a warning.
1119  //
1120  // Once the HardenedValidations amendment is enabled, validators include
1121  // their rippled software version in the validation messages of every
1122  // (flag - 1) ledger. We wait for one ledger time before checking the
1123  // version information to accumulate more validation messages.
1124 
1125  auto currentTime = app_.timeKeeper().now();
1126  bool needPrint = false;
1127 
1128  // The variable upgradeWarningPrevTime_ will be set when and only when
1129  // the warning is printed.
1131  {
1132  // Have not printed the warning before, check if need to print.
1133  auto const vals = app_.getValidations().getTrustedForLedger(
1134  ledger->info().parentHash, ledger->info().seq - 1);
1135  std::size_t higherVersionCount = 0;
1136  std::size_t rippledCount = 0;
1137  for (auto const& v : vals)
1138  {
1139  if (v->isFieldPresent(sfServerVersion))
1140  {
1141  auto version = v->getFieldU64(sfServerVersion);
1142  higherVersionCount +=
1143  BuildInfo::isNewerVersion(version) ? 1 : 0;
1144  rippledCount +=
1145  BuildInfo::isRippledVersion(version) ? 1 : 0;
1146  }
1147  }
1148  // We report only if (1) we have accumulated validation messages
1149  // from 90% validators from the UNL, (2) 60% of validators
1150  // running the rippled implementation have higher version numbers,
1151  // and (3) the calculation won't cause divide-by-zero.
1152  if (higherVersionCount > 0 && rippledCount > 0)
1153  {
1154  constexpr std::size_t reportingPercent = 90;
1155  constexpr std::size_t cutoffPercent = 60;
1156  auto const unlSize{
1157  app_.validators().getQuorumKeys().second.size()};
1158  needPrint = unlSize > 0 &&
1159  calculatePercent(vals.size(), unlSize) >=
1160  reportingPercent &&
1161  calculatePercent(higherVersionCount, rippledCount) >=
1162  cutoffPercent;
1163  }
1164  }
1165  // To throttle the warning messages, instead of printing a warning
1166  // every flag ledger, we print every week.
1167  else if (currentTime - upgradeWarningPrevTime_ >= weeks{1})
1168  {
1169  // Printed the warning before, and assuming most validators
1170  // do not downgrade, we keep printing the warning
1171  // until the local server is restarted.
1172  needPrint = true;
1173  }
1174 
1175  if (needPrint)
1176  {
1177  upgradeWarningPrevTime_ = currentTime;
1178  auto const upgradeMsg =
1179  "Check for upgrade: "
1180  "A majority of trusted validators are "
1181  "running a newer version.";
1182  std::cerr << upgradeMsg << std::endl;
1183  JLOG(m_journal.error()) << upgradeMsg;
1184  }
1185  }
1186 }
1187 
1189 void
1191  std::shared_ptr<Ledger const> const& ledger,
1192  uint256 const& consensusHash,
1193  Json::Value consensus)
1194 {
1195  // Because we just built a ledger, we are no longer building one
1196  setBuildingLedger(0);
1197 
1198  // No need to process validations in standalone mode
1199  if (standalone_)
1200  return;
1201 
1202  mLedgerHistory.builtLedger(ledger, consensusHash, std::move(consensus));
1203 
1204  if (ledger->info().seq <= mValidLedgerSeq)
1205  {
1206  auto stream = app_.journal("LedgerConsensus").info();
1207  JLOG(stream) << "Consensus built old ledger: " << ledger->info().seq
1208  << " <= " << mValidLedgerSeq;
1209  return;
1210  }
1211 
1212  // See if this ledger can be the new fully-validated ledger
1213  checkAccept(ledger);
1214 
1215  if (ledger->info().seq <= mValidLedgerSeq)
1216  {
1217  auto stream = app_.journal("LedgerConsensus").debug();
1218  JLOG(stream) << "Consensus ledger fully validated";
1219  return;
1220  }
1221 
1222  // This ledger cannot be the new fully-validated ledger, but
1223  // maybe we saved up validations for some other ledger that can be
1224 
1225  auto validations = app_.validators().negativeUNLFilter(
1227 
1228  // Track validation counts with sequence numbers
1229  class valSeq
1230  {
1231  public:
1232  valSeq() : valCount_(0), ledgerSeq_(0)
1233  {
1234  ;
1235  }
1236 
1237  void
1238  mergeValidation(LedgerIndex seq)
1239  {
1240  valCount_++;
1241 
1242  // If we didn't already know the sequence, now we do
1243  if (ledgerSeq_ == 0)
1244  ledgerSeq_ = seq;
1245  }
1246 
1247  std::size_t valCount_;
1248  LedgerIndex ledgerSeq_;
1249  };
1250 
1251  // Count the number of current, trusted validations
1253  for (auto const& v : validations)
1254  {
1255  valSeq& vs = count[v->getLedgerHash()];
1256  vs.mergeValidation(v->getFieldU32(sfLedgerSequence));
1257  }
1258 
1259  auto const neededValidations = getNeededValidations();
1260  auto maxSeq = mValidLedgerSeq.load();
1261  auto maxLedger = ledger->info().hash;
1262 
1263  // Of the ledgers with sufficient validations,
1264  // find the one with the highest sequence
1265  for (auto& v : count)
1266  if (v.second.valCount_ > neededValidations)
1267  {
1268  // If we still don't know the sequence, get it
1269  if (v.second.ledgerSeq_ == 0)
1270  {
1271  if (auto l = getLedgerByHash(v.first))
1272  v.second.ledgerSeq_ = l->info().seq;
1273  }
1274 
1275  if (v.second.ledgerSeq_ > maxSeq)
1276  {
1277  maxSeq = v.second.ledgerSeq_;
1278  maxLedger = v.first;
1279  }
1280  }
1281 
1282  if (maxSeq > mValidLedgerSeq)
1283  {
1284  auto stream = app_.journal("LedgerConsensus").debug();
1285  JLOG(stream) << "Consensus triggered check of ledger";
1286  checkAccept(maxLedger, maxSeq);
1287  }
1288 }
1289 
1292  LedgerIndex index,
1293  InboundLedger::Reason reason)
1294 {
1295  // Try to get the hash of a ledger we need to fetch for history
1297  auto const& l{
1299 
1300  if (l && l->info().seq >= index)
1301  {
1302  ret = hashOfSeq(*l, index, m_journal);
1303  if (!ret)
1304  ret = walkHashBySeq(index, l, reason);
1305  }
1306 
1307  if (!ret)
1308  ret = walkHashBySeq(index, reason);
1309 
1310  return ret;
1311 }
1312 
1316 {
1318 
1319  JLOG(m_journal.trace()) << "findNewLedgersToPublish<";
1320 
1321  // No valid ledger, nothing to do
1322  if (mValidLedger.empty())
1323  {
1324  JLOG(m_journal.trace()) << "No valid journal, nothing to publish.";
1325  return {};
1326  }
1327 
1328  if (!mPubLedger)
1329  {
1330  JLOG(m_journal.info())
1331  << "First published ledger will be " << mValidLedgerSeq;
1332  return {mValidLedger.get()};
1333  }
1334 
1336  {
1337  JLOG(m_journal.warn()) << "Gap in validated ledger stream "
1338  << mPubLedgerSeq << " - " << mValidLedgerSeq - 1;
1339 
1340  auto valLedger = mValidLedger.get();
1341  ret.push_back(valLedger);
1342  setPubLedger(valLedger);
1343  app_.getOrderBookDB().setup(valLedger);
1344 
1345  return {valLedger};
1346  }
1347 
1349  {
1350  JLOG(m_journal.trace()) << "No valid journal, nothing to publish.";
1351  return {};
1352  }
1353 
1354  int acqCount = 0;
1355 
1356  auto pubSeq = mPubLedgerSeq + 1; // Next sequence to publish
1357  auto valLedger = mValidLedger.get();
1358  std::uint32_t valSeq = valLedger->info().seq;
1359 
1360  ScopedUnlock sul{sl};
1361  try
1362  {
1363  for (std::uint32_t seq = pubSeq; seq <= valSeq; ++seq)
1364  {
1365  JLOG(m_journal.trace())
1366  << "Trying to fetch/publish valid ledger " << seq;
1367 
1369  // This can throw
1370  auto hash = hashOfSeq(*valLedger, seq, m_journal);
1371  // VFALCO TODO Restructure this code so that zero is not
1372  // used.
1373  if (!hash)
1374  hash = beast::zero; // kludge
1375  if (seq == valSeq)
1376  {
1377  // We need to publish the ledger we just fully validated
1378  ledger = valLedger;
1379  }
1380  else if (hash->isZero())
1381  {
1382  JLOG(m_journal.fatal()) << "Ledger: " << valSeq
1383  << " does not have hash for " << seq;
1384  assert(false);
1385  }
1386  else
1387  {
1388  ledger = mLedgerHistory.getLedgerByHash(*hash);
1389  }
1390 
1391  if (!app_.config().LEDGER_REPLAY)
1392  {
1393  // Can we try to acquire the ledger we need?
1394  if (!ledger && (++acqCount < ledger_fetch_size_))
1395  ledger = app_.getInboundLedgers().acquire(
1396  *hash, seq, InboundLedger::Reason::GENERIC);
1397  }
1398 
1399  // Did we acquire the next ledger we need to publish?
1400  if (ledger && (ledger->info().seq == pubSeq))
1401  {
1402  ledger->setValidated();
1403  ret.push_back(ledger);
1404  ++pubSeq;
1405  }
1406  }
1407 
1408  JLOG(m_journal.trace())
1409  << "ready to publish " << ret.size() << " ledgers.";
1410  }
1411  catch (std::exception const& ex)
1412  {
1413  JLOG(m_journal.error())
1414  << "Exception while trying to find ledgers to publish: "
1415  << ex.what();
1416  }
1417 
1418  if (app_.config().LEDGER_REPLAY)
1419  {
1420  /* Narrow down the gap of ledgers, and try to replay them.
1421  * When replaying a ledger gap, if the local node has
1422  * the start ledger, it saves an expensive InboundLedger
1423  * acquire. If the local node has the finish ledger, it
1424  * saves a skip list acquire.
1425  */
1426  auto const& startLedger = ret.empty() ? mPubLedger : ret.back();
1427  auto finishLedger = valLedger;
1428  while (startLedger->seq() + 1 < finishLedger->seq())
1429  {
1430  if (auto const parent = mLedgerHistory.getLedgerByHash(
1431  finishLedger->info().parentHash);
1432  parent)
1433  {
1434  finishLedger = parent;
1435  }
1436  else
1437  {
1438  auto numberLedgers =
1439  finishLedger->seq() - startLedger->seq() + 1;
1440  JLOG(m_journal.debug())
1441  << "Publish LedgerReplays " << numberLedgers
1442  << " ledgers, from seq=" << startLedger->info().seq << ", "
1443  << startLedger->info().hash
1444  << " to seq=" << finishLedger->info().seq << ", "
1445  << finishLedger->info().hash;
1448  finishLedger->info().hash,
1449  numberLedgers);
1450  break;
1451  }
1452  }
1453  }
1454 
1455  return ret;
1456 }
1457 
1458 void
1460 {
1462 
1463  // Can't advance without at least one fully-valid ledger
1464  mAdvanceWork = true;
1465  if (!mAdvanceThread && !mValidLedger.empty())
1466  {
1467  mAdvanceThread = true;
1468  app_.getJobQueue().addJob(jtADVANCE, "advanceLedger", [this]() {
1470 
1471  assert(!mValidLedger.empty() && mAdvanceThread);
1472 
1473  JLOG(m_journal.trace()) << "advanceThread<";
1474 
1475  try
1476  {
1477  doAdvance(sl);
1478  }
1479  catch (std::exception const& ex)
1480  {
1481  JLOG(m_journal.fatal()) << "doAdvance throws: " << ex.what();
1482  }
1483 
1484  mAdvanceThread = false;
1485  JLOG(m_journal.trace()) << "advanceThread>";
1486  });
1487  }
1488 }
1489 
1490 void
1492 {
1493  {
1496  {
1497  --mPathFindThread;
1498  JLOG(m_journal.debug()) << "Need network ledger for updating paths";
1499  return;
1500  }
1501  }
1502 
1503  while (!app_.getJobQueue().isStopping())
1504  {
1505  JLOG(m_journal.debug()) << "updatePaths running";
1507  {
1509 
1510  if (!mValidLedger.empty() &&
1511  (!mPathLedger || (mPathLedger->info().seq != mValidLedgerSeq)))
1512  { // We have a new valid ledger since the last full pathfinding
1514  lastLedger = mPathLedger;
1515  }
1516  else if (mPathFindNewRequest)
1517  { // We have a new request but no new ledger
1518  lastLedger = app_.openLedger().current();
1519  }
1520  else
1521  { // Nothing to do
1522  --mPathFindThread;
1523  JLOG(m_journal.debug()) << "Nothing to do for updating paths";
1524  return;
1525  }
1526  }
1527 
1528  if (!standalone_)
1529  { // don't pathfind with a ledger that's more than 60 seconds old
1530  using namespace std::chrono;
1531  auto age = time_point_cast<seconds>(app_.timeKeeper().closeTime()) -
1532  lastLedger->info().closeTime;
1533  if (age > 1min)
1534  {
1535  JLOG(m_journal.debug())
1536  << "Published ledger too old for updating paths";
1538  --mPathFindThread;
1539  return;
1540  }
1541  }
1542 
1543  try
1544  {
1545  auto& pathRequests = app_.getPathRequests();
1546  {
1548  if (!pathRequests.requestsPending())
1549  {
1550  --mPathFindThread;
1551  JLOG(m_journal.debug())
1552  << "No path requests found. Nothing to do for updating "
1553  "paths. "
1554  << mPathFindThread << " jobs remaining";
1555  return;
1556  }
1557  }
1558  JLOG(m_journal.debug()) << "Updating paths";
1559  pathRequests.updateAll(lastLedger);
1560 
1562  if (!pathRequests.requestsPending())
1563  {
1564  JLOG(m_journal.debug())
1565  << "No path requests left. No need for further updating "
1566  "paths";
1567  --mPathFindThread;
1568  return;
1569  }
1570  }
1571  catch (SHAMapMissingNode const& mn)
1572  {
1573  JLOG(m_journal.info()) << "During pathfinding: " << mn.what();
1574  if (lastLedger->open())
1575  {
1576  // our parent is the problem
1578  lastLedger->info().parentHash,
1579  lastLedger->info().seq - 1,
1581  }
1582  else
1583  {
1584  // this ledger is the problem
1586  lastLedger->info().hash,
1587  lastLedger->info().seq,
1589  }
1590  }
1591  }
1592 }
1593 
1594 bool
1596 {
1598  mPathFindNewRequest = newPFWork("pf:newRequest", ml);
1599  return mPathFindNewRequest;
1600 }
1601 
1602 bool
1604 {
1606  bool const ret = mPathFindNewRequest;
1607  mPathFindNewRequest = false;
1608  return ret;
1609 }
1610 
1611 // If the order book is radically updated, we need to reprocess all
1612 // pathfinding requests.
1613 bool
1615 {
1617  mPathLedger.reset();
1618 
1619  return newPFWork("pf:newOBDB", ml);
1620 }
1621 
1624 bool
1626  const char* name,
1628 {
1629  if (!app_.isStopping() && mPathFindThread < 2 &&
1631  {
1632  JLOG(m_journal.debug())
1633  << "newPFWork: Creating job. path find threads: "
1634  << mPathFindThread;
1635  if (app_.getJobQueue().addJob(
1636  jtUPDATE_PF, name, [this]() { updatePaths(); }))
1637  {
1638  ++mPathFindThread;
1639  }
1640  }
1641  // If we're stopping don't give callers the expectation that their
1642  // request will be fulfilled, even if it may be serviced.
1643  return mPathFindThread > 0 && !app_.isStopping();
1644 }
1645 
1648 {
1649  return m_mutex;
1650 }
1651 
1652 // The current ledger is the ledger we believe new transactions should go in
1655 {
1656  if (app_.config().reporting())
1657  {
1658  Throw<ReportingShouldProxy>();
1659  }
1660  return app_.openLedger().current();
1661 }
1662 
1665 {
1666 #ifdef RIPPLED_REPORTING
1667  if (app_.config().reporting())
1668  {
1670  if (!seq)
1671  return {};
1672  return getLedgerBySeq(*seq);
1673  }
1674 #endif
1675  return mValidLedger.get();
1676 }
1677 
1678 Rules
1680 {
1681  // Once we have a guarantee that there's always a last validated
1682  // ledger then we can dispense with the if.
1683 
1684  // Return the Rules from the last validated ledger.
1685  if (auto const ledger = getValidatedLedger())
1686  return ledger->rules();
1687 
1688  return Rules(app_.config().features);
1689 }
1690 
1691 // This is the last ledger we published to clients and can lag the validated
1692 // ledger.
1695 {
1696  std::lock_guard lock(m_mutex);
1697  return mPubLedger;
1698 }
1699 
1702 {
1703 #ifdef RIPPLED_REPORTING
1704  if (app_.config().reporting())
1705  return static_cast<PostgresDatabase*>(&app_.getRelationalDatabase())
1706  ->getCompleteLedgers();
1707 #endif
1709  return to_string(mCompleteLedgers);
1710 }
1711 
1714 {
1715  uint256 hash = getHashBySeq(ledgerIndex);
1716  return hash.isNonZero() ? getCloseTimeByHash(hash, ledgerIndex)
1717  : std::nullopt;
1718 }
1719 
1722  LedgerHash const& ledgerHash,
1723  std::uint32_t index)
1724 {
1725  auto nodeObject = app_.getNodeStore().fetchNodeObject(ledgerHash, index);
1726  if (nodeObject && (nodeObject->getData().size() >= 120))
1727  {
1728  SerialIter it(
1729  nodeObject->getData().data(), nodeObject->getData().size());
1730  if (safe_cast<HashPrefix>(it.get32()) == HashPrefix::ledgerMaster)
1731  {
1732  it.skip(
1733  4 + 8 + 32 + // seq drops parentHash
1734  32 + 32 + 4); // txHash acctHash parentClose
1736  }
1737  }
1738 
1739  return std::nullopt;
1740 }
1741 
1742 uint256
1744 {
1745  uint256 hash = mLedgerHistory.getLedgerHash(index);
1746 
1747  if (hash.isNonZero())
1748  return hash;
1749 
1750  return app_.getRelationalDatabase().getHashByIndex(index);
1751 }
1752 
1755 {
1756  std::optional<LedgerHash> ledgerHash;
1757 
1758  if (auto referenceLedger = mValidLedger.get())
1759  ledgerHash = walkHashBySeq(index, referenceLedger, reason);
1760 
1761  return ledgerHash;
1762 }
1763 
1766  std::uint32_t index,
1767  std::shared_ptr<ReadView const> const& referenceLedger,
1768  InboundLedger::Reason reason)
1769 {
1770  if (!referenceLedger || (referenceLedger->info().seq < index))
1771  {
1772  // Nothing we can do. No validated ledger.
1773  return std::nullopt;
1774  }
1775 
1776  // See if the hash for the ledger we need is in the reference ledger
1777  auto ledgerHash = hashOfSeq(*referenceLedger, index, m_journal);
1778  if (ledgerHash)
1779  return ledgerHash;
1780 
1781  // The hash is not in the reference ledger. Get another ledger which can
1782  // be located easily and should contain the hash.
1783  LedgerIndex refIndex = getCandidateLedger(index);
1784  auto const refHash = hashOfSeq(*referenceLedger, refIndex, m_journal);
1785  assert(refHash);
1786  if (refHash)
1787  {
1788  // Try the hash and sequence of a better reference ledger just found
1789  auto ledger = mLedgerHistory.getLedgerByHash(*refHash);
1790 
1791  if (ledger)
1792  {
1793  try
1794  {
1795  ledgerHash = hashOfSeq(*ledger, index, m_journal);
1796  }
1797  catch (SHAMapMissingNode const&)
1798  {
1799  ledger.reset();
1800  }
1801  }
1802 
1803  // Try to acquire the complete ledger
1804  if (!ledger)
1805  {
1806  if (auto const l = app_.getInboundLedgers().acquire(
1807  *refHash, refIndex, reason))
1808  {
1809  ledgerHash = hashOfSeq(*l, index, m_journal);
1810  assert(ledgerHash);
1811  }
1812  }
1813  }
1814  return ledgerHash;
1815 }
1816 
1819 {
1820  if (index <= mValidLedgerSeq)
1821  {
1822  // Always prefer a validated ledger
1823  if (auto valid = mValidLedger.get())
1824  {
1825  if (valid->info().seq == index)
1826  return valid;
1827 
1828  try
1829  {
1830  auto const hash = hashOfSeq(*valid, index, m_journal);
1831 
1832  if (hash)
1833  return mLedgerHistory.getLedgerByHash(*hash);
1834  }
1835  catch (std::exception const&)
1836  {
1837  // Missing nodes are already handled
1838  }
1839  }
1840  }
1841 
1842  if (auto ret = mLedgerHistory.getLedgerBySeq(index))
1843  return ret;
1844 
1845  auto ret = mClosedLedger.get();
1846  if (ret && (ret->info().seq == index))
1847  return ret;
1848 
1849  clearLedger(index);
1850  return {};
1851 }
1852 
1855 {
1856  if (auto ret = mLedgerHistory.getLedgerByHash(hash))
1857  return ret;
1858 
1859  auto ret = mClosedLedger.get();
1860  if (ret && (ret->info().hash == hash))
1861  return ret;
1862 
1863  return {};
1864 }
1865 
1866 void
1868 {
1870  mCompleteLedgers.insert(range(minV, maxV));
1871 }
1872 
1873 void
1875 {
1877  fetch_packs_.sweep();
1878 }
1879 
1880 float
1882 {
1884 }
1885 
1886 void
1888 {
1890  if (seq > 0)
1891  mCompleteLedgers.erase(range(0u, seq - 1));
1892 }
1893 
1894 void
1896 {
1898 }
1899 
1900 void
1902 {
1903  replayData = std::move(replay);
1904 }
1905 
1908 {
1909  return std::move(replayData);
1910 }
1911 
1912 void
1914  std::uint32_t missing,
1915  bool& progress,
1916  InboundLedger::Reason reason,
1918 {
1919  ScopedUnlock sul{sl};
1920  if (auto hash = getLedgerHashForHistory(missing, reason))
1921  {
1922  assert(hash->isNonZero());
1923  auto ledger = getLedgerByHash(*hash);
1924  if (!ledger)
1925  {
1926  if (!app_.getInboundLedgers().isFailure(*hash))
1927  {
1928  ledger =
1929  app_.getInboundLedgers().acquire(*hash, missing, reason);
1930  if (!ledger && missing != fetch_seq_ &&
1931  missing > app_.getNodeStore().earliestLedgerSeq())
1932  {
1933  JLOG(m_journal.trace())
1934  << "fetchForHistory want fetch pack " << missing;
1935  fetch_seq_ = missing;
1936  getFetchPack(missing, reason);
1937  }
1938  else
1939  JLOG(m_journal.trace())
1940  << "fetchForHistory no fetch pack for " << missing;
1941  }
1942  else
1943  JLOG(m_journal.debug())
1944  << "fetchForHistory found failed acquire";
1945  }
1946  if (ledger)
1947  {
1948  auto seq = ledger->info().seq;
1949  assert(seq == missing);
1950  JLOG(m_journal.trace()) << "fetchForHistory acquired " << seq;
1951  if (reason == InboundLedger::Reason::SHARD)
1952  {
1953  ledger->setFull();
1954  {
1955  std::lock_guard lock(m_mutex);
1956  mShardLedger = ledger;
1957  }
1958  if (!ledger->stateMap().family().isShardBacked())
1959  app_.getShardStore()->storeLedger(ledger);
1960  }
1961  else
1962  {
1963  setFullLedger(ledger, false, false);
1964  int fillInProgress;
1965  {
1966  std::lock_guard lock(m_mutex);
1967  mHistLedger = ledger;
1968  fillInProgress = mFillInProgress;
1969  }
1970  if (fillInProgress == 0 &&
1972  ledger->info().parentHash)
1973  {
1974  {
1975  // Previous ledger is in DB
1976  std::lock_guard lock(m_mutex);
1977  mFillInProgress = seq;
1978  }
1980  jtADVANCE, "tryFill", [this, ledger]() {
1981  tryFill(ledger);
1982  });
1983  }
1984  }
1985  progress = true;
1986  }
1987  else
1988  {
1989  std::uint32_t fetchSz;
1990  if (reason == InboundLedger::Reason::SHARD)
1991  // Do not fetch ledger sequences lower
1992  // than the shard's first ledger sequence
1993  fetchSz = app_.getShardStore()->firstLedgerSeq(
1994  app_.getShardStore()->seqToShardIndex(missing));
1995  else
1996  // Do not fetch ledger sequences lower
1997  // than the earliest ledger sequence
1998  fetchSz = app_.getNodeStore().earliestLedgerSeq();
1999  fetchSz = missing >= fetchSz
2000  ? std::min(ledger_fetch_size_, (missing - fetchSz) + 1)
2001  : 0;
2002  try
2003  {
2004  for (std::uint32_t i = 0; i < fetchSz; ++i)
2005  {
2006  std::uint32_t seq = missing - i;
2007  if (auto h = getLedgerHashForHistory(seq, reason))
2008  {
2009  assert(h->isNonZero());
2010  app_.getInboundLedgers().acquire(*h, seq, reason);
2011  }
2012  }
2013  }
2014  catch (std::exception const& ex)
2015  {
2016  JLOG(m_journal.warn())
2017  << "Threw while prefetching: " << ex.what();
2018  }
2019  }
2020  }
2021  else
2022  {
2023  JLOG(m_journal.fatal())
2024  << "Can't find ledger following prevMissing " << missing;
2025  JLOG(m_journal.fatal())
2026  << "Pub:" << mPubLedgerSeq << " Val:" << mValidLedgerSeq;
2027  JLOG(m_journal.fatal())
2028  << "Ledgers: " << app_.getLedgerMaster().getCompleteLedgers();
2029  JLOG(m_journal.fatal())
2030  << "Acquire reason: "
2031  << (reason == InboundLedger::Reason::HISTORY ? "HISTORY" : "SHARD");
2032  clearLedger(missing + 1);
2033  progress = true;
2034  }
2035 }
2036 
2037 // Try to publish ledgers, acquire missing ledgers
2038 void
2040 {
2041  do
2042  {
2043  mAdvanceWork = false; // If there's work to do, we'll make progress
2044  bool progress = false;
2045 
2046  auto const pubLedgers = findNewLedgersToPublish(sl);
2047  if (pubLedgers.empty())
2048  {
2049  if (!standalone_ && !app_.getFeeTrack().isLoadedLocal() &&
2054  {
2055  // We are in sync, so can acquire
2058  {
2060  missing = prevMissing(
2062  mPubLedger->info().seq,
2064  }
2065  if (missing)
2066  {
2067  JLOG(m_journal.trace())
2068  << "tryAdvance discovered missing " << *missing;
2069  if ((mFillInProgress == 0 || *missing > mFillInProgress) &&
2070  shouldAcquire(
2074  *missing,
2075  m_journal))
2076  {
2077  JLOG(m_journal.trace())
2078  << "advanceThread should acquire";
2079  }
2080  else
2081  missing = std::nullopt;
2082  }
2083  if (!missing && mFillInProgress == 0)
2084  {
2085  if (auto shardStore = app_.getShardStore())
2086  {
2087  missing = shardStore->prepareLedger(mValidLedgerSeq);
2088  if (missing)
2090  }
2091  }
2092  if (missing)
2093  {
2094  fetchForHistory(*missing, progress, reason, sl);
2096  {
2097  JLOG(m_journal.debug())
2098  << "tryAdvance found last valid changed";
2099  progress = true;
2100  }
2101  }
2102  }
2103  else
2104  {
2105  mHistLedger.reset();
2106  mShardLedger.reset();
2107  JLOG(m_journal.trace()) << "tryAdvance not fetching history";
2108  }
2109  }
2110  else
2111  {
2112  JLOG(m_journal.trace()) << "tryAdvance found " << pubLedgers.size()
2113  << " ledgers to publish";
2114  for (auto const& ledger : pubLedgers)
2115  {
2116  {
2117  ScopedUnlock sul{sl};
2118  JLOG(m_journal.debug())
2119  << "tryAdvance publishing seq " << ledger->info().seq;
2120  setFullLedger(ledger, true, true);
2121  }
2122 
2123  setPubLedger(ledger);
2124 
2125  {
2126  ScopedUnlock sul{sl};
2127  app_.getOPs().pubLedger(ledger);
2128  }
2129  }
2130 
2132  progress = newPFWork("pf:newLedger", sl);
2133  }
2134  if (progress)
2135  mAdvanceWork = true;
2136  } while (mAdvanceWork);
2137 }
2138 
2139 void
2141 {
2142  fetch_packs_.canonicalize_replace_client(hash, data);
2143 }
2144 
2147 {
2148  Blob data;
2149  if (fetch_packs_.retrieve(hash, data))
2150  {
2151  fetch_packs_.del(hash, false);
2152  if (hash == sha512Half(makeSlice(data)))
2153  return data;
2154  }
2155  return std::nullopt;
2156 }
2157 
2158 void
2160 {
2161  if (!mGotFetchPackThread.test_and_set(std::memory_order_acquire))
2162  {
2163  app_.getJobQueue().addJob(jtLEDGER_DATA, "gotFetchPack", [&]() {
2165  mGotFetchPackThread.clear(std::memory_order_release);
2166  });
2167  }
2168 }
2169 
2195 static void
2197  SHAMap const& want,
2198  SHAMap const* have,
2199  std::uint32_t cnt,
2200  protocol::TMGetObjectByHash* into,
2201  std::uint32_t seq,
2202  bool withLeaves = true)
2203 {
2204  assert(cnt != 0);
2205 
2206  Serializer s(1024);
2207 
2208  want.visitDifferences(
2209  have,
2210  [&s, withLeaves, &cnt, into, seq](SHAMapTreeNode const& n) -> bool {
2211  if (!withLeaves && n.isLeaf())
2212  return true;
2213 
2214  s.erase();
2215  n.serializeWithPrefix(s);
2216 
2217  auto const& hash = n.getHash().as_uint256();
2218 
2219  protocol::TMIndexedObject* obj = into->add_objects();
2220  obj->set_ledgerseq(seq);
2221  obj->set_hash(hash.data(), hash.size());
2222  obj->set_data(s.getDataPtr(), s.getLength());
2223 
2224  return --cnt != 0;
2225  });
2226 }
2227 
2228 void
2230  std::weak_ptr<Peer> const& wPeer,
2232  uint256 haveLedgerHash,
2233  UptimeClock::time_point uptime)
2234 {
2235  using namespace std::chrono_literals;
2236  if (UptimeClock::now() > uptime + 1s)
2237  {
2238  JLOG(m_journal.info()) << "Fetch pack request got stale";
2239  return;
2240  }
2241 
2242  if (app_.getFeeTrack().isLoadedLocal() || (getValidatedLedgerAge() > 40s))
2243  {
2244  JLOG(m_journal.info()) << "Too busy to make fetch pack";
2245  return;
2246  }
2247 
2248  auto peer = wPeer.lock();
2249 
2250  if (!peer)
2251  return;
2252 
2253  auto have = getLedgerByHash(haveLedgerHash);
2254 
2255  if (!have)
2256  {
2257  JLOG(m_journal.info())
2258  << "Peer requests fetch pack for ledger we don't have: " << have;
2259  peer->charge(Resource::feeRequestNoReply);
2260  return;
2261  }
2262 
2263  if (have->open())
2264  {
2265  JLOG(m_journal.warn())
2266  << "Peer requests fetch pack from open ledger: " << have;
2267  peer->charge(Resource::feeInvalidRequest);
2268  return;
2269  }
2270 
2271  if (have->info().seq < getEarliestFetch())
2272  {
2273  JLOG(m_journal.debug()) << "Peer requests fetch pack that is too early";
2274  peer->charge(Resource::feeInvalidRequest);
2275  return;
2276  }
2277 
2278  auto want = getLedgerByHash(have->info().parentHash);
2279 
2280  if (!want)
2281  {
2282  JLOG(m_journal.info())
2283  << "Peer requests fetch pack for ledger whose predecessor we "
2284  << "don't have: " << have;
2285  peer->charge(Resource::feeRequestNoReply);
2286  return;
2287  }
2288 
2289  try
2290  {
2291  Serializer hdr(128);
2292 
2293  protocol::TMGetObjectByHash reply;
2294  reply.set_query(false);
2295 
2296  if (request->has_seq())
2297  reply.set_seq(request->seq());
2298 
2299  reply.set_ledgerhash(request->ledgerhash());
2300  reply.set_type(protocol::TMGetObjectByHash::otFETCH_PACK);
2301 
2302  // Building a fetch pack:
2303  // 1. Add the header for the requested ledger.
2304  // 2. Add the nodes for the AccountStateMap of that ledger.
2305  // 3. If there are transactions, add the nodes for the
2306  // transactions of the ledger.
2307  // 4. If the FetchPack now contains at least 512 entries then stop.
2308  // 5. If not very much time has elapsed, then loop back and repeat
2309  // the same process adding the previous ledger to the FetchPack.
2310  do
2311  {
2312  std::uint32_t lSeq = want->info().seq;
2313 
2314  {
2315  // Serialize the ledger header:
2316  hdr.erase();
2317 
2319  addRaw(want->info(), hdr);
2320 
2321  // Add the data
2322  protocol::TMIndexedObject* obj = reply.add_objects();
2323  obj->set_hash(
2324  want->info().hash.data(), want->info().hash.size());
2325  obj->set_data(hdr.getDataPtr(), hdr.getLength());
2326  obj->set_ledgerseq(lSeq);
2327  }
2328 
2330  want->stateMap(), &have->stateMap(), 16384, &reply, lSeq);
2331 
2332  // We use nullptr here because transaction maps are per ledger
2333  // and so the requestor is unlikely to already have it.
2334  if (want->info().txHash.isNonZero())
2335  populateFetchPack(want->txMap(), nullptr, 512, &reply, lSeq);
2336 
2337  if (reply.objects().size() >= 512)
2338  break;
2339 
2340  have = std::move(want);
2341  want = getLedgerByHash(have->info().parentHash);
2342  } while (want && UptimeClock::now() <= uptime + 1s);
2343 
2344  auto msg = std::make_shared<Message>(reply, protocol::mtGET_OBJECTS);
2345 
2346  JLOG(m_journal.info())
2347  << "Built fetch pack with " << reply.objects().size() << " nodes ("
2348  << msg->getBufferSize() << " bytes)";
2349 
2350  peer->send(msg);
2351  }
2352  catch (std::exception const& ex)
2353  {
2354  JLOG(m_journal.warn())
2355  << "Exception building fetch pach. Exception: " << ex.what();
2356  }
2357 }
2358 
2361 {
2362  return fetch_packs_.getCacheSize();
2363 }
2364 
2365 // Returns the minimum ledger sequence in SQL database, if any.
2368 {
2370 }
2371 
2372 } // 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:630
ripple::LedgerMaster::mPubLedger
std::shared_ptr< Ledger const > mPubLedger
Definition: LedgerMaster.h:346
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:115
ripple::LedgerMaster::mClosedLedger
LedgerHolder mClosedLedger
Definition: LedgerMaster.h:340
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:1694
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:400
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:2229
ripple::LedgerMaster::clearLedgerCachePrior
void clearLedgerCachePrior(LedgerIndex seq)
Definition: LedgerMaster.cpp:1895
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:1874
ripple::SizedItem
SizedItem
Definition: Config.h:48
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:309
ripple::LedgerMaster::mBuildingLedgerSeq
std::atomic< LedgerIndex > mBuildingLedgerSeq
Definition: LedgerMaster.h:387
ripple::LedgerMaster::app_
Application & app_
Definition: LedgerMaster.h:334
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:360
std::atomic_flag::test_and_set
T test_and_set(T... args)
ripple::LedgerMaster::mHeldTransactions
CanonicalTXSet mHeldTransactions
Definition: LedgerMaster.h:362
ripple::Serializer::erase
void erase()
Definition: Serializer.h:209
ripple::Config::LEDGER_REPLAY
bool LEDGER_REPLAY
Definition: Config.h:228
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::addRaw
void addRaw(LedgerInfo const &info, Serializer &s, bool includeHash)
Definition: View.cpp:162
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:352
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:409
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:1907
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:1679
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:367
ripple::LedgerMaster::applyHeldTransactions
void applyHeldTransactions()
Apply held transactions to the open ledger This is normally called as we close the ledger.
Definition: LedgerMaster.cpp:549
ripple::LedgerMaster::switchLCL
void switchLCL(std::shared_ptr< Ledger const > const &lastClosed)
Definition: LedgerMaster.cpp:504
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:1625
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:1854
std::cerr
ripple::Application::isStopping
virtual bool isStopping() const =0
ripple::LedgerMaster::isNewPathRequest
bool isNewPathRequest()
Definition: LedgerMaster.cpp:1603
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::LedgerInfo::seq
LedgerIndex seq
Definition: ReadView.h:83
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:697
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:1754
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:911
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:856
std::atomic_flag::clear
T clear(T... args)
ripple::LedgerMaster::fetch_depth_
const std::uint32_t fetch_depth_
Definition: LedgerMaster.h:393
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:1701
ripple::LedgerMaster::ledger_fetch_size_
const std::uint32_t ledger_fetch_size_
Definition: LedgerMaster.h:398
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:1647
ripple::LedgerMaster::mGotFetchPackThread
std::atomic_flag mGotFetchPackThread
Definition: LedgerMaster.h:380
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:368
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:337
ripple::UptimeClock::now
static time_point now()
Definition: UptimeClock.cpp:63
ripple::LedgerMaster::mFillInProgress
int mFillInProgress
Definition: LedgerMaster.h:375
ripple::NetworkOPs::isNeedNetworkLedger
virtual bool isNeedNetworkLedger()=0
ripple::sfServerVersion
const SF_UINT64 sfServerVersion
ripple::LedgerMaster::replayData
std::unique_ptr< LedgerReplay > replayData
Definition: LedgerMaster.h:365
ripple::LedgerMaster::gotFetchPack
void gotFetchPack(bool progress, std::uint32_t seq)
Definition: LedgerMaster.cpp:2159
ripple::LedgerMaster::fetchForHistory
void fetchForHistory(std::uint32_t missing, bool &progress, InboundLedger::Reason reason, std::unique_lock< std::recursive_mutex > &)
Definition: LedgerMaster.cpp:1913
ripple::LedgerMaster::getFetchPack
std::optional< Blob > getFetchPack(uint256 const &hash) override
Retrieves partial ledger data of the coresponding hash from peers.
Definition: LedgerMaster.cpp:2146
ripple::LedgerMaster::failedSave
void failedSave(std::uint32_t seq, uint256 const &hash)
Definition: LedgerMaster.cpp:972
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:189
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:603
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:530
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:2196
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:436
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:588
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:194
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: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:219
std::chrono::time_point
ripple::LedgerMaster::minSqlSeq
std::optional< LedgerIndex > minSqlSeq()
Definition: LedgerMaster.cpp:2367
ripple::LedgerMaster::updatePaths
void updatePaths()
Definition: LedgerMaster.cpp:1491
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:37
std::copy
T copy(T... args)
ripple::LedgerMaster::getLedgerBySeq
std::shared_ptr< Ledger const > getLedgerBySeq(std::uint32_t index)
Definition: LedgerMaster.cpp:1818
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:1595
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:425
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:378
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: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:182
ripple::LedgerMaster::getCurrentLedger
std::shared_ptr< ReadView const > getCurrentLedger()
Definition: LedgerMaster.cpp:1654
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:1614
ripple::LedgerMaster::getNeededValidations
std::size_t getNeededValidations()
Determines how many validations are needed to fully validate a ledger.
Definition: LedgerMaster.cpp:1036
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:1954
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:371
ripple::LedgerMaster::checkAccept
void checkAccept(std::shared_ptr< Ledger const > const &ledger)
Definition: LedgerMaster.cpp:1042
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:406
ripple::Serializer
Definition: Serializer.h:39
ripple::LedgerMaster::getFetchPackCacheSize
std::size_t getFetchPackCacheSize() const
Definition: LedgerMaster.cpp:2360
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:349
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:374
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:125
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:282
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:383
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:396
ripple::LedgerMaster::mPubLedgerSeq
std::atomic< LedgerIndex > mPubLedgerSeq
Definition: LedgerMaster.h:384
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:1713
limits
ripple::LedgerMaster::addFetchPack
void addFetchPack(uint256 const &hash, std::shared_ptr< Blob > data)
Definition: LedgerMaster.cpp:2140
ripple::LedgerMaster::clearLedger
void clearLedger(std::uint32_t seq)
Definition: LedgerMaster.cpp:595
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:1291
ripple::LedgerMaster::m_journal
beast::Journal m_journal
Definition: LedgerMaster.h:335
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:386
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:1901
ripple::LedgerMaster::getValidatedLedger
std::shared_ptr< Ledger const > getValidatedLedger()
Definition: LedgerMaster.cpp:1664
ripple::LedgerMaster::mLastValidLedger
std::pair< uint256, LedgerIndex > mLastValidLedger
Definition: LedgerMaster.h:358
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
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:355
beast::Journal::debug
Stream debug() const
Definition: Journal.h:315
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:536
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:1867
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:199
ripple::getCandidateLedger
LedgerIndex getCandidateLedger(LedgerIndex requested)
Find a ledger index from which we could easily get the requested ledger.
Definition: View.h:219
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:1190
ripple::LedgerMaster::tryFill
void tryFill(std::shared_ptr< Ledger const > ledger)
Definition: LedgerMaster.cpp:711
ripple::SerialIter::get32
std::uint32_t get32()
Definition: Serializer.cpp:386
ripple::LedgerMaster::mValidLedger
LedgerHolder mValidLedger
Definition: LedgerMaster.h:343
ripple::LedgerMaster::fetch_seq_
std::uint32_t fetch_seq_
Definition: LedgerMaster.h:402
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:1743
ripple::LedgerMaster::findNewLedgersToPublish
std::vector< std::shared_ptr< Ledger const > > findNewLedgersToPublish(std::unique_lock< std::recursive_mutex > &)
Definition: LedgerMaster.cpp:1314
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:1721
ripple::LedgerMaster::mPathFindThread
int mPathFindThread
Definition: LedgerMaster.h:377
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:385
ripple::LedgerMaster::setBuildingLedger
void setBuildingLedger(LedgerIndex index)
Definition: LedgerMaster.cpp:582
ripple::LedgerMaster::doAdvance
void doAdvance(std::unique_lock< std::recursive_mutex > &)
Definition: LedgerMaster.cpp:2039
std::unordered_map
STL class.
ripple::LedgerMaster::tryAdvance
void tryAdvance()
Definition: LedgerMaster.cpp:1459
ripple::LedgerMaster::clearPriorLedgers
void clearPriorLedgers(LedgerIndex seq)
Definition: LedgerMaster.cpp:1887
ripple::LedgerMaster::setPubLedger
void setPubLedger(std::shared_ptr< Ledger const > const &l)
Definition: LedgerMaster.cpp:417
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:574
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:1881
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:337
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:435
ripple::LedgerMaster::standalone_
const bool standalone_
Definition: LedgerMaster.h:390
std::chrono