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