rippled
Loading...
Searching...
No Matches
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
20#include <test/jtx.h>
21#include <test/jtx/Env.h>
22
23#include <xrpld/overlay/Message.h>
24#include <xrpld/overlay/Peer.h>
25#include <xrpld/overlay/Slot.h>
26#include <xrpld/overlay/Squelch.h>
27#include <xrpld/overlay/detail/Handshake.h>
28
29#include <xrpl/basics/random.h>
30#include <xrpl/beast/unit_test.h>
31#include <xrpl/protocol/SecretKey.h>
32#include <xrpl/protocol/messages.h>
33
34#include <boost/thread.hpp>
35
36#include <chrono>
37#include <iostream>
38#include <numeric>
39#include <optional>
40
41namespace ripple {
42
43namespace test {
44
45using namespace std::chrono;
46
47class Link;
48
53using SquelchCB =
54 std::function<void(PublicKey const&, PeerWPtr const&, std::uint32_t)>;
55using UnsquelchCB = std::function<void(PublicKey const&, PeerWPtr const&)>;
57
58static constexpr std::uint32_t MAX_PEERS = 10;
59static constexpr std::uint32_t MAX_VALIDATORS = 10;
60static constexpr std::uint32_t MAX_MESSAGES = 200000;
61
65class PeerPartial : public Peer
66{
67public:
72
74 virtual ~PeerPartial()
75 {
76 }
77 virtual void
79 virtual void
80 onMessage(protocol::TMSquelch const& squelch) = 0;
81 void
82 send(protocol::TMSquelch const& squelch)
83 {
85 }
86
87 // dummy implementation
88 void
89 send(std::shared_ptr<Message> const& m) override
90 {
91 }
93 getRemoteAddress() const override
94 {
95 return {};
96 }
97 void
98 charge(Resource::Charge const& fee, std::string const& context = {})
99 override
100 {
101 }
102 bool
103 cluster() const override
104 {
105 return false;
106 }
107 bool
108 isHighLatency() const override
109 {
110 return false;
111 }
112 int
113 getScore(bool) const override
114 {
115 return 0;
116 }
117 PublicKey const&
118 getNodePublic() const override
119 {
120 return nodePublicKey_;
121 }
123 json() override
124 {
125 return {};
126 }
127 bool
129 {
130 return false;
131 }
133 publisherListSequence(PublicKey const&) const override
134 {
135 return {};
136 }
137 void
139 {
140 }
141 uint256 const&
142 getClosedLedgerHash() const override
143 {
144 static uint256 hash{};
145 return hash;
146 }
147 bool
148 hasLedger(uint256 const& hash, std::uint32_t seq) const override
149 {
150 return false;
151 }
152 void
153 ledgerRange(std::uint32_t& minSeq, std::uint32_t& maxSeq) const override
154 {
155 }
156 bool
157 hasTxSet(uint256 const& hash) const override
158 {
159 return false;
160 }
161 void
162 cycleStatus() override
163 {
164 }
165 bool
167 {
168 return false;
169 }
170 bool
171 compressionEnabled() const override
172 {
173 return false;
174 }
175 bool
176 txReduceRelayEnabled() const override
177 {
178 return false;
179 }
180 void
181 sendTxQueue() override
182 {
183 }
184 void
185 addTxQueue(uint256 const&) override
186 {
187 }
188 void
189 removeTxQueue(uint256 const&) override
190 {
191 }
192};
193
196{
197public:
198 typedef uint64_t rep;
202 inline static bool const is_steady = false;
203
204 static void
205 advance(duration d) noexcept
206 {
207 now_ += d;
208 }
209
210 static void
212 {
213 now_ += randDuration(min, max);
214 }
215
216 static void
217 reset() noexcept
218 {
219 now_ = time_point(seconds(0));
220 }
221
222 static time_point
223 now() noexcept
224 {
225 return now_;
226 }
227
228 static duration
230 {
231 return duration(milliseconds(rand_int(min.count(), max.count())));
232 }
233
234 explicit ManualClock() = default;
235
236private:
237 inline static time_point now_ = time_point(seconds(0));
238};
239
242{
243public:
244 Overlay() = default;
245 virtual ~Overlay() = default;
246
247 virtual void
249 uint256 const& key,
250 PublicKey const& validator,
251 Peer::id_t id,
252 SquelchCB f,
253 protocol::MessageType type = protocol::mtVALIDATION) = 0;
254
255 virtual void deleteIdlePeers(UnsquelchCB) = 0;
256
258};
259
260class Validator;
261
265class Link
266{
268
269public:
272 PeerSPtr peer,
273 Latency const& latency = {milliseconds(5), milliseconds(15)})
274 : validator_(validator), peer_(peer), latency_(latency), up_(true)
275 {
276 auto sp = peer_.lock();
277 assert(sp);
278 }
279 ~Link() = default;
280 void
282 {
283 if (!up_)
284 return;
285 auto sp = peer_.lock();
286 assert(sp);
288 peer->onMessage(m, f);
289 }
290 Validator&
292 {
293 return validator_;
294 }
295 void
296 up(bool linkUp)
297 {
298 up_ = linkUp;
299 }
302 {
303 auto p = peer_.lock();
304 assert(p);
305 return p->id();
306 }
309 {
310 auto p = peer_.lock();
311 assert(p);
312 return p;
313 }
314
315private:
319 bool up_;
320};
321
324{
326
327public:
329 {
330 protocol::TMValidation v;
331 v.set_validation("validation");
332 message_ = std::make_shared<Message>(v, protocol::mtVALIDATION, pkey_);
333 id_ = sid_++;
334 }
335 Validator(Validator const&) = default;
336 Validator(Validator&&) = default;
337 Validator&
338 operator=(Validator const&) = default;
339 Validator&
340 operator=(Validator&&) = default;
342 {
343 clear();
344 }
345
346 void
348 {
349 links_.clear();
350 }
351
352 static void
354 {
355 sid_ = 0;
356 }
357
358 PublicKey const&
360 {
361 return pkey_;
362 }
363
364 operator PublicKey() const
365 {
366 return pkey_;
367 }
368
369 void
371 {
373 std::make_pair(peer->id(), std::make_shared<Link>(*this, peer)));
374 }
375
376 void
378 {
379 links_.erase(id);
380 }
381
382 void
384 {
385 for (auto id : peers)
386 {
387 assert(links_.find(id) != links_.end());
388 f(*links_[id], message_);
389 }
390 }
391
392 void
393 for_links(LinkIterCB f, bool simulateSlow = false)
394 {
397 links_.begin(), links_.end(), std::back_inserter(v), [](auto& kv) {
398 return kv.second;
399 });
401 std::mt19937 g(d());
402 std::shuffle(v.begin(), v.end(), g);
403
404 for (auto& link : v)
405 {
406 f(*link, message_);
407 }
408 }
409
411 void
413 {
414 for_links(peers, [&](Link& link, MessageSPtr m) { link.send(m, f); });
415 }
416
418 void
420 {
421 for_links([&](Link& link, MessageSPtr m) { link.send(m, f); });
422 }
423
426 {
427 return message_;
428 }
429
432 {
433 return id_;
434 }
435
436 void
438 {
439 auto it = links_.find(id);
440 assert(it != links_.end());
441 it->second->up(true);
442 }
443
444 void
446 {
447 auto it = links_.find(id);
448 assert(it != links_.end());
449 it->second->up(false);
450 }
451
452private:
456 inline static std::uint16_t sid_ = 0;
458};
459
460class PeerSim : public PeerPartial, public std::enable_shared_from_this<PeerSim>
461{
462public:
464 PeerSim(Overlay& overlay, beast::Journal journal)
465 : overlay_(overlay), squelch_(journal)
466 {
467 id_ = sid_++;
468 }
469
470 ~PeerSim() = default;
471
472 id_t
473 id() const override
474 {
475 return id_;
476 }
477
478 std::string const&
479 fingerprint() const override
480 {
481 return fingerprint_;
482 }
483
484 static void
486 {
487 sid_ = 0;
488 }
489
491 void
492 onMessage(MessageSPtr const& m, SquelchCB f) override
493 {
494 auto validator = m->getValidatorKey();
495 assert(validator);
496 if (!squelch_.expireSquelch(*validator))
497 return;
498
500 }
501
503 virtual void
504 onMessage(protocol::TMSquelch const& squelch) override
505 {
506 auto validator = squelch.validatorpubkey();
507 PublicKey key(Slice(validator.data(), validator.size()));
508 if (squelch.squelch())
509 squelch_.addSquelch(
510 key, std::chrono::seconds{squelch.squelchduration()});
511 else
512 squelch_.removeSquelch(key);
513 }
514
515private:
516 inline static id_t sid_ = 0;
521};
522
524{
526
527public:
531 : slots_(app.logs(), *this, app.config()), logs_(app.logs())
532 {
533 }
534
535 ~OverlaySim() = default;
536
537 void
539 {
540 peers_.clear();
542 slots_.deleteIdlePeers();
543 }
544
547 {
548 auto res = slots_.inState(validator, state);
549 return res ? *res : 0;
550 }
551
552 void
554 uint256 const& key,
555 PublicKey const& validator,
556 Peer::id_t id,
557 SquelchCB f,
558 protocol::MessageType type = protocol::mtVALIDATION) override
559 {
560 squelch_ = f;
561 slots_.updateSlotAndSquelch(key, validator, id, type);
562 }
563
564 void
566 {
567 unsquelch_ = f;
568 slots_.deletePeer(id, true);
569 }
570
571 void
573 {
574 unsquelch_ = f;
575 slots_.deleteIdlePeers();
576 }
577
579 addPeer(bool useCache = true)
580 {
581 PeerSPtr peer{};
582 Peer::id_t id;
583 if (peersCache_.empty() || !useCache)
584 {
585 peer = std::make_shared<PeerSim>(*this, logs_.journal("Squelch"));
586 id = peer->id();
587 }
588 else
589 {
590 auto it = peersCache_.begin();
591 peer = it->second;
592 id = it->first;
593 peersCache_.erase(it);
594 }
595 peers_.emplace(std::make_pair(id, peer));
596 return peer;
597 }
598
599 void
600 deletePeer(Peer::id_t id, bool useCache = true)
601 {
602 auto it = peers_.find(id);
603 assert(it != peers_.end());
604 deletePeer(id, [&](PublicKey const&, PeerWPtr) {});
605 if (useCache)
606 peersCache_.emplace(std::make_pair(id, it->second));
607 peers_.erase(it);
608 }
609
610 void
612 {
613 while (!peers_.empty())
614 deletePeer(peers_.begin()->first);
615 while (!peersCache_.empty())
616 addPeer();
617 }
618
621 {
622 if (peers_.empty())
623 return {};
624
625 std::uint8_t maxId = 0;
626
627 for (auto& [id, _] : peers_)
628 {
629 (void)_;
630 if (id > maxId)
631 maxId = id;
632 }
633
634 deletePeer(maxId, false);
635
636 return maxId;
637 }
638
639 bool
644
647 {
648 return slots_.getSelected(validator);
649 }
650
651 bool
653 {
654 auto selected = slots_.getSelected(validator);
655 return selected.find(peer) != selected.end();
656 }
657
658 id_t
660 {
661 auto selected = slots_.getSelected(validator);
662 assert(selected.size());
663 return *selected.begin();
664 }
665
667 id_t,
674 {
675 return slots_.getPeers(validator);
676 }
677
680 {
681 return peers_.size();
682 }
683
684private:
685 void
687 PublicKey const& validator,
688 Peer::id_t id,
689 std::uint32_t squelchDuration) const override
690 {
691 if (auto it = peers_.find(id); it != peers_.end())
692 squelch_(validator, it->second, squelchDuration);
693 }
694 void
695 unsquelch(PublicKey const& validator, Peer::id_t id) const override
696 {
697 if (auto it = peers_.find(id); it != peers_.end())
698 unsquelch_(validator, it->second);
699 }
706};
707
709{
710public:
712 {
713 init();
714 }
715
716 void
718 {
720 for (int p = 0; p < MAX_PEERS; p++)
721 {
722 auto peer = overlay_.addPeer();
723 for (auto& v : validators_)
724 v.addPeer(peer);
725 }
726 }
727
728 ~Network() = default;
729
730 void
732 {
733 validators_.clear();
734 overlay_.clear();
737 init();
738 }
739
742 {
743 auto peer = overlay_.addPeer();
744 for (auto& v : validators_)
745 v.addPeer(peer);
746 return peer->id();
747 }
748
749 void
751 {
752 auto id = overlay_.deleteLastPeer();
753
754 if (!id)
755 return;
756
757 for (auto& validator : validators_)
759 }
760
761 void
763 {
764 while (overlay_.getNumPeers() > MAX_PEERS)
766 }
767
768 Validator&
770 {
771 assert(v < validators_.size());
772 return validators_[v];
773 }
774
777 {
778 return overlay_;
779 }
780
781 void
782 enableLink(std::uint16_t validatorId, Peer::id_t peer, bool enable)
783 {
784 auto it =
785 std::find_if(validators_.begin(), validators_.end(), [&](auto& v) {
786 return v.id() == validatorId;
787 });
788 assert(it != validators_.end());
789 if (enable)
790 it->linkUp(peer);
791 else
792 it->linkDown(peer);
793 }
794
795 void
797 {
798 // Send unsquelch to the Peer on all links. This way when
799 // the Peer "reconnects" it starts sending messages on the link.
800 // We expect that if a Peer disconnects and then reconnects, it's
801 // unsquelched.
802 protocol::TMSquelch squelch;
803 squelch.set_squelch(false);
804 for (auto& v : validators_)
805 {
806 PublicKey key = v;
807 squelch.clear_validatorpubkey();
808 squelch.set_validatorpubkey(key.data(), key.size());
809 v.for_links({peer}, [&](Link& l, MessageSPtr) {
811 });
812 }
813 }
814
815 void
817 std::uint32_t min,
818 std::uint32_t max,
820 {
821 auto size = max - min;
823 std::iota(s.begin(), s.end(), min);
825 std::mt19937 g(d());
826 std::shuffle(s.begin(), s.end(), g);
827 for (auto v : s)
828 f(v);
829 }
830
831 void
833 LinkIterCB link,
834 std::uint16_t nValidators = MAX_VALIDATORS,
835 std::uint32_t nMessages = MAX_MESSAGES,
836 bool purge = true,
837 bool resetClock = true)
838 {
839 if (resetClock)
841
842 if (purge)
843 {
844 purgePeers();
846 }
847
848 for (int m = 0; m < nMessages; ++m)
849 {
851 for_rand(0, nValidators, [&](std::uint32_t v) {
852 validators_[v].for_links(link);
853 });
854 }
855 }
856
858 bool
860 {
861 for (auto& v : validators_)
862 {
863 if (overlay_.isSelected(v, id))
864 return true;
865 }
866 return false;
867 }
868
873 bool
875 {
876 for (auto& v : validators_)
877 {
878 if (!overlay_.isSelected(v, peer))
879 continue;
880 auto peers = overlay_.getPeers(v);
881 for (auto& [_, v] : peers)
882 {
883 (void)_;
886 return false;
887 }
888 }
889 return true;
890 }
891
892private:
895};
896
898{
901
902protected:
903 void
905 {
907 std::cout << msg << " "
908 << "num peers " << (int)network_.overlay().getNumPeers()
909 << std::endl;
910 for (auto& [k, v] : peers)
911 std::cout << k << ":" << (int)std::get<reduce_relay::PeerState>(v)
912 << " ";
914 }
915
919 PublicKey const& validator,
920 PeerWPtr const& peerPtr,
922 {
923 protocol::TMSquelch squelch;
924 bool res = duration ? true : false;
925 squelch.set_squelch(res);
926 squelch.set_validatorpubkey(validator.data(), validator.size());
927 if (res)
928 squelch.set_squelchduration(*duration);
929 auto sp = peerPtr.lock();
930 assert(sp);
932 return sp->id();
933 }
934
935 enum State { On, Off, WaitReset };
937 // Link down or Peer disconnect event
938 // TBD - add new peer event
939 // TBD - add overlapping type of events at any
940 // time in any quantity
953
957 void
959 {
961 {LinkDown, {}}, {PeerDisconnected, {}}};
963
964 network_.reset();
965 network_.propagate([&](Link& link, MessageSPtr m) {
966 auto& validator = link.validator();
967 auto now = ManualClock::now();
968
969 bool squelched = false;
971
972 link.send(
973 m,
974 [&](PublicKey const& key,
975 PeerWPtr const& peerPtr,
977 assert(key == validator);
978 auto p = sendSquelch(key, peerPtr, duration);
979 squelched = true;
980 str << p << " ";
981 });
982
983 if (squelched)
984 {
985 auto selected = network_.overlay().getSelected(validator);
986 str << " selected: ";
987 for (auto s : selected)
988 str << s << " ";
989 if (log)
991 << (double)reduce_relay::epoch<milliseconds>(now)
992 .count() /
993 1000.
994 << " random, squelched, validator: " << validator.id()
995 << " peers: " << str.str() << std::endl;
996 auto countingState =
998 BEAST_EXPECT(
999 countingState == false &&
1000 selected.size() ==
1001 env_.app()
1002 .config()
1004 }
1005
1006 // Trigger Link Down or Peer Disconnect event
1007 // Only one Link Down at a time
1008 if (events[EventType::LinkDown].state_ == State::Off)
1009 {
1010 auto update = [&](EventType event) {
1011 events[event].cnt_++;
1012 events[event].validator_ = validator.id();
1013 events[event].key_ = validator;
1014 events[event].peer_ = link.peerId();
1015 events[event].state_ = State::On;
1016 events[event].time_ = now;
1017 if (event == EventType::LinkDown)
1018 {
1020 validator.id(), link.peerId(), false);
1021 events[event].isSelected_ =
1023 validator, link.peerId());
1024 }
1025 else
1026 events[event].isSelected_ =
1027 network_.isSelected(link.peerId());
1028 };
1029 auto r = rand_int(0, 1000);
1030 if (r == (int)EventType::LinkDown ||
1032 {
1033 update(static_cast<EventType>(r));
1034 }
1035 }
1036
1037 if (events[EventType::PeerDisconnected].state_ == State::On)
1038 {
1039 auto& event = events[EventType::PeerDisconnected];
1040 bool allCounting = network_.allCounting(event.peer_);
1042 event.peer_,
1043 [&](PublicKey const& v, PeerWPtr const& peerPtr) {
1044 if (event.isSelected_)
1045 sendSquelch(v, peerPtr, {});
1046 event.handled_ = true;
1047 });
1048 // Should only be unsquelched if the peer is in Selected state
1049 // If in Selected state it's possible unsquelching didn't
1050 // take place because there is no peers in Squelched state in
1051 // any of the slots where the peer is in Selected state
1052 // (allCounting is true)
1053 bool handled =
1054 (event.isSelected_ == false && !event.handled_) ||
1055 (event.isSelected_ == true &&
1056 (event.handled_ || allCounting));
1057 BEAST_EXPECT(handled);
1058 event.state_ = State::Off;
1059 event.isSelected_ = false;
1060 event.handledCnt_ += handled;
1061 event.handled_ = false;
1062 network_.onDisconnectPeer(event.peer_);
1063 }
1064
1065 auto& event = events[EventType::LinkDown];
1066 // Check every sec for idled peers. Idled peers are
1067 // created by Link Down event.
1068 if (now - lastCheck > milliseconds(1000))
1069 {
1070 lastCheck = now;
1071 // Check if Link Down event must be handled by
1072 // deleteIdlePeer(): 1) the peer is in Selected state;
1073 // 2) the peer has not received any messages for IDLED time;
1074 // 3) there are peers in Squelched state in the slot.
1075 // 4) peer is in Slot's peers_ (if not then it is deleted
1076 // by Slots::deleteIdlePeers())
1077 bool mustHandle = false;
1078 if (event.state_ == State::On && BEAST_EXPECT(event.key_))
1079 {
1080 event.isSelected_ =
1081 network_.overlay().isSelected(*event.key_, event.peer_);
1082 auto peers = network_.overlay().getPeers(*event.key_);
1083 auto d = reduce_relay::epoch<milliseconds>(now).count() -
1084 std::get<3>(peers[event.peer_]);
1085 mustHandle = event.isSelected_ &&
1089 0 &&
1090 peers.find(event.peer_) != peers.end();
1091 }
1093 [&](PublicKey const& v, PeerWPtr const& ptr) {
1094 event.handled_ = true;
1095 if (mustHandle && v == event.key_)
1096 {
1097 event.state_ = State::WaitReset;
1098 sendSquelch(validator, ptr, {});
1099 }
1100 });
1101 bool handled =
1102 (event.handled_ && event.state_ == State::WaitReset) ||
1103 (!event.handled_ && !mustHandle);
1104 BEAST_EXPECT(handled);
1105 }
1106 if (event.state_ == State::WaitReset ||
1107 (event.state_ == State::On &&
1108 (now - event.time_ > (reduce_relay::IDLED + seconds(2)))))
1109 {
1110 bool handled =
1111 event.state_ == State::WaitReset || !event.handled_;
1112 BEAST_EXPECT(handled);
1113 event.state_ = State::Off;
1114 event.isSelected_ = false;
1115 event.handledCnt_ += handled;
1116 event.handled_ = false;
1117 network_.enableLink(event.validator_, event.peer_, true);
1118 }
1119 });
1120
1121 auto& down = events[EventType::LinkDown];
1122 auto& disconnected = events[EventType::PeerDisconnected];
1123 // It's possible the last Down Link event is not handled
1124 BEAST_EXPECT(down.handledCnt_ >= down.cnt_ - 1);
1125 // All Peer Disconnect events must be handled
1126 BEAST_EXPECT(disconnected.cnt_ == disconnected.handledCnt_);
1127 if (log)
1128 std::cout << "link down count: " << down.cnt_ << "/"
1129 << down.handledCnt_
1130 << " peer disconnect count: " << disconnected.cnt_ << "/"
1131 << disconnected.handledCnt_;
1132 }
1133
1134 bool
1135 checkCounting(PublicKey const& validator, bool isCountingState)
1136 {
1137 auto countingState = network_.overlay().isCountingState(validator);
1138 BEAST_EXPECT(countingState == isCountingState);
1139 return countingState == isCountingState;
1140 }
1141
1142 void
1143 doTest(std::string const& msg, bool log, std::function<void(bool)> f)
1144 {
1145 testcase(msg);
1146 f(log);
1147 }
1148
1154 void
1156 {
1157 doTest("Initial Round", log, [this](bool log) {
1158 BEAST_EXPECT(propagateAndSquelch(log));
1159 });
1160 }
1161
1165 void
1167 {
1168 doTest("Peer Unsquelched Too Soon", log, [this](bool log) {
1169 BEAST_EXPECT(propagateNoSquelch(log, 1, false, false, false));
1170 });
1171 }
1172
1176 void
1178 {
1179 ManualClock::advance(seconds(601));
1180 doTest("Peer Unsquelched", log, [this](bool log) {
1181 BEAST_EXPECT(propagateNoSquelch(log, 2, true, true, false));
1182 });
1183 }
1184
1186 bool
1187 propagateAndSquelch(bool log, bool purge = true, bool resetClock = true)
1188 {
1189 int n = 0;
1190 network_.propagate(
1191 [&](Link& link, MessageSPtr message) {
1192 std::uint16_t squelched = 0;
1193 link.send(
1194 message,
1195 [&](PublicKey const& key,
1196 PeerWPtr const& peerPtr,
1198 squelched++;
1199 sendSquelch(key, peerPtr, duration);
1200 });
1201 if (squelched)
1202 {
1203 BEAST_EXPECT(
1204 squelched ==
1205 MAX_PEERS -
1206 env_.app()
1207 .config()
1208 .VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS);
1209 n++;
1210 }
1211 },
1212 1,
1214 purge,
1215 resetClock);
1216 auto selected = network_.overlay().getSelected(network_.validator(0));
1217 BEAST_EXPECT(
1218 selected.size() ==
1219 env_.app().config().VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS);
1220 BEAST_EXPECT(n == 1); // only one selection round
1221 auto res = checkCounting(network_.validator(0), false);
1222 BEAST_EXPECT(res);
1223 return n == 1 && res;
1224 }
1225
1227 bool
1229 bool log,
1230 std::uint16_t nMessages,
1231 bool countingState,
1232 bool purge = true,
1233 bool resetClock = true)
1234 {
1235 bool squelched = false;
1236 network_.propagate(
1237 [&](Link& link, MessageSPtr message) {
1238 link.send(
1239 message,
1240 [&](PublicKey const& key,
1241 PeerWPtr const& peerPtr,
1243 squelched = true;
1244 BEAST_EXPECT(false);
1245 });
1246 },
1247 1,
1248 nMessages,
1249 purge,
1250 resetClock);
1251 auto res = checkCounting(network_.validator(0), countingState);
1252 return !squelched && res;
1253 }
1254
1258 void
1259 testNewPeer(bool log)
1260 {
1261 doTest("New Peer", log, [this](bool log) {
1262 BEAST_EXPECT(propagateAndSquelch(log, true, false));
1263 network_.addPeer();
1264 BEAST_EXPECT(propagateNoSquelch(log, 1, true, false, false));
1265 });
1266 }
1267
1270 void
1272 {
1273 doTest("Selected Peer Disconnects", log, [this](bool log) {
1274 ManualClock::advance(seconds(601));
1275 BEAST_EXPECT(propagateAndSquelch(log, true, false));
1276 auto id = network_.overlay().getSelectedPeer(network_.validator(0));
1277 std::uint16_t unsquelched = 0;
1278 network_.overlay().deletePeer(
1279 id, [&](PublicKey const& key, PeerWPtr const& peer) {
1280 unsquelched++;
1281 });
1282 BEAST_EXPECT(
1283 unsquelched ==
1284 MAX_PEERS -
1285 env_.app()
1286 .config()
1287 .VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS);
1288 BEAST_EXPECT(checkCounting(network_.validator(0), true));
1289 });
1290 }
1291
1294 void
1296 {
1297 doTest("Selected Peer Stops Relaying", log, [this](bool log) {
1298 ManualClock::advance(seconds(601));
1299 BEAST_EXPECT(propagateAndSquelch(log, true, false));
1300 ManualClock::advance(reduce_relay::IDLED + seconds(1));
1301 std::uint16_t unsquelched = 0;
1302 network_.overlay().deleteIdlePeers(
1303 [&](PublicKey const& key, PeerWPtr const& peer) {
1304 unsquelched++;
1305 });
1306 auto peers = network_.overlay().getPeers(network_.validator(0));
1307 BEAST_EXPECT(
1308 unsquelched ==
1309 MAX_PEERS -
1310 env_.app()
1311 .config()
1312 .VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS);
1313 BEAST_EXPECT(checkCounting(network_.validator(0), true));
1314 });
1315 }
1316
1319 void
1321 {
1322 doTest("Squelched Peer Disconnects", log, [this](bool log) {
1323 ManualClock::advance(seconds(601));
1324 BEAST_EXPECT(propagateAndSquelch(log, true, false));
1325 auto peers = network_.overlay().getPeers(network_.validator(0));
1326 auto it = std::find_if(peers.begin(), peers.end(), [&](auto it) {
1327 return std::get<reduce_relay::PeerState>(it.second) ==
1328 reduce_relay::PeerState::Squelched;
1329 });
1330 assert(it != peers.end());
1331 std::uint16_t unsquelched = 0;
1332 network_.overlay().deletePeer(
1333 it->first, [&](PublicKey const& key, PeerWPtr const& peer) {
1334 unsquelched++;
1335 });
1336 BEAST_EXPECT(unsquelched == 0);
1337 BEAST_EXPECT(checkCounting(network_.validator(0), false));
1338 });
1339 }
1340
1341 void
1342 testConfig(bool log)
1343 {
1344 doTest("Test Config - squelch enabled (legacy)", log, [&](bool log) {
1345 Config c;
1346
1347 std::string toLoad(R"rippleConfig(
1348[reduce_relay]
1349vp_enable=1
1350)rippleConfig");
1351
1352 c.loadFromString(toLoad);
1353 BEAST_EXPECT(c.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE == true);
1354 });
1355
1356 doTest("Test Config - squelch disabled (legacy)", log, [&](bool log) {
1357 Config c;
1358
1359 std::string toLoad(R"rippleConfig(
1360[reduce_relay]
1361vp_enable=0
1362)rippleConfig");
1363
1364 c.loadFromString(toLoad);
1365 BEAST_EXPECT(c.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE == false);
1366
1367 Config c1;
1368
1369 toLoad = R"rippleConfig(
1370[reduce_relay]
1371)rippleConfig";
1372
1373 c1.loadFromString(toLoad);
1374 BEAST_EXPECT(c1.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE == false);
1375 });
1376
1377 doTest("Test Config - squelch enabled", log, [&](bool log) {
1378 Config c;
1379
1380 std::string toLoad(R"rippleConfig(
1381[reduce_relay]
1382vp_base_squelch_enable=1
1383)rippleConfig");
1384
1385 c.loadFromString(toLoad);
1386 BEAST_EXPECT(c.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE == true);
1387 });
1388
1389 doTest("Test Config - squelch disabled", log, [&](bool log) {
1390 Config c;
1391
1392 std::string toLoad(R"rippleConfig(
1393[reduce_relay]
1394vp_base_squelch_enable=0
1395)rippleConfig");
1396
1397 c.loadFromString(toLoad);
1398 BEAST_EXPECT(c.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE == false);
1399 });
1400
1401 doTest("Test Config - legacy and new", log, [&](bool log) {
1402 Config c;
1403
1404 std::string toLoad(R"rippleConfig(
1405[reduce_relay]
1406vp_base_squelch_enable=0
1407vp_enable=0
1408)rippleConfig");
1409
1410 std::string error;
1411 auto const expectedError =
1412 "Invalid reduce_relay"
1413 " cannot specify both vp_base_squelch_enable and vp_enable "
1414 "options. "
1415 "vp_enable was deprecated and replaced by "
1416 "vp_base_squelch_enable";
1417
1418 try
1419 {
1420 c.loadFromString(toLoad);
1421 }
1422 catch (std::runtime_error& e)
1423 {
1424 error = e.what();
1425 }
1426
1427 BEAST_EXPECT(error == expectedError);
1428 });
1429
1430 doTest("Test Config - max selected peers", log, [&](bool log) {
1431 Config c;
1432
1433 std::string toLoad(R"rippleConfig(
1434[reduce_relay]
1435)rippleConfig");
1436
1437 c.loadFromString(toLoad);
1438 BEAST_EXPECT(c.VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS == 5);
1439
1440 Config c1;
1441
1442 toLoad = R"rippleConfig(
1443[reduce_relay]
1444vp_base_squelch_max_selected_peers=6
1445)rippleConfig";
1446
1447 c1.loadFromString(toLoad);
1448 BEAST_EXPECT(c1.VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS == 6);
1449
1450 Config c2;
1451
1452 toLoad = R"rippleConfig(
1453[reduce_relay]
1454vp_base_squelch_max_selected_peers=2
1455)rippleConfig";
1456
1457 std::string error;
1458 auto const expectedError =
1459 "Invalid reduce_relay"
1460 " vp_base_squelch_max_selected_peers must be "
1461 "greater than or equal to 3";
1462 try
1463 {
1464 c2.loadFromString(toLoad);
1465 }
1466 catch (std::runtime_error& e)
1467 {
1468 error = e.what();
1469 }
1470
1471 BEAST_EXPECT(error == expectedError);
1472 });
1473 }
1474
1475 void
1477 {
1478 doTest("BaseSquelchReady", log, [&](bool log) {
1479 ManualClock::reset();
1480 auto createSlots = [&](bool baseSquelchEnabled)
1482 env_.app().config().VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE =
1483 baseSquelchEnabled;
1485 env_.app().logs(), network_.overlay(), env_.app().config());
1486 };
1487 // base squelching must not be ready if squelching is disabled
1488 BEAST_EXPECT(!createSlots(false).baseSquelchReady());
1489
1490 // base squelch must not be ready as not enough time passed from
1491 // bootup
1492 BEAST_EXPECT(!createSlots(true).baseSquelchReady());
1493
1494 ManualClock::advance(reduce_relay::WAIT_ON_BOOTUP + minutes{1});
1495
1496 // base squelch enabled and bootup time passed
1497 BEAST_EXPECT(createSlots(true).baseSquelchReady());
1498
1499 // even if time passed, base squelching must not be ready if turned
1500 // off in the config
1501 BEAST_EXPECT(!createSlots(false).baseSquelchReady());
1502 });
1503 }
1504
1505 void
1507 {
1508 doTest("Duplicate Message", log, [&](bool log) {
1509 network_.reset();
1510 // update message count for the same peer/validator
1511 std::int16_t nMessages = 5;
1512 for (int i = 0; i < nMessages; i++)
1513 {
1514 uint256 key(i);
1515 network_.overlay().updateSlotAndSquelch(
1516 key,
1517 network_.validator(0),
1518 0,
1519 [&](PublicKey const&, PeerWPtr, std::uint32_t) {});
1520 }
1521 auto peers = network_.overlay().getPeers(network_.validator(0));
1522 // first message changes Slot state to Counting and is not counted,
1523 // hence '-1'.
1524 BEAST_EXPECT(std::get<1>(peers[0]) == (nMessages - 1));
1525 // add duplicate
1526 uint256 key(nMessages - 1);
1527 network_.overlay().updateSlotAndSquelch(
1528 key,
1529 network_.validator(0),
1530 0,
1531 [&](PublicKey const&, PeerWPtr, std::uint32_t) {});
1532 // confirm the same number of messages
1533 peers = network_.overlay().getPeers(network_.validator(0));
1534 BEAST_EXPECT(std::get<1>(peers[0]) == (nMessages - 1));
1535 // advance the clock
1536 ManualClock::advance(reduce_relay::IDLED + seconds(1));
1537 network_.overlay().updateSlotAndSquelch(
1538 key,
1539 network_.validator(0),
1540 0,
1541 [&](PublicKey const&, PeerWPtr, std::uint32_t) {});
1542 peers = network_.overlay().getPeers(network_.validator(0));
1543 // confirm message number increased
1544 BEAST_EXPECT(std::get<1>(peers[0]) == nMessages);
1545 });
1546 }
1547
1549 {
1550 Handler() : maxDuration_(0)
1551 {
1552 }
1553 void
1555 const override
1556 {
1557 if (duration > maxDuration_)
1558 maxDuration_ = duration;
1559 }
1560 void
1561 unsquelch(PublicKey const&, Peer::id_t) const override
1562 {
1563 }
1564 mutable int maxDuration_;
1565 };
1566
1567 void
1569 {
1570 doTest("Random Squelch", l, [&](bool l) {
1572 Handler handler;
1573
1574 auto run = [&](int npeers) {
1575 handler.maxDuration_ = 0;
1577 env_.app().logs(), handler, env_.app().config());
1578 // 1st message from a new peer switches the slot
1579 // to counting state and resets the counts of all peers +
1580 // MAX_MESSAGE_THRESHOLD + 1 messages to reach the threshold
1581 // and switch the slot's state to peer selection.
1582 for (int m = 1; m <= reduce_relay::MAX_MESSAGE_THRESHOLD + 2;
1583 m++)
1584 {
1585 for (int peer = 0; peer < npeers; peer++)
1586 {
1587 // make unique message hash to make the
1588 // slot's internal hash router accept the message
1589 std::uint64_t mid = m * 1000 + peer;
1590 uint256 const message{mid};
1592 message,
1593 validator,
1594 peer,
1595 protocol::MessageType::mtVALIDATION);
1596 }
1597 }
1598 // make Slot's internal hash router expire all messages
1599 ManualClock::advance(hours(1));
1600 };
1601
1602 using namespace reduce_relay;
1603 // expect max duration less than MAX_UNSQUELCH_EXPIRE_DEFAULT with
1604 // less than or equal to 60 peers
1605 run(20);
1606 BEAST_EXPECT(
1607 handler.maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1608 handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count());
1609 run(60);
1610 BEAST_EXPECT(
1611 handler.maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1612 handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count());
1613 // expect max duration greater than MIN_UNSQUELCH_EXPIRE and less
1614 // than MAX_UNSQUELCH_EXPIRE_PEERS with peers greater than 60
1615 // and less than 360
1616 run(350);
1617 // can't make this condition stronger. squelch
1618 // duration is probabilistic and max condition may still fail.
1619 // log when the value is low
1620 BEAST_EXPECT(
1621 handler.maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1622 handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_PEERS.count());
1623 using namespace beast::unit_test::detail;
1624 if (handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count())
1625 log << make_reason(
1626 "warning: squelch duration is low",
1627 __FILE__,
1628 __LINE__)
1629 << std::endl
1630 << std::flush;
1631 // more than 400 is still less than MAX_UNSQUELCH_EXPIRE_PEERS
1632 run(400);
1633 BEAST_EXPECT(
1634 handler.maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1635 handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_PEERS.count());
1636 if (handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count())
1637 log << make_reason(
1638 "warning: squelch duration is low",
1639 __FILE__,
1640 __LINE__)
1641 << std::endl
1642 << std::flush;
1643 });
1644 }
1645
1646 void
1648 {
1649 doTest("Handshake", log, [&](bool log) {
1650 auto setEnv = [&](bool enable) {
1651 Config c;
1653 str << "[reduce_relay]\n"
1654 << "vp_enable=" << enable << "\n"
1655 << "[compression]\n"
1656 << "1\n";
1657 c.loadFromString(str.str());
1658 env_.app().config().VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE =
1660
1661 env_.app().config().COMPRESSION = c.COMPRESSION;
1662 };
1663 auto handshake = [&](int outboundEnable, int inboundEnable) {
1664 beast::IP::Address addr =
1665 boost::asio::ip::make_address("172.1.1.100");
1666
1667 setEnv(outboundEnable);
1668 auto request = ripple::makeRequest(
1669 true,
1670 env_.app().config().COMPRESSION,
1671 false,
1672 env_.app().config().TX_REDUCE_RELAY_ENABLE,
1673 env_.app().config().VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE);
1674 http_request_type http_request;
1675 http_request.version(request.version());
1676 http_request.base() = request.base();
1677 // feature enabled on the peer's connection only if both sides
1678 // are enabled
1679 auto const peerEnabled = inboundEnable && outboundEnable;
1680 // inbound is enabled if the request's header has the feature
1681 // enabled and the peer's configuration is enabled
1682 auto const inboundEnabled = peerFeatureEnabled(
1683 http_request, FEATURE_VPRR, inboundEnable);
1684 BEAST_EXPECT(!(peerEnabled ^ inboundEnabled));
1685
1686 setEnv(inboundEnable);
1687 auto http_resp = ripple::makeResponse(
1688 true,
1689 http_request,
1690 addr,
1691 addr,
1692 uint256{1},
1693 1,
1694 {1, 0},
1695 env_.app());
1696 // outbound is enabled if the response's header has the feature
1697 // enabled and the peer's configuration is enabled
1698 auto const outboundEnabled =
1699 peerFeatureEnabled(http_resp, FEATURE_VPRR, outboundEnable);
1700 BEAST_EXPECT(!(peerEnabled ^ outboundEnabled));
1701 };
1702 handshake(1, 1);
1703 handshake(1, 0);
1704 handshake(0, 1);
1705 handshake(0, 0);
1706 });
1707 }
1708
1711
1712public:
1714 : env_(*this, jtx::envconfig([](std::unique_ptr<Config> cfg) {
1715 cfg->VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE = true;
1716 cfg->VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS = 6;
1717 return cfg;
1718 }))
1719 , network_(env_.app())
1720 {
1721 }
1722
1723 void
1724 run() override
1725 {
1726 bool log = false;
1727 testConfig(log);
1728 testInitialRound(log);
1729 testPeerUnsquelchedTooSoon(log);
1730 testPeerUnsquelched(log);
1731 testNewPeer(log);
1732 testSquelchedPeerDisconnects(log);
1733 testSelectedPeerDisconnects(log);
1734 testSelectedPeerStopsRelaying(log);
1735 testInternalHashRouter(log);
1736 testRandomSquelch(log);
1737 testHandshake(log);
1738 testBaseSquelchReady(log);
1739 }
1740};
1741
1743{
1744 void
1745 testRandom(bool log)
1746 {
1747 doTest("Random Test", log, [&](bool log) { random(log); });
1748 }
1749
1750 void
1751 run() override
1752 {
1753 bool log = false;
1754 testRandom(log);
1755 }
1756};
1757
1758BEAST_DEFINE_TESTSUITE(reduce_relay, overlay, ripple);
1759BEAST_DEFINE_TESTSUITE_MANUAL(reduce_relay_simulate, overlay, ripple);
1760
1761} // namespace test
1762
1763} // namespace ripple
T back_inserter(T... args)
T begin(T... args)
Represents a JSON value.
Definition json_value.h:149
A version-independent IP address and port combination.
Definition IPEndpoint.h:38
A generic endpoint for log messages.
Definition Journal.h:60
A testsuite class.
Definition suite.h:55
log_os< char > log
Logging output stream.
Definition suite.h:152
virtual Config & config()=0
bool VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE
Definition Config.h:248
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition Config.cpp:479
bool COMPRESSION
Definition Config.h:220
std::size_t VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS
Definition Config.h:254
Manages partitions for logging.
Definition Log.h:52
beast::Journal journal(std::string const &name)
Definition Log.cpp:160
Represents a peer connection in the overlay.
std::uint32_t id_t
Uniquely identifies a peer.
A public key.
Definition PublicKey.h:62
std::uint8_t const * data() const noexcept
Definition PublicKey.h:87
std::size_t size() const noexcept
Definition PublicKey.h:93
A consumption charge.
Definition Charge.h:30
An immutable linear range of bytes.
Definition Slice.h:46
Slot is associated with a specific validator via validator's public key.
Slots is a container for validator's Slot and handles Slot update when a message is received from a v...
void updateSlotAndSquelch(uint256 const &key, PublicKey const &validator, id_t id, protocol::MessageType type)
Calls Slot::update of Slot associated with the validator, with a noop callback.
Maintains squelching of relaying messages from validators.
Definition Squelch.h:39
Manually advanced clock.
static void reset() noexcept
std::chrono::duration< std::uint32_t, period > duration
static void advance(duration d) noexcept
static duration randDuration(milliseconds min, milliseconds max)
std::chrono::time_point< ManualClock > time_point
static void randAdvance(milliseconds min, milliseconds max)
static time_point now() noexcept
Validator & validator(std::uint16_t v)
std::vector< Validator > validators_
bool isSelected(Peer::id_t id)
Is peer in Selected state in any of the slots.
bool allCounting(Peer::id_t peer)
Check if there are peers to unsquelch - peer is in Selected state in any of the slots and there are p...
void propagate(LinkIterCB link, std::uint16_t nValidators=MAX_VALIDATORS, std::uint32_t nMessages=MAX_MESSAGES, bool purge=true, bool resetClock=true)
void for_rand(std::uint32_t min, std::uint32_t max, std::function< void(std::uint32_t)> f)
void onDisconnectPeer(Peer::id_t peer)
void enableLink(std::uint16_t validatorId, Peer::id_t peer, bool enable)
reduce_relay::Slots< ManualClock > slots_
std::uint16_t getNumPeers() const
std::uint16_t inState(PublicKey const &validator, reduce_relay::PeerState state)
void unsquelch(PublicKey const &validator, Peer::id_t id) const override
Unsquelch handler.
PeerSPtr addPeer(bool useCache=true)
void deletePeer(id_t id, UnsquelchCB f) override
std::optional< Peer::id_t > deleteLastPeer()
void updateSlotAndSquelch(uint256 const &key, PublicKey const &validator, Peer::id_t id, SquelchCB f, protocol::MessageType type=protocol::mtVALIDATION) override
void deleteIdlePeers(UnsquelchCB f) override
void squelch(PublicKey const &validator, Peer::id_t id, std::uint32_t squelchDuration) const override
Squelch handler.
bool isSelected(PublicKey const &validator, Peer::id_t peer)
void deletePeer(Peer::id_t id, bool useCache=true)
bool isCountingState(PublicKey const &validator)
std::set< id_t > getSelected(PublicKey const &validator)
std::unordered_map< id_t, std::tuple< reduce_relay::PeerState, std::uint16_t, std::uint32_t, std::uint32_t > > getPeers(PublicKey const &validator)
id_t getSelectedPeer(PublicKey const &validator)
Simulate server's OverlayImpl.
virtual void updateSlotAndSquelch(uint256 const &key, PublicKey const &validator, Peer::id_t id, SquelchCB f, protocol::MessageType type=protocol::mtVALIDATION)=0
virtual ~Overlay()=default
virtual void deletePeer(Peer::id_t, UnsquelchCB)=0
virtual void deleteIdlePeers(UnsquelchCB)=0
Simulate two entities - peer directly connected to the server (via squelch in PeerSim) and PeerImp (v...
virtual void onMessage(protocol::TMSquelch const &squelch)=0
void removeTxQueue(uint256 const &) override
Remove hash from the transactions' hashes queue.
std::optional< std::size_t > publisherListSequence(PublicKey const &) const override
void send(protocol::TMSquelch const &squelch)
bool txReduceRelayEnabled() const override
void addTxQueue(uint256 const &) override
Aggregate transaction's hash.
uint256 const & getClosedLedgerHash() const override
bool hasRange(std::uint32_t uMin, std::uint32_t uMax) override
virtual void onMessage(MessageSPtr const &m, SquelchCB f)=0
Json::Value json() override
void send(std::shared_ptr< Message > const &m) override
bool compressionEnabled() const override
beast::IP::Endpoint getRemoteAddress() const override
bool cluster() const override
Returns true if this connection is a member of the cluster.
void setPublisherListSequence(PublicKey const &, std::size_t const) override
int getScore(bool) const override
void charge(Resource::Charge const &fee, std::string const &context={}) override
Adjust this peer's load balance based on the type of load imposed.
bool supportsFeature(ProtocolFeature f) const override
PublicKey const & getNodePublic() const override
bool isHighLatency() const override
bool hasTxSet(uint256 const &hash) const override
bool hasLedger(uint256 const &hash, std::uint32_t seq) const override
void sendTxQueue() override
Send aggregated transactions' hashes.
void ledgerRange(std::uint32_t &minSeq, std::uint32_t &maxSeq) const override
PeerSim(Overlay &overlay, beast::Journal journal)
virtual void onMessage(protocol::TMSquelch const &squelch) override
Remote Peer (Directly connected Peer)
void onMessage(MessageSPtr const &m, SquelchCB f) override
Local Peer (PeerImp)
reduce_relay::Squelch< ManualClock > squelch_
std::string const & fingerprint() const override
id_t id() const override
static std::uint16_t sid_
void addPeer(PeerSPtr peer)
Validator(Validator &&)=default
void send(SquelchCB f)
Send to all peers.
Validator & operator=(Validator &&)=default
void linkDown(Peer::id_t id)
void for_links(std::vector< Peer::id_t > peers, LinkIterCB f)
void deletePeer(Peer::id_t id)
void for_links(LinkIterCB f, bool simulateSlow=false)
Validator(Validator const &)=default
void send(std::vector< Peer::id_t > peers, SquelchCB f)
Send to specific peers.
Validator & operator=(Validator const &)=default
A transaction testing environment.
Definition Env.h:121
Application & app()
Definition Env.h:261
Set the fee on a JTx.
Definition fee.h:37
void testSquelchedPeerDisconnects(bool log)
Squelched peer disconnects.
void testNewPeer(bool log)
Receiving a message from new peer should change the slot's state to Counting.
void random(bool log)
Randomly brings the link between a validator and a peer down.
bool checkCounting(PublicKey const &validator, bool isCountingState)
bool propagateAndSquelch(bool log, bool purge=true, bool resetClock=true)
Propagate enough messages to generate one squelch event.
bool propagateNoSquelch(bool log, std::uint16_t nMessages, bool countingState, bool purge=true, bool resetClock=true)
Send fewer message so that squelch event is not generated.
Peer::id_t sendSquelch(PublicKey const &validator, PeerWPtr const &peerPtr, std::optional< std::uint32_t > duration)
Send squelch (if duration is set) or unsquelch (if duration not set)
void testPeerUnsquelched(bool log)
Receiving message from squelched peer should change the slot's state to Counting.
void testInitialRound(bool log)
Initial counting round: three peers receive message "faster" then others.
void testSelectedPeerStopsRelaying(bool log)
Selected peer stops relaying.
void run() override
Runs the suite.
void testPeerUnsquelchedTooSoon(bool log)
Receiving message from squelched peer too soon should not change the slot's state to Counting.
void testSelectedPeerDisconnects(bool log)
Selected peer disconnects.
void printPeers(std::string const &msg, std::uint16_t validator=0)
void doTest(std::string const &msg, bool log, std::function< void(bool)> f)
T clear(T... args)
T emplace(T... args)
T empty(T... args)
T end(T... args)
T endl(T... args)
T erase(T... args)
T find(T... args)
T flush(T... args)
T iota(T... args)
T is_same_v
T lock(T... args)
T make_pair(T... args)
boost::asio::ip::address Address
Definition IPAddress.h:39
static constexpr auto IDLED
PeerState
Peer's State.
static constexpr uint16_t MAX_MESSAGE_THRESHOLD
static constexpr auto WAIT_ON_BOOTUP
std::unique_ptr< Config > validator(std::unique_ptr< Config >, std::string const &)
adjust configuration with params needed to be a validator
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition envconfig.h:54
std::shared_ptr< Message > MessageSPtr
static constexpr std::uint32_t MAX_PEERS
static constexpr std::uint32_t MAX_VALIDATORS
static constexpr std::uint32_t MAX_MESSAGES
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:25
std::enable_if_t< std::is_integral< Integral >::value, Integral > rand_int()
http_response_type makeResponse(bool crawlPublic, http_request_type const &req, beast::IP::Address public_ip, beast::IP::Address remote_ip, uint256 const &sharedValue, std::optional< std::uint32_t > networkID, ProtocolVersion protocol, Application &app)
Make http response.
PublicKey derivePublicKey(KeyType type, SecretKey const &sk)
Derive the public key from a secret key.
int run(int argc, char **argv)
Definition Main.cpp:349
SecretKey randomSecretKey()
Create a secret key using secure random numbers.
KeyType
Definition KeyType.h:28
boost::beast::http::request< boost::beast::http::dynamic_body > http_request_type
Definition Handoff.h:33
bool peerFeatureEnabled(headers const &request, std::string const &feature, std::string value, bool config)
Check if a feature should be enabled for a peer.
Definition Handshake.h:198
T get(Section const &section, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
auto makeRequest(bool crawlPublic, bool comprEnabled, bool ledgerReplayEnabled, bool txReduceRelayEnabled, bool vpReduceRelayEnabled) -> request_type
Make outbound http request.
std::pair< PublicKey, SecretKey > randomKeyPair(KeyType type)
Create a key pair using secure random numbers.
constexpr Number squelch(Number const &x, Number const &limit) noexcept
Definition Number.h:381
static constexpr char FEATURE_VPRR[]
Definition Handshake.h:143
STL namespace.
T shuffle(T... args)
T size(T... args)
T str(T... args)
Set the sequence number on a JTx.
Definition seq.h:34
void squelch(PublicKey const &, Peer::id_t, std::uint32_t duration) const override
Squelch handler.
void unsquelch(PublicKey const &, Peer::id_t) const override
Unsquelch handler.
T transform(T... args)
T what(T... args)