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