rippled
InboundLedger.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/ledger/AccountStateSF.h>
21 #include <ripple/app/ledger/InboundLedger.h>
22 #include <ripple/app/ledger/InboundLedgers.h>
23 #include <ripple/app/ledger/LedgerMaster.h>
24 #include <ripple/app/ledger/TransactionStateSF.h>
25 #include <ripple/app/main/Application.h>
26 #include <ripple/app/misc/NetworkOPs.h>
27 #include <ripple/basics/Log.h>
28 #include <ripple/core/JobQueue.h>
29 #include <ripple/nodestore/DatabaseShard.h>
30 #include <ripple/overlay/Overlay.h>
31 #include <ripple/protocol/HashPrefix.h>
32 #include <ripple/protocol/jss.h>
33 #include <ripple/resource/Fees.h>
34 #include <ripple/shamap/SHAMapNodeID.h>
35 
36 #include <algorithm>
37 
38 namespace ripple {
39 
40 using namespace std::chrono_literals;
41 
42 enum {
43  // Number of peers to start with
45 
46  // Number of peers to add on a timeout
47  ,
49 
50  // how many timeouts before we giveup
51  ,
53 
54  // how many timeouts before we get aggressive
55  ,
57 
58  // Number of nodes to find initially
59  ,
61 
62  // Number of nodes to request for a reply
63  ,
65 
66  // Number of nodes to request blindly
67  ,
69 };
70 
71 // millisecond for each ledger timeout
72 auto constexpr ledgerAcquireTimeout = 2500ms;
73 
75  Application& app,
76  uint256 const& hash,
77  std::uint32_t seq,
78  Reason reason,
79  clock_type& clock)
80  : PeerSet(
81  app,
82  hash,
84  clock,
85  app.journal("InboundLedger"))
86  , mHaveHeader(false)
87  , mHaveState(false)
88  , mHaveTransactions(false)
89  , mSignaled(false)
90  , mByHash(true)
91  , mSeq(seq)
92  , mReason(reason)
93  , mReceiveDispatched(false)
94 {
95  JLOG(m_journal.trace()) << "Acquiring ledger " << mHash;
96 }
97 
98 void
100 {
101  ScopedLockType sl(mLock);
102  collectionLock.unlock();
103  tryDB(app_.family());
104  if (mFailed)
105  return;
106  if (!mComplete)
107  {
108  auto shardStore = app_.getShardStore();
109  if (mReason == Reason::SHARD)
110  {
111  if (!shardStore || !app_.shardFamily())
112  {
113  JLOG(m_journal.error())
114  << "Acquiring shard with no shard store available";
115  mFailed = true;
116  return;
117  }
118  mHaveHeader = false;
119  mHaveTransactions = false;
120  mHaveState = false;
121  mLedger.reset();
122  tryDB(*app_.shardFamily());
123  if (mFailed)
124  return;
125  }
126  else if (shardStore && mSeq >= shardStore->earliestLedgerSeq())
127  {
128  if (auto l = shardStore->fetchLedger(mHash, mSeq))
129  {
130  mHaveHeader = true;
131  mHaveTransactions = true;
132  mHaveState = true;
133  mComplete = true;
134  mLedger = std::move(l);
135  }
136  }
137  }
138  if (!mComplete)
139  {
140  addPeers();
141  execute();
142  return;
143  }
144 
145  JLOG(m_journal.debug()) << "Acquiring ledger we already have in "
146  << " local store. " << mHash;
147  mLedger->setImmutable(app_.config());
148 
150  return;
151 
153 
154  // Check if this could be a newer fully-validated ledger
155  if (mReason == Reason::CONSENSUS)
157 }
158 
159 void
161 {
163  {
164  JLOG(m_journal.debug()) << "Deferring InboundLedger timer due to load";
165  setTimer();
166  return;
167  }
168 
170  jtLEDGER_DATA, "InboundLedger", [ptr = shared_from_this()](Job&) {
171  ptr->invokeOnTimer();
172  });
173 }
174 void
176 {
177  ScopedLockType sl(mLock);
178 
179  // If we didn't know the sequence number, but now do, save it
180  if ((seq != 0) && (mSeq == 0))
181  mSeq = seq;
182 
183  // Prevent this from being swept
184  touch();
185 }
186 
187 bool
189 {
190  ScopedLockType sl(mLock);
191  if (!isDone())
192  {
193  if (mLedger)
194  tryDB(mLedger->stateMap().family());
195  else if (mReason == Reason::SHARD)
196  tryDB(*app_.shardFamily());
197  else
198  tryDB(app_.family());
199  if (mFailed || mComplete)
200  {
201  done();
202  return true;
203  }
204  }
205  return false;
206 }
207 
209 {
210  // Save any received AS data not processed. It could be useful
211  // for populating a different ledger
212  for (auto& entry : mReceivedData)
213  {
214  if (entry.second->type() == protocol::liAS_NODE)
215  app_.getInboundLedgers().gotStaleData(entry.second);
216  }
217  if (!isDone())
218  {
219  JLOG(m_journal.debug())
220  << "Acquire " << mHash << " abort "
221  << ((getTimeouts() == 0) ? std::string()
222  : (std::string("timeouts:") +
223  std::to_string(getTimeouts()) + " "))
224  << mStats.get();
225  }
226 }
227 
230 {
232 
233  if (mLedger->info().txHash.isNonZero())
234  {
235  if (mLedger->txMap().getHash().isZero())
236  ret.push_back(mLedger->info().txHash);
237  else
238  ret = mLedger->txMap().getNeededHashes(max, filter);
239  }
240 
241  return ret;
242 }
243 
246 {
248 
249  if (mLedger->info().accountHash.isNonZero())
250  {
251  if (mLedger->stateMap().getHash().isZero())
252  ret.push_back(mLedger->info().accountHash);
253  else
254  ret = mLedger->stateMap().getNeededHashes(max, filter);
255  }
256 
257  return ret;
258 }
259 
262 {
263  SerialIter sit(data.data(), data.size());
264 
265  if (hasPrefix)
266  sit.get32();
267 
268  LedgerInfo info;
269 
270  info.seq = sit.get32();
271  info.drops = sit.get64();
272  info.parentHash = sit.get256();
273  info.txHash = sit.get256();
274  info.accountHash = sit.get256();
275  info.parentCloseTime =
279  info.closeFlags = sit.get8();
280 
281  return info;
282 }
283 
284 // See how much of the ledger data is stored locally
285 // Data found in a fetch pack will be stored
286 void
288 {
289  if (!mHaveHeader)
290  {
291  auto makeLedger = [&, this](Blob const& data) {
292  JLOG(m_journal.trace()) << "Ledger header found in fetch pack";
293  mLedger = std::make_shared<Ledger>(
294  deserializeHeader(makeSlice(data), true), app_.config(), f);
295  if (mLedger->info().hash != mHash ||
296  (mSeq != 0 && mSeq != mLedger->info().seq))
297  {
298  // We know for a fact the ledger can never be acquired
299  JLOG(m_journal.warn())
300  << "hash " << mHash << " seq " << std::to_string(mSeq)
301  << " cannot be a ledger";
302  mLedger.reset();
303  mFailed = true;
304  }
305  };
306 
307  // Try to fetch the ledger header from the DB
308  auto node = f.db().fetch(mHash, mSeq);
309  if (!node)
310  {
311  auto data = app_.getLedgerMaster().getFetchPack(mHash);
312  if (!data)
313  return;
314  JLOG(m_journal.trace()) << "Ledger header found in fetch pack";
315  makeLedger(*data);
316  if (mLedger)
317  f.db().store(
318  hotLEDGER, std::move(*data), mHash, mLedger->info().seq);
319  }
320  else
321  {
322  JLOG(m_journal.trace()) << "Ledger header found in node store";
323  makeLedger(node->getData());
324  }
325  if (mFailed)
326  return;
327  if (mSeq == 0)
328  mSeq = mLedger->info().seq;
329  mLedger->stateMap().setLedgerSeq(mSeq);
330  mLedger->txMap().setLedgerSeq(mSeq);
331  mHaveHeader = true;
332  }
333 
334  if (!mHaveTransactions)
335  {
336  if (mLedger->info().txHash.isZero())
337  {
338  JLOG(m_journal.trace()) << "No TXNs to fetch";
339  mHaveTransactions = true;
340  }
341  else
342  {
343  TransactionStateSF filter(
344  mLedger->txMap().family().db(), app_.getLedgerMaster());
345  if (mLedger->txMap().fetchRoot(
346  SHAMapHash{mLedger->info().txHash}, &filter))
347  {
348  if (neededTxHashes(1, &filter).empty())
349  {
350  JLOG(m_journal.trace()) << "Had full txn map locally";
351  mHaveTransactions = true;
352  }
353  }
354  }
355  }
356 
357  if (!mHaveState)
358  {
359  if (mLedger->info().accountHash.isZero())
360  {
361  JLOG(m_journal.fatal())
362  << "We are acquiring a ledger with a zero account hash";
363  mFailed = true;
364  return;
365  }
366  AccountStateSF filter(
367  mLedger->stateMap().family().db(), app_.getLedgerMaster());
368  if (mLedger->stateMap().fetchRoot(
369  SHAMapHash{mLedger->info().accountHash}, &filter))
370  {
371  if (neededStateHashes(1, &filter).empty())
372  {
373  JLOG(m_journal.trace()) << "Had full AS map locally";
374  mHaveState = true;
375  }
376  }
377  }
378 
380  {
381  JLOG(m_journal.debug()) << "Had everything locally";
382  mComplete = true;
383  mLedger->setImmutable(app_.config());
384  }
385 }
386 
389 void
391 {
392  mRecentNodes.clear();
393 
394  if (isDone())
395  {
396  JLOG(m_journal.info()) << "Already done " << mHash;
397  return;
398  }
399 
401  {
402  if (mSeq != 0)
403  {
404  JLOG(m_journal.warn())
405  << getTimeouts() << " timeouts for ledger " << mSeq;
406  }
407  else
408  {
409  JLOG(m_journal.warn())
410  << getTimeouts() << " timeouts for ledger " << mHash;
411  }
412  setFailed();
413  done();
414  return;
415  }
416 
417  if (!wasProgress)
418  {
419  checkLocal();
420 
421  mByHash = true;
422 
423  std::size_t pc = getPeerCount();
424  JLOG(m_journal.debug())
425  << "No progress(" << pc << ") for ledger " << mHash;
426 
427  // addPeers triggers if the reason is not HISTORY
428  // So if the reason IS HISTORY, need to trigger after we add
429  // otherwise, we need to trigger before we add
430  // so each peer gets triggered once
431  if (mReason != Reason::HISTORY)
433  addPeers();
434  if (mReason == Reason::HISTORY)
436  }
437 }
438 
440 void
442 {
444  *this,
447 }
448 
451 {
452  return std::dynamic_pointer_cast<PeerSet>(shared_from_this());
453 }
454 
455 void
457 {
458  if (mSignaled)
459  return;
460 
461  mSignaled = true;
462  touch();
463 
464  JLOG(m_journal.debug())
465  << "Acquire " << mHash << (mFailed ? " fail " : " ")
466  << ((getTimeouts() == 0) ? std::string()
467  : (std::string("timeouts:") +
468  std::to_string(getTimeouts()) + " "))
469  << mStats.get();
470 
471  assert(mComplete || mFailed);
472 
473  if (mComplete && !mFailed && mLedger)
474  {
475  mLedger->setImmutable(app_.config());
476  switch (mReason)
477  {
478  case Reason::SHARD:
480  [[fallthrough]];
481  case Reason::HISTORY:
483  break;
484  default:
486  break;
487  }
488  }
489 
490  // We hold the PeerSet lock, so must dispatch
492  jtLEDGER_DATA, "AcquisitionDone", [self = shared_from_this()](Job&) {
493  if (self->mComplete && !self->mFailed)
494  {
495  self->app().getLedgerMaster().checkAccept(self->getLedger());
496  self->app().getLedgerMaster().tryAdvance();
497  }
498  else
499  self->app().getInboundLedgers().logFailure(
500  self->getHash(), self->getSeq());
501  });
502 }
503 
506 void
508 {
509  ScopedLockType sl(mLock);
510 
511  if (isDone())
512  {
513  JLOG(m_journal.debug())
514  << "Trigger on ledger: " << mHash << (mComplete ? " completed" : "")
515  << (mFailed ? " failed" : "");
516  return;
517  }
518 
519  if (auto stream = m_journal.trace())
520  {
521  if (peer)
522  stream << "Trigger acquiring ledger " << mHash << " from " << peer;
523  else
524  stream << "Trigger acquiring ledger " << mHash;
525 
526  if (mComplete || mFailed)
527  stream << "complete=" << mComplete << " failed=" << mFailed;
528  else
529  stream << "header=" << mHaveHeader << " tx=" << mHaveTransactions
530  << " as=" << mHaveState;
531  }
532 
533  if (!mHaveHeader)
534  {
536  if (mFailed)
537  {
538  JLOG(m_journal.warn()) << " failed local for " << mHash;
539  return;
540  }
541  }
542 
543  protocol::TMGetLedger tmGL;
544  tmGL.set_ledgerhash(mHash.begin(), mHash.size());
545 
546  if (getTimeouts() != 0)
547  { // Be more aggressive if we've timed out at least once
548  tmGL.set_querytype(protocol::qtINDIRECT);
549 
550  if (!isProgress() && !mFailed && mByHash &&
552  {
553  auto need = getNeededHashes();
554 
555  if (!need.empty())
556  {
557  protocol::TMGetObjectByHash tmBH;
558  bool typeSet = false;
559  tmBH.set_query(true);
560  tmBH.set_ledgerhash(mHash.begin(), mHash.size());
561  for (auto const& p : need)
562  {
563  JLOG(m_journal.warn()) << "Want: " << p.second;
564 
565  if (!typeSet)
566  {
567  tmBH.set_type(p.first);
568  typeSet = true;
569  }
570 
571  if (p.first == tmBH.type())
572  {
573  protocol::TMIndexedObject* io = tmBH.add_objects();
574  io->set_hash(p.second.begin(), p.second.size());
575  if (mSeq != 0)
576  io->set_ledgerseq(mSeq);
577  }
578  }
579 
580  auto packet =
581  std::make_shared<Message>(tmBH, protocol::mtGET_OBJECTS);
582 
583  for (auto id : mPeers)
584  {
585  if (auto p = app_.overlay().findPeerByShortID(id))
586  {
587  mByHash = false;
588  p->send(packet);
589  }
590  }
591  }
592  else
593  {
594  JLOG(m_journal.info())
595  << "getNeededHashes says acquire is complete";
596  mHaveHeader = true;
597  mHaveTransactions = true;
598  mHaveState = true;
599  mComplete = true;
600  }
601  }
602  }
603 
604  // We can't do much without the header data because we don't know the
605  // state or transaction root hashes.
606  if (!mHaveHeader && !mFailed)
607  {
608  tmGL.set_itype(protocol::liBASE);
609  if (mSeq != 0)
610  tmGL.set_ledgerseq(mSeq);
611  JLOG(m_journal.trace()) << "Sending header request to "
612  << (peer ? "selected peer" : "all peers");
613  sendRequest(tmGL, peer);
614  return;
615  }
616 
617  if (mLedger)
618  tmGL.set_ledgerseq(mLedger->info().seq);
619 
620  if (reason != TriggerReason::reply)
621  {
622  // If we're querying blind, don't query deep
623  tmGL.set_querydepth(0);
624  }
625  else if (peer && peer->isHighLatency())
626  {
627  // If the peer has high latency, query extra deep
628  tmGL.set_querydepth(2);
629  }
630  else
631  tmGL.set_querydepth(1);
632 
633  // Get the state data first because it's the most likely to be useful
634  // if we wind up abandoning this fetch.
635  if (mHaveHeader && !mHaveState && !mFailed)
636  {
637  assert(mLedger);
638 
639  if (!mLedger->stateMap().isValid())
640  {
641  mFailed = true;
642  }
643  else if (mLedger->stateMap().getHash().isZero())
644  {
645  // we need the root node
646  tmGL.set_itype(protocol::liAS_NODE);
647  *tmGL.add_nodeids() = SHAMapNodeID().getRawString();
648  JLOG(m_journal.trace()) << "Sending AS root request to "
649  << (peer ? "selected peer" : "all peers");
650  sendRequest(tmGL, peer);
651  return;
652  }
653  else
654  {
655  AccountStateSF filter(
656  mLedger->stateMap().family().db(), app_.getLedgerMaster());
657 
658  // Release the lock while we process the large state map
659  sl.unlock();
660  auto nodes =
661  mLedger->stateMap().getMissingNodes(missingNodesFind, &filter);
662  sl.lock();
663 
664  // Make sure nothing happened while we released the lock
665  if (!mFailed && !mComplete && !mHaveState)
666  {
667  if (nodes.empty())
668  {
669  if (!mLedger->stateMap().isValid())
670  mFailed = true;
671  else
672  {
673  mHaveState = true;
674 
675  if (mHaveTransactions)
676  mComplete = true;
677  }
678  }
679  else
680  {
681  filterNodes(nodes, reason);
682 
683  if (!nodes.empty())
684  {
685  tmGL.set_itype(protocol::liAS_NODE);
686  for (auto const& id : nodes)
687  {
688  *(tmGL.add_nodeids()) = id.first.getRawString();
689  }
690 
691  JLOG(m_journal.trace())
692  << "Sending AS node request (" << nodes.size()
693  << ") to "
694  << (peer ? "selected peer" : "all peers");
695  sendRequest(tmGL, peer);
696  return;
697  }
698  else
699  {
700  JLOG(m_journal.trace()) << "All AS nodes filtered";
701  }
702  }
703  }
704  }
705  }
706 
708  {
709  assert(mLedger);
710 
711  if (!mLedger->txMap().isValid())
712  {
713  mFailed = true;
714  }
715  else if (mLedger->txMap().getHash().isZero())
716  {
717  // we need the root node
718  tmGL.set_itype(protocol::liTX_NODE);
719  *(tmGL.add_nodeids()) = SHAMapNodeID().getRawString();
720  JLOG(m_journal.trace()) << "Sending TX root request to "
721  << (peer ? "selected peer" : "all peers");
722  sendRequest(tmGL, peer);
723  return;
724  }
725  else
726  {
727  TransactionStateSF filter(
728  mLedger->txMap().family().db(), app_.getLedgerMaster());
729 
730  auto nodes =
731  mLedger->txMap().getMissingNodes(missingNodesFind, &filter);
732 
733  if (nodes.empty())
734  {
735  if (!mLedger->txMap().isValid())
736  mFailed = true;
737  else
738  {
739  mHaveTransactions = true;
740 
741  if (mHaveState)
742  mComplete = true;
743  }
744  }
745  else
746  {
747  filterNodes(nodes, reason);
748 
749  if (!nodes.empty())
750  {
751  tmGL.set_itype(protocol::liTX_NODE);
752  for (auto const& n : nodes)
753  {
754  *(tmGL.add_nodeids()) = n.first.getRawString();
755  }
756  JLOG(m_journal.trace())
757  << "Sending TX node request (" << nodes.size()
758  << ") to " << (peer ? "selected peer" : "all peers");
759  sendRequest(tmGL, peer);
760  return;
761  }
762  else
763  {
764  JLOG(m_journal.trace()) << "All TX nodes filtered";
765  }
766  }
767  }
768  }
769 
770  if (mComplete || mFailed)
771  {
772  JLOG(m_journal.debug())
773  << "Done:" << (mComplete ? " complete" : "")
774  << (mFailed ? " failed " : " ") << mLedger->info().seq;
775  sl.unlock();
776  done();
777  }
778 }
779 
780 void
783  TriggerReason reason)
784 {
785  // Sort nodes so that the ones we haven't recently
786  // requested come before the ones we have.
787  auto dup = std::stable_partition(
788  nodes.begin(), nodes.end(), [this](auto const& item) {
789  return mRecentNodes.count(item.second) == 0;
790  });
791 
792  // If everything is a duplicate we don't want to send
793  // any query at all except on a timeout where we need
794  // to query everyone:
795  if (dup == nodes.begin())
796  {
797  JLOG(m_journal.trace()) << "filterNodes: all duplicates";
798 
799  if (reason != TriggerReason::timeout)
800  {
801  nodes.clear();
802  return;
803  }
804  }
805  else
806  {
807  JLOG(m_journal.trace()) << "filterNodes: pruning duplicates";
808 
809  nodes.erase(dup, nodes.end());
810  }
811 
812  std::size_t const limit =
814 
815  if (nodes.size() > limit)
816  nodes.resize(limit);
817 
818  for (auto const& n : nodes)
819  mRecentNodes.insert(n.second);
820 }
821 
825 // data must not have hash prefix
826 bool
828 {
829  // Return value: true=normal, false=bad data
830  JLOG(m_journal.trace()) << "got header acquiring ledger " << mHash;
831 
832  if (mComplete || mFailed || mHaveHeader)
833  return true;
834 
835  auto* f = mReason == Reason::SHARD ? app_.shardFamily() : &app_.family();
836  mLedger = std::make_shared<Ledger>(
837  deserializeHeader(makeSlice(data), false), app_.config(), *f);
838  if (mLedger->info().hash != mHash ||
839  (mSeq != 0 && mSeq != mLedger->info().seq))
840  {
841  JLOG(m_journal.warn())
842  << "Acquire hash mismatch: " << mLedger->info().hash
843  << "!=" << mHash;
844  mLedger.reset();
845  return false;
846  }
847  if (mSeq == 0)
848  mSeq = mLedger->info().seq;
849  mLedger->stateMap().setLedgerSeq(mSeq);
850  mLedger->txMap().setLedgerSeq(mSeq);
851  mHaveHeader = true;
852 
853  Serializer s(data.size() + 4);
855  s.addRaw(data.data(), data.size());
856  f->db().store(hotLEDGER, std::move(s.modData()), mHash, mSeq);
857 
858  if (mLedger->info().txHash.isZero())
859  mHaveTransactions = true;
860 
861  if (mLedger->info().accountHash.isZero())
862  mHaveState = true;
863 
864  mLedger->txMap().setSynching();
865  mLedger->stateMap().setSynching();
866 
867  return true;
868 }
869 
873 bool
875  const std::vector<SHAMapNodeID>& nodeIDs,
876  const std::vector<Blob>& data,
877  SHAMapAddNode& san)
878 {
879  if (!mHaveHeader)
880  {
881  JLOG(m_journal.warn()) << "TX node without header";
882  san.incInvalid();
883  return false;
884  }
885 
886  if (mHaveTransactions || mFailed)
887  {
888  san.incDuplicate();
889  return true;
890  }
891 
892  auto nodeIDit = nodeIDs.cbegin();
893  auto nodeDatait = data.begin();
894  TransactionStateSF filter(
895  mLedger->txMap().family().db(), app_.getLedgerMaster());
896 
897  while (nodeIDit != nodeIDs.cend())
898  {
899  if (nodeIDit->isRoot())
900  {
901  san += mLedger->txMap().addRootNode(
902  SHAMapHash{mLedger->info().txHash},
903  makeSlice(*nodeDatait),
904  snfWIRE,
905  &filter);
906  if (!san.isGood())
907  return false;
908  }
909  else
910  {
911  san += mLedger->txMap().addKnownNode(
912  *nodeIDit, makeSlice(*nodeDatait), &filter);
913  if (!san.isGood())
914  return false;
915  }
916 
917  ++nodeIDit;
918  ++nodeDatait;
919  }
920 
921  if (!mLedger->txMap().isSynching())
922  {
923  mHaveTransactions = true;
924 
925  if (mHaveState)
926  {
927  mComplete = true;
928  done();
929  }
930  }
931 
932  return true;
933 }
934 
938 bool
940  const std::vector<SHAMapNodeID>& nodeIDs,
941  const std::vector<Blob>& data,
942  SHAMapAddNode& san)
943 {
944  JLOG(m_journal.trace())
945  << "got ASdata (" << nodeIDs.size() << ") acquiring ledger " << mHash;
946  if (nodeIDs.size() == 1)
947  {
948  JLOG(m_journal.trace()) << "got AS node: " << nodeIDs.front();
949  }
950 
951  ScopedLockType sl(mLock);
952 
953  if (!mHaveHeader)
954  {
955  JLOG(m_journal.warn()) << "Don't have ledger header";
956  san.incInvalid();
957  return false;
958  }
959 
960  if (mHaveState || mFailed)
961  {
962  san.incDuplicate();
963  return true;
964  }
965 
966  auto nodeIDit = nodeIDs.cbegin();
967  auto nodeDatait = data.begin();
968  AccountStateSF filter(
969  mLedger->stateMap().family().db(), app_.getLedgerMaster());
970 
971  while (nodeIDit != nodeIDs.cend())
972  {
973  if (nodeIDit->isRoot())
974  {
975  san += mLedger->stateMap().addRootNode(
976  SHAMapHash{mLedger->info().accountHash},
977  makeSlice(*nodeDatait),
978  snfWIRE,
979  &filter);
980  if (!san.isGood())
981  {
982  JLOG(m_journal.warn()) << "Bad ledger header";
983  return false;
984  }
985  }
986  else
987  {
988  san += mLedger->stateMap().addKnownNode(
989  *nodeIDit, makeSlice(*nodeDatait), &filter);
990  if (!san.isGood())
991  {
992  JLOG(m_journal.warn()) << "Unable to add AS node";
993  return false;
994  }
995  }
996 
997  ++nodeIDit;
998  ++nodeDatait;
999  }
1000 
1001  if (!mLedger->stateMap().isSynching())
1002  {
1003  mHaveState = true;
1004 
1005  if (mHaveTransactions)
1006  {
1007  mComplete = true;
1008  done();
1009  }
1010  }
1011 
1012  return true;
1013 }
1014 
1018 bool
1020 {
1021  if (mFailed || mHaveState)
1022  {
1023  san.incDuplicate();
1024  return true;
1025  }
1026 
1027  if (!mHaveHeader)
1028  {
1029  assert(false);
1030  return false;
1031  }
1032 
1033  AccountStateSF filter(
1034  mLedger->stateMap().family().db(), app_.getLedgerMaster());
1035  san += mLedger->stateMap().addRootNode(
1036  SHAMapHash{mLedger->info().accountHash}, data, snfWIRE, &filter);
1037  return san.isGood();
1038 }
1039 
1043 bool
1045 {
1046  if (mFailed || mHaveTransactions)
1047  {
1048  san.incDuplicate();
1049  return true;
1050  }
1051 
1052  if (!mHaveHeader)
1053  {
1054  assert(false);
1055  return false;
1056  }
1057 
1058  TransactionStateSF filter(
1059  mLedger->txMap().family().db(), app_.getLedgerMaster());
1060  san += mLedger->txMap().addRootNode(
1061  SHAMapHash{mLedger->info().txHash}, data, snfWIRE, &filter);
1062  return san.isGood();
1063 }
1064 
1067 {
1069 
1070  if (!mHaveHeader)
1071  {
1072  ret.push_back(
1073  std::make_pair(protocol::TMGetObjectByHash::otLEDGER, mHash));
1074  return ret;
1075  }
1076 
1077  if (!mHaveState)
1078  {
1079  AccountStateSF filter(
1080  mLedger->stateMap().family().db(), app_.getLedgerMaster());
1081  for (auto const& h : neededStateHashes(4, &filter))
1082  {
1083  ret.push_back(
1084  std::make_pair(protocol::TMGetObjectByHash::otSTATE_NODE, h));
1085  }
1086  }
1087 
1088  if (!mHaveTransactions)
1089  {
1090  TransactionStateSF filter(
1091  mLedger->txMap().family().db(), app_.getLedgerMaster());
1092  for (auto const& h : neededTxHashes(4, &filter))
1093  {
1095  protocol::TMGetObjectByHash::otTRANSACTION_NODE, h));
1096  }
1097  }
1098 
1099  return ret;
1100 }
1101 
1105 bool
1107  std::weak_ptr<Peer> peer,
1109 {
1111 
1112  if (isDone())
1113  return false;
1114 
1115  mReceivedData.emplace_back(peer, data);
1116 
1117  if (mReceiveDispatched)
1118  return false;
1119 
1120  mReceiveDispatched = true;
1121  return true;
1122 }
1123 
1127 // VFALCO NOTE, it is not necessary to pass the entire Peer,
1128 // we can get away with just a Resource::Consumer endpoint.
1129 //
1130 // TODO Change peer to Consumer
1131 //
1132 int
1134  std::shared_ptr<Peer> peer,
1135  protocol::TMLedgerData& packet)
1136 {
1137  ScopedLockType sl(mLock);
1138 
1139  if (packet.type() == protocol::liBASE)
1140  {
1141  if (packet.nodes_size() < 1)
1142  {
1143  JLOG(m_journal.warn()) << "Got empty header data";
1144  peer->charge(Resource::feeInvalidRequest);
1145  return -1;
1146  }
1147 
1148  SHAMapAddNode san;
1149 
1150  if (!mHaveHeader)
1151  {
1152  if (takeHeader(packet.nodes(0).nodedata()))
1153  san.incUseful();
1154  else
1155  {
1156  JLOG(m_journal.warn()) << "Got invalid header data";
1157  peer->charge(Resource::feeInvalidRequest);
1158  return -1;
1159  }
1160  }
1161 
1162  if (!mHaveState && (packet.nodes().size() > 1) &&
1163  !takeAsRootNode(makeSlice(packet.nodes(1).nodedata()), san))
1164  {
1165  JLOG(m_journal.warn()) << "Included AS root invalid";
1166  }
1167 
1168  if (!mHaveTransactions && (packet.nodes().size() > 2) &&
1169  !takeTxRootNode(makeSlice(packet.nodes(2).nodedata()), san))
1170  {
1171  JLOG(m_journal.warn()) << "Included TX root invalid";
1172  }
1173 
1174  if (san.isUseful())
1175  progress();
1176 
1177  mStats += san;
1178  return san.getGood();
1179  }
1180 
1181  if ((packet.type() == protocol::liTX_NODE) ||
1182  (packet.type() == protocol::liAS_NODE))
1183  {
1184  if (packet.nodes().size() == 0)
1185  {
1186  JLOG(m_journal.info()) << "Got response with no nodes";
1187  peer->charge(Resource::feeInvalidRequest);
1188  return -1;
1189  }
1190 
1191  std::vector<SHAMapNodeID> nodeIDs;
1192  nodeIDs.reserve(packet.nodes().size());
1193  std::vector<Blob> nodeData;
1194  nodeData.reserve(packet.nodes().size());
1195 
1196  for (int i = 0; i < packet.nodes().size(); ++i)
1197  {
1198  const protocol::TMLedgerNode& node = packet.nodes(i);
1199 
1200  if (!node.has_nodeid() || !node.has_nodedata())
1201  {
1202  JLOG(m_journal.warn()) << "Got bad node";
1203  peer->charge(Resource::feeInvalidRequest);
1204  return -1;
1205  }
1206 
1207  nodeIDs.push_back(
1208  SHAMapNodeID(node.nodeid().data(), node.nodeid().size()));
1209  nodeData.push_back(
1210  Blob(node.nodedata().begin(), node.nodedata().end()));
1211  }
1212 
1213  SHAMapAddNode san;
1214 
1215  if (packet.type() == protocol::liTX_NODE)
1216  {
1217  takeTxNode(nodeIDs, nodeData, san);
1218  JLOG(m_journal.debug()) << "Ledger TX node stats: " << san.get();
1219  }
1220  else
1221  {
1222  takeAsNode(nodeIDs, nodeData, san);
1223  JLOG(m_journal.debug()) << "Ledger AS node stats: " << san.get();
1224  }
1225 
1226  if (san.isUseful())
1227  progress();
1228 
1229  mStats += san;
1230  return san.getGood();
1231  }
1232 
1233  return -1;
1234 }
1235 
1239 void
1241 {
1242  std::shared_ptr<Peer> chosenPeer;
1243  int chosenPeerCount = -1;
1244 
1246 
1247  for (;;)
1248  {
1249  data.clear();
1250  {
1252 
1253  if (mReceivedData.empty())
1254  {
1255  mReceiveDispatched = false;
1256  break;
1257  }
1258 
1259  data.swap(mReceivedData);
1260  }
1261 
1262  // Select the peer that gives us the most nodes that are useful,
1263  // breaking ties in favor of the peer that responded first.
1264  for (auto& entry : data)
1265  {
1266  if (auto peer = entry.first.lock())
1267  {
1268  int count = processData(peer, *(entry.second));
1269  if (count > chosenPeerCount)
1270  {
1271  chosenPeerCount = count;
1272  chosenPeer = std::move(peer);
1273  }
1274  }
1275  }
1276  }
1277 
1278  if (chosenPeer)
1279  trigger(chosenPeer, TriggerReason::reply);
1280 }
1281 
1284 {
1286 
1287  ScopedLockType sl(mLock);
1288 
1289  ret[jss::hash] = to_string(mHash);
1290 
1291  if (mComplete)
1292  ret[jss::complete] = true;
1293 
1294  if (mFailed)
1295  ret[jss::failed] = true;
1296 
1297  if (!mComplete && !mFailed)
1298  ret[jss::peers] = static_cast<int>(mPeers.size());
1299 
1300  ret[jss::have_header] = mHaveHeader;
1301 
1302  if (mHaveHeader)
1303  {
1304  ret[jss::have_state] = mHaveState;
1305  ret[jss::have_transactions] = mHaveTransactions;
1306  }
1307 
1308  ret[jss::timeouts] = getTimeouts();
1309 
1310  if (mHaveHeader && !mHaveState)
1311  {
1313  for (auto const& h : neededStateHashes(16, nullptr))
1314  {
1315  hv.append(to_string(h));
1316  }
1317  ret[jss::needed_state_hashes] = hv;
1318  }
1319 
1321  {
1323  for (auto const& h : neededTxHashes(16, nullptr))
1324  {
1325  hv.append(to_string(h));
1326  }
1327  ret[jss::needed_transaction_hashes] = hv;
1328  }
1329 
1330  return ret;
1331 }
1332 
1333 } // namespace ripple
ripple::InboundLedger::mRecentNodes
std::set< uint256 > mRecentNodes
Definition: InboundLedger.h:191
beast::Journal::fatal
Stream fatal() const
Definition: Journal.h:339
ripple::Resource::feeInvalidRequest
const Charge feeInvalidRequest
Schedule of fees charged for imposing load on the server.
ripple::Application
Definition: Application.h:94
ripple::SHAMapAddNode
Definition: SHAMapAddNode.h:28
ripple::SHAMapAddNode::get
std::string get() const
Definition: SHAMapAddNode.h:156
ripple::InboundLedger::Reason::HISTORY
@ HISTORY
ripple::InboundLedger::getNeededHashes
std::vector< neededHash_t > getNeededHashes()
Definition: InboundLedger.cpp:1066
ripple::HashPrefix::ledgerMaster
@ ledgerMaster
ledger master data for signing
ripple::InboundLedger::mReason
const Reason mReason
Definition: InboundLedger.h:189
std::unique_lock::lock
T lock(T... args)
ripple::Blob
std::vector< unsigned char > Blob
Storage for linear binary data.
Definition: Blob.h:30
ripple::PeerSet::setFailed
void setFailed()
Definition: PeerSet.h:158
ripple::InboundLedger::getJson
Json::Value getJson(int)
Return a Json::objectValue.
Definition: InboundLedger.cpp:1283
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:194
ripple::InboundLedger::TriggerReason
TriggerReason
Definition: InboundLedger.h:115
ripple::reqNodes
@ reqNodes
Definition: InboundLedger.cpp:68
std::string
STL class.
ripple::InboundLedger::Reason::CONSENSUS
@ CONSENSUS
std::shared_ptr
STL class.
ripple::InboundLedger::mHaveState
bool mHaveState
Definition: InboundLedger.h:184
ripple::LedgerInfo::parentHash
uint256 parentHash
Definition: ReadView.h:99
ripple::PeerSet::getPeerCount
std::size_t getPeerCount() const
Definition: PeerSet.cpp:149
beast::Journal::trace
Stream trace() const
Severity stream access functions.
Definition: Journal.h:309
ripple::Serializer::modData
Blob & modData()
Definition: Serializer.h:212
ripple::Slice
An immutable linear range of bytes.
Definition: Slice.h:43
Json::arrayValue
@ arrayValue
array value (ordered list)
Definition: json_value.h:42
ripple::InboundLedger::mSignaled
bool mSignaled
Definition: InboundLedger.h:186
std::pair
std::vector::reserve
T reserve(T... args)
ripple::ledgerAcquireTimeout
constexpr auto ledgerAcquireTimeout
Definition: InboundLedger.cpp:72
std::vector
STL class.
std::vector::size
T size(T... args)
ripple::InboundLedger::update
void update(std::uint32_t seq)
Definition: InboundLedger.cpp:175
ripple::InboundLedger::InboundLedger
InboundLedger(Application &app, uint256 const &hash, std::uint32_t seq, Reason reason, clock_type &)
Definition: InboundLedger.cpp:74
ripple::PeerSet::mPeers
std::set< Peer::id_t > mPeers
Definition: PeerSet.h:199
ripple::PeerSet::mHash
uint256 mHash
Definition: PeerSet.h:187
std::chrono::duration
ripple::peerCountStart
@ peerCountStart
Definition: InboundLedger.cpp:44
ripple::InboundLedger::~InboundLedger
~InboundLedger()
Definition: InboundLedger.cpp:208
ripple::InboundLedger::mByHash
bool mByHash
Definition: InboundLedger.h:187
ripple::InboundLedger::filterNodes
void filterNodes(std::vector< std::pair< SHAMapNodeID, uint256 >> &nodes, TriggerReason reason)
Definition: InboundLedger.cpp:781
beast::Journal::warn
Stream warn() const
Definition: Journal.h:327
ripple::InboundLedger::processData
int processData(std::shared_ptr< Peer > peer, protocol::TMLedgerData &data)
Process one TMLedgerData Returns the number of useful nodes.
Definition: InboundLedger.cpp:1133
std::lock_guard
STL class.
ripple::InboundLedger::execute
void execute() override
Definition: InboundLedger.cpp:160
ripple::Application::getShardStore
virtual NodeStore::DatabaseShard * getShardStore()=0
ripple::PeerSet::mComplete
bool mComplete
Definition: PeerSet.h:190
ripple::InboundLedger::neededStateHashes
std::vector< uint256 > neededStateHashes(int max, SHAMapSyncFilter *filter) const
Definition: InboundLedger.cpp:245
ripple::Serializer::add32
int add32(std::uint32_t)
Definition: Serializer.cpp:49
ripple::PeerSet::isDone
virtual bool isDone() const
Definition: PeerSet.h:111
ripple::AccountStateSF
Definition: AccountStateSF.h:31
ripple::JobQueue::addJob
bool addJob(JobType type, std::string const &name, JobHandler &&jobHandler)
Adds a job to the JobQueue.
Definition: JobQueue.h:166
ripple::LedgerInfo::seq
LedgerIndex seq
Definition: ReadView.h:88
ripple::to_string
std::string to_string(ListDisposition disposition)
Definition: ValidatorList.cpp:41
ripple::SHAMapNodeID
Definition: SHAMapNodeID.h:33
ripple::PeerSet::touch
void touch()
Definition: PeerSet.h:92
std::vector::front
T front(T... args)
ripple::Family::db
virtual NodeStore::Database & db()=0
ripple::LedgerInfo::txHash
uint256 txHash
Definition: ReadView.h:97
ripple::SHAMapHash
Definition: SHAMapTreeNode.h:43
algorithm
ripple::jtLEDGER_DATA
@ jtLEDGER_DATA
Definition: Job.h:47
ripple::Application::getInboundLedgers
virtual InboundLedgers & getInboundLedgers()=0
ripple::base_uint::size
constexpr static std::size_t size()
Definition: base_uint.h:462
std::unique_lock::unlock
T unlock(T... args)
ripple::InboundLedger::neededTxHashes
std::vector< uint256 > neededTxHashes(int max, SHAMapSyncFilter *filter) const
Definition: InboundLedger.cpp:229
std::vector::push_back
T push_back(T... args)
ripple::LedgerInfo::closeTime
NetClock::time_point closeTime
Definition: ReadView.h:119
ripple::base_uint< 256 >
ripple::InboundLedger::takeHeader
bool takeHeader(std::string const &data)
Take ledger header data Call with a lock.
Definition: InboundLedger.cpp:827
ripple::JobQueue::getJobCountTotal
int getJobCountTotal(JobType t) const
Jobs waiting plus running at this priority.
Definition: JobQueue.cpp:131
ripple::reqNodesReply
@ reqNodesReply
Definition: InboundLedger.cpp:64
ripple::InboundLedger::gotData
bool gotData(std::weak_ptr< Peer >, std::shared_ptr< protocol::TMLedgerData > const &)
Stash a TMLedgerData received from a peer for later processing Returns 'true' if we need to dispatch.
Definition: InboundLedger.cpp:1106
ripple::NodeStore::Database::store
virtual void store(NodeObjectType type, Blob &&data, uint256 const &hash, std::uint32_t seq)=0
Store the object.
ripple::InboundLedger::takeTxNode
bool takeTxNode(const std::vector< SHAMapNodeID > &IDs, const std::vector< Blob > &data, SHAMapAddNode &)
Process TX data received from a peer Call with a lock.
Definition: InboundLedger.cpp:874
Json::Value::append
Value & append(const Value &value)
Append value to array at the end.
Definition: json_value.cpp:882
ripple::InboundLedger::mLedger
std::shared_ptr< Ledger > mLedger
Definition: InboundLedger.h:182
ripple::Application::shardFamily
virtual Family * shardFamily()=0
std::enable_shared_from_this< InboundLedger >::shared_from_this
T shared_from_this(T... args)
ripple::InboundLedger::deserializeHeader
static LedgerInfo deserializeHeader(Slice data, bool hasPrefix)
Definition: InboundLedger.cpp:261
ripple::SerialIter::get8
unsigned char get8()
Definition: Serializer.cpp:506
ripple::Application::family
virtual Family & family()=0
ripple::SHAMapAddNode::isUseful
bool isUseful() const
Definition: SHAMapAddNode.h:116
Json::objectValue
@ objectValue
object value (collection of name/value pairs).
Definition: json_value.h:43
ripple::SerialIter::get256
uint256 get256()
Definition: Serializer.h:434
ripple::SerialIter::get64
std::uint64_t get64()
Definition: Serializer.cpp:543
ripple::InboundLedger::addPeers
void addPeers()
Add more peers to the set, if possible.
Definition: InboundLedger.cpp:441
ripple::peerCountAdd
@ peerCountAdd
Definition: InboundLedger.cpp:48
ripple::Application::getLedgerMaster
virtual LedgerMaster & getLedgerMaster()=0
ripple::InboundLedgers::gotStaleData
virtual void gotStaleData(std::shared_ptr< protocol::TMLedgerData > packet)=0
ripple::LedgerMaster::getFetchPack
boost::optional< Blob > getFetchPack(uint256 const &hash) override
Retrieves partial ledger data of the coresponding hash from peers.
Definition: LedgerMaster.cpp:1976
ripple::NodeStore::Database::fetch
virtual std::shared_ptr< NodeObject > fetch(uint256 const &hash, std::uint32_t seq)=0
Fetch an object.
ripple::Application::config
virtual Config & config()=0
ripple::InboundLedgers::onLedgerFetched
virtual void onLedgerFetched()=0
Called when a complete ledger is obtained.
ripple::SHAMapAddNode::isGood
bool isGood() const
Definition: SHAMapAddNode.h:132
std::unique_lock
STL class.
ripple::SHAMapNodeID::getRawString
std::string getRawString() const
Definition: SHAMapNodeID.cpp:92
ripple::Serializer::addRaw
int addRaw(Blob const &vector)
Definition: Serializer.cpp:127
ripple::LedgerInfo::closeFlags
int closeFlags
Definition: ReadView.h:110
std::to_string
T to_string(T... args)
ripple::Application::getJobQueue
virtual JobQueue & getJobQueue()=0
ripple::InboundLedger::takeTxRootNode
bool takeTxRootNode(Slice const &data, SHAMapAddNode &)
Process AS root node received from a peer Call with a lock.
Definition: InboundLedger.cpp:1044
beast::Journal::error
Stream error() const
Definition: Journal.h:333
beast::Journal::info
Stream info() const
Definition: Journal.h:321
std::chrono::time_point
ripple::Family
Definition: Family.h:32
ripple::Job
Definition: Job.h:82
ripple::SerialIter
Definition: Serializer.h:368
ripple::InboundLedger::pmDowncast
std::weak_ptr< PeerSet > pmDowncast() override
Definition: InboundLedger.cpp:450
ripple::Overlay::selectPeers
virtual std::size_t selectPeers(PeerSet &set, std::size_t limit, std::function< bool(std::shared_ptr< Peer > const &)> score)=0
Select from active peers.
std::uint32_t
ripple::missingNodesFind
@ missingNodesFind
Definition: InboundLedger.cpp:60
ripple::InboundLedger::mReceiveDispatched
bool mReceiveDispatched
Definition: InboundLedger.h:198
ripple::InboundLedger::mHaveHeader
bool mHaveHeader
Definition: InboundLedger.h:183
beast::abstract_clock< std::chrono::steady_clock >
ripple::LedgerMaster::checkAccept
void checkAccept(std::shared_ptr< Ledger const > const &ledger)
Definition: LedgerMaster.cpp:998
ripple::LedgerInfo::drops
XRPAmount drops
Definition: ReadView.h:101
ripple::PeerSet::sendRequest
void sendRequest(const protocol::TMGetLedger &message)
Definition: PeerSet.cpp:132
std::weak_ptr
STL class.
ripple::Serializer
Definition: Serializer.h:43
ripple::InboundLedger::TriggerReason::timeout
@ timeout
ripple::InboundLedger::TriggerReason::reply
@ reply
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::InboundLedger::mStats
SHAMapAddNode mStats
Definition: InboundLedger.h:193
ripple::PeerSet::getTimeouts
int getTimeouts() const
Returns the number of times we timed out.
Definition: PeerSet.h:76
ripple::base_uint::begin
iterator begin()
Definition: base_uint.h:114
ripple::PeerSet::app_
Application & app_
Definition: PeerSet.h:181
std::vector::cbegin
T cbegin(T... args)
ripple::InboundLedger::mSeq
std::uint32_t mSeq
Definition: InboundLedger.h:188
ripple::InboundLedger::takeAsRootNode
bool takeAsRootNode(Slice const &data, SHAMapAddNode &)
Process AS root node received from a peer Call with a lock.
Definition: InboundLedger.cpp:1019
ripple::LedgerInfo::closeTimeResolution
NetClock::duration closeTimeResolution
Definition: ReadView.h:113
ripple::PeerSet
Supports data retrieval by managing a set of peers.
Definition: PeerSet.h:48
ripple::PeerSet::mFailed
bool mFailed
Definition: PeerSet.h:191
ripple::ScoreHasLedger
Definition: Overlay.h:262
ripple::snfWIRE
@ snfWIRE
Definition: SHAMapTreeNode.h:37
ripple::NodeStore::DatabaseShard::setStored
virtual void setStored(std::shared_ptr< Ledger const > const &ledger)=0
Notifies the database that the given ledger has been fully acquired and stored.
ripple::Application::overlay
virtual Overlay & overlay()=0
ripple::InboundLedger::done
void done()
Definition: InboundLedger.cpp:456
ripple::InboundLedger::takeAsNode
bool takeAsNode(const std::vector< SHAMapNodeID > &IDs, const std::vector< Blob > &data, SHAMapAddNode &)
Process AS data received from a peer Call with a lock.
Definition: InboundLedger.cpp:939
ripple::InboundLedger::trigger
void trigger(std::shared_ptr< Peer > const &, TriggerReason)
Request more nodes, perhaps from a specific peer.
Definition: InboundLedger.cpp:507
ripple::PeerSet::m_journal
beast::Journal m_journal
Definition: PeerSet.h:182
beast::Journal::debug
Stream debug() const
Definition: Journal.h:315
ripple::SHAMapAddNode::incInvalid
void incInvalid()
Definition: SHAMapAddNode.h:80
std::size_t
ripple::SHAMapAddNode::incUseful
void incUseful()
Definition: SHAMapAddNode.h:86
ripple::hotLEDGER
@ hotLEDGER
Definition: NodeObject.h:34
std::make_pair
T make_pair(T... args)
ripple::LedgerInfo
Information about the notional ledger backing the view.
Definition: ReadView.h:80
ripple::SHAMapAddNode::getGood
int getGood() const
Definition: SHAMapAddNode.h:104
ripple::LedgerMaster::storeLedger
bool storeLedger(std::shared_ptr< Ledger const > ledger)
Definition: LedgerMaster.cpp:525
std::vector::cend
T cend(T... args)
ripple::InboundLedger::Reason
Reason
Definition: InboundLedger.h:49
ripple::PeerSet::getHash
uint256 const & getHash() const
Returns the hash of the data we want.
Definition: PeerSet.h:55
ripple::SHAMapAddNode::incDuplicate
void incDuplicate()
Definition: SHAMapAddNode.h:92
ripple::InboundLedger::runData
void runData()
Process pending TMLedgerData Query the 'best' peer.
Definition: InboundLedger.cpp:1240
ripple::SerialIter::get32
std::uint32_t get32()
Definition: Serializer.cpp:530
ripple::InboundLedger::mReceivedData
std::vector< PeerDataPairType > mReceivedData
Definition: InboundLedger.h:197
ripple::ledgerBecomeAggressiveThreshold
@ ledgerBecomeAggressiveThreshold
Definition: InboundLedger.cpp:56
ripple::SHAMapSyncFilter
Definition: SHAMapSyncFilter.h:30
std::stable_partition
T stable_partition(T... args)
ripple::InboundLedger::Reason::SHARD
@ SHARD
ripple::PeerSet::isProgress
bool isProgress()
Definition: PeerSet.h:147
ripple::InboundLedger::onTimer
void onTimer(bool progress, ScopedLockType &peerSetLock) override
Called with a lock by the PeerSet when the timer expires.
Definition: InboundLedger.cpp:390
ripple::InboundLedger::mReceivedDataLock
std::mutex mReceivedDataLock
Definition: InboundLedger.h:196
ripple::InboundLedger::checkLocal
bool checkLocal()
Definition: InboundLedger.cpp:188
ripple::TransactionStateSF
Definition: TransactionStateSF.h:31
ripple::ledgerTimeoutRetriesMax
@ ledgerTimeoutRetriesMax
Definition: InboundLedger.cpp:52
ripple::PeerSet::setTimer
void setTimer()
Definition: PeerSet.cpp:74
ripple::InboundLedger::mHaveTransactions
bool mHaveTransactions
Definition: InboundLedger.h:185
ripple::Overlay::findPeerByShortID
virtual std::shared_ptr< Peer > findPeerByShortID(Peer::id_t const &id)=0
Returns the peer with the matching short id, or null.
ripple::InboundLedger::init
void init(ScopedLockType &collectionLock)
Definition: InboundLedger.cpp:99
ripple::LedgerInfo::accountHash
uint256 accountHash
Definition: ReadView.h:98
ripple::PeerSet::progress
void progress()
Called to indicate that forward progress has been made.
Definition: PeerSet.h:86
ripple::InboundLedger::tryDB
void tryDB(Family &f)
Definition: InboundLedger.cpp:287
ripple::PeerSet::mLock
std::recursive_mutex mLock
Definition: PeerSet.h:185
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::LedgerInfo::parentCloseTime
NetClock::time_point parentCloseTime
Definition: ReadView.h:89