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