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