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>
40 using namespace std::chrono_literals;
86 app.journal(
"InboundLedger"))
90 , mHaveTransactions(
false)
95 , mReceiveDispatched(
false)
96 , mPeerSet(std::move(peerSet))
98 JLOG(journal_.trace()) <<
"Acquiring ledger " << hash_;
120 <<
"Acquiring shard with no shard store available";
134 else if (shardStore &&
mSeq >= shardStore->earliestLedgerSeq())
136 if (
auto l = shardStore->fetchLedger(
hash_,
mSeq))
153 JLOG(
journal_.
debug()) <<
"Acquiring ledger we already have in "
154 <<
" local store. " <<
hash_;
170 auto const& peerIds =
mPeerSet->getPeerIds();
171 return std::count_if(peerIds.begin(), peerIds.end(), [
this](
auto id) {
172 return (app_.overlay().findPeerByShortID(id) != nullptr);
182 if ((seq != 0) && (
mSeq == 0))
216 if (entry.second->type() == protocol::liAS_NODE)
222 <<
"Acquire " <<
hash_ <<
" abort "
247 for (
auto const& n : mn)
305 auto makeLedger = [&,
this](
Blob const& data) {
306 JLOG(
journal_.
trace()) <<
"Ledger header found in fetch pack";
307 mLedger = std::make_shared<Ledger>(
318 <<
" cannot be a ledger";
327 JLOG(
journal_.
trace()) <<
"Ledger header found in local store";
329 makeLedger(nodeObject->getData());
334 auto& dstDB{
mLedger->stateMap().family().db()};
337 Blob blob{nodeObject->getData()};
349 JLOG(
journal_.
trace()) <<
"Ledger header found in fetch pack";
356 mLedger->stateMap().family().db().store(
369 if (
mLedger->info().txHash.isZero())
378 if (
mLedger->txMap().fetchRoot(
392 if (
mLedger->info().accountHash.isZero())
395 <<
"We are acquiring a ledger with a zero account hash";
401 if (
mLedger->stateMap().fetchRoot(
402 SHAMapHash{mLedger->info().accountHash}, &filter))
458 <<
"No progress(" << pc <<
") for ledger " <<
hash_;
478 [
this](
auto peer) {
return peer->hasLedger(
hash_,
mSeq); },
531 if (self->complete_ && !self->failed_)
533 self->app_.getLedgerMaster().checkAccept(self->getLedger());
534 self->app_.getLedgerMaster().tryAdvance();
537 self->app_.getInboundLedgers().logFailure(
538 self->hash_, self->mSeq);
552 <<
"Trigger on ledger: " <<
hash_ << (
complete_ ?
" completed" :
"")
560 stream <<
"Trigger acquiring ledger " <<
hash_ <<
" from " << peer;
562 stream <<
"Trigger acquiring ledger " <<
hash_;
583 protocol::TMGetLedger tmGL;
589 tmGL.set_querytype(protocol::qtINDIRECT);
598 protocol::TMGetObjectByHash tmBH;
599 bool typeSet =
false;
600 tmBH.set_query(
true);
602 for (
auto const& p : need)
608 tmBH.set_type(p.first);
612 if (p.first == tmBH.type())
614 protocol::TMIndexedObject* io = tmBH.add_objects();
615 io->set_hash(p.second.begin(), p.second.size());
617 io->set_ledgerseq(
mSeq);
622 std::make_shared<Message>(tmBH, protocol::mtGET_OBJECTS);
623 auto const& peerIds =
mPeerSet->getPeerIds();
625 peerIds.begin(), peerIds.end(), [
this, &packet](
auto id) {
626 if (auto p = app_.overlay().findPeerByShortID(id))
636 <<
"getNeededHashes says acquire is complete";
647 if (!mHaveHeader && !failed_)
649 tmGL.set_itype(protocol::liBASE);
651 tmGL.set_ledgerseq(mSeq);
652 JLOG(journal_.trace()) <<
"Sending header request to "
653 << (peer ?
"selected peer" :
"all peers");
654 mPeerSet->sendRequest(tmGL, peer);
659 tmGL.set_ledgerseq(mLedger->info().seq);
661 if (reason != TriggerReason::reply)
664 tmGL.set_querydepth(0);
666 else if (peer && peer->isHighLatency())
669 tmGL.set_querydepth(2);
672 tmGL.set_querydepth(1);
676 if (mHaveHeader && !mHaveState && !failed_)
680 if (!mLedger->stateMap().isValid())
684 else if (mLedger->stateMap().getHash().isZero())
687 tmGL.set_itype(protocol::liAS_NODE);
688 *tmGL.add_nodeids() = SHAMapNodeID().getRawString();
689 JLOG(journal_.trace()) <<
"Sending AS root request to "
690 << (peer ?
"selected peer" :
"all peers");
691 mPeerSet->sendRequest(tmGL, peer);
696 AccountStateSF filter(
697 mLedger->stateMap().family().db(), app_.getLedgerMaster());
706 if (!failed_ && !complete_ && !mHaveState)
710 if (!mLedger->stateMap().isValid())
716 if (mHaveTransactions)
722 filterNodes(nodes, reason);
726 tmGL.set_itype(protocol::liAS_NODE);
727 for (
auto const&
id : nodes)
729 *(tmGL.add_nodeids()) =
id.first.getRawString();
732 JLOG(journal_.trace())
733 <<
"Sending AS node request (" << nodes.size()
735 << (peer ?
"selected peer" :
"all peers");
736 mPeerSet->sendRequest(tmGL, peer);
741 JLOG(journal_.trace()) <<
"All AS nodes filtered";
748 if (mHaveHeader && !mHaveTransactions && !failed_)
752 if (!mLedger->txMap().isValid())
756 else if (mLedger->txMap().getHash().isZero())
759 tmGL.set_itype(protocol::liTX_NODE);
760 *(tmGL.add_nodeids()) = SHAMapNodeID().getRawString();
761 JLOG(journal_.trace()) <<
"Sending TX root request to "
762 << (peer ?
"selected peer" :
"all peers");
763 mPeerSet->sendRequest(tmGL, peer);
768 TransactionStateSF filter(
769 mLedger->txMap().family().db(), app_.getLedgerMaster());
776 if (!mLedger->txMap().isValid())
780 mHaveTransactions =
true;
788 filterNodes(nodes, reason);
792 tmGL.set_itype(protocol::liTX_NODE);
793 for (
auto const& n : nodes)
795 *(tmGL.add_nodeids()) = n.first.getRawString();
797 JLOG(journal_.trace())
798 <<
"Sending TX node request (" << nodes.size()
799 <<
") to " << (peer ?
"selected peer" :
"all peers");
800 mPeerSet->sendRequest(tmGL, peer);
805 JLOG(journal_.trace()) <<
"All TX nodes filtered";
811 if (complete_ || failed_)
813 JLOG(journal_.debug())
814 <<
"Done:" << (complete_ ?
" complete" :
"")
815 << (failed_ ?
" failed " :
" ") << mLedger->info().seq;
822 InboundLedger::filterNodes(
829 nodes.begin(), nodes.end(), [
this](
auto const& item) {
830 return mRecentNodes.count(item.second) == 0;
836 if (dup == nodes.begin())
838 JLOG(journal_.trace()) <<
"filterNodes: all duplicates";
840 if (reason != TriggerReason::timeout)
848 JLOG(journal_.trace()) <<
"filterNodes: pruning duplicates";
850 nodes.erase(dup, nodes.end());
856 if (nodes.size() > limit)
859 for (
auto const& n : nodes)
860 mRecentNodes.insert(n.second);
871 JLOG(journal_.trace()) <<
"got header acquiring ledger " << hash_;
873 if (complete_ || failed_ || mHaveHeader)
876 auto* f = mReason == Reason::SHARD ? app_.getShardFamily()
877 : &app_.getNodeFamily();
878 mLedger = std::make_shared<Ledger>(
880 if (mLedger->info().hash != hash_ ||
881 (mSeq != 0 && mSeq != mLedger->info().seq))
883 JLOG(journal_.warn())
884 <<
"Acquire hash mismatch: " << mLedger->info().hash
890 mSeq = mLedger->info().seq;
891 mLedger->stateMap().setLedgerSeq(mSeq);
892 mLedger->txMap().setLedgerSeq(mSeq);
896 s.
add32(HashPrefix::ledgerMaster);
897 s.
addRaw(data.data(), data.size());
900 if (mLedger->info().txHash.isZero())
901 mHaveTransactions =
true;
903 if (mLedger->info().accountHash.isZero())
906 mLedger->txMap().setSynching();
907 mLedger->stateMap().setSynching();
916 InboundLedger::receiveNode(protocol::TMLedgerData& packet,
SHAMapAddNode& san)
920 JLOG(journal_.warn()) <<
"Missing ledger header";
924 if (packet.type() == protocol::liTX_NODE)
926 if (mHaveTransactions || failed_)
932 else if (mHaveState || failed_)
938 auto [map, rootHash, filter] = [&]()
940 if (packet.type() == protocol::liTX_NODE)
944 std::make_unique<TransactionStateSF>(
945 mLedger->txMap().family().db(), app_.getLedgerMaster())};
949 std::make_unique<AccountStateSF>(
950 mLedger->stateMap().family().db(), app_.getLedgerMaster())};
955 for (
auto const& node : packet.nodes())
965 if (nodeID->isRoot())
966 san += map.addRootNode(
967 rootHash,
makeSlice(node.nodedata()), filter.get());
969 san += map.addKnownNode(
970 *nodeID,
makeSlice(node.nodedata()), filter.get());
974 JLOG(journal_.warn()) <<
"Received bad node data";
981 JLOG(journal_.error()) <<
"Received bad node data: " << e.
what();
986 if (!map.isSynching())
988 if (packet.type() == protocol::liTX_NODE)
989 mHaveTransactions =
true;
993 if (mHaveTransactions && mHaveState)
1007 if (failed_ || mHaveState)
1020 mLedger->stateMap().family().db(), app_.getLedgerMaster());
1021 san += mLedger->stateMap().addRootNode(
1022 SHAMapHash{mLedger->info().accountHash}, data, &filter);
1032 if (failed_ || mHaveTransactions)
1045 mLedger->txMap().family().db(), app_.getLedgerMaster());
1046 san += mLedger->txMap().addRootNode(
1047 SHAMapHash{mLedger->info().txHash}, data, &filter);
1052 InboundLedger::getNeededHashes()
1066 mLedger->stateMap().family().db(), app_.getLedgerMaster());
1067 for (
auto const& h : neededStateHashes(4, &filter))
1074 if (!mHaveTransactions)
1077 mLedger->txMap().family().db(), app_.getLedgerMaster());
1078 for (
auto const& h : neededTxHashes(4, &filter))
1081 protocol::TMGetObjectByHash::otTRANSACTION_NODE, h));
1092 InboundLedger::gotData(
1101 mReceivedData.emplace_back(peer, data);
1103 if (mReceiveDispatched)
1106 mReceiveDispatched =
true;
1119 InboundLedger::processData(
1121 protocol::TMLedgerData& packet)
1125 if (packet.type() == protocol::liBASE)
1127 if (packet.nodes_size() < 1)
1129 JLOG(journal_.warn()) <<
"Got empty header data";
1130 peer->charge(Resource::feeInvalidRequest);
1140 if (!takeHeader(packet.nodes(0).nodedata()))
1142 JLOG(journal_.warn()) <<
"Got invalid header data";
1143 peer->charge(Resource::feeInvalidRequest);
1150 if (!mHaveState && (packet.nodes().size() > 1) &&
1151 !takeAsRootNode(
makeSlice(packet.nodes(1).nodedata()), san))
1153 JLOG(journal_.warn()) <<
"Included AS root invalid";
1156 if (!mHaveTransactions && (packet.nodes().size() > 2) &&
1157 !takeTxRootNode(
makeSlice(packet.nodes(2).nodedata()), san))
1159 JLOG(journal_.warn()) <<
"Included TX root invalid";
1164 JLOG(journal_.warn())
1165 <<
"Included AS/TX root invalid: " << ex.
what();
1166 peer->charge(Resource::feeBadData);
1177 if ((packet.type() == protocol::liTX_NODE) ||
1178 (packet.type() == protocol::liAS_NODE))
1180 if (packet.nodes().size() == 0)
1182 JLOG(journal_.info()) <<
"Got response with no nodes";
1183 peer->charge(Resource::feeInvalidRequest);
1188 for (
auto const& node : packet.nodes())
1190 if (!node.has_nodeid() || !node.has_nodedata())
1192 JLOG(journal_.warn()) <<
"Got bad node";
1193 peer->charge(Resource::feeInvalidRequest);
1199 receiveNode(packet, san);
1201 if (packet.type() == protocol::liTX_NODE)
1203 JLOG(journal_.debug()) <<
"Ledger TX node stats: " << san.
get();
1207 JLOG(journal_.debug()) <<
"Ledger AS node stats: " << san.
get();
1224 InboundLedger::runData()
1227 int chosenPeerCount = -1;
1237 if (mReceivedData.empty())
1239 mReceiveDispatched =
false;
1243 data.swap(mReceivedData);
1248 for (
auto& entry : data)
1250 if (
auto peer = entry.first.lock())
1252 int count = processData(peer, *(entry.second));
1253 if (count > chosenPeerCount)
1255 chosenPeerCount = count;
1256 chosenPeer = std::move(peer);
1263 trigger(chosenPeer, TriggerReason::reply);
1267 InboundLedger::getJson(
int)
1273 ret[jss::hash] = to_string(hash_);
1276 ret[jss::complete] =
true;
1279 ret[jss::failed] =
true;
1281 if (!complete_ && !failed_)
1282 ret[jss::peers] =
static_cast<int>(mPeerSet->getPeerIds().size());
1284 ret[jss::have_header] = mHaveHeader;
1288 ret[jss::have_state] = mHaveState;
1289 ret[jss::have_transactions] = mHaveTransactions;
1292 ret[jss::timeouts] = timeouts_;
1294 if (mHaveHeader && !mHaveState)
1297 for (
auto const& h : neededStateHashes(16,
nullptr))
1301 ret[jss::needed_state_hashes] = hv;
1304 if (mHaveHeader && !mHaveTransactions)
1307 for (
auto const& h : neededTxHashes(16,
nullptr))
1311 ret[jss::needed_transaction_hashes] = hv;