xrpld
Loading...
Searching...
No Matches
TMGetObjectByHash_test.cpp
1#include <test/jtx/Env.h>
2
3#include <xrpld/app/main/Application.h>
4#include <xrpld/overlay/Compression.h>
5#include <xrpld/overlay/Message.h>
6#include <xrpld/overlay/Peer.h>
7#include <xrpld/overlay/detail/OverlayImpl.h>
8#include <xrpld/overlay/detail/PeerImp.h>
9#include <xrpld/overlay/detail/ProtocolVersion.h>
10#include <xrpld/overlay/detail/Tuning.h>
11#include <xrpld/peerfinder/Slot.h>
12
13#include <xrpl/basics/Blob.h>
14#include <xrpl/basics/base_uint.h>
15#include <xrpl/basics/make_SSLContext.h>
16#include <xrpl/beast/net/IPEndpoint.h>
17#include <xrpl/beast/unit_test/suite.h>
18#include <xrpl/nodestore/NodeObject.h>
19#include <xrpl/protocol/KeyType.h>
20#include <xrpl/protocol/PublicKey.h>
21#include <xrpl/protocol/SecretKey.h>
22#include <xrpl/protocol/digest.h>
23#include <xrpl/resource/Consumer.h>
24#include <xrpl/server/Handoff.h>
25
26#include <boost/asio/ip/address.hpp>
27#include <boost/asio/ip/tcp.hpp>
28#include <boost/asio/ssl/context.hpp>
29#include <boost/beast/core/tcp_stream.hpp>
30#include <boost/beast/ssl/ssl_stream.hpp>
31
32#include <xrpl.pb.h>
33
34#include <cstddef>
35#include <memory>
36#include <utility>
37#include <vector>
38
39namespace xrpl::test {
40
41using namespace jtx;
42
51{
52 using middle_type = boost::beast::tcp_stream;
53 using stream_type = boost::beast::ssl_stream<middle_type>;
54 using socket_type = boost::asio::ip::tcp::socket;
59 class PeerTest : public PeerImp
60 {
61 public:
63 Application& app,
65 http_request_type&& request,
66 PublicKey const& publicKey,
68 Resource::Consumer consumer,
70 OverlayImpl& overlay)
71 : PeerImp(
72 app,
73 id++,
74 slot,
75 std::move(request),
76 publicKey,
78 consumer,
79 std::move(streamPtr),
80 overlay)
81 {
82 }
83
84 ~PeerTest() override = default;
85
86 void
87 run() override
88 {
89 }
90
91 void
92 send(std::shared_ptr<Message> const& m) override
93 {
95 }
96
99 {
100 return lastSentMessage_;
101 }
102
103 // Synchronous test access to the JobQueue-dispatched processor.
104 // The production path runs this on JtLedgerReq; tests need a
105 // synchronous entry point to inspect the reply via send().
106 // PeerImp::processGetObjectByHash is `protected` so the derived
107 // test subclass can call it directly.
108 void
113
114 static void
116 {
117 id = 0;
118 }
119
120 private:
121 inline static Peer::id_t id = 0;
123 };
124
127
130 {
131 auto& overlay = dynamic_cast<OverlayImpl&>(env.app().getOverlay());
132 boost::beast::http::request<boost::beast::http::dynamic_body> request;
133 auto streamPtr =
135
136 beast::IP::Endpoint const local(boost::asio::ip::make_address("172.1.1.1"), 51235);
137 beast::IP::Endpoint const remote(boost::asio::ip::make_address("172.1.1.2"), 51235);
138
139 PublicKey const key(std::get<0>(randomKeyPair(KeyType::Ed25519)));
140 auto consumer = overlay.resourceManager().newInboundEndpoint(remote);
141 auto [slot, _] = overlay.peerFinder().newInboundSlot(local, remote);
142
143 auto peer = std::make_shared<PeerTest>(
144 env.app(),
145 slot,
146 std::move(request),
147 key,
149 consumer,
150 std::move(streamPtr),
151 overlay);
152
153 overlay.addActive(peer);
154 return peer;
155 }
156
158 createRequest(size_t const numObjects, Env& env)
159 {
160 // Store objects in the NodeStore that will be found during the query
161 auto& nodeStore = env.app().getNodeStore();
162
163 // Create and store objects
165 hashes.reserve(numObjects);
166 for (int i = 0; i < numObjects; ++i)
167 {
168 uint256 const hash(xrpl::sha512Half(i));
169 hashes.push_back(hash);
170
171 Blob data(100, static_cast<unsigned char>(i % 256));
172 nodeStore.store(
173 NodeObjectType::Ledger, std::move(data), hash, nodeStore.earliestLedgerSeq());
174 }
175
176 // Create a request with more objects than hardMaxReplyNodes
178 request->set_type(protocol::TMGetObjectByHash_ObjectType_otLEDGER);
179 request->set_query(true);
180
181 for (int i = 0; i < numObjects; ++i)
182 {
183 auto object = request->add_objects();
184 object->set_hash(hashes[i].data(), hashes[i].size());
185 object->set_ledgerseq(i);
186 }
187 return request;
188 }
189
198 void
199 testReplyLimit(size_t const numObjects, int const expectedReplySize)
200 {
201 testcase("Reply Limit");
202
203 Env env(*this);
205
206 auto peer = createPeer(env);
207
208 auto request = createRequest(numObjects, env);
209 peer->runProcessGetObjectByHash(request);
210
211 // Verify that a reply was sent
212 auto sentMessage = peer->getLastSentMessage();
213 BEAST_EXPECT(sentMessage != nullptr);
214
215 // Parse the reply message
216 auto const& buffer = sentMessage->getBuffer(compression::Compressed::Off);
217
218 BEAST_EXPECT(buffer.size() > 6);
219 // Skip the message header (6 bytes: 4 for size, 2 for type)
220 protocol::TMGetObjectByHash reply;
221 BEAST_EXPECT(reply.ParseFromArray(buffer.data() + 6, buffer.size() - 6) == true);
222
223 // Verify the reply is limited to expectedReplySize
224 BEAST_EXPECT(reply.objects_size() == expectedReplySize);
225 }
226
227 void
228 run() override
229 {
230 int const limit = static_cast<int>(Tuning::kHardMaxReplyNodes);
231 testReplyLimit(limit + 1, limit);
232 testReplyLimit(limit, limit);
233 testReplyLimit(limit - 1, limit - 1);
234 }
235};
236
237BEAST_DEFINE_TESTSUITE(TMGetObjectByHash, overlay, xrpl);
238
239} // namespace xrpl::test
A version-independent IP address and port combination.
Definition IPEndpoint.h:17
A testsuite class.
Definition suite.h:50
TestcaseT testcase
Memberspace for declaring test cases.
Definition suite.h:149
std::shared_ptr< PeerFinder::Slot > const & slot()
Definition PeerImp.h:257
PeerImp(PeerImp const &)=delete
void processGetObjectByHash(std::shared_ptr< protocol::TMGetObjectByHash > const &m)
Process a generic-query TMGetObjectByHash message.
Definition PeerImp.cpp:2573
friend class OverlayImpl
Definition PeerImp.h:181
std::uint32_t id_t
Uniquely identifies a peer.
A public key.
Definition PublicKey.h:42
An endpoint that consumes resources.
Definition Consumer.h:15
virtual NodeStore::Database & getNodeStore()=0
virtual boost::asio::io_context & getIOContext()=0
void runProcessGetObjectByHash(std::shared_ptr< protocol::TMGetObjectByHash > const &m)
PeerTest(Application &app, std::shared_ptr< PeerFinder::Slot > const &slot, http_request_type &&request, PublicKey const &publicKey, ProtocolVersion protocol, Resource::Consumer consumer, std::unique_ptr< TMGetObjectByHash_test::stream_type > &&streamPtr, OverlayImpl &overlay)
std::shared_ptr< Message > getLastSentMessage() const
void send(std::shared_ptr< Message > const &m) override
Test for TMGetObjectByHash reply size limiting.
static std::shared_ptr< protocol::TMGetObjectByHash > createRequest(size_t const numObjects, Env &env)
boost::beast::ssl_stream< middle_type > stream_type
void testReplyLimit(size_t const numObjects, int const expectedReplySize)
Test that reply is limited to hardMaxReplyNodes when more objects are requested than the limit allows...
std::shared_ptr< PeerTest > createPeer(jtx::Env &env)
std::shared_ptr< boost::asio::ssl::context > shared_context
boost::asio::ip::tcp::socket socket_type
A transaction testing environment.
Definition Env.h:143
Application & app()
Definition Env.h:280
T make_shared(T... args)
T make_unique(T... args)
STL namespace.
static constexpr auto kHardMaxReplyNodes
The hard cap on the number of ledger entries in a single reply.
BEAST_DEFINE_TESTSUITE(AMMClawback, app, xrpl)
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
std::pair< PublicKey, SecretKey > randomKeyPair(KeyType type)
Create a key pair using secure random numbers.
sha512_half_hasher::result_type sha512Half(Args const &... args)
Returns the SHA512-Half of a series of objects.
Definition digest.h:204
std::shared_ptr< boost::asio::ssl::context > makeSslContext(std::string const &cipherList)
Create a self-signed SSL context that allows anonymous Diffie Hellman.
std::pair< std::uint16_t, std::uint16_t > ProtocolVersion
Represents a particular version of the peer-to-peer protocol.
boost::beast::http::request< boost::beast::http::dynamic_body > http_request_type
Definition Handoff.h:12
std::vector< unsigned char > Blob
Storage for linear binary data.
Definition Blob.h:10
BaseUInt< 256 > uint256
Definition base_uint.h:562
T push_back(T... args)
T reserve(T... args)