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  // It can be expensive to modify the open ledger even with no transactions
553  // to process. Regardless, make sure to reset held transactions with
554  // the parent.
555  if (mHeldTransactions.size())
556  {
557  app_.openLedger().modify([&](OpenView& view, beast::Journal j) {
558  bool any = false;
559  for (auto const& it : mHeldTransactions)
560  {
561  ApplyFlags flags = tapNONE;
562  auto const result =
563  app_.getTxQ().apply(app_, view, it.second, flags, j);
564  if (result.second)
565  any = true;
566  }
567  return any;
568  });
569  }
570 
571  // VFALCO NOTE The hash for an open ledger is undefined so we use
572  // something that is a reasonable substitute.
573  mHeldTransactions.reset(app_.openLedger().current()->info().parentHash);
574 }
575 
578 {
580 
582 }
583 
584 void
586 {
587  mBuildingLedgerSeq.store(i);
588 }
589 
590 bool
592 {
594  return boost::icl::contains(mCompleteLedgers, seq);
595 }
596 
597 void
599 {
601  mCompleteLedgers.erase(seq);
602 }
603 
604 bool
606 {
607  if (app_.config().reporting())
608  return true; // Reporting mode only supports validated ledger
609 
610  if (ledger.open())
611  return false;
612 
613  if (ledger.info().validated)
614  return true;
615 
616  auto const seq = ledger.info().seq;
617  try
618  {
619  // Use the skip list in the last validated ledger to see if ledger
620  // comes before the last validated ledger (and thus has been
621  // validated).
622  auto const hash = walkHashBySeq(seq, InboundLedger::Reason::GENERIC);
623 
624  if (!hash || ledger.info().hash != *hash)
625  {
626  // This ledger's hash is not the hash of the validated ledger
627  if (hash)
628  {
629  assert(hash->isNonZero());
630  uint256 valHash =
632  if (valHash == ledger.info().hash)
633  {
634  // SQL database doesn't match ledger chain
635  clearLedger(seq);
636  }
637  }
638  return false;
639  }
640  }
641  catch (SHAMapMissingNode const& mn)
642  {
643  JLOG(m_journal.warn()) << "Ledger #" << seq << ": " << mn.what();
644  return false;
645  }
646 
647  // Mark ledger as validated to save time if we see it again.
648  ledger.info().validated = true;
649  return true;
650 }
651 
652 // returns Ledgers we have all the nodes for
653 bool
655  std::uint32_t& minVal,
656  std::uint32_t& maxVal)
657 {
658  // Validated ledger is likely not stored in the DB yet so we use the
659  // published ledger which is.
660  maxVal = mPubLedgerSeq.load();
661 
662  if (!maxVal)
663  return false;
664 
666  {
668  maybeMin = prevMissing(mCompleteLedgers, maxVal);
669  }
670 
671  if (maybeMin == std::nullopt)
672  minVal = maxVal;
673  else
674  minVal = 1 + *maybeMin;
675 
676  return true;
677 }
678 
679 // Returns Ledgers we have all the nodes for and are indexed
680 bool
682 {
683  if (app_.config().reporting())
684  {
686  try
687  {
688  if (res == "empty" || res == "error" || res.empty())
689  return false;
690  else if (size_t delim = res.find('-'); delim != std::string::npos)
691  {
692  minVal = std::stol(res.substr(0, delim));
693  maxVal = std::stol(res.substr(delim + 1));
694  }
695  else
696  {
697  minVal = maxVal = std::stol(res);
698  }
699  return true;
700  }
701  catch (std::exception const& e)
702  {
703  JLOG(m_journal.error()) << "LedgerMaster::getValidatedRange: "
704  "exception parsing complete ledgers: "
705  << e.what();
706  return false;
707  }
708  }
709  if (!getFullValidatedRange(minVal, maxVal))
710  return false;
711 
712  // Remove from the validated range any ledger sequences that may not be
713  // fully updated in the database yet
714 
715  auto const pendingSaves = app_.pendingSaves().getSnapshot();
716 
717  if (!pendingSaves.empty() && ((minVal != 0) || (maxVal != 0)))
718  {
719  // Ensure we shrink the tips as much as possible. If we have 7-9 and
720  // 8,9 are invalid, we don't want to see the 8 and shrink to just 9
721  // because then we'll have nothing when we could have 7.
722  while (pendingSaves.count(maxVal) > 0)
723  --maxVal;
724  while (pendingSaves.count(minVal) > 0)
725  ++minVal;
726 
727  // Best effort for remaining exclusions
728  for (auto v : pendingSaves)
729  {
730  if ((v.first >= minVal) && (v.first <= maxVal))
731  {
732  if (v.first > ((minVal + maxVal) / 2))
733  maxVal = v.first - 1;
734  else
735  minVal = v.first + 1;
736  }
737  }
738 
739  if (minVal > maxVal)
740  minVal = maxVal = 0;
741  }
742 
743  return true;
744 }
745 
746 // Get the earliest ledger we will let peers fetch
749 {
750  // The earliest ledger we will let people fetch is ledger zero,
751  // unless that creates a larger range than allowed
752  std::uint32_t e = getClosedLedger()->info().seq;
753 
754  if (e > fetch_depth_)
755  e -= fetch_depth_;
756  else
757  e = 0;
758  return e;
759 }
760 
761 void
763 {
764  std::uint32_t seq = ledger->info().seq;
765  uint256 prevHash = ledger->info().parentHash;
766 
768 
769  std::uint32_t minHas = seq;
770  std::uint32_t maxHas = seq;
771 
772  NodeStore::Database& nodeStore{app_.getNodeStore()};
773  while (!app_.getJobQueue().isStopping() && seq > 0)
774  {
775  {
777  minHas = seq;
778  --seq;
779 
780  if (haveLedger(seq))
781  break;
782  }
783 
784  auto it(ledgerHashes.find(seq));
785 
786  if (it == ledgerHashes.end())
787  {
788  if (app_.isStopping())
789  return;
790 
791  {
793  mCompleteLedgers.insert(range(minHas, maxHas));
794  }
795  maxHas = minHas;
797  (seq < 500) ? 0 : (seq - 499), seq);
798  it = ledgerHashes.find(seq);
799 
800  if (it == ledgerHashes.end())
801  break;
802 
803  if (!nodeStore.fetchNodeObject(
804  ledgerHashes.begin()->second.ledgerHash,
805  ledgerHashes.begin()->first))
806  {
807  // The ledger is not backed by the node store
808  JLOG(m_journal.warn()) << "SQL DB ledger sequence " << seq
809  << " mismatches node store";
810  break;
811  }
812  }
813 
814  if (it->second.ledgerHash != prevHash)
815  break;
816 
817  prevHash = it->second.parentHash;
818  }
819 
820  {
822  mCompleteLedgers.insert(range(minHas, maxHas));
823  }
824  {
826  mFillInProgress = 0;
827  tryAdvance();
828  }
829 }
830 
833 void
835 {
836  LedgerIndex const ledgerIndex([&]() {
837  if (reason == InboundLedger::Reason::SHARD)
838  {
839  // Do not acquire a ledger sequence greater
840  // than the last ledger in the shard
841  auto const shardStore{app_.getShardStore()};
842  auto const shardIndex{shardStore->seqToShardIndex(missing)};
843  return std::min(missing + 1, shardStore->lastLedgerSeq(shardIndex));
844  }
845  return missing + 1;
846  }());
847 
848  auto const haveHash{getLedgerHashForHistory(ledgerIndex, reason)};
849  if (!haveHash || haveHash->isZero())
850  {
851  if (reason == InboundLedger::Reason::SHARD)
852  {
853  auto const shardStore{app_.getShardStore()};
854  auto const shardIndex{shardStore->seqToShardIndex(missing)};
855  if (missing < shardStore->lastLedgerSeq(shardIndex))
856  {
857  JLOG(m_journal.error())
858  << "No hash for fetch pack. "
859  << "Missing ledger sequence " << missing
860  << " while acquiring shard " << shardIndex;
861  }
862  }
863  else
864  {
865  JLOG(m_journal.error())
866  << "No hash for fetch pack. Missing Index " << missing;
867  }
868  return;
869  }
870 
871  // Select target Peer based on highest score. The score is randomized
872  // but biased in favor of Peers with low latency.
873  std::shared_ptr<Peer> target;
874  {
875  int maxScore = 0;
876  auto peerList = app_.overlay().getActivePeers();
877  for (auto const& peer : peerList)
878  {
879  if (peer->hasRange(missing, missing + 1))
880  {
881  int score = peer->getScore(true);
882  if (!target || (score > maxScore))
883  {
884  target = peer;
885  maxScore = score;
886  }
887  }
888  }
889  }
890 
891  if (target)
892  {
893  protocol::TMGetObjectByHash tmBH;
894  tmBH.set_query(true);
895  tmBH.set_type(protocol::TMGetObjectByHash::otFETCH_PACK);
896  tmBH.set_ledgerhash(haveHash->begin(), 32);
897  auto packet = std::make_shared<Message>(tmBH, protocol::mtGET_OBJECTS);
898 
899  target->send(packet);
900  JLOG(m_journal.trace()) << "Requested fetch pack for " << missing;
901  }
902  else
903  JLOG(m_journal.debug()) << "No peer for fetch pack";
904 }
905 
906 void
908 {
909  int invalidate = 0;
911 
912  for (std::uint32_t lSeq = ledger.info().seq - 1; lSeq > 0; --lSeq)
913  {
914  if (haveLedger(lSeq))
915  {
916  try
917  {
918  hash = hashOfSeq(ledger, lSeq, m_journal);
919  }
920  catch (std::exception const& ex)
921  {
922  JLOG(m_journal.warn())
923  << "fixMismatch encounters partial ledger. Exception: "
924  << ex.what();
925  clearLedger(lSeq);
926  return;
927  }
928 
929  if (hash)
930  {
931  // try to close the seam
932  auto otherLedger = getLedgerBySeq(lSeq);
933 
934  if (otherLedger && (otherLedger->info().hash == *hash))
935  {
936  // we closed the seam
937  if (invalidate != 0)
938  {
939  JLOG(m_journal.warn())
940  << "Match at " << lSeq << ", " << invalidate
941  << " prior ledgers invalidated";
942  }
943 
944  return;
945  }
946  }
947 
948  clearLedger(lSeq);
949  ++invalidate;
950  }
951  }
952 
953  // all prior ledgers invalidated
954  if (invalidate != 0)
955  {
956  JLOG(m_journal.warn())
957  << "All " << invalidate << " prior ledgers invalidated";
958  }
959 }
960 
961 void
963  std::shared_ptr<Ledger const> const& ledger,
964  bool isSynchronous,
965  bool isCurrent)
966 {
967  // A new ledger has been accepted as part of the trusted chain
968  JLOG(m_journal.debug()) << "Ledger " << ledger->info().seq
969  << " accepted :" << ledger->info().hash;
970  assert(ledger->stateMap().getHash().isNonZero());
971 
972  ledger->setValidated();
973  ledger->setFull();
974 
975  if (isCurrent)
976  mLedgerHistory.insert(ledger, true);
977 
978  {
979  // Check the SQL database's entry for the sequence before this
980  // ledger, if it's not this ledger's parent, invalidate it
981  uint256 prevHash =
982  app_.getRelationalDatabase().getHashByIndex(ledger->info().seq - 1);
983  if (prevHash.isNonZero() && prevHash != ledger->info().parentHash)
984  clearLedger(ledger->info().seq - 1);
985  }
986 
987  pendSaveValidated(app_, ledger, isSynchronous, isCurrent);
988 
989  {
991  mCompleteLedgers.insert(ledger->info().seq);
992  }
993 
994  {
996 
997  if (ledger->info().seq > mValidLedgerSeq)
998  setValidLedger(ledger);
999  if (!mPubLedger)
1000  {
1001  setPubLedger(ledger);
1002  app_.getOrderBookDB().setup(ledger);
1003  }
1004 
1005  if (ledger->info().seq != 0 && haveLedger(ledger->info().seq - 1))
1006  {
1007  // we think we have the previous ledger, double check
1008  auto prevLedger = getLedgerBySeq(ledger->info().seq - 1);
1009 
1010  if (!prevLedger ||
1011  (prevLedger->info().hash != ledger->info().parentHash))
1012  {
1013  JLOG(m_journal.warn())
1014  << "Acquired ledger invalidates previous ledger: "
1015  << (prevLedger ? "hashMismatch" : "missingLedger");
1016  fixMismatch(*ledger);
1017  }
1018  }
1019  }
1020 }
1021 
1022 void
1024 {
1025  clearLedger(seq);
1027 }
1028 
1029 // Check if the specified ledger can become the new last fully-validated
1030 // ledger.
1031 void
1033 {
1034  std::size_t valCount = 0;
1035 
1036  if (seq != 0)
1037  {
1038  // Ledger is too old
1039  if (seq < mValidLedgerSeq)
1040  return;
1041 
1042  auto validations = app_.validators().negativeUNLFilter(
1043  app_.getValidations().getTrustedForLedger(hash, seq));
1044  valCount = validations.size();
1045  if (valCount >= app_.validators().quorum())
1046  {
1048  if (seq > mLastValidLedger.second)
1049  mLastValidLedger = std::make_pair(hash, seq);
1050  }
1051 
1052  if (seq == mValidLedgerSeq)
1053  return;
1054 
1055  // Ledger could match the ledger we're already building
1056  if (seq == mBuildingLedgerSeq)
1057  return;
1058  }
1059 
1060  auto ledger = mLedgerHistory.getLedgerByHash(hash);
1061 
1062  if (!ledger)
1063  {
1064  if ((seq != 0) && (getValidLedgerIndex() == 0))
1065  {
1066  // Set peers converged early if we can
1067  if (valCount >= app_.validators().quorum())
1068  app_.overlay().checkTracking(seq);
1069  }
1070 
1071  // FIXME: We may not want to fetch a ledger with just one
1072  // trusted validation
1073  ledger = app_.getInboundLedgers().acquire(
1074  hash, seq, InboundLedger::Reason::GENERIC);
1075  }
1076 
1077  if (ledger)
1078  checkAccept(ledger);
1079 }
1080 
1088 {
1089  return standalone_ ? 0 : app_.validators().quorum();
1090 }
1091 
1092 void
1094 {
1095  // Can we accept this ledger as our new last fully-validated ledger
1096 
1097  if (!canBeCurrent(ledger))
1098  return;
1099 
1100  // Can we advance the last fully-validated ledger? If so, can we
1101  // publish?
1103 
1104  if (ledger->info().seq <= mValidLedgerSeq)
1105  return;
1106 
1107  auto const minVal = getNeededValidations();
1108  auto validations = app_.validators().negativeUNLFilter(
1110  ledger->info().hash, ledger->info().seq));
1111  auto const tvc = validations.size();
1112  if (tvc < minVal) // nothing we can do
1113  {
1114  JLOG(m_journal.trace())
1115  << "Only " << tvc << " validations for " << ledger->info().hash;
1116  return;
1117  }
1118 
1119  JLOG(m_journal.info()) << "Advancing accepted ledger to "
1120  << ledger->info().seq << " with >= " << minVal
1121  << " validations";
1122 
1123  ledger->setValidated();
1124  ledger->setFull();
1125  setValidLedger(ledger);
1126  if (!mPubLedger)
1127  {
1128  pendSaveValidated(app_, ledger, true, true);
1129  setPubLedger(ledger);
1130  app_.getOrderBookDB().setup(ledger);
1131  }
1132 
1133  std::uint32_t const base = app_.getFeeTrack().getLoadBase();
1134  auto fees = app_.getValidations().fees(ledger->info().hash, base);
1135  {
1136  auto fees2 =
1137  app_.getValidations().fees(ledger->info().parentHash, base);
1138  fees.reserve(fees.size() + fees2.size());
1139  std::copy(fees2.begin(), fees2.end(), std::back_inserter(fees));
1140  }
1141  std::uint32_t fee;
1142  if (!fees.empty())
1143  {
1144  std::sort(fees.begin(), fees.end());
1145  if (auto stream = m_journal.debug())
1146  {
1148  s << "Received fees from validations: (" << fees.size() << ") ";
1149  for (auto const fee1 : fees)
1150  {
1151  s << " " << fee1;
1152  }
1153  stream << s.str();
1154  }
1155  fee = fees[fees.size() / 2]; // median
1156  }
1157  else
1158  {
1159  fee = base;
1160  }
1161 
1162  app_.getFeeTrack().setRemoteFee(fee);
1163 
1164  tryAdvance();
1165 
1166  if (ledger->seq() % 256 == 0)
1167  {
1168  // Check if the majority of validators run a higher version rippled
1169  // software. If so print a warning.
1170  //
1171  // Once the HardenedValidations amendment is enabled, validators include
1172  // their rippled software version in the validation messages of every
1173  // (flag - 1) ledger. We wait for one ledger time before checking the
1174  // version information to accumulate more validation messages.
1175 
1176  auto currentTime = app_.timeKeeper().now();
1177  bool needPrint = false;
1178 
1179  // The variable upgradeWarningPrevTime_ will be set when and only when
1180  // the warning is printed.
1182  {
1183  // Have not printed the warning before, check if need to print.
1184  auto const vals = app_.getValidations().getTrustedForLedger(
1185  ledger->info().parentHash, ledger->info().seq - 1);
1186  std::size_t higherVersionCount = 0;
1187  std::size_t rippledCount = 0;
1188  for (auto const& v : vals)
1189  {
1190  if (v->isFieldPresent(sfServerVersion))
1191  {
1192  auto version = v->getFieldU64(sfServerVersion);
1193  higherVersionCount +=
1194  BuildInfo::isNewerVersion(version) ? 1 : 0;
1195  rippledCount +=
1196  BuildInfo::isRippledVersion(version) ? 1 : 0;
1197  }
1198  }
1199  // We report only if (1) we have accumulated validation messages
1200  // from 90% validators from the UNL, (2) 60% of validators
1201  // running the rippled implementation have higher version numbers,
1202  // and (3) the calculation won't cause divide-by-zero.
1203  if (higherVersionCount > 0 && rippledCount > 0)
1204  {
1205  constexpr std::size_t reportingPercent = 90;
1206  constexpr std::size_t cutoffPercent = 60;
1207  auto const unlSize{
1208  app_.validators().getQuorumKeys().second.size()};
1209  needPrint = unlSize > 0 &&
1210  calculatePercent(vals.size(), unlSize) >=
1211  reportingPercent &&
1212  calculatePercent(higherVersionCount, rippledCount) >=
1213  cutoffPercent;
1214  }
1215  }
1216  // To throttle the warning messages, instead of printing a warning
1217  // every flag ledger, we print every week.
1218  else if (currentTime - upgradeWarningPrevTime_ >= weeks{1})
1219  {
1220  // Printed the warning before, and assuming most validators
1221  // do not downgrade, we keep printing the warning
1222  // until the local server is restarted.
1223  needPrint = true;
1224  }
1225 
1226  if (needPrint)
1227  {
1228  upgradeWarningPrevTime_ = currentTime;
1229  auto const upgradeMsg =
1230  "Check for upgrade: "
1231  "A majority of trusted validators are "
1232  "running a newer version.";
1233  std::cerr << upgradeMsg << std::endl;
1234  JLOG(m_journal.error()) << upgradeMsg;
1235  }
1236  }
1237 }
1238 
1240 void
1242  std::shared_ptr<Ledger const> const& ledger,
1243  uint256 const& consensusHash,
1244  Json::Value consensus)
1245 {
1246  // Because we just built a ledger, we are no longer building one
1247  setBuildingLedger(0);
1248 
1249  // No need to process validations in standalone mode
1250  if (standalone_)
1251  return;
1252 
1253  mLedgerHistory.builtLedger(ledger, consensusHash, std::move(consensus));
1254 
1255  if (ledger->info().seq <= mValidLedgerSeq)
1256  {
1257  auto stream = app_.journal("LedgerConsensus").info();
1258  JLOG(stream) << "Consensus built old ledger: " << ledger->info().seq
1259  << " <= " << mValidLedgerSeq;
1260  return;
1261  }
1262 
1263  // See if this ledger can be the new fully-validated ledger
1264  checkAccept(ledger);
1265 
1266  if (ledger->info().seq <= mValidLedgerSeq)
1267  {
1268  auto stream = app_.journal("LedgerConsensus").debug();
1269  JLOG(stream) << "Consensus ledger fully validated";
1270  return;
1271  }
1272 
1273  // This ledger cannot be the new fully-validated ledger, but
1274  // maybe we saved up validations for some other ledger that can be
1275 
1276  auto validations = app_.validators().negativeUNLFilter(
1278 
1279  // Track validation counts with sequence numbers
1280  class valSeq
1281  {
1282  public:
1283  valSeq() : valCount_(0), ledgerSeq_(0)
1284  {
1285  ;
1286  }
1287 
1288  void
1289  mergeValidation(LedgerIndex seq)
1290  {
1291  valCount_++;
1292 
1293  // If we didn't already know the sequence, now we do
1294  if (ledgerSeq_ == 0)
1295  ledgerSeq_ = seq;
1296  }
1297 
1298  std::size_t valCount_;
1299  LedgerIndex ledgerSeq_;
1300  };
1301 
1302  // Count the number of current, trusted validations
1304  for (auto const& v : validations)
1305  {
1306  valSeq& vs = count[v->getLedgerHash()];
1307  vs.mergeValidation(v->getFieldU32(sfLedgerSequence));
1308  }
1309 
1310  auto const neededValidations = getNeededValidations();
1311  auto maxSeq = mValidLedgerSeq.load();
1312  auto maxLedger = ledger->info().hash;
1313 
1314  // Of the ledgers with sufficient validations,
1315  // find the one with the highest sequence
1316  for (auto& v : count)
1317  if (v.second.valCount_ > neededValidations)
1318  {
1319  // If we still don't know the sequence, get it
1320  if (v.second.ledgerSeq_ == 0)
1321  {
1322  if (auto l = getLedgerByHash(v.first))
1323  v.second.ledgerSeq_ = l->info().seq;
1324  }
1325 
1326  if (v.second.ledgerSeq_ > maxSeq)
1327  {
1328  maxSeq = v.second.ledgerSeq_;
1329  maxLedger = v.first;
1330  }
1331  }
1332 
1333  if (maxSeq > mValidLedgerSeq)
1334  {
1335  auto stream = app_.journal("LedgerConsensus").debug();
1336  JLOG(stream) << "Consensus triggered check of ledger";
1337  checkAccept(maxLedger, maxSeq);
1338  }
1339 }
1340 
1343  LedgerIndex index,
1344  InboundLedger::Reason reason)
1345 {
1346  // Try to get the hash of a ledger we need to fetch for history
1348  auto const& l{
1350 
1351  if (l && l->info().seq >= index)
1352  {
1353  ret = hashOfSeq(*l, index, m_journal);
1354  if (!ret)
1355  ret = walkHashBySeq(index, l, reason);
1356  }
1357 
1358  if (!ret)
1359  ret = walkHashBySeq(index, reason);
1360 
1361  return ret;
1362 }
1363 
1367 {
1369 
1370  JLOG(m_journal.trace()) << "findNewLedgersToPublish<";
1371 
1372  // No valid ledger, nothing to do
1373  if (mValidLedger.empty())
1374  {
1375  JLOG(m_journal.trace()) << "No valid journal, nothing to publish.";
1376  return {};
1377  }
1378 
1379  if (!mPubLedger)
1380  {
1381  JLOG(m_journal.info())
1382  << "First published ledger will be " << mValidLedgerSeq;
1383  return {mValidLedger.get()};
1384  }
1385 
1387  {
1388  JLOG(m_journal.warn()) << "Gap in validated ledger stream "
1389  << mPubLedgerSeq << " - " << mValidLedgerSeq - 1;
1390 
1391  auto valLedger = mValidLedger.get();
1392  ret.push_back(valLedger);
1393  setPubLedger(valLedger);
1394  app_.getOrderBookDB().setup(valLedger);
1395 
1396  return {valLedger};
1397  }
1398 
1400  {
1401  JLOG(m_journal.trace()) << "No valid journal, nothing to publish.";
1402  return {};
1403  }
1404 
1405  int acqCount = 0;
1406 
1407  auto pubSeq = mPubLedgerSeq + 1; // Next sequence to publish
1408  auto valLedger = mValidLedger.get();
1409  std::uint32_t valSeq = valLedger->info().seq;
1410 
1411  ScopedUnlock sul{sl};
1412  try
1413  {
1414  for (std::uint32_t seq = pubSeq; seq <= valSeq; ++seq)
1415  {
1416  JLOG(m_journal.trace())
1417  << "Trying to fetch/publish valid ledger " << seq;
1418 
1420  // This can throw
1421  auto hash = hashOfSeq(*valLedger, seq, m_journal);
1422  // VFALCO TODO Restructure this code so that zero is not
1423  // used.
1424  if (!hash)
1425  hash = beast::zero; // kludge
1426  if (seq == valSeq)
1427  {
1428  // We need to publish the ledger we just fully validated
1429  ledger = valLedger;
1430  }
1431  else if (hash->isZero())
1432  {
1433  JLOG(m_journal.fatal()) << "Ledger: " << valSeq
1434  << " does not have hash for " << seq;
1435  assert(false);
1436  }
1437  else
1438  {
1439  ledger = mLedgerHistory.getLedgerByHash(*hash);
1440  }
1441 
1442  if (!app_.config().LEDGER_REPLAY)
1443  {
1444  // Can we try to acquire the ledger we need?
1445  if (!ledger && (++acqCount < ledger_fetch_size_))
1446  ledger = app_.getInboundLedgers().acquire(
1447  *hash, seq, InboundLedger::Reason::GENERIC);
1448  }
1449 
1450  // Did we acquire the next ledger we need to publish?
1451  if (ledger && (ledger->info().seq == pubSeq))
1452  {
1453  ledger->setValidated();
1454  ret.push_back(ledger);
1455  ++pubSeq;
1456  }
1457  }
1458 
1459  JLOG(m_journal.trace())
1460  << "ready to publish " << ret.size() << " ledgers.";
1461  }
1462  catch (std::exception const& ex)
1463  {
1464  JLOG(m_journal.error())
1465  << "Exception while trying to find ledgers to publish: "
1466  << ex.what();
1467  }
1468 
1469  if (app_.config().LEDGER_REPLAY)
1470  {
1471  /* Narrow down the gap of ledgers, and try to replay them.
1472  * When replaying a ledger gap, if the local node has
1473  * the start ledger, it saves an expensive InboundLedger
1474  * acquire. If the local node has the finish ledger, it
1475  * saves a skip list acquire.
1476  */
1477  auto const& startLedger = ret.empty() ? mPubLedger : ret.back();
1478  auto finishLedger = valLedger;
1479  while (startLedger->seq() + 1 < finishLedger->seq())
1480  {
1481  if (auto const parent = mLedgerHistory.getLedgerByHash(
1482  finishLedger->info().parentHash);
1483  parent)
1484  {
1485  finishLedger = parent;
1486  }
1487  else
1488  {
1489  auto numberLedgers =
1490  finishLedger->seq() - startLedger->seq() + 1;
1491  JLOG(m_journal.debug())
1492  << "Publish LedgerReplays " << numberLedgers
1493  << " ledgers, from seq=" << startLedger->info().seq << ", "
1494  << startLedger->info().hash
1495  << " to seq=" << finishLedger->info().seq << ", "
1496  << finishLedger->info().hash;
1499  finishLedger->info().hash,
1500  numberLedgers);
1501  break;
1502  }
1503  }
1504  }
1505 
1506  return ret;
1507 }
1508 
1509 void
1511 {
1513 
1514  // Can't advance without at least one fully-valid ledger
1515  mAdvanceWork = true;
1516  if (!mAdvanceThread && !mValidLedger.empty())
1517  {
1518  mAdvanceThread = true;
1519  app_.getJobQueue().addJob(jtADVANCE, "advanceLedger", [this]() {
1521 
1522  assert(!mValidLedger.empty() && mAdvanceThread);
1523 
1524  JLOG(m_journal.trace()) << "advanceThread<";
1525 
1526  try
1527  {
1528  doAdvance(sl);
1529  }
1530  catch (std::exception const& ex)
1531  {
1532  JLOG(m_journal.fatal()) << "doAdvance throws: " << ex.what();
1533  }
1534 
1535  mAdvanceThread = false;
1536  JLOG(m_journal.trace()) << "advanceThread>";
1537  });
1538  }
1539 }
1540 
1541 void
1543 {
1544  {
1547  {
1548  --mPathFindThread;
1549  JLOG(m_journal.debug()) << "Need network ledger for updating paths";
1550  return;
1551  }
1552  }
1553 
1554  while (!app_.getJobQueue().isStopping())
1555  {
1556  JLOG(m_journal.debug()) << "updatePaths running";
1558  {
1560 
1561  if (!mValidLedger.empty() &&
1562  (!mPathLedger || (mPathLedger->info().seq != mValidLedgerSeq)))
1563  { // We have a new valid ledger since the last full pathfinding
1565  lastLedger = mPathLedger;
1566  }
1567  else if (mPathFindNewRequest)
1568  { // We have a new request but no new ledger
1569  lastLedger = app_.openLedger().current();
1570  }
1571  else
1572  { // Nothing to do
1573  --mPathFindThread;
1574  JLOG(m_journal.debug()) << "Nothing to do for updating paths";
1575  return;
1576  }
1577  }
1578 
1579  if (!standalone_)
1580  { // don't pathfind with a ledger that's more than 60 seconds old
1581  using namespace std::chrono;
1582  auto age = time_point_cast<seconds>(app_.timeKeeper().closeTime()) -
1583  lastLedger->info().closeTime;
1584  if (age > 1min)
1585  {
1586  JLOG(m_journal.debug())
1587  << "Published ledger too old for updating paths";
1589  --mPathFindThread;
1590  return;
1591  }
1592  }
1593 
1594  try
1595  {
1596  auto& pathRequests = app_.getPathRequests();
1597  {
1599  if (!pathRequests.requestsPending())
1600  {
1601  --mPathFindThread;
1602  JLOG(m_journal.debug())
1603  << "No path requests found. Nothing to do for updating "
1604  "paths. "
1605  << mPathFindThread << " jobs remaining";
1606  return;
1607  }
1608  }
1609  JLOG(m_journal.debug()) << "Updating paths";
1610  pathRequests.updateAll(lastLedger);
1611 
1613  if (!pathRequests.requestsPending())
1614  {
1615  JLOG(m_journal.debug())
1616  << "No path requests left. No need for further updating "
1617  "paths";
1618  --mPathFindThread;
1619  return;
1620  }
1621  }
1622  catch (SHAMapMissingNode const& mn)
1623  {
1624  JLOG(m_journal.info()) << "During pathfinding: " << mn.what();
1625  if (lastLedger->open())
1626  {
1627  // our parent is the problem
1629  lastLedger->info().parentHash,
1630  lastLedger->info().seq - 1,
1632  }
1633  else
1634  {
1635  // this ledger is the problem
1637  lastLedger->info().hash,
1638  lastLedger->info().seq,
1640  }
1641  }
1642  }
1643 }
1644 
1645 bool
1647 {
1649  mPathFindNewRequest = newPFWork("pf:newRequest", ml);
1650  return mPathFindNewRequest;
1651 }
1652 
1653 bool
1655 {
1657  bool const ret = mPathFindNewRequest;
1658  mPathFindNewRequest = false;
1659  return ret;
1660 }
1661 
1662 // If the order book is radically updated, we need to reprocess all
1663 // pathfinding requests.
1664 bool
1666 {
1668  mPathLedger.reset();
1669 
1670  return newPFWork("pf:newOBDB", ml);
1671 }
1672 
1675 bool
1677  const char* name,
1679 {
1680  if (!app_.isStopping() && mPathFindThread < 2 &&
1682  {
1683  JLOG(m_journal.debug())
1684  << "newPFWork: Creating job. path find threads: "
1685  << mPathFindThread;
1686  if (app_.getJobQueue().addJob(
1687  jtUPDATE_PF, name, [this]() { updatePaths(); }))
1688  {
1689  ++mPathFindThread;
1690  }
1691  }
1692  // If we're stopping don't give callers the expectation that their
1693  // request will be fulfilled, even if it may be serviced.
1694  return mPathFindThread > 0 && !app_.isStopping();
1695 }
1696 
1699 {
1700  return m_mutex;
1701 }
1702 
1703 // The current ledger is the ledger we believe new transactions should go in
1706 {
1707  if (app_.config().reporting())
1708  {
1709  Throw<ReportingShouldProxy>();
1710  }
1711  return app_.openLedger().current();
1712 }
1713 
1716 {
1717 #ifdef RIPPLED_REPORTING
1718  if (app_.config().reporting())
1719  {
1721  if (!seq)
1722  return {};
1723  return getLedgerBySeq(*seq);
1724  }
1725 #endif
1726  return mValidLedger.get();
1727 }
1728 
1729 Rules
1731 {
1732  // Once we have a guarantee that there's always a last validated
1733  // ledger then we can dispense with the if.
1734 
1735  // Return the Rules from the last validated ledger.
1736  if (auto const ledger = getValidatedLedger())
1737  return ledger->rules();
1738 
1739  return Rules(app_.config().features);
1740 }
1741 
1742 // This is the last ledger we published to clients and can lag the validated
1743 // ledger.
1746 {
1747  std::lock_guard lock(m_mutex);
1748  return mPubLedger;
1749 }
1750 
1753 {
1754 #ifdef RIPPLED_REPORTING
1755  if (app_.config().reporting())
1756  return static_cast<PostgresDatabase*>(&app_.getRelationalDatabase())
1757  ->getCompleteLedgers();
1758 #endif
1760  return to_string(mCompleteLedgers);
1761 }
1762 
1765 {
1766  uint256 hash = getHashBySeq(ledgerIndex);
1767  return hash.isNonZero() ? getCloseTimeByHash(hash, ledgerIndex)
1768  : std::nullopt;
1769 }
1770 
1773  LedgerHash const& ledgerHash,
1774  std::uint32_t index)
1775 {
1776  auto nodeObject = app_.getNodeStore().fetchNodeObject(ledgerHash, index);
1777  if (nodeObject && (nodeObject->getData().size() >= 120))
1778  {
1779  SerialIter it(
1780  nodeObject->getData().data(), nodeObject->getData().size());
1781  if (safe_cast<HashPrefix>(it.get32()) == HashPrefix::ledgerMaster)
1782  {
1783  it.skip(
1784  4 + 8 + 32 + // seq drops parentHash
1785  32 + 32 + 4); // txHash acctHash parentClose
1787  }
1788  }
1789 
1790  return std::nullopt;
1791 }
1792 
1793 uint256
1795 {
1796  uint256 hash = mLedgerHistory.getLedgerHash(index);
1797 
1798  if (hash.isNonZero())
1799  return hash;
1800 
1801  return app_.getRelationalDatabase().getHashByIndex(index);
1802 }
1803 
1806 {
1807  std::optional<LedgerHash> ledgerHash;
1808 
1809  if (auto referenceLedger = mValidLedger.get())
1810  ledgerHash = walkHashBySeq(index, referenceLedger, reason);
1811 
1812  return ledgerHash;
1813 }
1814 
1817  std::uint32_t index,
1818  std::shared_ptr<ReadView const> const& referenceLedger,
1819  InboundLedger::Reason reason)
1820 {
1821  if (!referenceLedger || (referenceLedger->info().seq < index))
1822  {
1823  // Nothing we can do. No validated ledger.
1824  return std::nullopt;
1825  }
1826 
1827  // See if the hash for the ledger we need is in the reference ledger
1828  auto ledgerHash = hashOfSeq(*referenceLedger, index, m_journal);
1829  if (ledgerHash)
1830  return ledgerHash;
1831 
1832  // The hash is not in the reference ledger. Get another ledger which can
1833  // be located easily and should contain the hash.
1834  LedgerIndex refIndex = getCandidateLedger(index);
1835  auto const refHash = hashOfSeq(*referenceLedger, refIndex, m_journal);
1836  assert(refHash);
1837  if (refHash)
1838  {
1839  // Try the hash and sequence of a better reference ledger just found
1840  auto ledger = mLedgerHistory.getLedgerByHash(*refHash);
1841 
1842  if (ledger)
1843  {
1844  try
1845  {
1846  ledgerHash = hashOfSeq(*ledger, index, m_journal);
1847  }
1848  catch (SHAMapMissingNode const&)
1849  {
1850  ledger.reset();
1851  }
1852  }
1853 
1854  // Try to acquire the complete ledger
1855  if (!ledger)
1856  {
1857  if (auto const l = app_.getInboundLedgers().acquire(
1858  *refHash, refIndex, reason))
1859  {
1860  ledgerHash = hashOfSeq(*l, index, m_journal);
1861  assert(ledgerHash);
1862  }
1863  }
1864  }
1865  return ledgerHash;
1866 }
1867 
1870 {
1871  if (index <= mValidLedgerSeq)
1872  {
1873  // Always prefer a validated ledger
1874  if (auto valid = mValidLedger.get())
1875  {
1876  if (valid->info().seq == index)
1877  return valid;
1878 
1879  try
1880  {
1881  auto const hash = hashOfSeq(*valid, index, m_journal);
1882 
1883  if (hash)
1884  return mLedgerHistory.getLedgerByHash(*hash);
1885  }
1886  catch (std::exception const&)
1887  {
1888  // Missing nodes are already handled
1889  }
1890  }
1891  }
1892 
1893  if (auto ret = mLedgerHistory.getLedgerBySeq(index))
1894  return ret;
1895 
1896  auto ret = mClosedLedger.get();
1897  if (ret && (ret->info().seq == index))
1898  return ret;
1899 
1900  clearLedger(index);
1901  return {};
1902 }
1903 
1906 {
1907  if (auto ret = mLedgerHistory.getLedgerByHash(hash))
1908  return ret;
1909 
1910  auto ret = mClosedLedger.get();
1911  if (ret && (ret->info().hash == hash))
1912  return ret;
1913 
1914  return {};
1915 }
1916 
1917 void
1919 {
1921  mCompleteLedgers.insert(range(minV, maxV));
1922 }
1923 
1924 void
1926 {
1928  fetch_packs_.sweep();
1929 }
1930 
1931 float
1933 {
1935 }
1936 
1937 void
1939 {
1941  if (seq > 0)
1942  mCompleteLedgers.erase(range(0u, seq - 1));
1943 }
1944 
1945 void
1947 {
1949 }
1950 
1951 void
1953 {
1954  replayData = std::move(replay);
1955 }
1956 
1959 {
1960  return std::move(replayData);
1961 }
1962 
1963 void
1965  std::uint32_t missing,
1966  bool& progress,
1967  InboundLedger::Reason reason,
1969 {
1970  ScopedUnlock sul{sl};
1971  if (auto hash = getLedgerHashForHistory(missing, reason))
1972  {
1973  assert(hash->isNonZero());
1974  auto ledger = getLedgerByHash(*hash);
1975  if (!ledger)
1976  {
1977  if (!app_.getInboundLedgers().isFailure(*hash))
1978  {
1979  ledger =
1980  app_.getInboundLedgers().acquire(*hash, missing, reason);
1981  if (!ledger && missing != fetch_seq_ &&
1982  missing > app_.getNodeStore().earliestLedgerSeq())
1983  {
1984  JLOG(m_journal.trace())
1985  << "fetchForHistory want fetch pack " << missing;
1986  fetch_seq_ = missing;
1987  getFetchPack(missing, reason);
1988  }
1989  else
1990  JLOG(m_journal.trace())
1991  << "fetchForHistory no fetch pack for " << missing;
1992  }
1993  else
1994  JLOG(m_journal.debug())
1995  << "fetchForHistory found failed acquire";
1996  }
1997  if (ledger)
1998  {
1999  auto seq = ledger->info().seq;
2000  assert(seq == missing);
2001  JLOG(m_journal.trace()) << "fetchForHistory acquired " << seq;
2002  if (reason == InboundLedger::Reason::SHARD)
2003  {
2004  ledger->setFull();
2005  {
2006  std::lock_guard lock(m_mutex);
2007  mShardLedger = ledger;
2008  }
2009  if (!ledger->stateMap().family().isShardBacked())
2010  app_.getShardStore()->storeLedger(ledger);
2011  }
2012  else
2013  {
2014  setFullLedger(ledger, false, false);
2015  int fillInProgress;
2016  {
2017  std::lock_guard lock(m_mutex);
2018  mHistLedger = ledger;
2019  fillInProgress = mFillInProgress;
2020  }
2021  if (fillInProgress == 0 &&
2023  ledger->info().parentHash)
2024  {
2025  {
2026  // Previous ledger is in DB
2027  std::lock_guard lock(m_mutex);
2028  mFillInProgress = seq;
2029  }
2031  jtADVANCE, "tryFill", [this, ledger]() {
2032  tryFill(ledger);
2033  });
2034  }
2035  }
2036  progress = true;
2037  }
2038  else
2039  {
2040  std::uint32_t fetchSz;
2041  if (reason == InboundLedger::Reason::SHARD)
2042  // Do not fetch ledger sequences lower
2043  // than the shard's first ledger sequence
2044  fetchSz = app_.getShardStore()->firstLedgerSeq(
2045  app_.getShardStore()->seqToShardIndex(missing));
2046  else
2047  // Do not fetch ledger sequences lower
2048  // than the earliest ledger sequence
2049  fetchSz = app_.getNodeStore().earliestLedgerSeq();
2050  fetchSz = missing >= fetchSz
2051  ? std::min(ledger_fetch_size_, (missing - fetchSz) + 1)
2052  : 0;
2053  try
2054  {
2055  for (std::uint32_t i = 0; i < fetchSz; ++i)
2056  {
2057  std::uint32_t seq = missing - i;
2058  if (auto h = getLedgerHashForHistory(seq, reason))
2059  {
2060  assert(h->isNonZero());
2061  app_.getInboundLedgers().acquire(*h, seq, reason);
2062  }
2063  }
2064  }
2065  catch (std::exception const& ex)
2066  {
2067  JLOG(m_journal.warn())
2068  << "Threw while prefetching: " << ex.what();
2069  }
2070  }
2071  }
2072  else
2073  {
2074  JLOG(m_journal.fatal())
2075  << "Can't find ledger following prevMissing " << missing;
2076  JLOG(m_journal.fatal())
2077  << "Pub:" << mPubLedgerSeq << " Val:" << mValidLedgerSeq;
2078  JLOG(m_journal.fatal())
2079  << "Ledgers: " << app_.getLedgerMaster().getCompleteLedgers();
2080  JLOG(m_journal.fatal())
2081  << "Acquire reason: "
2082  << (reason == InboundLedger::Reason::HISTORY ? "HISTORY" : "SHARD");
2083  clearLedger(missing + 1);
2084  progress = true;
2085  }
2086 }
2087 
2088 // Try to publish ledgers, acquire missing ledgers
2089 void
2091 {
2092  do
2093  {
2094  mAdvanceWork = false; // If there's work to do, we'll make progress
2095  bool progress = false;
2096 
2097  auto const pubLedgers = findNewLedgersToPublish(sl);
2098  if (pubLedgers.empty())
2099  {
2100  if (!standalone_ && !app_.getFeeTrack().isLoadedLocal() &&
2105  {
2106  // We are in sync, so can acquire
2109  {
2111  missing = prevMissing(
2113  mPubLedger->info().seq,
2115  }
2116  if (missing)
2117  {
2118  JLOG(m_journal.trace())
2119  << "tryAdvance discovered missing " << *missing;
2120  if ((mFillInProgress == 0 || *missing > mFillInProgress) &&
2121  shouldAcquire(
2125  *missing,
2126  m_journal))
2127  {
2128  JLOG(m_journal.trace())
2129  << "advanceThread should acquire";
2130  }
2131  else
2132  missing = std::nullopt;
2133  }
2134  if (!missing && mFillInProgress == 0)
2135  {
2136  if (auto shardStore = app_.getShardStore())
2137  {
2138  missing = shardStore->prepareLedger(mValidLedgerSeq);
2139  if (missing)
2141  }
2142  }
2143  if (missing)
2144  {
2145  fetchForHistory(*missing, progress, reason, sl);
2147  {
2148  JLOG(m_journal.debug())
2149  << "tryAdvance found last valid changed";
2150  progress = true;
2151  }
2152  }
2153  }
2154  else
2155  {
2156  mHistLedger.reset();
2157  mShardLedger.reset();
2158  JLOG(m_journal.trace()) << "tryAdvance not fetching history";
2159  }
2160  }
2161  else
2162  {
2163  JLOG(m_journal.trace()) << "tryAdvance found " << pubLedgers.size()
2164  << " ledgers to publish";
2165  for (auto const& ledger : pubLedgers)
2166  {
2167  {
2168  ScopedUnlock sul{sl};
2169  JLOG(m_journal.debug())
2170  << "tryAdvance publishing seq " << ledger->info().seq;
2171  setFullLedger(ledger, true, true);
2172  }
2173 
2174  setPubLedger(ledger);
2175 
2176  {
2177  ScopedUnlock sul{sl};
2178  app_.getOPs().pubLedger(ledger);
2179  }
2180  }
2181 
2183  progress = newPFWork("pf:newLedger", sl);
2184  }
2185  if (progress)
2186  mAdvanceWork = true;
2187  } while (mAdvanceWork);
2188 }
2189 
2190 void
2192 {
2193  fetch_packs_.canonicalize_replace_client(hash, data);
2194 }
2195 
2198 {
2199  Blob data;
2200  if (fetch_packs_.retrieve(hash, data))
2201  {
2202  fetch_packs_.del(hash, false);
2203  if (hash == sha512Half(makeSlice(data)))
2204  return data;
2205  }
2206  return std::nullopt;
2207 }
2208 
2209 void
2211 {
2212  if (!mGotFetchPackThread.test_and_set(std::memory_order_acquire))
2213  {
2214  app_.getJobQueue().addJob(jtLEDGER_DATA, "gotFetchPack", [&]() {
2216  mGotFetchPackThread.clear(std::memory_order_release);
2217  });
2218  }
2219 }
2220 
2246 static void
2248  SHAMap const& want,
2249  SHAMap const* have,
2250  std::uint32_t cnt,
2251  protocol::TMGetObjectByHash* into,
2252  std::uint32_t seq,
2253  bool withLeaves = true)
2254 {
2255  assert(cnt != 0);
2256 
2257  Serializer s(1024);
2258 
2259  want.visitDifferences(
2260  have,
2261  [&s, withLeaves, &cnt, into, seq](SHAMapTreeNode const& n) -> bool {
2262  if (!withLeaves && n.isLeaf())
2263  return true;
2264 
2265  s.erase();
2266  n.serializeWithPrefix(s);
2267 
2268  auto const& hash = n.getHash().as_uint256();
2269 
2270  protocol::TMIndexedObject* obj = into->add_objects();
2271  obj->set_ledgerseq(seq);
2272  obj->set_hash(hash.data(), hash.size());
2273  obj->set_data(s.getDataPtr(), s.getLength());
2274 
2275  return --cnt != 0;
2276  });
2277 }
2278 
2279 void
2281  std::weak_ptr<Peer> const& wPeer,
2283  uint256 haveLedgerHash,
2284  UptimeClock::time_point uptime)
2285 {
2286  using namespace std::chrono_literals;
2287  if (UptimeClock::now() > uptime + 1s)
2288  {
2289  JLOG(m_journal.info()) << "Fetch pack request got stale";
2290  return;
2291  }
2292 
2293  if (app_.getFeeTrack().isLoadedLocal() || (getValidatedLedgerAge() > 40s))
2294  {
2295  JLOG(m_journal.info()) << "Too busy to make fetch pack";
2296  return;
2297  }
2298 
2299  auto peer = wPeer.lock();
2300 
2301  if (!peer)
2302  return;
2303 
2304  auto have = getLedgerByHash(haveLedgerHash);
2305 
2306  if (!have)
2307  {
2308  JLOG(m_journal.info())
2309  << "Peer requests fetch pack for ledger we don't have: " << have;
2310  peer->charge(Resource::feeRequestNoReply);
2311  return;
2312  }
2313 
2314  if (have->open())
2315  {
2316  JLOG(m_journal.warn())
2317  << "Peer requests fetch pack from open ledger: " << have;
2318  peer->charge(Resource::feeInvalidRequest);
2319  return;
2320  }
2321 
2322  if (have->info().seq < getEarliestFetch())
2323  {
2324  JLOG(m_journal.debug()) << "Peer requests fetch pack that is too early";
2325  peer->charge(Resource::feeInvalidRequest);
2326  return;
2327  }
2328 
2329  auto want = getLedgerByHash(have->info().parentHash);
2330 
2331  if (!want)
2332  {
2333  JLOG(m_journal.info())
2334  << "Peer requests fetch pack for ledger whose predecessor we "
2335  << "don't have: " << have;
2336  peer->charge(Resource::feeRequestNoReply);
2337  return;
2338  }
2339 
2340  try
2341  {
2342  Serializer hdr(128);
2343 
2344  protocol::TMGetObjectByHash reply;
2345  reply.set_query(false);
2346 
2347  if (request->has_seq())
2348  reply.set_seq(request->seq());
2349 
2350  reply.set_ledgerhash(request->ledgerhash());
2351  reply.set_type(protocol::TMGetObjectByHash::otFETCH_PACK);
2352 
2353  // Building a fetch pack:
2354  // 1. Add the header for the requested ledger.
2355  // 2. Add the nodes for the AccountStateMap of that ledger.
2356  // 3. If there are transactions, add the nodes for the
2357  // transactions of the ledger.
2358  // 4. If the FetchPack now contains at least 512 entries then stop.
2359  // 5. If not very much time has elapsed, then loop back and repeat
2360  // the same process adding the previous ledger to the FetchPack.
2361  do
2362  {
2363  std::uint32_t lSeq = want->info().seq;
2364 
2365  {
2366  // Serialize the ledger header:
2367  hdr.erase();
2368 
2370  addRaw(want->info(), hdr);
2371 
2372  // Add the data
2373  protocol::TMIndexedObject* obj = reply.add_objects();
2374  obj->set_hash(
2375  want->info().hash.data(), want->info().hash.size());
2376  obj->set_data(hdr.getDataPtr(), hdr.getLength());
2377  obj->set_ledgerseq(lSeq);
2378  }
2379 
2381  want->stateMap(), &have->stateMap(), 16384, &reply, lSeq);
2382 
2383  // We use nullptr here because transaction maps are per ledger
2384  // and so the requestor is unlikely to already have it.
2385  if (want->info().txHash.isNonZero())
2386  populateFetchPack(want->txMap(), nullptr, 512, &reply, lSeq);
2387 
2388  if (reply.objects().size() >= 512)
2389  break;
2390 
2391  have = std::move(want);
2392  want = getLedgerByHash(have->info().parentHash);
2393  } while (want && UptimeClock::now() <= uptime + 1s);
2394 
2395  auto msg = std::make_shared<Message>(reply, protocol::mtGET_OBJECTS);
2396 
2397  JLOG(m_journal.info())
2398  << "Built fetch pack with " << reply.objects().size() << " nodes ("
2399  << msg->getBufferSize() << " bytes)";
2400 
2401  peer->send(msg);
2402  }
2403  catch (std::exception const& ex)
2404  {
2405  JLOG(m_journal.warn())
2406  << "Exception building fetch pach. Exception: " << ex.what();
2407  }
2408 }
2409 
2412 {
2413  return fetch_packs_.getCacheSize();
2414 }
2415 
2416 // Returns the minimum ledger sequence in SQL database, if any.
2419 {
2421 }
2422 
2424 LedgerMaster::txnIdFromIndex(uint32_t ledgerSeq, uint32_t txnIndex)
2425 {
2426  uint32_t first = 0, last = 0;
2427 
2428  if (!getValidatedRange(first, last) || last < ledgerSeq)
2429  return {};
2430 
2431  auto const lgr = getLedgerBySeq(ledgerSeq);
2432  if (!lgr || lgr->txs.empty())
2433  return {};
2434 
2435  for (auto it = lgr->txs.begin(); it != lgr->txs.end(); ++it)
2436  if (it->first && it->second &&
2437  it->second->isFieldPresent(sfTransactionIndex) &&
2438  it->second->getFieldU32(sfTransactionIndex) == txnIndex)
2439  return it->first->getTransactionID();
2440 
2441  return {};
2442 }
2443 
2444 } // namespace ripple
ripple::NetworkOPs::pubLedger
virtual void pubLedger(std::shared_ptr< ReadView const > const &lpAccepted)=0
beast::Journal::fatal
Stream fatal() const
Definition: Journal.h:338
ripple::ReadView::info
virtual LedgerInfo const & info() const =0
Returns information about the ledger.
ripple::LedgerMaster::getValidatedRange
bool getValidatedRange(std::uint32_t &minVal, std::uint32_t &maxVal)
Definition: LedgerMaster.cpp:681
ripple::LedgerMaster::mPubLedger
std::shared_ptr< Ledger const > mPubLedger
Definition: LedgerMaster.h:352
ripple::Resource::feeInvalidRequest
const Charge feeInvalidRequest
Schedule of fees charged for imposing load on the server.
ripple::RelationalDatabase::getMaxLedgerSeq
virtual std::optional< LedgerIndex > getMaxLedgerSeq()=0
getMaxLedgerSeq Returns the maximum ledger sequence in the Ledgers table.
ripple::Application
Definition: Application.h:116
ripple::LedgerMaster::mClosedLedger
LedgerHolder mClosedLedger
Definition: LedgerMaster.h:346
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:1745
ripple::LedgerIndex
std::uint32_t LedgerIndex
A ledger index.
Definition: Protocol.h:99
std::bind
T bind(T... args)
ripple::LedgerMaster::fetch_packs_
TaggedCache< uint256, Blob > fetch_packs_
Definition: LedgerMaster.h:406
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:2280
ripple::LedgerMaster::clearLedgerCachePrior
void clearLedgerCachePrior(LedgerIndex seq)
Definition: LedgerMaster.cpp:1946
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:1925
ripple::SizedItem
SizedItem
Definition: Config.h:51
std::exception
STL class.
ripple::base_uint::isNonZero
bool isNonZero() const
Definition: base_uint.h:537
beast::Journal::trace
Stream trace() const
Severity stream access functions.
Definition: Journal.h:308
ripple::LedgerMaster::mBuildingLedgerSeq
std::atomic< LedgerIndex > mBuildingLedgerSeq
Definition: LedgerMaster.h:393
ripple::LedgerMaster::app_
Application & app_
Definition: LedgerMaster.h:340
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:366
std::atomic_flag::test_and_set
T test_and_set(T... args)
ripple::LedgerMaster::mHeldTransactions
CanonicalTXSet mHeldTransactions
Definition: LedgerMaster.h:368
ripple::Serializer::erase
void erase()
Definition: Serializer.h:210
ripple::Config::LEDGER_REPLAY
bool LEDGER_REPLAY
Definition: Config.h:233
std::pair::second
T second
std::vector::reserve
T reserve(T... args)
ripple::CanonicalTXSet::popAcctTransaction
std::shared_ptr< STTx const > popAcctTransaction(std::shared_ptr< STTx const > const &tx)
Definition: CanonicalTXSet.cpp:62
ripple::LedgerHistory::fixIndex
bool fixIndex(LedgerIndex ledgerIndex, LedgerHash const &ledgerHash)
Repair a hash to index mapping.
Definition: LedgerHistory.cpp:508
ripple::Validations::fees
std::vector< std::uint32_t > fees(ID const &ledgerID, std::uint32_t baseFee)
Returns fees reported by trusted full validators in the given ledger.
Definition: Validations.h:1079
ripple::LedgerHolder::set
void set(std::shared_ptr< Ledger const > ledger)
Definition: LedgerHolder.h:44
ripple::LedgerMaster::getValidLedgerIndex
LedgerIndex getValidLedgerIndex()
Definition: LedgerMaster.cpp:213
ripple::Application::getAmendmentTable
virtual AmendmentTable & getAmendmentTable()=0
ripple::OpenView
Writable ledger view that accumulates state and tx changes.
Definition: OpenView.h:55
ripple::InboundLedger::Reason::GENERIC
@ GENERIC
vector
std::string::find
T find(T... args)
std::vector::size
T size(T... args)
ripple::LedgerMaster::mHistLedger
std::shared_ptr< Ledger const > mHistLedger
Definition: LedgerMaster.h:358
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:415
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:1958
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:1730
ripple::AmendmentTable::doValidatedLedger
void doValidatedLedger(std::shared_ptr< ReadView const > const &lastValidatedLedger)
Called when a new fully-validated ledger is accepted.
Definition: AmendmentTable.h:92
ripple::LedgerHeader::seq
LedgerIndex seq
Definition: LedgerHeader.h:41
ripple::LedgerMaster::mCompleteLock
std::recursive_mutex mCompleteLock
Definition: LedgerMaster.h:373
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:326
std::recursive_mutex
STL class.
ripple::LedgerMaster::newPFWork
bool newPFWork(const char *name, std::unique_lock< std::recursive_mutex > &)
A thread needs to be dispatched to handle pathfinding work of some kind.
Definition: LedgerMaster.cpp:1676
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:1905
std::cerr
ripple::Application::isStopping
virtual bool isStopping() const =0
ripple::LedgerMaster::isNewPathRequest
bool isNewPathRequest()
Definition: LedgerMaster.cpp:1654
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:120
std::vector::back
T back(T... args)
ripple::LoadFeeTrack::getLoadBase
std::uint32_t getLoadBase() const
Definition: LoadFeeTrack.h:89
ripple::jtUPDATE_PF
@ jtUPDATE_PF
Definition: Job.h:57
ripple::Application::timeKeeper
virtual TimeKeeper & timeKeeper()=0
ripple::LedgerMaster::getEarliestFetch
std::uint32_t getEarliestFetch()
Definition: LedgerMaster.cpp:748
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:1805
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::TimeKeeper::closeTime
time_point closeTime() const
Returns the predicted close time, in network time.
Definition: TimeKeeper.h:76
ripple::LedgerMaster::setFullLedger
void setFullLedger(std::shared_ptr< Ledger const > const &ledger, bool isSynchronous, bool isCurrent)
Definition: LedgerMaster.cpp:962
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:907
std::atomic_flag::clear
T clear(T... args)
ripple::LedgerMaster::fetch_depth_
const std::uint32_t fetch_depth_
Definition: LedgerMaster.h:399
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:1752
ripple::LedgerMaster::ledger_fetch_size_
const std::uint32_t ledger_fetch_size_
Definition: LedgerMaster.h:404
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:1698
ripple::LedgerHeader::hash
uint256 hash
Definition: LedgerHeader.h:49
ripple::LedgerMaster::mGotFetchPackThread
std::atomic_flag mGotFetchPackThread
Definition: LedgerMaster.h:386
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:374
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:351
ripple::UptimeClock::now
static time_point now()
Definition: UptimeClock.cpp:63
ripple::LedgerMaster::mFillInProgress
int mFillInProgress
Definition: LedgerMaster.h:381
ripple::NetworkOPs::isNeedNetworkLedger
virtual bool isNeedNetworkLedger()=0
ripple::sfServerVersion
const SF_UINT64 sfServerVersion
ripple::LedgerMaster::replayData
std::unique_ptr< LedgerReplay > replayData
Definition: LedgerMaster.h:371
ripple::LedgerMaster::gotFetchPack
void gotFetchPack(bool progress, std::uint32_t seq)
Definition: LedgerMaster.cpp:2210
ripple::LedgerMaster::fetchForHistory
void fetchForHistory(std::uint32_t missing, bool &progress, InboundLedger::Reason reason, std::unique_lock< std::recursive_mutex > &)
Definition: LedgerMaster.cpp:1964
ripple::LedgerMaster::getFetchPack
std::optional< Blob > getFetchPack(uint256 const &hash) override
Retrieves partial ledger data of the coresponding hash from peers.
Definition: LedgerMaster.cpp:2197
ripple::LedgerMaster::failedSave
void failedSave(std::uint32_t seq, uint256 const &hash)
Definition: LedgerMaster.cpp:1023
ripple::Application::getLedgerMaster
virtual LedgerMaster & getLedgerMaster()=0
ripple::InboundLedgers::acquire
virtual std::shared_ptr< Ledger const > acquire(uint256 const &hash, std::uint32_t seq, InboundLedger::Reason)=0
std::atomic::load
T load(T... args)
ripple::NetworkOPs::setAmendmentWarned
virtual void setAmendmentWarned()=0
ripple::Application::pendingSaves
virtual PendingSaves & pendingSaves()=0
ripple::LedgerHolder::empty
bool empty()
Definition: LedgerHolder.h:63
ripple::LedgerHistory::getLedgerByHash
std::shared_ptr< Ledger const > getLedgerByHash(LedgerHash const &ledgerHash)
Retrieve a ledger given its hash.
Definition: LedgerHistory.cpp:116
ripple::Serializer::getDataPtr
const void * getDataPtr() const
Definition: Serializer.h:190
ripple::MAX_LEDGER_GAP
static constexpr int MAX_LEDGER_GAP
Definition: LedgerMaster.cpp:146
ripple::RelationalDatabase::getHashByIndex
virtual uint256 getHashByIndex(LedgerIndex ledgerIndex)=0
getHashByIndex Returns the hash of the ledger with the given sequence.
chrono
ripple::LedgerMaster::getFullValidatedRange
bool getFullValidatedRange(std::uint32_t &minVal, std::uint32_t &maxVal)
Definition: LedgerMaster.cpp:654
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:2247
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:591
ripple::AmendmentTable::firstUnsupportedExpected
virtual std::optional< NetClock::time_point > firstUnsupportedExpected() const =0
ripple::JobQueue::isStopping
bool isStopping() const
Definition: JobQueue.h:230
ripple::calculatePercent
constexpr std::size_t calculatePercent(std::size_t count, std::size_t total)
Calculate one number divided by another number in percentage.
Definition: MathUtilities.h:44
beast::Journal::Stream
Provide a light-weight way to check active() before string formatting.
Definition: Journal.h:193
ripple::RelationalDatabase::getMinLedgerSeq
virtual std::optional< LedgerIndex > getMinLedgerSeq()=0
getMinLedgerSeq Returns the minimum ledger sequence in the Ledgers table.
beast::Journal::error
Stream error() const
Definition: Journal.h:332
beast::Journal::info
Stream info() const
Definition: Journal.h:320
ripple::LedgerMaster::isCompatible
bool isCompatible(ReadView const &, beast::Journal::Stream, char const *reason)
Definition: LedgerMaster.cpp:219
std::chrono::time_point
ripple::LedgerMaster::minSqlSeq
std::optional< LedgerIndex > minSqlSeq()
Definition: LedgerMaster.cpp:2418
ripple::LedgerMaster::updatePaths
void updatePaths()
Definition: LedgerMaster.cpp:1542
ripple::SHAMapTreeNode::isLeaf
virtual bool isLeaf() const =0
Determines if this is a leaf node.
ripple::hashOfSeq
std::optional< uint256 > hashOfSeq(ReadView const &ledger, LedgerIndex seq, beast::Journal journal)
Return the hash of a ledger by sequence.
Definition: View.cpp:661
ripple::OrderBookDB::setup
void setup(std::shared_ptr< ReadView const > const &ledger)
Definition: OrderBookDB.cpp:38
std::copy
T copy(T... args)
ripple::LedgerMaster::getLedgerBySeq
std::shared_ptr< Ledger const > getLedgerBySeq(std::uint32_t index)
Definition: LedgerMaster.cpp:1869
ripple::LedgerMaster::txnIdFromIndex
std::optional< uint256 > txnIdFromIndex(uint32_t ledgerSeq, uint32_t txnIndex)
Definition: LedgerMaster.cpp:2424
ripple::Overlay::getActivePeers
virtual PeerSequence getActivePeers() const =0
Returns a sequence representing the current list of peers.
ripple::LedgerMaster::newPathRequest
bool newPathRequest()
Definition: LedgerMaster.cpp:1646
ripple::SerialIter
Definition: Serializer.h:311
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
ripple::Application::getValidations
virtual RCLValidations & getValidations()=0
std::uint32_t
ripple::LedgerReplayer::replay
void replay(InboundLedger::Reason r, uint256 const &finishLedgerHash, std::uint32_t totalNumLedgers)
Replay a range of ledgers.
Definition: LedgerReplayer.cpp:45
ripple::LedgerMaster::addHeldTransaction
void addHeldTransaction(std::shared_ptr< Transaction > const &trans)
Definition: LedgerMaster.cpp: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:384
ripple::range
ClosedInterval< T > range(T low, T high)
Create a closed range interval.
Definition: RangeSet.h:54
ripple::Application::getPathRequests
virtual PathRequests & getPathRequests()=0
ripple::LedgerHolder::get
std::shared_ptr< Ledger const > get()
Definition: LedgerHolder.h:56
ripple::CanonicalTXSet::insert
void insert(std::shared_ptr< STTx const > const &txn)
Definition: CanonicalTXSet.cpp:52
ripple::prevMissing
std::optional< T > prevMissing(RangeSet< T > const &rs, T t, T minVal=0)
Find the largest value not in the set that is less than a given value.
Definition: RangeSet.h:183
ripple::LedgerMaster::getCurrentLedger
std::shared_ptr< ReadView const > getCurrentLedger()
Definition: LedgerMaster.cpp:1705
ripple::TimeKeeper::now
time_point now() const override
Returns the current time, using the server's clock.
Definition: TimeKeeper.h:64
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:1665
ripple::LedgerMaster::getNeededValidations
std::size_t getNeededValidations()
Determines how many validations are needed to fully validate a ledger.
Definition: LedgerMaster.cpp:1087
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:499
ripple::LedgerMaster::mAdvanceThread
bool mAdvanceThread
Definition: LedgerMaster.h:377
ripple::LedgerMaster::checkAccept
void checkAccept(std::shared_ptr< Ledger const > const &ledger)
Definition: LedgerMaster.cpp:1093
ripple::Application::validators
virtual ValidatorList & validators()=0
ripple::AmendmentTable::hasUnsupportedEnabled
virtual bool hasUnsupportedEnabled() const =0
returns true if one or more amendments on the network have been enabled that this server does not sup...
std::weak_ptr< Peer >
ripple::sfTransactionIndex
const SF_UINT32 sfTransactionIndex
std::min
T min(T... args)
ripple::SHAMapTreeNode::getHash
SHAMapHash const & getHash() const
Return the hash of this node.
Definition: SHAMapTreeNode.h:143
ripple::LedgerMaster::max_ledger_difference_
const LedgerIndex max_ledger_difference_
Definition: LedgerMaster.h:412
ripple::Serializer
Definition: Serializer.h:40
ripple::LedgerMaster::getFetchPackCacheSize
std::size_t getFetchPackCacheSize() const
Definition: LedgerMaster.cpp:2411
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:355
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:380
ripple::ReadView
A view into a ledger.
Definition: ReadView.h:54
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::NetworkOPs::isBlocked
virtual bool isBlocked()=0
ripple::Config::features
std::unordered_set< uint256, beast::uhash<> > features
Definition: Config.h:288
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:389
ripple::Application::getNodeStore
virtual NodeStore::Database & getNodeStore()=0
ripple::Application::journal
virtual beast::Journal journal(std::string const &name)=0
ripple::addRaw
void addRaw(LedgerHeader const &info, Serializer &s, bool includeHash)
Definition: protocol/impl/LedgerHeader.cpp:25
ripple::LedgerHeader::validated
bool validated
Definition: LedgerHeader.h:59
ripple::LedgerMaster::ledger_history_
const std::uint32_t ledger_history_
Definition: LedgerMaster.h:402
ripple::LedgerMaster::mPubLedgerSeq
std::atomic< LedgerIndex > mPubLedgerSeq
Definition: LedgerMaster.h:390
cstdlib
std::endl
T endl(T... args)
ripple::LedgerHistory::getCacheHitRate
float getCacheHitRate()
Get the ledgers_by_hash cache hit rate.
Definition: LedgerHistory.h:53
ripple::CanonicalTXSet::size
size_t size() const
Definition: CanonicalTXSet.h:155
ripple::LedgerMaster::getCloseTimeBySeq
std::optional< NetClock::time_point > getCloseTimeBySeq(LedgerIndex ledgerIndex)
Definition: LedgerMaster.cpp:1764
ripple::LedgerMaster::isValidated
bool isValidated(ReadView const &ledger)
Definition: LedgerMaster.cpp:605
limits
ripple::LedgerMaster::addFetchPack
void addFetchPack(uint256 const &hash, std::shared_ptr< Blob > data)
Definition: LedgerMaster.cpp:2191
ripple::LedgerMaster::clearLedger
void clearLedger(std::uint32_t seq)
Definition: LedgerMaster.cpp:598
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:1342
ripple::LedgerMaster::m_journal
beast::Journal m_journal
Definition: LedgerMaster.h:341
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:392
ripple::PostgresDatabase
Definition: PostgresDatabase.h:27
ripple::LedgerMaster::getCurrentLedgerIndex
LedgerIndex getCurrentLedgerIndex()
Definition: LedgerMaster.cpp:207
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:1952
ripple::LedgerMaster::getValidatedLedger
std::shared_ptr< Ledger const > getValidatedLedger()
Definition: LedgerMaster.cpp:1715
ripple::LedgerMaster::mLastValidLedger
std::pair< uint256, LedgerIndex > mLastValidLedger
Definition: LedgerMaster.h:364
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:361
beast::Journal::debug
Stream debug() const
Definition: Journal.h:314
std::size_t
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
std::make_pair
T make_pair(T... args)
ripple::Serializer::add32
int add32(std::uint32_t i)
Definition: Serializer.cpp:38
ripple::LedgerMaster::storeLedger
bool storeLedger(std::shared_ptr< Ledger const > ledger)
Definition: LedgerMaster.cpp: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:1918
ripple::NodeStore::Database::earliestLedgerSeq
std::uint32_t earliestLedgerSeq() const noexcept
Definition: Database.h:238
ripple::jtADVANCE
@ jtADVANCE
Definition: Job.h:68
std::max
T max(T... args)
ripple::Serializer::getLength
int getLength() const
Definition: Serializer.h:200
ripple::getCandidateLedger
LedgerIndex getCandidateLedger(LedgerIndex requested)
Find a ledger index from which we could easily get the requested ledger.
Definition: View.h:252
ripple::LedgerMaster::consensusBuilt
void consensusBuilt(std::shared_ptr< Ledger const > const &ledger, uint256 const &consensusHash, Json::Value consensus)
Report that the consensus process built a particular ledger.
Definition: LedgerMaster.cpp:1241
ripple::LedgerMaster::tryFill
void tryFill(std::shared_ptr< Ledger const > ledger)
Definition: LedgerMaster.cpp:762
ripple::SerialIter::get32
std::uint32_t get32()
Definition: Serializer.cpp:386
ripple::LedgerMaster::mValidLedger
LedgerHolder mValidLedger
Definition: LedgerMaster.h:349
ripple::LedgerMaster::fetch_seq_
std::uint32_t fetch_seq_
Definition: LedgerMaster.h:408
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:1794
ripple::LedgerMaster::findNewLedgersToPublish
std::vector< std::shared_ptr< Ledger const > > findNewLedgersToPublish(std::unique_lock< std::recursive_mutex > &)
Definition: LedgerMaster.cpp:1365
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:1772
ripple::LedgerMaster::mPathFindThread
int mPathFindThread
Definition: LedgerMaster.h:383
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:391
ripple::LedgerMaster::setBuildingLedger
void setBuildingLedger(LedgerIndex index)
Definition: LedgerMaster.cpp:585
ripple::LedgerMaster::doAdvance
void doAdvance(std::unique_lock< std::recursive_mutex > &)
Definition: LedgerMaster.cpp:2090
std::unordered_map
STL class.
ripple::LedgerMaster::tryAdvance
void tryAdvance()
Definition: LedgerMaster.cpp:1510
ripple::ReadView::open
virtual bool open() const =0
Returns true if this reflects an open ledger.
ripple::LedgerMaster::clearPriorLedgers
void clearPriorLedgers(LedgerIndex seq)
Definition: LedgerMaster.cpp:1938
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:577
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::runtime_error::what
T what(T... args)
ripple::LedgerMaster::getCacheHitRate
float getCacheHitRate()
Definition: LedgerMaster.cpp:1932
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:343
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:441
ripple::LedgerMaster::standalone_
const bool standalone_
Definition: LedgerMaster.h:396
std::chrono