Skip to content
88 changes: 53 additions & 35 deletions src/xrpld/overlay/detail/PeerImp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
#include <xrpl/resource/Gossip.h>
#include <xrpl/server/LoadFeeTrack.h>
#include <xrpl/server/NetworkOPs.h>
#include <xrpl/shamap/SHAMap.h>
#include <xrpl/shamap/SHAMapNodeID.h>
#include <xrpl/tx/apply.h>

Expand Down Expand Up @@ -1477,23 +1478,12 @@
}
}

// Verify ledger node IDs
if (itype != protocol::liBASE)
// Verify ledger node counts. Full parsing of the node IDs is deferred to the job, so the I/O
// thread is not burdened with SHAMapNodeID deserialization for every TMGetLedger message.
if (itype != protocol::liBASE && m->nodeids_size() <= 0)
{
if (m->nodeids_size() <= 0)
{
badData("Invalid ledger node IDs");
return;
}

for (auto const& nodeId : m->nodeids())
{
if (deserializeSHAMapNodeID(nodeId) == std::nullopt)
{
badData("Invalid SHAMap node ID");
return;
}
}
badData("Invalid ledger node IDs");
return;

Check warning on line 1486 in src/xrpld/overlay/detail/PeerImp.cpp

View check run for this annotation

Codecov / codecov/patch

src/xrpld/overlay/detail/PeerImp.cpp#L1486

Added line #L1486 was not covered by tests
}

// Verify query type
Expand All @@ -1513,11 +1503,40 @@
}
}

// Queue a job to process the request
// Queue a job to process the request.
std::weak_ptr<PeerImp> const weak = shared_from_this();
app_.getJobQueue().addJob(JtLedgerReq, "RcvGetLedger", [weak, m]() {
if (auto peer = weak.lock())
peer->processLedgerRequest(m);
app_.getJobQueue().addJob(JtLedgerReq, "RcvGetLedger", [weak, m, itype]() {
auto peer = weak.lock();

Check warning on line 1509 in src/xrpld/overlay/detail/PeerImp.cpp

View check run for this annotation

Codecov / codecov/patch

src/xrpld/overlay/detail/PeerImp.cpp#L1509

Added line #L1509 was not covered by tests
if (!peer)
return;

Check warning on line 1511 in src/xrpld/overlay/detail/PeerImp.cpp

View check run for this annotation

Codecov / codecov/patch

src/xrpld/overlay/detail/PeerImp.cpp#L1511

Added line #L1511 was not covered by tests

std::vector<SHAMapNodeID> nodeIDs;

Check warning on line 1513 in src/xrpld/overlay/detail/PeerImp.cpp

View check run for this annotation

Codecov / codecov/patch

src/xrpld/overlay/detail/PeerImp.cpp#L1513

Added line #L1513 was not covered by tests
if (itype != protocol::liBASE)
{
nodeIDs.reserve(std::min(m->nodeids_size(), Tuning::kSoftMaxReplyNodes));
for (auto const& nodeId : m->nodeids())
{
if (nodeIDs.size() >= Tuning::kSoftMaxReplyNodes)
{
// Charge the peer for requesting too many node IDs, but continue processing the
// received node IDs up to the limit. If the request is legitimate then at least
// they will get a response and won't have to resend these nodes in their next
// request.
peer->charge(
Resource::kFeeModerateBurdenPeer, "TMGetLedger: too many node IDs");
break;

Check warning on line 1527 in src/xrpld/overlay/detail/PeerImp.cpp

View check run for this annotation

Codecov / codecov/patch

src/xrpld/overlay/detail/PeerImp.cpp#L1527

Added line #L1527 was not covered by tests
}
auto parsed = deserializeSHAMapNodeID(nodeId);
if (!parsed)
{
peer->charge(Resource::kFeeInvalidData, "TMGetLedger: Invalid node ID");
return;

Check warning on line 1533 in src/xrpld/overlay/detail/PeerImp.cpp

View check run for this annotation

Codecov / codecov/patch

src/xrpld/overlay/detail/PeerImp.cpp#L1533

Added line #L1533 was not covered by tests
}
Comment thread
bthomee marked this conversation as resolved.
Comment thread
bthomee marked this conversation as resolved.
nodeIDs.push_back(std::move(*parsed));
}
}
Comment thread
bthomee marked this conversation as resolved.

peer->processLedgerRequest(m, std::move(nodeIDs));
});
}

Expand Down Expand Up @@ -3286,7 +3305,9 @@
}

void
PeerImp::processLedgerRequest(std::shared_ptr<protocol::TMGetLedger> const& m)
PeerImp::processLedgerRequest(

Check warning on line 3308 in src/xrpld/overlay/detail/PeerImp.cpp

View check run for this annotation

Codecov / codecov/patch

src/xrpld/overlay/detail/PeerImp.cpp#L3308

Added line #L3308 was not covered by tests
std::shared_ptr<protocol::TMGetLedger> const& m,
std::vector<SHAMapNodeID> nodeIDs)
{
// Do not resource charge a peer responding to a relay
if (!m->has_requestcookie())
Expand Down Expand Up @@ -3371,26 +3392,23 @@
}

// Add requested node data to reply
if (m->nodeids_size() > 0)
if (!nodeIDs.empty())
{
std::uint32_t const defaultDepth = isHighLatency() ? 2 : 1;
auto const queryDepth{m->has_querydepth() ? m->querydepth() : defaultDepth};

std::vector<std::pair<SHAMapNodeID, Blob>> data;

for (int i = 0;
i < m->nodeids_size() && ledgerData.nodes_size() < Tuning::kSoftMaxReplyNodes;
++i)
data.reserve(Tuning::kSoftMaxReplyNodes);
for (auto const& nodeID : nodeIDs)
{
auto const shaMapNodeId{deserializeSHAMapNodeID(m->nodeids(i))};
if (ledgerData.nodes_size() >= Tuning::kSoftMaxReplyNodes)
break;

Check warning on line 3405 in src/xrpld/overlay/detail/PeerImp.cpp

View check run for this annotation

Codecov / codecov/patch

src/xrpld/overlay/detail/PeerImp.cpp#L3405

Added line #L3405 was not covered by tests

data.clear();
data.reserve(Tuning::kSoftMaxReplyNodes);

try
{
// NOLINTNEXTLINE(bugprone-unchecked-optional-access) nodeids checked in onGetLedger
if (map->getNodeFat(*shaMapNodeId, data, fatLeaves, queryDepth))
if (map->getNodeFat(nodeID, data, fatLeaves, queryDepth))
{
JLOG(pJournal_.trace())
<< "processLedgerRequest: getNodeFat got " << data.size() << " nodes";
Expand All @@ -3399,9 +3417,9 @@
{
if (ledgerData.nodes_size() >= Tuning::kHardMaxReplyNodes)
break;
protocol::TMLedgerNode* node{ledgerData.add_nodes()};
node->set_nodeid(d.first.getRawString());
node->set_nodedata(d.second.data(), d.second.size());
protocol::TMLedgerNode* ledgerNode{ledgerData.add_nodes()};
ledgerNode->set_nodeid(d.first.getRawString());
ledgerNode->set_nodedata(d.second.data(), d.second.size());

Check warning on line 3422 in src/xrpld/overlay/detail/PeerImp.cpp

View check run for this annotation

Codecov / codecov/patch

src/xrpld/overlay/detail/PeerImp.cpp#L3422

Added line #L3422 was not covered by tests
}
}
else
Expand Down Expand Up @@ -3440,13 +3458,13 @@
info += ", no hash specified";

JLOG(pJournal_.warn())
<< "processLedgerRequest: getNodeFat with nodeId " << *shaMapNodeId
<< "processLedgerRequest: getNodeFat with nodeId " << nodeID
<< " and ledger info type " << info << " throws exception: " << e.what();
}
}

JLOG(pJournal_.info()) << "processLedgerRequest: Got request for " << m->nodeids_size()
Comment thread
bthomee marked this conversation as resolved.
<< " nodes at depth " << queryDepth << ", return "
<< " node IDs at depth " << queryDepth << ", return "
<< ledgerData.nodes_size() << " nodes";
}

Expand Down
5 changes: 4 additions & 1 deletion src/xrpld/overlay/detail/PeerImp.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include <xrpl/resource/Consumer.h>
#include <xrpl/resource/Fees.h>
#include <xrpl/server/Handoff.h>
#include <xrpl/shamap/SHAMapNodeID.h>

#include <boost/circular_buffer.hpp>
#include <boost/endian/conversion.hpp>
Expand Down Expand Up @@ -660,7 +661,9 @@ class PeerImp : public Peer, public std::enable_shared_from_this<PeerImp>, publi
getTxSet(std::shared_ptr<protocol::TMGetLedger> const& m) const;

void
processLedgerRequest(std::shared_ptr<protocol::TMGetLedger> const& m);
processLedgerRequest(
std::shared_ptr<protocol::TMGetLedger> const& m,
std::vector<SHAMapNodeID> nodeIDs);

protected:
// Kept `protected` so test subclasses (see
Expand Down
Loading