rippled
Loading...
Searching...
No Matches
tx_reduce_relay_test.cpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of rippled: https://github.com/ripple/rippled
4 Copyright 2020 Ripple Labs Inc.
5
6 Permission to use, copy, modify, and/or distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19#include <test/jtx/Env.h>
20#include <xrpld/overlay/detail/OverlayImpl.h>
21#include <xrpld/overlay/detail/PeerImp.h>
22#include <xrpld/peerfinder/detail/SlotImp.h>
23#include <xrpl/basics/make_SSLContext.h>
24#include <xrpl/beast/unit_test.h>
25
26namespace ripple {
27
28namespace test {
29
31{
32public:
33 using socket_type = boost::asio::ip::tcp::socket;
34 using middle_type = boost::beast::tcp_stream;
35 using stream_type = boost::beast::ssl_stream<middle_type>;
37
38private:
39 void
40 doTest(const std::string& msg, bool log, std::function<void(bool)> f)
41 {
42 testcase(msg);
43 f(log);
44 }
45
46 void
48 {
49 doTest("Config Test", log, [&](bool log) {
50 auto test = [&](bool enable,
51 bool metrics,
52 std::uint16_t min,
53 std::uint16_t pct,
54 bool success = true) {
55 std::stringstream str("[reduce_relay]");
56 str << "[reduce_relay]\n"
57 << "tx_enable=" << static_cast<int>(enable) << "\n"
58 << "tx_metrics=" << static_cast<int>(metrics) << "\n"
59 << "tx_min_peers=" << min << "\n"
60 << "tx_relay_percentage=" << pct << "\n";
61 Config c;
62 try
63 {
64 c.loadFromString(str.str());
65
66 BEAST_EXPECT(c.TX_REDUCE_RELAY_ENABLE == enable);
67 BEAST_EXPECT(c.TX_REDUCE_RELAY_METRICS == metrics);
68 BEAST_EXPECT(c.TX_REDUCE_RELAY_MIN_PEERS == min);
69 BEAST_EXPECT(c.TX_RELAY_PERCENTAGE == pct);
70 if (success)
71 pass();
72 else
73 fail();
74 }
75 catch (...)
76 {
77 if (success)
78 fail();
79 else
80 pass();
81 }
82 };
83
84 test(true, true, 20, 25);
85 test(false, false, 20, 25);
86 test(false, false, 20, 0, false);
87 test(false, false, 20, 101, false);
88 test(false, false, 9, 10, false);
89 test(false, false, 10, 9, false);
90 });
91 }
92
93 class PeerTest : public PeerImp
94 {
95 public:
97 Application& app,
99 http_request_type&& request,
100 PublicKey const& publicKey,
102 Resource::Consumer consumer,
104 OverlayImpl& overlay)
105 : PeerImp(
106 app,
107 sid_,
108 slot,
109 std::move(request),
110 publicKey,
111 protocol,
112 consumer,
113 std::move(stream_ptr),
114 overlay)
115 {
116 sid_++;
117 }
118 ~PeerTest() = default;
119
120 void
121 run() override
122 {
123 }
124 void
126 {
127 sendTx_++;
128 }
129 void
130 addTxQueue(const uint256& hash) override
131 {
132 queueTx_++;
133 }
134 static void
136 {
137 queueTx_ = 0;
138 sendTx_ = 0;
139 sid_ = 0;
140 }
141 inline static std::size_t sid_ = 0;
142 inline static std::uint16_t queueTx_ = 0;
143 inline static std::uint16_t sendTx_ = 0;
144 };
145
150 boost::beast::multi_buffer read_buf_;
151
152public:
155 {
156 }
157
158private:
159 void
161 jtx::Env& env,
163 std::uint16_t& nDisabled)
164 {
165 auto& overlay = dynamic_cast<OverlayImpl&>(env.app().overlay());
166 boost::beast::http::request<boost::beast::http::dynamic_body> request;
167 (nDisabled == 0)
168 ? (void)request.insert(
169 "X-Protocol-Ctl",
170 makeFeaturesRequestHeader(false, false, true, false))
171 : (void)nDisabled--;
172 auto stream_ptr = std::make_unique<stream_type>(
173 socket_type(std::forward<boost::asio::io_service&>(
174 env.app().getIOService())),
175 *context_);
177 beast::IP::Address::from_string("172.1.1." + std::to_string(lid_)));
178 beast::IP::Endpoint remote(
179 beast::IP::Address::from_string("172.1.1." + std::to_string(rid_)));
180 PublicKey key(std::get<0>(randomKeyPair(KeyType::ed25519)));
181 auto consumer = overlay.resourceManager().newInboundEndpoint(remote);
182 auto slot = overlay.peerFinder().new_inbound_slot(local, remote);
183 auto const peer = std::make_shared<PeerTest>(
184 env.app(),
185 slot,
186 std::move(request),
187 key,
189 consumer,
190 std::move(stream_ptr),
191 overlay);
192 BEAST_EXPECT(
193 overlay.findPeerByPublicKey(key) == std::shared_ptr<PeerImp>{});
194 overlay.add_active(peer);
195 BEAST_EXPECT(overlay.findPeerByPublicKey(key) == peer);
196 peers.emplace_back(peer); // overlay stores week ptr to PeerImp
197 lid_ += 2;
198 rid_ += 2;
199 assert(lid_ <= 254);
200 }
201
202 void
204 std::string const& test,
205 bool txRREnabled,
206 std::uint16_t nPeers,
207 std::uint16_t nDisabled,
208 std::uint16_t minPeers,
209 std::uint16_t relayPercentage,
210 std::uint16_t expectRelay,
211 std::uint16_t expectQueue,
212 std::set<Peer::id_t> const& toSkip = {})
213 {
214 testcase(test);
215 jtx::Env env(*this);
217 env.app().config().TX_REDUCE_RELAY_ENABLE = txRREnabled;
218 env.app().config().TX_REDUCE_RELAY_MIN_PEERS = minPeers;
219 env.app().config().TX_RELAY_PERCENTAGE = relayPercentage;
221 lid_ = 0;
222 rid_ = 0;
223 for (int i = 0; i < nPeers; i++)
224 addPeer(env, peers, nDisabled);
225 protocol::TMTransaction m;
226 m.set_rawtransaction("transaction");
227 m.set_deferred(false);
228 m.set_status(protocol::TransactionStatus::tsNEW);
229 env.app().overlay().relay(uint256{0}, m, toSkip);
230 BEAST_EXPECT(
231 PeerTest::sendTx_ == expectRelay &&
232 PeerTest::queueTx_ == expectQueue);
233 }
234
235 void
236 run() override
237 {
238 bool log = false;
239 std::set<Peer::id_t> skip = {0, 1, 2, 3, 4};
241 // relay to all peers, no hash queue
242 testRelay("feature disabled", false, 10, 0, 10, 25, 10, 0);
243 // relay to nPeers - skip (10-5=5)
244 testRelay("feature disabled & skip", false, 10, 0, 10, 25, 5, 0, skip);
245 // relay to all peers because min is greater than nPeers
246 testRelay("relay all 1", true, 10, 0, 20, 25, 10, 0);
247 // relay to all peers because min + disabled is greater thant nPeers
248 testRelay("relay all 2", true, 20, 15, 10, 25, 20, 0);
249 // relay to minPeers + 25% of nPeers-minPeers (20+0.25*(60-20)=30),
250 // queue the rest (30)
251 testRelay("relay & queue", true, 60, 0, 20, 25, 30, 30);
252 // relay to minPeers + 25% of (nPeers - nPeers) - skip
253 // (20+0.25*(60-20)-5=25), queue the rest, skip counts towards relayed
254 // (60-25-5=30)
255 testRelay("skip", true, 60, 0, 20, 25, 25, 30, skip);
256 // relay to minPeers + disabled + 25% of (nPeers - minPeers - disalbed)
257 // (20+10+0.25*(70-20-10)=40), queue the rest (30)
258 testRelay("disabled", true, 70, 10, 20, 25, 40, 30);
259 // relay to minPeers + disabled-not-in-skip + 25% of (nPeers - minPeers
260 // - disabled) (20+5+0.25*(70-20-10)=35), queue the rest, skip counts
261 // towards relayed (70-35-5=30))
262 testRelay("disabled & skip", true, 70, 10, 20, 25, 35, 30, skip);
263 // relay to minPeers + disabled + 25% of (nPeers - minPeers - disabled)
264 // - skip (10+5+0.25*(15-10-5)-10=5), queue the rest, skip counts
265 // towards relayed (15-5-10=0)
266 skip = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
267 testRelay("disabled & skip, no queue", true, 15, 5, 10, 25, 5, 0, skip);
268 // relay to minPeers + disabled + 25% of (nPeers - minPeers - disabled)
269 // - skip (10+2+0.25*(20-10-2)-14=0), queue the rest, skip counts
270 // towards relayed (20-14=6)
271 skip = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13};
272 testRelay("disabled & skip, no relay", true, 20, 2, 10, 25, 0, 6, skip);
273 }
274};
275
276BEAST_DEFINE_TESTSUITE(tx_reduce_relay, ripple_data, ripple);
277} // namespace test
278} // namespace ripple
A version-independent IP address and port combination.
Definition: IPEndpoint.h:39
A testsuite class.
Definition: suite.h:53
log_os< char > log
Logging output stream.
Definition: suite.h:150
void pass()
Record a successful test condition.
Definition: suite.h:509
testcase_t testcase
Memberspace for declaring test cases.
Definition: suite.h:153
void fail(String const &reason, char const *file, int line)
Record a failure.
Definition: suite.h:531
virtual Overlay & overlay()=0
virtual boost::asio::io_service & getIOService()=0
std::size_t TX_REDUCE_RELAY_MIN_PEERS
Definition: Config.h:276
bool TX_REDUCE_RELAY_ENABLE
Definition: Config.h:266
bool TX_REDUCE_RELAY_METRICS
Definition: Config.h:273
std::size_t TX_RELAY_PERCENTAGE
Definition: Config.h:279
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition: Config.cpp:446
std::shared_ptr< PeerFinder::Slot > const & slot()
Definition: PeerImp.h:255
A public key.
Definition: PublicKey.h:62
An endpoint that consumes resources.
Definition: Consumer.h:35
A transaction testing environment.
Definition: Env.h:117
Application & app()
Definition: Env.h:255
void send(std::shared_ptr< Message > const &) override
void addTxQueue(const uint256 &hash) override
Aggregate transaction's hash.
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 > &&stream_ptr, 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 doTest(const std::string &msg, bool log, std::function< void(bool)> f)
void addPeer(jtx::Env &env, std::vector< std::shared_ptr< PeerTest > > &peers, std::uint16_t &nDisabled)
boost::beast::ssl_stream< middle_type > stream_type
void run() override
Runs the suite.
boost::asio::ip::tcp::socket socket_type
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: algorithm.h:26
std::string makeFeaturesRequestHeader(bool comprEnabled, bool ledgerReplayEnabled, bool txReduceRelayEnabled, bool vpReduceRelayEnabled)
Make request header X-Protocol-Ctl value with supported features.
Definition: Handshake.cpp:72
std::shared_ptr< boost::asio::ssl::context > make_SSLContext(std::string const &cipherList)
Create a self-signed SSL context that allows anonymous Diffie Hellman.
boost::beast::http::request< boost::beast::http::dynamic_body > http_request_type
Definition: Handoff.h:31
std::pair< PublicKey, SecretKey > randomKeyPair(KeyType type)
Create a key pair using secure random numbers.
Definition: SecretKey.cpp:368
STL namespace.
T str(T... args)
T to_string(T... args)