#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace xrpl::test { using namespace jtx; class TMGetLedger_test : public beast::unit_test::Suite { PeerTest::SharedContext context_{makeSslContext("")}; ProtocolVersion protocolVersion_{1, 7}; // Build a well-formed TMGetLedger node request carrying `numNodeIds` node // IDs. static std::shared_ptr createRequest(std::size_t const numNodeIds) { auto request = std::make_shared(); request->set_itype(protocol::liTX_NODE); // A uint256-sized ledger hash, as a well-formed request carries. uint256 const ledgerHash{1}; request->set_ledgerhash(ledgerHash.data(), ledgerHash.size()); // Valid, deserializable SHAMap node IDs. auto const rootNodeId = SHAMapNodeID{}.getRawString(); for (std::size_t i = 0; i < numNodeIds; ++i) { request->add_nodeids(rootNodeId); } return request; } void testNodeIdCountAccepted(std::size_t const numNodeIds, bool const expectRejected) { testcase("Node ID Count Accepted"); Env env{*this}; PeerTest::resetId(); auto peer = makePeerTest(env, context_, protocolVersion_); peer->onMessage(createRequest(numNodeIds)); // A request outside the accepted node-ID count is charged kFeeInvalidData; one inside // it is not. The JobQueue handler may run concurrently and update the fee in the // accepted case. BEAST_EXPECT( expectRejected ? (peer->getCurrentFeeCharge() == resource::kFeeInvalidData) : !(peer->getCurrentFeeCharge() == resource::kFeeInvalidData)); } void testProcessLedgerRequestNodeCount(std::size_t const numNodeIds) { testcase("Process Ledger Request Node Count"); Env env{*this}; env.close(); PeerTest::resetId(); auto peer = makePeerTest(env, context_, protocolVersion_); // Ask for the account-state root node of the closed ledger. auto request = createRequest(numNodeIds); request->clear_ledgerhash(); request->set_itype(protocol::liAS_NODE); request->set_ltype(protocol::ltCLOSED); peer->runProcessLedgerRequest(request, std::vector(numNodeIds)); auto sentMessage = peer->getLastSentMessage(); BEAST_EXPECT(sentMessage != nullptr); if (!sentMessage) { return; } auto const& buffer = sentMessage->getBuffer(compression::Compressed::Off); BEAST_EXPECT(buffer.size() > 6); // Skip the message header (6 bytes: 4 for size, 2 for type). protocol::TMLedgerData reply; BEAST_EXPECT(reply.ParseFromArray(buffer.data() + 6, buffer.size() - 6) == true); BEAST_EXPECT(reply.type() == protocol::liAS_NODE); BEAST_EXPECT(reply.nodes_size() > 0); BEAST_EXPECT(reply.nodes_size() <= static_cast(tuning::kHardMaxReplyNodes)); } void run() override { auto const limit = static_cast(tuning::kHardMaxReplyNodes); testNodeIdCountAccepted(limit + 1, true); testNodeIdCountAccepted(limit, false); testNodeIdCountAccepted(limit - 1, false); testProcessLedgerRequestNodeCount(limit + 1); testProcessLedgerRequestNodeCount(limit); testProcessLedgerRequestNodeCount(limit - 1); } }; BEAST_DEFINE_TESTSUITE(TMGetLedger, overlay, xrpl); } // namespace xrpl::test