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