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