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