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