xrpld
Loading...
Searching...
No Matches
tx_reduce_relay_test.cpp
1#include <test/jtx/Env.h>
2#include <test/jtx/noop.h>
3
4#include <xrpld/app/main/Application.h>
5#include <xrpld/core/Config.h>
6#include <xrpld/overlay/Message.h>
7#include <xrpld/overlay/Peer.h>
8#include <xrpld/overlay/detail/Handshake.h>
9#include <xrpld/overlay/detail/OverlayImpl.h>
10#include <xrpld/overlay/detail/PeerImp.h>
11#include <xrpld/overlay/detail/ProtocolVersion.h>
12#include <xrpld/peerfinder/Slot.h>
13
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/protocol/KeyType.h>
19#include <xrpl/protocol/PublicKey.h>
20#include <xrpl/protocol/SecretKey.h>
21#include <xrpl/protocol/Serializer.h>
22#include <xrpl/resource/Consumer.h>
23#include <xrpl/server/Handoff.h>
24
25#include <boost/asio/io_context.hpp>
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/multi_buffer.hpp>
30#include <boost/beast/core/tcp_stream.hpp>
31#include <boost/beast/ssl/ssl_stream.hpp>
32
33#include <xrpl.pb.h>
34
35#include <cassert>
36#include <cstddef>
37#include <cstdint>
38#include <functional>
39#include <memory>
40#include <set>
41#include <sstream>
42#include <string>
43#include <utility>
44#include <vector>
45
46namespace xrpl::test {
47
49{
50public:
51 using socket_type = boost::asio::ip::tcp::socket;
52 using middle_type = boost::beast::tcp_stream;
53 using stream_type = boost::beast::ssl_stream<middle_type>;
55
56private:
57 void
58 doTest(std::string const& msg, bool log, std::function<void(bool)> f)
59 {
60 testcase(msg);
61 f(log);
62 }
63
64 void
66 {
67 doTest("Config Test", log, [&](bool log) {
68 auto test = [&](bool enable,
69 bool metrics,
70 std::uint16_t min,
71 std::uint16_t pct,
72 bool success = true) {
73 std::stringstream str("[reduce_relay]");
74 str << "[reduce_relay]\n"
75 << "tx_enable=" << static_cast<int>(enable) << "\n"
76 << "tx_metrics=" << static_cast<int>(metrics) << "\n"
77 << "tx_min_peers=" << min << "\n"
78 << "tx_relay_percentage=" << pct << "\n";
79 Config c;
80 try
81 {
82 c.loadFromString(str.str());
83
84 BEAST_EXPECT(c.txReduceRelayEnable == enable);
85 BEAST_EXPECT(c.txReduceRelayMetrics == metrics);
86 BEAST_EXPECT(c.txReduceRelayMinPeers == min);
87 BEAST_EXPECT(c.txRelayPercentage == pct);
88 if (success)
89 {
90 pass();
91 }
92 else
93 {
94 fail();
95 }
96 }
97 catch (...)
98 {
99 if (success)
100 {
101 fail();
102 }
103 else
104 {
105 pass();
106 }
107 }
108 };
109
110 test(true, true, 20, 25);
111 test(false, false, 20, 25);
112 test(false, false, 20, 0, false);
113 test(false, false, 20, 101, false);
114 test(false, false, 9, 10, false);
115 test(false, false, 10, 9, false);
116 });
117 }
118
119 class PeerTest : public PeerImp
120 {
121 public:
123 Application& app,
125 http_request_type&& request,
126 PublicKey const& publicKey,
128 Resource::Consumer consumer,
130 OverlayImpl& overlay)
131 : PeerImp(
132 app,
133 sid,
134 slot,
135 std::move(request),
136 publicKey,
137 protocol,
138 consumer,
139 std::move(streamPtr),
140 overlay)
141 {
142 sid++;
143 }
144 ~PeerTest() override = default;
145
146 void
147 run() override
148 {
149 }
150 void
152 {
153 sendTx++;
154 }
155 void
156 addTxQueue(uint256 const& hash) override
157 {
158 queueTx++;
159 }
160 static void
162 {
163 queueTx = 0;
164 sendTx = 0;
165 sid = 0;
166 }
167 inline static std::size_t sid = 0;
168 inline static std::uint16_t queueTx = 0;
169 inline static std::uint16_t sendTx = 0;
170 };
171
176 boost::beast::multi_buffer readBuf_;
177
178public:
182
183private:
184 void
186 {
187 auto& overlay = dynamic_cast<OverlayImpl&>(env.app().getOverlay());
188 boost::beast::http::request<boost::beast::http::dynamic_body> request;
189 (nDisabled == 0)
190 ? request.insert("X-Protocol-Ctl", makeFeaturesRequestHeader(false, false, true, false))
191 : (void)nDisabled--;
192 auto streamPtr = std::make_unique<stream_type>(
194 *context_);
195 beast::IP::Endpoint const local(
196 boost::asio::ip::make_address("172.1.1." + std::to_string(lid_)));
197 beast::IP::Endpoint const remote(
198 boost::asio::ip::make_address("172.1.1." + std::to_string(rid_)));
199 PublicKey const key(std::get<0>(randomKeyPair(KeyType::Ed25519)));
200 auto consumer = overlay.resourceManager().newInboundEndpoint(remote);
201 auto [slot, _] = overlay.peerFinder().newInboundSlot(local, remote);
202 auto const peer = std::make_shared<PeerTest>(
203 env.app(),
204 slot,
205 std::move(request),
206 key,
208 consumer,
209 std::move(streamPtr),
210 overlay);
211 BEAST_EXPECT(overlay.findPeerByPublicKey(key) == std::shared_ptr<PeerImp>{});
212 overlay.addActive(peer);
213 BEAST_EXPECT(overlay.findPeerByPublicKey(key) == peer);
214 peers.emplace_back(peer); // overlay stores week ptr to PeerImp
215 lid_ += 2;
216 rid_ += 2;
217 assert(lid_ <= 254);
218 }
219
220 void
222 std::string const& test,
223 bool txRREnabled,
224 std::uint16_t nPeers,
225 std::uint16_t nDisabled,
226 std::uint16_t minPeers,
227 std::uint16_t relayPercentage,
228 std::uint16_t expectRelay,
229 std::uint16_t expectQueue,
230 std::set<Peer::id_t> const& toSkip = {})
231 {
232 testcase(test);
233 jtx::Env env(*this);
235 env.app().config().txReduceRelayEnable = txRREnabled;
236 env.app().config().txReduceRelayMinPeers = minPeers;
237 env.app().config().txRelayPercentage = relayPercentage;
239 lid_ = 0;
240 rid_ = 0;
241 for (int i = 0; i < nPeers; i++)
242 addPeer(env, peers, nDisabled);
243
244 auto const jtx = env.jt(noop(env.master));
245 if (BEAST_EXPECT(jtx.stx))
246 {
247 protocol::TMTransaction m;
248 Serializer s;
249 jtx.stx->add(s);
250 m.set_rawtransaction(s.data(), s.size());
251 m.set_deferred(false);
252 m.set_status(protocol::TransactionStatus::tsNEW);
253 env.app().getOverlay().relay(uint256{0}, m, toSkip);
254 BEAST_EXPECT(PeerTest::sendTx == expectRelay && PeerTest::queueTx == expectQueue);
255 }
256 }
257
258 void
259 run() override
260 {
261 bool const log = false;
262 std::set<Peer::id_t> skip = {0, 1, 2, 3, 4};
264 // relay to all peers, no hash queue
265 testRelay("feature disabled", false, 10, 0, 10, 25, 10, 0);
266 // relay to nPeers - skip (10-5=5)
267 testRelay("feature disabled & skip", false, 10, 0, 10, 25, 5, 0, skip);
268 // relay to all peers because min is greater than nPeers
269 testRelay("relay all 1", true, 10, 0, 20, 25, 10, 0);
270 // relay to all peers because min + disabled is greater thant nPeers
271 testRelay("relay all 2", true, 20, 15, 10, 25, 20, 0);
272 // relay to minPeers + 25% of nPeers-minPeers (20+0.25*(60-20)=30),
273 // queue the rest (30)
274 testRelay("relay & queue", true, 60, 0, 20, 25, 30, 30);
275 // relay to minPeers + 25% of (nPeers - nPeers) - skip
276 // (20+0.25*(60-20)-5=25), queue the rest, skip counts towards relayed
277 // (60-25-5=30)
278 testRelay("skip", true, 60, 0, 20, 25, 25, 30, skip);
279 // relay to minPeers + disabled + 25% of (nPeers - minPeers - disabled)
280 // (20+10+0.25*(70-20-10)=40), queue the rest (30)
281 testRelay("disabled", true, 70, 10, 20, 25, 40, 30);
282 // relay to minPeers + disabled-not-in-skip + 25% of (nPeers - minPeers
283 // - disabled) (20+5+0.25*(70-20-10)=35), queue the rest, skip counts
284 // towards relayed (70-35-5=30))
285 testRelay("disabled & skip", true, 70, 10, 20, 25, 35, 30, skip);
286 // relay to minPeers + disabled + 25% of (nPeers - minPeers - disabled)
287 // - skip (10+5+0.25*(15-10-5)-10=5), queue the rest, skip counts
288 // towards relayed (15-5-10=0)
289 skip = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
290 testRelay("disabled & skip, no queue", true, 15, 5, 10, 25, 5, 0, skip);
291 // relay to minPeers + disabled + 25% of (nPeers - minPeers - disabled)
292 // - skip (10+2+0.25*(20-10-2)-14=0), queue the rest, skip counts
293 // towards relayed (20-14=6)
294 skip = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
295 testRelay("disabled & skip, no relay", true, 20, 2, 10, 25, 0, 6, skip);
296 }
297};
298
299BEAST_DEFINE_TESTSUITE(tx_reduce_relay, overlay, xrpl);
300} // namespace xrpl::test
A version-independent IP address and port combination.
Definition IPEndpoint.h:17
A testsuite class.
Definition suite.h:50
void pass()
Record a successful test condition.
Definition suite.h:500
void fail(String const &reason, char const *file, int line)
Record a failure.
Definition suite.h:522
LogOs< char > log
Logging output stream.
Definition suite.h:146
TestcaseT testcase
Memberspace for declaring test cases.
Definition suite.h:149
std::size_t txReduceRelayMinPeers
Definition Config.h:253
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition Config.cpp:473
std::size_t txRelayPercentage
Definition Config.h:256
bool txReduceRelayMetrics
Definition Config.h:250
bool txReduceRelayEnable
Definition Config.h:243
std::shared_ptr< PeerFinder::Slot > const & slot()
Definition PeerImp.h:257
PeerImp(PeerImp const &)=delete
friend class OverlayImpl
Definition PeerImp.h:181
A public key.
Definition PublicKey.h:42
An endpoint that consumes resources.
Definition Consumer.h:15
std::size_t size() const noexcept
Definition Serializer.h:50
void const * data() const noexcept
Definition Serializer.h:56
virtual boost::asio::io_context & getIOContext()=0
A transaction testing environment.
Definition Env.h:143
Application & app()
Definition Env.h:280
void addTxQueue(uint256 const &hash) override
Add transaction's hash to the transactions' hashes queue.
void send(std::shared_ptr< Message > const &) override
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< tx_reduce_relay_test::stream_type > &&streamPtr, OverlayImpl &overlay)
void testRelay(std::string const &test, bool txRREnabled, std::uint16_t nPeers, std::uint16_t nDisabled, std::uint16_t minPeers, std::uint16_t relayPercentage, std::uint16_t expectRelay, std::uint16_t expectQueue, std::set< Peer::id_t > const &toSkip={})
void addPeer(jtx::Env &env, std::vector< std::shared_ptr< PeerTest > > &peers, std::uint16_t &nDisabled)
boost::asio::ip::tcp::socket socket_type
std::shared_ptr< boost::asio::ssl::context > shared_context
void run() override
Runs the suite.
boost::beast::ssl_stream< middle_type > stream_type
void doTest(std::string const &msg, bool log, std::function< void(bool)> f)
T forward(T... args)
T make_shared(T... args)
T make_unique(T... args)
STL namespace.
json::Value noop(Account const &account)
The null transaction.
Definition noop.h:9
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.
std::shared_ptr< boost::asio::ssl::context > makeSslContext(std::string const &cipherList)
Create a self-signed SSL context that allows anonymous Diffie Hellman.
std::string makeFeaturesRequestHeader(bool comprEnabled, bool ledgerReplayEnabled, bool txReduceRelayEnabled, bool vpReduceRelayEnabled)
Make request header X-Protocol-Ctl value with supported features.
Definition Handshake.cpp:83
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
BaseUInt< 256 > uint256
Definition base_uint.h:562
T str(T... args)
T to_string(T... args)