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