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&)
870  {
871  JLOG(m_journal.warn())
872  << "fixMismatch encounters partial ledger";
873  clearLedger(lSeq);
874  return;
875  }
876 
877  if (hash)
878  {
879  // try to close the seam
880  auto otherLedger = getLedgerBySeq(lSeq);
881 
882  if (otherLedger && (otherLedger->info().hash == *hash))
883  {
884  // we closed the seam
885  if (invalidate != 0)
886  {
887  JLOG(m_journal.warn())
888  << "Match at " << lSeq << ", " << invalidate
889  << " prior ledgers invalidated";
890  }
891 
892  return;
893  }
894  }
895 
896  clearLedger(lSeq);
897  ++invalidate;
898  }
899  }
900 
901  // all prior ledgers invalidated
902  if (invalidate != 0)
903  {
904  JLOG(m_journal.warn())
905  << "All " << invalidate << " prior ledgers invalidated";
906  }
907 }
908 
909 void
911  std::shared_ptr<Ledger const> const& ledger,
912  bool isSynchronous,
913  bool isCurrent)
914 {
915  // A new ledger has been accepted as part of the trusted chain
916  JLOG(m_journal.debug()) << "Ledger " << ledger->info().seq
917  << " accepted :" << ledger->info().hash;
918  assert(ledger->stateMap().getHash().isNonZero());
919 
920  ledger->setValidated();
921  ledger->setFull();
922 
923  if (isCurrent)
924  mLedgerHistory.insert(ledger, true);
925 
926  {
927  // Check the SQL database's entry for the sequence before this
928  // ledger, if it's not this ledger's parent, invalidate it
929  uint256 prevHash =
930  app_.getRelationalDatabase().getHashByIndex(ledger->info().seq - 1);
931  if (prevHash.isNonZero() && prevHash != ledger->info().parentHash)
932  clearLedger(ledger->info().seq - 1);
933  }
934 
935  pendSaveValidated(app_, ledger, isSynchronous, isCurrent);
936 
937  {
939  mCompleteLedgers.insert(ledger->info().seq);
940  }
941 
942  {
944 
945  if (ledger->info().seq > mValidLedgerSeq)
946  setValidLedger(ledger);
947  if (!mPubLedger)
948  {
949  setPubLedger(ledger);
950  app_.getOrderBookDB().setup(ledger);
951  }
952 
953  if (ledger->info().seq != 0 && haveLedger(ledger->info().seq - 1))
954  {
955  // we think we have the previous ledger, double check
956  auto prevLedger = getLedgerBySeq(ledger->info().seq - 1);
957 
958  if (!prevLedger ||
959  (prevLedger->info().hash != ledger->info().parentHash))
960  {
961  JLOG(m_journal.warn())
962  << "Acquired ledger invalidates previous ledger: "
963  << (prevLedger ? "hashMismatch" : "missingLedger");
964  fixMismatch(*ledger);
965  }
966  }
967  }
968 }
969 
970 void
972 {
973  clearLedger(seq);
975 }
976 
977 // Check if the specified ledger can become the new last fully-validated
978 // ledger.
979 void
981 {
982  std::size_t valCount = 0;
983 
984  if (seq != 0)
985  {
986  // Ledger is too old
987  if (seq < mValidLedgerSeq)
988  return;
989 
990  auto validations = app_.validators().negativeUNLFilter(
992  valCount = validations.size();
993  if (valCount >= app_.validators().quorum())
994  {
996  if (seq > mLastValidLedger.second)
997  mLastValidLedger = std::make_pair(hash, seq);
998  }
999 
1000  if (seq == mValidLedgerSeq)
1001  return;
1002 
1003  // Ledger could match the ledger we're already building
1004  if (seq == mBuildingLedgerSeq)
1005  return;
1006  }
1007 
1008  auto ledger = mLedgerHistory.getLedgerByHash(hash);
1009 
1010  if (!ledger)
1011  {
1012  if ((seq != 0) && (getValidLedgerIndex() == 0))
1013  {
1014  // Set peers converged early if we can
1015  if (valCount >= app_.validators().quorum())
1016  app_.overlay().checkTracking(seq);
1017  }
1018 
1019  // FIXME: We may not want to fetch a ledger with just one
1020  // trusted validation
1021  ledger = app_.getInboundLedgers().acquire(
1022  hash, seq, InboundLedger::Reason::GENERIC);
1023  }
1024 
1025  if (ledger)
1026  checkAccept(ledger);
1027 }
1028 
1036 {
1037  return standalone_ ? 0 : app_.validators().quorum();
1038 }
1039 
1040 void
1042 {
1043  // Can we accept this ledger as our new last fully-validated ledger
1044 
1045  if (!canBeCurrent(ledger))
1046  return;
1047 
1048  // Can we advance the last fully-validated ledger? If so, can we
1049  // publish?
1051 
1052  if (ledger->info().seq <= mValidLedgerSeq)
1053  return;
1054 
1055  auto const minVal = getNeededValidations();
1056  auto validations = app_.validators().negativeUNLFilter(
1058  ledger->info().hash, ledger->info().seq));
1059  auto const tvc = validations.size();
1060  if (tvc < minVal) // nothing we can do
1061  {
1062  JLOG(m_journal.trace())
1063  << "Only " << tvc << " validations for " << ledger->info().hash;
1064  return;
1065  }
1066 
1067  JLOG(m_journal.info()) << "Advancing accepted ledger to "
1068  << ledger->info().seq << " with >= " << minVal
1069  << " validations";
1070 
1071  ledger->setValidated();
1072  ledger->setFull();
1073  setValidLedger(ledger);
1074  if (!mPubLedger)
1075  {
1076  pendSaveValidated(app_, ledger, true, true);
1077  setPubLedger(ledger);
1078  app_.getOrderBookDB().setup(ledger);
1079  }
1080 
1081  std::uint32_t const base = app_.getFeeTrack().getLoadBase();
1082  auto fees = app_.getValidations().fees(ledger->info().hash, base);
1083  {
1084  auto fees2 =
1085  app_.getValidations().fees(ledger->info().parentHash, base);
1086  fees.reserve(fees.size() + fees2.size());
1087  std::copy(fees2.begin(), fees2.end(), std::back_inserter(fees));
1088  }
1089  std::uint32_t fee;
1090  if (!fees.empty())
1091  {
1092  std::sort(fees.begin(), fees.end());
1093  if (auto stream = m_journal.debug())
1094  {
1096  s << "Received fees from validations: (" << fees.size() << ") ";
1097  for (auto const fee1 : fees)
1098  {
1099  s << " " << fee1;
1100  }
1101  stream << s.str();
1102  }
1103  fee = fees[fees.size() / 2]; // median
1104  }
1105  else
1106  {
1107  fee = base;
1108  }
1109 
1110  app_.getFeeTrack().setRemoteFee(fee);
1111 
1112  tryAdvance();
1113 
1114  if (ledger->seq() % 256 == 0)
1115  {
1116  // Check if the majority of validators run a higher version rippled
1117  // software. If so print a warning.
1118  //
1119  // Once the HardenedValidations amendment is enabled, validators include
1120  // their rippled software version in the validation messages of every
1121  // (flag - 1) ledger. We wait for one ledger time before checking the
1122  // version information to accumulate more validation messages.
1123 
1124  auto currentTime = app_.timeKeeper().now();
1125  bool needPrint = false;
1126 
1127  // The variable upgradeWarningPrevTime_ will be set when and only when
1128  // the warning is printed.
1130  {
1131  // Have not printed the warning before, check if need to print.
1132  auto const vals = app_.getValidations().getTrustedForLedger(
1133  ledger->info().parentHash, ledger->info().seq - 1);
1134  std::size_t higherVersionCount = 0;
1135  std::size_t rippledCount = 0;
1136  for (auto const& v : vals)
1137  {
1138  if (v->isFieldPresent(sfServerVersion))
1139  {
1140  auto version = v->getFieldU64(sfServerVersion);
1141  higherVersionCount +=
1142  BuildInfo::isNewerVersion(version) ? 1 : 0;
1143  rippledCount +=
1144  BuildInfo::isRippledVersion(version) ? 1 : 0;
1145  }
1146  }
1147  // We report only if (1) we have accumulated validation messages
1148  // from 90% validators from the UNL, (2) 60% of validators
1149  // running the rippled implementation have higher version numbers,
1150  // and (3) the calculation won't cause divide-by-zero.
1151  if (higherVersionCount > 0 && rippledCount > 0)
1152  {
1153  constexpr std::size_t reportingPercent = 90;
1154  constexpr std::size_t cutoffPercent = 60;
1155  auto const unlSize{
1156  app_.validators().getQuorumKeys().second.size()};
1157  needPrint = unlSize > 0 &&
1158  calculatePercent(vals.size(), unlSize) >=
1159  reportingPercent &&
1160  calculatePercent(higherVersionCount, rippledCount) >=
1161  cutoffPercent;
1162  }
1163  }
1164  // To throttle the warning messages, instead of printing a warning
1165  // every flag ledger, we print every week.
1166  else if (currentTime - upgradeWarningPrevTime_ >= weeks{1})
1167  {
1168  // Printed the warning before, and assuming most validators
1169  // do not downgrade, we keep printing the warning
1170  // until the local server is restarted.
1171  needPrint = true;
1172  }
1173 
1174  if (needPrint)
1175  {
1176  upgradeWarningPrevTime_ = currentTime;
1177  auto const upgradeMsg =
1178  "Check for upgrade: "
1179  "A majority of trusted validators are "
1180  "running a newer version.";
1181  std::cerr << upgradeMsg << std::endl;
1182  JLOG(m_journal.error()) << upgradeMsg;
1183  }
1184  }
1185 }
1186 
1188 void
1190  std::shared_ptr<Ledger const> const& ledger,
1191  uint256 const& consensusHash,
1192  Json::Value consensus)
1193 {
1194  // Because we just built a ledger, we are no longer building one
1195  setBuildingLedger(0);
1196 
1197  // No need to process validations in standalone mode
1198  if (standalone_)
1199  return;
1200 
1201  mLedgerHistory.builtLedger(ledger, consensusHash, std::move(consensus));
1202 
1203  if (ledger->info().seq <= mValidLedgerSeq)
1204  {
1205  auto stream = app_.journal("LedgerConsensus").info();
1206  JLOG(stream) << "Consensus built old ledger: " << ledger->info().seq
1207  << " <= " << mValidLedgerSeq;
1208  return;
1209  }
1210 
1211  // See if this ledger can be the new fully-validated ledger
1212  checkAccept(ledger);
1213 
1214  if (ledger->info().seq <= mValidLedgerSeq)
1215  {
1216  auto stream = app_.journal("LedgerConsensus").debug();
1217  JLOG(stream) << "Consensus ledger fully validated";
1218  return;
1219  }
1220 
1221  // This ledger cannot be the new fully-validated ledger, but
1222  // maybe we saved up validations for some other ledger that can be
1223 
1224  auto validations = app_.validators().negativeUNLFilter(
1226 
1227  // Track validation counts with sequence numbers
1228  class valSeq
1229  {
1230  public:
1231  valSeq() : valCount_(0), ledgerSeq_(0)
1232  {
1233  ;
1234  }
1235 
1236  void
1237  mergeValidation(LedgerIndex seq)
1238  {
1239  valCount_++;
1240 
1241  // If we didn't already know the sequence, now we do
1242  if (ledgerSeq_ == 0)
1243  ledgerSeq_ = seq;
1244  }
1245 
1246  std::size_t valCount_;
1247  LedgerIndex ledgerSeq_;
1248  };
1249 
1250  // Count the number of current, trusted validations
1252  for (auto const& v : validations)
1253  {
1254  valSeq& vs = count[v->getLedgerHash()];
1255  vs.mergeValidation(v->getFieldU32(sfLedgerSequence));
1256  }
1257 
1258  auto const neededValidations = getNeededValidations();
1259  auto maxSeq = mValidLedgerSeq.load();
1260  auto maxLedger = ledger->info().hash;
1261 
1262  // Of the ledgers with sufficient validations,
1263  // find the one with the highest sequence
1264  for (auto& v : count)
1265  if (v.second.valCount_ > neededValidations)
1266  {
1267  // If we still don't know the sequence, get it
1268  if (v.second.ledgerSeq_ == 0)
1269  {
1270  if (auto l = getLedgerByHash(v.first))
1271  v.second.ledgerSeq_ = l->info().seq;
1272  }
1273 
1274  if (v.second.ledgerSeq_ > maxSeq)
1275  {
1276  maxSeq = v.second.ledgerSeq_;
1277  maxLedger = v.first;
1278  }
1279  }
1280 
1281  if (maxSeq > mValidLedgerSeq)
1282  {
1283  auto stream = app_.journal("LedgerConsensus").debug();
1284  JLOG(stream) << "Consensus triggered check of ledger";
1285  checkAccept(maxLedger, maxSeq);
1286  }
1287 }
1288 
1291  LedgerIndex index,
1292  InboundLedger::Reason reason)
1293 {
1294  // Try to get the hash of a ledger we need to fetch for history
1296  auto const& l{
1298 
1299  if (l && l->info().seq >= index)
1300  {
1301  ret = hashOfSeq(*l, index, m_journal);
1302  if (!ret)
1303  ret = walkHashBySeq(index, l, reason);
1304  }
1305 
1306  if (!ret)
1307  ret = walkHashBySeq(index, reason);
1308 
1309  return ret;
1310 }
1311 
1315 {
1317 
1318  JLOG(m_journal.trace()) << "findNewLedgersToPublish<";
1319 
1320  // No valid ledger, nothing to do
1321  if (mValidLedger.empty())
1322  {
1323  JLOG(m_journal.trace()) << "No valid journal, nothing to publish.";
1324  return {};
1325  }
1326 
1327  if (!mPubLedger)
1328  {
1329  JLOG(m_journal.info())
1330  << "First published ledger will be " << mValidLedgerSeq;
1331  return {mValidLedger.get()};
1332  }
1333 
1335  {
1336  JLOG(m_journal.warn()) << "Gap in validated ledger stream "
1337  << mPubLedgerSeq << " - " << mValidLedgerSeq - 1;
1338 
1339  auto valLedger = mValidLedger.get();
1340  ret.push_back(valLedger);
1341  setPubLedger(valLedger);
1342  app_.getOrderBookDB().setup(valLedger);
1343 
1344  return {valLedger};
1345  }
1346 
1348  {
1349  JLOG(m_journal.trace()) << "No valid journal, nothing to publish.";
1350  return {};
1351  }
1352 
1353  int acqCount = 0;
1354 
1355  auto pubSeq = mPubLedgerSeq + 1; // Next sequence to publish
1356  auto valLedger = mValidLedger.get();
1357  std::uint32_t valSeq = valLedger->info().seq;
1358 
1359  ScopedUnlock sul{sl};
1360  try
1361  {
1362  for (std::uint32_t seq = pubSeq; seq <= valSeq; ++seq)
1363  {
1364  JLOG(m_journal.trace())
1365  << "Trying to fetch/publish valid ledger " << seq;
1366 
1368  // This can throw
1369  auto hash = hashOfSeq(*valLedger, seq, m_journal);
1370  // VFALCO TODO Restructure this code so that zero is not
1371  // used.
1372  if (!hash)
1373  hash = beast::zero; // kludge
1374  if (seq == valSeq)
1375  {
1376  // We need to publish the ledger we just fully validated
1377  ledger = valLedger;
1378  }
1379  else if (hash->isZero())
1380  {
1381  JLOG(m_journal.fatal()) << "Ledger: " << valSeq
1382  << " does not have hash for " << seq;
1383  assert(false);
1384  }
1385  else
1386  {
1387  ledger = mLedgerHistory.getLedgerByHash(*hash);
1388  }
1389 
1390  if (!app_.config().LEDGER_REPLAY)
1391  {
1392  // Can we try to acquire the ledger we need?
1393  if (!ledger && (++acqCount < ledger_fetch_size_))
1394  ledger = app_.getInboundLedgers().acquire(
1395  *hash, seq, InboundLedger::Reason::GENERIC);
1396  }
1397 
1398  // Did we acquire the next ledger we need to publish?
1399  if (ledger && (ledger->info().seq == pubSeq))
1400  {
1401  ledger->setValidated();
1402  ret.push_back(ledger);
1403  ++pubSeq;
1404  }
1405  }
1406 
1407  JLOG(m_journal.trace())
1408  << "ready to publish " << ret.size() << " ledgers.";
1409  }
1410  catch (std::exception const&)
1411  {
1412  JLOG(m_journal.error())
1413  << "Exception while trying to find ledgers to publish.";
1414  }
1415 
1416  if (app_.config().LEDGER_REPLAY)
1417  {
1418  /* Narrow down the gap of ledgers, and try to replay them.
1419  * When replaying a ledger gap, if the local node has
1420  * the start ledger, it saves an expensive InboundLedger
1421  * acquire. If the local node has the finish ledger, it
1422  * saves a skip list acquire.
1423  */
1424  auto const& startLedger = ret.empty() ? mPubLedger : ret.back();
1425  auto finishLedger = valLedger;
1426  while (startLedger->seq() + 1 < finishLedger->seq())
1427  {
1428  if (auto const parent = mLedgerHistory.getLedgerByHash(
1429  finishLedger->info().parentHash);
1430  parent)
1431  {
1432  finishLedger = parent;
1433  }
1434  else
1435  {
1436  auto numberLedgers =
1437  finishLedger->seq() - startLedger->seq() + 1;
1438  JLOG(m_journal.debug())
1439  << "Publish LedgerReplays " << numberLedgers
1440  << " ledgers, from seq=" << startLedger->info().seq << ", "
1441  << startLedger->info().hash
1442  << " to seq=" << finishLedger->info().seq << ", "
1443  << finishLedger->info().hash;
1446  finishLedger->info().hash,
1447  numberLedgers);
1448  break;
1449  }
1450  }
1451  }
1452 
1453  return ret;
1454 }
1455 
1456 void
1458 {
1460 
1461  // Can't advance without at least one fully-valid ledger
1462  mAdvanceWork = true;
1463  if (!mAdvanceThread && !mValidLedger.empty())
1464  {
1465  mAdvanceThread = true;
1466  app_.getJobQueue().addJob(jtADVANCE, "advanceLedger", [this]() {
1468 
1469  assert(!mValidLedger.empty() && mAdvanceThread);
1470 
1471  JLOG(m_journal.trace()) << "advanceThread<";
1472 
1473  try
1474  {
1475  doAdvance(sl);
1476  }
1477  catch (std::exception const& ex)
1478  {
1479  JLOG(m_journal.fatal()) << "doAdvance throws: " << ex.what();
1480  }
1481 
1482  mAdvanceThread = false;
1483  JLOG(m_journal.trace()) << "advanceThread>";
1484  });
1485  }
1486 }
1487 
1488 void
1490 {
1491  {
1494  {
1495  --mPathFindThread;
1496  JLOG(m_journal.debug()) << "Need network ledger for updating paths";
1497  return;
1498  }
1499  }
1500 
1501  while (!app_.getJobQueue().isStopping())
1502  {
1503  JLOG(m_journal.debug()) << "updatePaths running";
1505  {
1507 
1508  if (!mValidLedger.empty() &&
1509  (!mPathLedger || (mPathLedger->info().seq != mValidLedgerSeq)))
1510  { // We have a new valid ledger since the last full pathfinding
1512  lastLedger = mPathLedger;
1513  }
1514  else if (mPathFindNewRequest)
1515  { // We have a new request but no new ledger
1516  lastLedger = app_.openLedger().current();
1517  }
1518  else
1519  { // Nothing to do
1520  --mPathFindThread;
1521  JLOG(m_journal.debug()) << "Nothing to do for updating paths";
1522  return;
1523  }
1524  }
1525 
1526  if (!standalone_)
1527  { // don't pathfind with a ledger that's more than 60 seconds old
1528  using namespace std::chrono;
1529  auto age = time_point_cast<seconds>(app_.timeKeeper().closeTime()) -
1530  lastLedger->info().closeTime;
1531  if (age > 1min)
1532  {
1533  JLOG(m_journal.debug())
1534  << "Published ledger too old for updating paths";
1536  --mPathFindThread;
1537  return;
1538  }
1539  }
1540 
1541  try
1542  {
1543  auto& pathRequests = app_.getPathRequests();
1544  {
1546  if (!pathRequests.requestsPending())
1547  {
1548  --mPathFindThread;
1549  JLOG(m_journal.debug())
1550  << "No path requests found. Nothing to do for updating "
1551  "paths. "
1552  << mPathFindThread << " jobs remaining";
1553  return;
1554  }
1555  }
1556  JLOG(m_journal.debug()) << "Updating paths";
1557  pathRequests.updateAll(lastLedger);
1558 
1560  if (!pathRequests.requestsPending())
1561  {
1562  JLOG(m_journal.debug())
1563  << "No path requests left. No need for further updating "
1564  "paths";
1565  --mPathFindThread;
1566  return;
1567  }
1568  }
1569  catch (SHAMapMissingNode const& mn)
1570  {
1571  JLOG(m_journal.info()) << "During pathfinding: " << mn.what();
1572  if (lastLedger->open())
1573  {
1574  // our parent is the problem
1576  lastLedger->info().parentHash,
1577  lastLedger->info().seq - 1,
1579  }
1580  else
1581  {
1582  // this ledger is the problem
1584  lastLedger->info().hash,
1585  lastLedger->info().seq,
1587  }
1588  }
1589  }
1590 }
1591 
1592 bool
1594 {
1596  mPathFindNewRequest = newPFWork("pf:newRequest", ml);
1597  return mPathFindNewRequest;
1598 }
1599 
1600 bool
1602 {
1604  bool const ret = mPathFindNewRequest;
1605  mPathFindNewRequest = false;
1606  return ret;
1607 }
1608 
1609 // If the order book is radically updated, we need to reprocess all
1610 // pathfinding requests.
1611 bool
1613 {
1615  mPathLedger.reset();
1616 
1617  return newPFWork("pf:newOBDB", ml);
1618 }
1619 
1622 bool
1624  const char* name,
1626 {
1627  if (!app_.isStopping() && mPathFindThread < 2 &&
1629  {
1630  JLOG(m_journal.debug())
1631  << "newPFWork: Creating job. path find threads: "
1632  << mPathFindThread;
1633  if (app_.getJobQueue().addJob(
1634  jtUPDATE_PF, name, [this]() { updatePaths(); }))
1635  {
1636  ++mPathFindThread;
1637  }
1638  }
1639  // If we're stopping don't give callers the expectation that their
1640  // request will be fulfilled, even if it may be serviced.
1641  return mPathFindThread > 0 && !app_.isStopping();
1642 }
1643 
1646 {
1647  return m_mutex;
1648 }
1649 
1650 // The current ledger is the ledger we believe new transactions should go in
1653 {
1654  if (app_.config().reporting())
1655  {
1656  Throw<ReportingShouldProxy>();
1657  }
1658  return app_.openLedger().current();
1659 }
1660 
1663 {
1664 #ifdef RIPPLED_REPORTING
1665  if (app_.config().reporting())
1666  {
1668  if (!seq)
1669  return {};
1670  return getLedgerBySeq(*seq);
1671  }
1672 #endif
1673  return mValidLedger.get();
1674 }
1675 
1676 Rules
1678 {
1679  // Once we have a guarantee that there's always a last validated
1680  // ledger then we can dispense with the if.
1681 
1682  // Return the Rules from the last validated ledger.
1683  if (auto const ledger = getValidatedLedger())
1684  return ledger->rules();
1685 
1686  return Rules(app_.config().features);
1687 }
1688 
1689 // This is the last ledger we published to clients and can lag the validated
1690 // ledger.
1693 {
1694  std::lock_guard lock(m_mutex);
1695  return mPubLedger;
1696 }
1697 
1700 {
1701 #ifdef RIPPLED_REPORTING
1702  if (app_.config().reporting())
1703  return static_cast<PostgresDatabase*>(&app_.getRelationalDatabase())
1704  ->getCompleteLedgers();
1705 #endif
1707  return to_string(mCompleteLedgers);
1708 }
1709 
1712 {
1713  uint256 hash = getHashBySeq(ledgerIndex);
1714  return hash.isNonZero() ? getCloseTimeByHash(hash, ledgerIndex)
1715  : std::nullopt;
1716 }
1717 
1720  LedgerHash const& ledgerHash,
1721  std::uint32_t index)
1722 {
1723  auto nodeObject = app_.getNodeStore().fetchNodeObject(ledgerHash, index);
1724  if (nodeObject && (nodeObject->getData().size() >= 120))
1725  {
1726  SerialIter it(
1727  nodeObject->getData().data(), nodeObject->getData().size());
1728  if (safe_cast<HashPrefix>(it.get32()) == HashPrefix::ledgerMaster)
1729  {
1730  it.skip(
1731  4 + 8 + 32 + // seq drops parentHash
1732  32 + 32 + 4); // txHash acctHash parentClose
1734  }
1735  }
1736 
1737  return std::nullopt;
1738 }
1739 
1740 uint256
1742 {
1743  uint256 hash = mLedgerHistory.getLedgerHash(index);
1744 
1745  if (hash.isNonZero())
1746  return hash;
1747 
1748  return app_.getRelationalDatabase().getHashByIndex(index);
1749 }
1750 
1753 {
1754  std::optional<LedgerHash> ledgerHash;
1755 
1756  if (auto referenceLedger = mValidLedger.get())
1757  ledgerHash = walkHashBySeq(index, referenceLedger, reason);
1758 
1759  return ledgerHash;
1760 }
1761 
1764  std::uint32_t index,
1765  std::shared_ptr<ReadView const> const& referenceLedger,
1766  InboundLedger::Reason reason)
1767 {
1768  if (!referenceLedger || (referenceLedger->info().seq < index))
1769  {
1770  // Nothing we can do. No validated ledger.
1771  return std::nullopt;
1772  }
1773 
1774  // See if the hash for the ledger we need is in the reference ledger
1775  auto ledgerHash = hashOfSeq(*referenceLedger, index, m_journal);
1776  if (ledgerHash)
1777  return ledgerHash;
1778 
1779  // The hash is not in the reference ledger. Get another ledger which can
1780  // be located easily and should contain the hash.
1781  LedgerIndex refIndex = getCandidateLedger(index);
1782  auto const refHash = hashOfSeq(*referenceLedger, refIndex, m_journal);
1783  assert(refHash);
1784  if (refHash)
1785  {
1786  // Try the hash and sequence of a better reference ledger just found
1787  auto ledger = mLedgerHistory.getLedgerByHash(*refHash);
1788 
1789  if (ledger)
1790  {
1791  try
1792  {
1793  ledgerHash = hashOfSeq(*ledger, index, m_journal);
1794  }
1795  catch (SHAMapMissingNode const&)
1796  {
1797  ledger.reset();
1798  }
1799  }
1800 
1801  // Try to acquire the complete ledger
1802  if (!ledger)
1803  {
1804  if (auto const l = app_.getInboundLedgers().acquire(
1805  *refHash, refIndex, reason))
1806  {
1807  ledgerHash = hashOfSeq(*l, index, m_journal);
1808  assert(ledgerHash);
1809  }
1810  }
1811  }
1812  return ledgerHash;
1813 }
1814 
1817 {
1818  if (index <= mValidLedgerSeq)
1819  {
1820  // Always prefer a validated ledger
1821  if (auto valid = mValidLedger.get())
1822  {
1823  if (valid->info().seq == index)
1824  return valid;
1825 
1826  try
1827  {
1828  auto const hash = hashOfSeq(*valid, index, m_journal);
1829 
1830  if (hash)
1831  return mLedgerHistory.getLedgerByHash(*hash);
1832  }
1833  catch (std::exception const&)
1834  {
1835  // Missing nodes are already handled
1836  }
1837  }
1838  }
1839 
1840  if (auto ret = mLedgerHistory.getLedgerBySeq(index))
1841  return ret;
1842 
1843  auto ret = mClosedLedger.get();
1844  if (ret && (ret->info().seq == index))
1845  return ret;
1846 
1847  clearLedger(index);
1848  return {};
1849 }
1850 
1853 {
1854  if (auto ret = mLedgerHistory.getLedgerByHash(hash))
1855  return ret;
1856 
1857  auto ret = mClosedLedger.get();
1858  if (ret && (ret->info().hash == hash))
1859  return ret;
1860 
1861  return {};
1862 }
1863 
1864 void
1866 {
1868  mCompleteLedgers.insert(range(minV, maxV));
1869 }
1870 
1871 void
1873 {
1875  fetch_packs_.sweep();
1876 }
1877 
1878 float
1880 {
1882 }
1883 
1884 void
1886 {
1888  if (seq > 0)
1889  mCompleteLedgers.erase(range(0u, seq - 1));
1890 }
1891 
1892 void
1894 {
1896 }
1897 
1898 void
1900 {
1901  replayData = std::move(replay);
1902 }
1903 
1906 {
1907  return std::move(replayData);
1908 }
1909 
1910 void
1912  std::uint32_t missing,
1913  bool& progress,
1914  InboundLedger::Reason reason,
1916 {
1917  ScopedUnlock sul{sl};
1918  if (auto hash = getLedgerHashForHistory(missing, reason))
1919  {
1920  assert(hash->isNonZero());
1921  auto ledger = getLedgerByHash(*hash);
1922  if (!ledger)
1923  {
1924  if (!app_.getInboundLedgers().isFailure(*hash))
1925  {
1926  ledger =
1927  app_.getInboundLedgers().acquire(*hash, missing, reason);
1928  if (!ledger && missing != fetch_seq_ &&
1929  missing > app_.getNodeStore().earliestLedgerSeq())
1930  {
1931  JLOG(m_journal.trace())
1932  << "fetchForHistory want fetch pack " << missing;
1933  fetch_seq_ = missing;
1934  getFetchPack(missing, reason);
1935  }
1936  else
1937  JLOG(m_journal.trace())
1938  << "fetchForHistory no fetch pack for " << missing;
1939  }
1940  else
1941  JLOG(m_journal.debug())
1942  << "fetchForHistory found failed acquire";
1943  }
1944  if (ledger)
1945  {
1946  auto seq = ledger->info().seq;
1947  assert(seq == missing);
1948  JLOG(m_journal.trace()) << "fetchForHistory acquired " << seq;
1949  if (reason == InboundLedger::Reason::SHARD)
1950  {
1951  ledger->setFull();
1952  {
1953  std::lock_guard lock(m_mutex);
1954  mShardLedger = ledger;
1955  }
1956  if (!ledger->stateMap().family().isShardBacked())
1957  app_.getShardStore()->storeLedger(ledger);
1958  }
1959  else
1960  {
1961  setFullLedger(ledger, false, false);
1962  int fillInProgress;
1963  {
1964  std::lock_guard lock(m_mutex);
1965  mHistLedger = ledger;
1966  fillInProgress = mFillInProgress;
1967  }
1968  if (fillInProgress == 0 &&
1970  ledger->info().parentHash)
1971  {
1972  {
1973  // Previous ledger is in DB
1974  std::lock_guard lock(m_mutex);
1975  mFillInProgress = seq;
1976  }
1978  jtADVANCE, "tryFill", [this, ledger]() {
1979  tryFill(ledger);
1980  });
1981  }
1982  }
1983  progress = true;
1984  }
1985  else
1986  {
1987  std::uint32_t fetchSz;
1988  if (reason == InboundLedger::Reason::SHARD)
1989  // Do not fetch ledger sequences lower
1990  // than the shard's first ledger sequence
1991  fetchSz = app_.getShardStore()->firstLedgerSeq(
1992  app_.getShardStore()->seqToShardIndex(missing));
1993  else
1994  // Do not fetch ledger sequences lower
1995  // than the earliest ledger sequence
1996  fetchSz = app_.getNodeStore().earliestLedgerSeq();
1997  fetchSz = missing >= fetchSz
1998  ? std::min(ledger_fetch_size_, (missing - fetchSz) + 1)
1999  : 0;
2000  try
2001  {
2002  for (std::uint32_t i = 0; i < fetchSz; ++i)
2003  {
2004  std::uint32_t seq = missing - i;
2005  if (auto h = getLedgerHashForHistory(seq, reason))
2006  {
2007  assert(h->isNonZero());
2008  app_.getInboundLedgers().acquire(*h, seq, reason);
2009  }
2010  }
2011  }
2012  catch (std::exception const&)
2013  {
2014  JLOG(m_journal.warn()) << "Threw while prefetching";
2015  }
2016  }
2017  }
2018  else
2019  {
2020  JLOG(m_journal.fatal())
2021  << "Can't find ledger following prevMissing " << missing;
2022  JLOG(m_journal.fatal())
2023  << "Pub:" << mPubLedgerSeq << " Val:" << mValidLedgerSeq;
2024  JLOG(m_journal.fatal())
2025  << "Ledgers: " << app_.getLedgerMaster().getCompleteLedgers();
2026  JLOG(m_journal.fatal())
2027  << "Acquire reason: "
2028  << (reason == InboundLedger::Reason::HISTORY ? "HISTORY" : "SHARD");
2029  clearLedger(missing + 1);
2030  progress = true;
2031  }
2032 }
2033 
2034 // Try to publish ledgers, acquire missing ledgers
2035 void
2037 {
2038  do
2039  {
2040  mAdvanceWork = false; // If there's work to do, we'll make progress
2041  bool progress = false;
2042 
2043  auto const pubLedgers = findNewLedgersToPublish(sl);
2044  if (pubLedgers.empty())
2045  {
2046  if (!standalone_ && !app_.getFeeTrack().isLoadedLocal() &&
2051  {
2052  // We are in sync, so can acquire
2055  {
2057  missing = prevMissing(
2059  mPubLedger->info().seq,
2061  }
2062  if (missing)
2063  {
2064  JLOG(m_journal.trace())
2065  << "tryAdvance discovered missing " << *missing;
2066  if ((mFillInProgress == 0 || *missing > mFillInProgress) &&
2067  shouldAcquire(
2071  *missing,
2072  m_journal))
2073  {
2074  JLOG(m_journal.trace())
2075  << "advanceThread should acquire";
2076  }
2077  else
2078  missing = std::nullopt;
2079  }
2080  if (!missing && mFillInProgress == 0)
2081  {
2082  if (auto shardStore = app_.getShardStore())
2083  {
2084  missing = shardStore->prepareLedger(mValidLedgerSeq);
2085  if (missing)
2087  }
2088  }
2089  if (missing)
2090  {
2091  fetchForHistory(*missing, progress, reason, sl);
2093  {
2094  JLOG(m_journal.debug())
2095  << "tryAdvance found last valid changed";
2096  progress = true;
2097  }
2098  }
2099  }
2100  else
2101  {
2102  mHistLedger.reset();
2103  mShardLedger.reset();
2104  JLOG(m_journal.trace()) << "tryAdvance not fetching history";
2105  }
2106  }
2107  else
2108  {
2109  JLOG(m_journal.trace()) << "tryAdvance found " << pubLedgers.size()
2110  << " ledgers to publish";
2111  for (auto const& ledger : pubLedgers)
2112  {
2113  {
2114  ScopedUnlock sul{sl};
2115  JLOG(m_journal.debug())
2116  << "tryAdvance publishing seq " << ledger->info().seq;
2117  setFullLedger(ledger, true, true);
2118  }
2119 
2120  setPubLedger(ledger);
2121 
2122  {
2123  ScopedUnlock sul{sl};
2124  app_.getOPs().pubLedger(ledger);
2125  }
2126  }
2127 
2129  progress = newPFWork("pf:newLedger", sl);
2130  }
2131  if (progress)
2132  mAdvanceWork = true;
2133  } while (mAdvanceWork);
2134 }
2135 
2136 void
2138 {
2139  fetch_packs_.canonicalize_replace_client(hash, data);
2140 }
2141 
2144 {
2145  Blob data;
2146  if (fetch_packs_.retrieve(hash, data))
2147  {
2148  fetch_packs_.del(hash, false);
2149  if (hash == sha512Half(makeSlice(data)))
2150  return data;
2151  }
2152  return std::nullopt;
2153 }
2154 
2155 void
2157 {
2158  if (!mGotFetchPackThread.test_and_set(std::memory_order_acquire))
2159  {
2160  app_.getJobQueue().addJob(jtLEDGER_DATA, "gotFetchPack", [&]() {
2162  mGotFetchPackThread.clear(std::memory_order_release);
2163  });
2164  }
2165 }
2166 
2192 static void
2194  SHAMap const& want,
2195  SHAMap const* have,
2196  std::uint32_t cnt,
2197  protocol::TMGetObjectByHash* into,
2198  std::uint32_t seq,
2199  bool withLeaves = true)
2200 {
2201  assert(cnt != 0);
2202 
2203  Serializer s(1024);
2204 
2205  want.visitDifferences(
2206  have,
2207  [&s, withLeaves, &cnt, into, seq](SHAMapTreeNode const& n) -> bool {
2208  if (!withLeaves && n.isLeaf())
2209  return true;
2210 
2211  s.erase();
2212  n.serializeWithPrefix(s);
2213 
2214  auto const& hash = n.getHash().as_uint256();
2215 
2216  protocol::TMIndexedObject* obj = into->add_objects();
2217  obj->set_ledgerseq(seq);
2218  obj->set_hash(hash.data(), hash.size());
2219  obj->set_data(s.getDataPtr(), s.getLength());
2220 
2221  return --cnt != 0;
2222  });
2223 }
2224 
2225 void
2227  std::weak_ptr<Peer> const& wPeer,
2229  uint256 haveLedgerHash,
2230  UptimeClock::time_point uptime)
2231 {
2232  using namespace std::chrono_literals;
2233  if (UptimeClock::now() > uptime + 1s)
2234  {
2235  JLOG(m_journal.info()) << "Fetch pack request got stale";
2236  return;
2237  }
2238 
2239  if (app_.getFeeTrack().isLoadedLocal() || (getValidatedLedgerAge() > 40s))
2240  {
2241  JLOG(m_journal.info()) << "Too busy to make fetch pack";
2242  return;
2243  }
2244 
2245  auto peer = wPeer.lock();
2246 
2247  if (!peer)
2248  return;
2249 
2250  auto have = getLedgerByHash(haveLedgerHash);
2251 
2252  if (!have)
2253  {
2254  JLOG(m_journal.info())
2255  << "Peer requests fetch pack for ledger we don't have: " << have;
2256  peer->charge(Resource::feeRequestNoReply);
2257  return;
2258  }
2259 
2260  if (have->open())
2261  {
2262  JLOG(m_journal.warn())
2263  << "Peer requests fetch pack from open ledger: " << have;
2264  peer->charge(Resource::feeInvalidRequest);
2265  return;
2266  }
2267 
2268  if (have->info().seq < getEarliestFetch())
2269  {
2270  JLOG(m_journal.debug()) << "Peer requests fetch pack that is too early";
2271  peer->charge(Resource::feeInvalidRequest);
2272  return;
2273  }
2274 
2275  auto want = getLedgerByHash(have->info().parentHash);
2276 
2277  if (!want)
2278  {
2279  JLOG(m_journal.info())
2280  << "Peer requests fetch pack for ledger whose predecessor we "
2281  << "don't have: " << have;
2282  peer->charge(Resource::feeRequestNoReply);
2283  return;
2284  }
2285 
2286  try
2287  {
2288  Serializer hdr(128);
2289 
2290  protocol::TMGetObjectByHash reply;
2291  reply.set_query(false);
2292 
2293  if (request->has_seq())
2294  reply.set_seq(request->seq());
2295 
2296  reply.set_ledgerhash(request->ledgerhash());
2297  reply.set_type(protocol::TMGetObjectByHash::otFETCH_PACK);
2298 
2299  // Building a fetch pack:
2300  // 1. Add the header for the requested ledger.
2301  // 2. Add the nodes for the AccountStateMap of that ledger.
2302  // 3. If there are transactions, add the nodes for the
2303  // transactions of the ledger.
2304  // 4. If the FetchPack now contains at least 512 entries then stop.
2305  // 5. If not very much time has elapsed, then loop back and repeat
2306  // the same process adding the previous ledger to the FetchPack.
2307  do
2308  {
2309  std::uint32_t lSeq = want->info().seq;
2310 
2311  {
2312  // Serialize the ledger header:
2313  hdr.erase();
2314 
2316  addRaw(want->info(), hdr);
2317 
2318  // Add the data
2319  protocol::TMIndexedObject* obj = reply.add_objects();
2320  obj->set_hash(
2321  want->info().hash.data(), want->info().hash.size());
2322  obj->set_data(hdr.getDataPtr(), hdr.getLength());
2323  obj->set_ledgerseq(lSeq);
2324  }
2325 
2327  want->stateMap(), &have->stateMap(), 16384, &reply, lSeq);
2328 
2329  // We use nullptr here because transaction maps are per ledger
2330  // and so the requestor is unlikely to already have it.
2331  if (want->info().txHash.isNonZero())
2332  populateFetchPack(want->txMap(), nullptr, 512, &reply, lSeq);
2333 
2334  if (reply.objects().size() >= 512)
2335  break;
2336 
2337  have = std::move(want);
2338  want = getLedgerByHash(have->info().parentHash);
2339  } while (want && UptimeClock::now() <= uptime + 1s);
2340 
2341  auto msg = std::make_shared<Message>(reply, protocol::mtGET_OBJECTS);
2342 
2343  JLOG(m_journal.info())
2344  << "Built fetch pack with " << reply.objects().size() << " nodes ("
2345  << msg->getBufferSize() << " bytes)";
2346 
2347  peer->send(msg);
2348  }
2349  catch (std::exception const&)
2350  {
2351  JLOG(m_journal.warn()) << "Exception building fetch pach";
2352  }
2353 }
2354 
2357 {
2358  return fetch_packs_.getCacheSize();
2359 }
2360 
2361 // Returns the minimum ledger sequence in SQL database, if any.
2364 {
2366 }
2367 
2368 } // 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:1692
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:2226
ripple::LedgerMaster::clearLedgerCachePrior
void clearLedgerCachePrior(LedgerIndex seq)
Definition: LedgerMaster.cpp:1893
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:1872
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:209
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:505
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:1905
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:1677
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:1623
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:1852
std::cerr
ripple::Application::isStopping
virtual bool isStopping() const =0
ripple::LedgerMaster::isNewPathRequest
bool isNewPathRequest()
Definition: LedgerMaster.cpp:1601
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:1752
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:72
ripple::LedgerMaster::setFullLedger
void setFullLedger(std::shared_ptr< Ledger const > const &ledger, bool isSynchronous, bool isCurrent)
Definition: LedgerMaster.cpp:910
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:423
ripple::Application::getFeeTrack
virtual LoadFeeTrack & getFeeTrack()=0
ripple::LedgerMaster::getCompleteLedgers
std::string getCompleteLedgers()
Definition: LedgerMaster.cpp:1699
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:1645
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:318
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::LedgerHistory::insert
bool insert(std::shared_ptr< Ledger const > ledger, bool validated)
Track a ledger.
Definition: LedgerHistory.cpp:54
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:2156
ripple::LedgerMaster::fetchForHistory
void fetchForHistory(std::uint32_t missing, bool &progress, InboundLedger::Reason reason, std::unique_lock< std::recursive_mutex > &)
Definition: LedgerMaster.cpp:1911
ripple::LedgerMaster::getFetchPack
std::optional< Blob > getFetchPack(uint256 const &hash) override
Retrieves partial ledger data of the coresponding hash from peers.
Definition: LedgerMaster.cpp:2143
ripple::LedgerMaster::failedSave
void failedSave(std::uint32_t seq, uint256 const &hash)
Definition: LedgerMaster.cpp:971
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:117
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:2193
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:464
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:2363
ripple::LedgerMaster::updatePaths
void updatePaths()
Definition: LedgerMaster.cpp:1489
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:1816
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:1593
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:84
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:1652
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:1612
ripple::LedgerMaster::getNeededValidations
std::size_t getNeededValidations()
Determines how many validations are needed to fully validate a ledger.
Definition: LedgerMaster.cpp:1035
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:371
ripple::LedgerMaster::checkAccept
void checkAccept(std::shared_ptr< Ledger const > const &ledger)
Definition: LedgerMaster.cpp:1041
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:2356
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:263
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:1711
limits
ripple::LedgerMaster::addFetchPack
void addFetchPack(uint256 const &hash, std::shared_ptr< Blob > data)
Definition: LedgerMaster.cpp:2137
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:1290
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:1899
ripple::LedgerMaster::getValidatedLedger
std::shared_ptr< Ledger const > getValidatedLedger()
Definition: LedgerMaster.cpp:1662
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:519
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:1865
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:1189
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:1741
ripple::LedgerMaster::findNewLedgersToPublish
std::vector< std::shared_ptr< Ledger const > > findNewLedgersToPublish(std::unique_lock< std::recursive_mutex > &)
Definition: LedgerMaster.cpp:1313
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:976
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:1719
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:2036
std::unordered_map
STL class.
ripple::LedgerMaster::tryAdvance
void tryAdvance()
Definition: LedgerMaster.cpp:1457
ripple::LedgerMaster::clearPriorLedgers
void clearPriorLedgers(LedgerIndex seq)
Definition: LedgerMaster.cpp:1885
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:1879
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