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