rippled
Loading...
Searching...
No Matches
reduce_relay_test.cpp
1#include <test/jtx.h>
2#include <test/jtx/Env.h>
3
4#include <xrpld/overlay/Message.h>
5#include <xrpld/overlay/Peer.h>
6#include <xrpld/overlay/Slot.h>
7#include <xrpld/overlay/Squelch.h>
8#include <xrpld/overlay/detail/Handshake.h>
9
10#include <xrpl/basics/random.h>
11#include <xrpl/beast/unit_test.h>
12#include <xrpl/protocol/SecretKey.h>
13#include <xrpl/protocol/messages.h>
14
15#include <boost/thread.hpp>
16
17#include <algorithm>
18#include <chrono>
19#include <iostream>
20#include <numeric>
21#include <optional>
22
23namespace xrpl {
24
25namespace test {
26
27using namespace std::chrono;
28
29class Link;
30
36using UnsquelchCB = std::function<void(PublicKey const&, PeerWPtr const&)>;
38
39static constexpr std::uint32_t MAX_PEERS = 10;
40static constexpr std::uint32_t MAX_VALIDATORS = 10;
41static constexpr std::uint32_t MAX_MESSAGES = 200000;
42
46class PeerPartial : public Peer
47{
48public:
52
54 virtual ~PeerPartial()
55 {
56 }
57 virtual void
59 virtual void
60 onMessage(protocol::TMSquelch const& squelch) = 0;
61 void
62 send(protocol::TMSquelch const& squelch)
63 {
65 }
66
67 // dummy implementation
68 void
69 send(std::shared_ptr<Message> const& m) override
70 {
71 }
73 getRemoteAddress() const override
74 {
75 return {};
76 }
77 void
78 charge(Resource::Charge const& fee, std::string const& context = {}) override
79 {
80 }
81 bool
82 cluster() const override
83 {
84 return false;
85 }
86 bool
87 isHighLatency() const override
88 {
89 return false;
90 }
91 int
92 getScore(bool) const override
93 {
94 return 0;
95 }
96 PublicKey const&
97 getNodePublic() const override
98 {
99 return nodePublicKey_;
100 }
102 json() override
103 {
104 return {};
105 }
106 bool
108 {
109 return false;
110 }
112 publisherListSequence(PublicKey const&) const override
113 {
114 return {};
115 }
116 void
118 {
119 }
120 uint256 const&
121 getClosedLedgerHash() const override
122 {
123 static uint256 const hash{};
124 return hash;
125 }
126 bool
127 hasLedger(uint256 const& hash, std::uint32_t seq) const override
128 {
129 return false;
130 }
131 void
132 ledgerRange(std::uint32_t& minSeq, std::uint32_t& maxSeq) const override
133 {
134 }
135 bool
136 hasTxSet(uint256 const& hash) const override
137 {
138 return false;
139 }
140 void
141 cycleStatus() override
142 {
143 }
144 bool
146 {
147 return false;
148 }
149 bool
150 compressionEnabled() const override
151 {
152 return false;
153 }
154 bool
155 txReduceRelayEnabled() const override
156 {
157 return false;
158 }
159 void
160 sendTxQueue() override
161 {
162 }
163 void
164 addTxQueue(uint256 const&) override
165 {
166 }
167 void
168 removeTxQueue(uint256 const&) override
169 {
170 }
171};
172
175{
176public:
177 typedef uint64_t rep;
181 inline static bool const is_steady = false;
182
183 static void
184 advance(duration d) noexcept
185 {
186 now_ += d;
187 }
188
189 static void
191 {
192 now_ += randDuration(min, max);
193 }
194
195 static void
196 reset() noexcept
197 {
198 now_ = time_point(seconds(0));
199 }
200
201 static time_point
202 now() noexcept
203 {
204 return now_;
205 }
206
207 static duration
209 {
210 return duration(milliseconds(rand_int(min.count(), max.count())));
211 }
212
213 explicit ManualClock() = default;
214
215private:
216 inline static time_point now_ = time_point(seconds(0));
217};
218
221{
222public:
223 Overlay() = default;
224 virtual ~Overlay() = default;
225
226 virtual void
228 uint256 const& key,
229 PublicKey const& validator,
230 Peer::id_t id,
231 SquelchCB f,
232 protocol::MessageType type = protocol::mtVALIDATION) = 0;
233
234 virtual void deleteIdlePeers(UnsquelchCB) = 0;
235
237};
238
239class Validator;
240
244class Link
245{
247
248public:
251 PeerSPtr peer,
252 Latency const& latency = {milliseconds(5), milliseconds(15)})
253 : validator_(validator), peer_(peer), latency_(latency)
254 {
255 auto sp = peer_.lock();
256 assert(sp);
257 }
258 ~Link() = default;
259 void
261 {
262 if (!up_)
263 return;
264 auto sp = peer_.lock();
265 assert(sp);
267 peer->onMessage(m, f);
268 }
269 Validator&
271 {
272 return validator_;
273 }
274 void
275 up(bool linkUp)
276 {
277 up_ = linkUp;
278 }
281 {
282 auto p = peer_.lock();
283 assert(p);
284 return p->id();
285 }
288 {
289 auto p = peer_.lock();
290 assert(p);
291 return p;
292 }
293
294private:
298 bool up_{true};
299};
300
303{
305
306public:
308 {
309 protocol::TMValidation v;
310 v.set_validation("validation");
311 message_ = std::make_shared<Message>(v, protocol::mtVALIDATION, pkey_);
312 id_ = sid_++;
313 }
314 Validator(Validator const&) = default;
315 Validator(Validator&&) = default;
316 Validator&
317 operator=(Validator const&) = default;
318 Validator&
319 operator=(Validator&&) = default;
321 {
322 clear();
323 }
324
325 void
327 {
328 links_.clear();
329 }
330
331 static void
333 {
334 sid_ = 0;
335 }
336
337 PublicKey const&
339 {
340 return pkey_;
341 }
342
343 operator PublicKey() const
344 {
345 return pkey_;
346 }
347
348 void
350 {
351 links_.emplace(std::make_pair(peer->id(), std::make_shared<Link>(*this, peer)));
352 }
353
354 void
356 {
357 links_.erase(id);
358 }
359
360 void
362 {
363 for (auto id : peers)
364 {
365 assert(links_.contains(id));
366 f(*links_[id], message_);
367 }
368 }
369
370 void
371 for_links(LinkIterCB f, bool simulateSlow = false)
372 {
374 std::transform(links_.begin(), links_.end(), std::back_inserter(v), [](auto& kv) {
375 return kv.second;
376 });
378 std::mt19937 g(d());
379 std::shuffle(v.begin(), v.end(), g);
380
381 for (auto& link : v)
382 {
383 f(*link, message_);
384 }
385 }
386
388 void
390 {
391 for_links(peers, [&](Link& link, MessageSPtr m) { link.send(m, f); });
392 }
393
395 void
397 {
398 for_links([&](Link& link, MessageSPtr m) { link.send(m, f); });
399 }
400
403 {
404 return message_;
405 }
406
408 id() const
409 {
410 return id_;
411 }
412
413 void
415 {
416 auto it = links_.find(id);
417 assert(it != links_.end());
418 it->second->up(true);
419 }
420
421 void
423 {
424 auto it = links_.find(id);
425 assert(it != links_.end());
426 it->second->up(false);
427 }
428
429private:
433 inline static std::uint16_t sid_ = 0;
435};
436
437class PeerSim : public PeerPartial, public std::enable_shared_from_this<PeerSim>
438{
439public:
441 PeerSim(Overlay& overlay, beast::Journal journal) : overlay_(overlay), squelch_(journal)
442 {
443 id_ = sid_++;
444 }
445
446 ~PeerSim() = default;
447
448 id_t
449 id() const override
450 {
451 return id_;
452 }
453
454 std::string const&
455 fingerprint() const override
456 {
457 return fingerprint_;
458 }
459
460 static void
462 {
463 sid_ = 0;
464 }
465
467 void
468 onMessage(MessageSPtr const& m, SquelchCB f) override
469 {
470 auto validator = m->getValidatorKey();
471 assert(validator);
472 if (!squelch_.expireSquelch(*validator)) // NOLINT(bugprone-unchecked-optional-access)
473 return;
474
476 {}, *validator, id(), f); // NOLINT(bugprone-unchecked-optional-access)
477 }
478
480 virtual void
481 onMessage(protocol::TMSquelch const& squelch) override
482 {
483 auto validator = squelch.validatorpubkey();
484 PublicKey const key(Slice(validator.data(), validator.size()));
485 if (squelch.squelch())
486 {
487 squelch_.addSquelch(key, std::chrono::seconds{squelch.squelchduration()});
488 }
489 else
490 {
491 squelch_.removeSquelch(key);
492 }
493 }
494
495private:
496 inline static id_t sid_ = 0;
501};
502
504{
506
507public:
510 OverlaySim(Application& app) : slots_(app, *this, app.config()), registry_(app)
511 {
512 }
513
514 ~OverlaySim() = default;
515
516 void
518 {
519 peers_.clear();
521 slots_.deleteIdlePeers();
522 }
523
526 {
527 auto res = slots_.inState(validator, state);
528 return res ? *res : 0;
529 }
530
531 void
533 uint256 const& key,
534 PublicKey const& validator,
535 Peer::id_t id,
536 SquelchCB f,
537 protocol::MessageType type = protocol::mtVALIDATION) override
538 {
539 squelch_ = f;
540 slots_.updateSlotAndSquelch(key, validator, id, type);
541 }
542
543 void
545 {
546 unsquelch_ = f;
547 slots_.deletePeer(id, true);
548 }
549
550 void
552 {
553 unsquelch_ = f;
554 slots_.deleteIdlePeers();
555 }
556
558 addPeer(bool useCache = true)
559 {
560 PeerSPtr peer{};
561 Peer::id_t id = 0;
562 if (peersCache_.empty() || !useCache)
563 {
564 peer = std::make_shared<PeerSim>(*this, registry_.getJournal("Squelch"));
565 id = peer->id();
566 }
567 else
568 {
569 auto it = peersCache_.begin();
570 peer = it->second;
571 id = it->first;
572 peersCache_.erase(it);
573 }
574 peers_.emplace(std::make_pair(id, peer));
575 return peer;
576 }
577
578 void
579 deletePeer(Peer::id_t id, bool useCache = true)
580 {
581 auto it = peers_.find(id);
582 assert(it != peers_.end());
583 deletePeer(id, [&](PublicKey const&, PeerWPtr) {});
584 if (useCache)
585 peersCache_.emplace(std::make_pair(id, it->second));
586 peers_.erase(it);
587 }
588
589 void
591 {
592 while (!peers_.empty())
593 deletePeer(peers_.begin()->first);
594 while (!peersCache_.empty())
595 addPeer();
596 }
597
600 {
601 if (peers_.empty())
602 return {};
603
604 std::uint8_t maxId = 0;
605
606 for (auto& [id, _] : peers_)
607 {
608 (void)_;
609 maxId = std::max<unsigned int>(id, maxId);
610 }
611
612 deletePeer(maxId, false);
613
614 return maxId;
615 }
616
617 bool
622
625 {
626 return slots_.getSelected(validator);
627 }
628
629 bool
631 {
632 auto selected = slots_.getSelected(validator);
633 return selected.contains(peer);
634 }
635
636 id_t
638 {
639 auto selected = slots_.getSelected(validator);
640 assert(!selected.empty());
641 return *selected.begin();
642 }
643
645 id_t,
648 {
649 return slots_.getPeers(validator);
650 }
651
654 {
655 return peers_.size();
656 }
657
658private:
659 void
660 squelch(PublicKey const& validator, Peer::id_t id, std::uint32_t squelchDuration) const override
661 {
662 if (auto it = peers_.find(id); it != peers_.end())
663 squelch_(validator, it->second, squelchDuration);
664 }
665 void
666 unsquelch(PublicKey const& validator, Peer::id_t id) const override
667 {
668 if (auto it = peers_.find(id); it != peers_.end())
669 unsquelch_(validator, it->second);
670 }
677};
678
680{
681public:
683 {
684 init();
685 }
686
687 void
689 {
691 for (int p = 0; p < MAX_PEERS; p++)
692 {
693 auto peer = overlay_.addPeer();
694 for (auto& v : validators_)
695 v.addPeer(peer);
696 }
697 }
698
699 ~Network() = default;
700
701 void
703 {
704 validators_.clear();
705 overlay_.clear();
708 init();
709 }
710
713 {
714 auto peer = overlay_.addPeer();
715 for (auto& v : validators_)
716 v.addPeer(peer);
717 return peer->id();
718 }
719
720 void
722 {
723 auto id = overlay_.deleteLastPeer();
724
725 if (!id)
726 return;
727
728 for (auto& validator : validators_)
730 }
731
732 void
734 {
735 while (overlay_.getNumPeers() > MAX_PEERS)
737 }
738
739 Validator&
741 {
742 assert(v < validators_.size());
743 return validators_[v];
744 }
745
748 {
749 return overlay_;
750 }
751
752 void
753 enableLink(std::uint16_t validatorId, Peer::id_t peer, bool enable)
754 {
755 auto it = std::find_if(
756 validators_.begin(), validators_.end(), [&](auto& v) { return v.id() == validatorId; });
757 assert(it != validators_.end());
758 if (enable)
759 {
760 it->linkUp(peer);
761 }
762 else
763 {
764 it->linkDown(peer);
765 }
766 }
767
768 void
770 {
771 // Send unsquelch to the Peer on all links. This way when
772 // the Peer "reconnects" it starts sending messages on the link.
773 // We expect that if a Peer disconnects and then reconnects, it's
774 // unsquelched.
775 protocol::TMSquelch squelch;
776 squelch.set_squelch(false);
777 for (auto& v : validators_)
778 {
779 PublicKey const key = v;
780 squelch.clear_validatorpubkey();
781 squelch.set_validatorpubkey(key.data(), key.size());
782 v.for_links({peer}, [&](Link& l, MessageSPtr) {
784 });
785 }
786 }
787
788 static void
790 {
791 auto size = max - min;
793 std::iota(s.begin(), s.end(), min);
795 std::mt19937 g(d());
796 std::shuffle(s.begin(), s.end(), g);
797 for (auto v : s)
798 f(v);
799 }
800
801 void
803 LinkIterCB link,
804 std::uint16_t nValidators = MAX_VALIDATORS,
805 std::uint32_t nMessages = MAX_MESSAGES,
806 bool purge = true,
807 bool resetClock = true)
808 {
809 if (resetClock)
811
812 if (purge)
813 {
814 purgePeers();
816 }
817
818 for (int m = 0; m < nMessages; ++m)
819 {
821 for_rand(0, nValidators, [&](std::uint32_t v) { validators_[v].for_links(link); });
822 }
823 }
824
826 bool
828 {
829 for (auto& v : validators_)
830 {
831 if (overlay_.isSelected(v, id))
832 return true;
833 }
834 return false;
835 }
836
841 bool
843 {
844 for (auto& v : validators_)
845 {
846 if (!overlay_.isSelected(v, peer))
847 continue;
848 auto peers = overlay_.getPeers(v);
849 for (auto& [_, v] : peers)
850 {
851 (void)_;
853 return false;
854 }
855 }
856 return true;
857 }
858
859private:
862};
863
865{
868
869protected:
870 void
872 {
874 std::cout << msg << " "
875 << "num peers " << (int)network_.overlay().getNumPeers() << std::endl;
876 for (auto& [k, v] : peers)
877 std::cout << k << ":" << (int)std::get<reduce_relay::PeerState>(v) << " ";
879 }
880
882 static Peer::id_t
884 PublicKey const& validator,
885 PeerWPtr const& peerPtr,
887 {
888 protocol::TMSquelch squelch;
889 bool const res = static_cast<bool>(duration);
890 squelch.set_squelch(res);
891 squelch.set_validatorpubkey(validator.data(), validator.size());
892 if (res)
893 squelch.set_squelchduration(*duration);
894 auto sp = peerPtr.lock();
895 assert(sp);
897 return sp->id();
898 }
899
900 enum State { On, Off, WaitReset };
902 // Link down or Peer disconnect event
903 // TBD - add new peer event
904 // TBD - add overlapping type of events at any
905 // time in any quantity
918
922 void
924 {
927
928 network_.reset();
929 network_.propagate([&](Link& link, MessageSPtr m) {
930 auto& validator = link.validator();
931 auto now = ManualClock::now();
932
933 bool squelched = false;
935
936 link.send(
937 m, [&](PublicKey const& key, PeerWPtr const& peerPtr, std::uint32_t duration) {
938 assert(key == validator);
939 auto p = sendSquelch(key, peerPtr, duration);
940 squelched = true;
941 str << p << " ";
942 });
943
944 if (squelched)
945 {
946 auto selected = network_.overlay().getSelected(validator);
947 str << " selected: ";
948 for (auto s : selected)
949 str << s << " ";
950 if (log)
951 {
953 << " random, squelched, validator: " << validator.id()
954 << " peers: " << str.str() << std::endl;
955 }
956 auto countingState = network_.overlay().isCountingState(validator);
957 BEAST_EXPECT(
958 countingState == false &&
959 selected.size() ==
961 }
962
963 // Trigger Link Down or Peer Disconnect event
964 // Only one Link Down at a time
965 if (events[EventType::LinkDown].state_ == State::Off)
966 {
967 auto update = [&](EventType event) {
968 events[event].cnt_++;
969 events[event].validator_ = validator.id();
970 events[event].key_ = validator;
971 events[event].peer_ = link.peerId();
972 events[event].state_ = State::On;
973 events[event].time_ = now;
974 if (event == EventType::LinkDown)
975 {
976 network_.enableLink(validator.id(), link.peerId(), false);
977 events[event].isSelected_ =
979 }
980 else
981 {
982 events[event].isSelected_ = network_.isSelected(link.peerId());
983 }
984 };
985 auto r = rand_int(0, 1000);
986 if (r == (int)EventType::LinkDown || r == (int)EventType::PeerDisconnected)
987 {
988 update(static_cast<EventType>(r));
989 }
990 }
991
992 if (events[EventType::PeerDisconnected].state_ == State::On)
993 {
994 auto& event = events[EventType::PeerDisconnected];
995 bool const allCounting = network_.allCounting(event.peer_);
997 event.peer_, [&](PublicKey const& v, PeerWPtr const& peerPtr) {
998 if (event.isSelected_)
999 sendSquelch(v, peerPtr, {});
1000 event.handled_ = true;
1001 });
1002 // Should only be unsquelched if the peer is in Selected state
1003 // If in Selected state it's possible unsquelching didn't
1004 // take place because there is no peers in Squelched state in
1005 // any of the slots where the peer is in Selected state
1006 // (allCounting is true)
1007 bool const handled = (!event.isSelected_ && !event.handled_) ||
1008 (event.isSelected_ && (event.handled_ || allCounting));
1009 BEAST_EXPECT(handled);
1010 event.state_ = State::Off;
1011 event.isSelected_ = false;
1012 event.handledCnt_ += handled;
1013 event.handled_ = false;
1014 network_.onDisconnectPeer(event.peer_);
1015 }
1016
1017 auto& event = events[EventType::LinkDown];
1018 // Check every sec for idled peers. Idled peers are
1019 // created by Link Down event.
1020 if (now - lastCheck > milliseconds(1000))
1021 {
1022 lastCheck = now;
1023 // Check if Link Down event must be handled by
1024 // deleteIdlePeer(): 1) the peer is in Selected state;
1025 // 2) the peer has not received any messages for IDLED time;
1026 // 3) there are peers in Squelched state in the slot.
1027 // 4) peer is in Slot's peers_ (if not then it is deleted
1028 // by Slots::deleteIdlePeers())
1029 bool mustHandle = false;
1030 if (event.state_ == State::On && BEAST_EXPECT(event.key_))
1031 {
1032 event.isSelected_ = network_.overlay().isSelected(*event.key_, event.peer_);
1033 auto peers = network_.overlay().getPeers(*event.key_);
1034 auto d = reduce_relay::epoch<milliseconds>(now).count() -
1035 std::get<3>(peers[event.peer_]);
1036 mustHandle = event.isSelected_ &&
1039 *event.key_, reduce_relay::PeerState::Squelched) > 0 &&
1040 peers.contains(event.peer_);
1041 }
1042 network_.overlay().deleteIdlePeers([&](PublicKey const& v, PeerWPtr const& ptr) {
1043 event.handled_ = true;
1044 if (mustHandle && v == event.key_)
1045 {
1046 event.state_ = State::WaitReset;
1047 sendSquelch(validator, ptr, {});
1048 }
1049 });
1050 bool const handled = (event.handled_ && event.state_ == State::WaitReset) ||
1051 (!event.handled_ && !mustHandle);
1052 BEAST_EXPECT(handled);
1053 }
1054 if (event.state_ == State::WaitReset ||
1055 (event.state_ == State::On &&
1056 (now - event.time_ > (reduce_relay::IDLED + seconds(2)))))
1057 {
1058 bool const handled = event.state_ == State::WaitReset || !event.handled_;
1059 BEAST_EXPECT(handled);
1060 event.state_ = State::Off;
1061 event.isSelected_ = false;
1062 event.handledCnt_ += handled;
1063 event.handled_ = false;
1064 network_.enableLink(event.validator_, event.peer_, true);
1065 }
1066 });
1067
1068 auto& down = events[EventType::LinkDown];
1069 auto& disconnected = events[EventType::PeerDisconnected];
1070 // It's possible the last Down Link event is not handled
1071 BEAST_EXPECT(down.handledCnt_ >= down.cnt_ - 1);
1072 // All Peer Disconnect events must be handled
1073 BEAST_EXPECT(disconnected.cnt_ == disconnected.handledCnt_);
1074 if (log)
1075 {
1076 std::cout << "link down count: " << down.cnt_ << "/" << down.handledCnt_
1077 << " peer disconnect count: " << disconnected.cnt_ << "/"
1078 << disconnected.handledCnt_;
1079 }
1080 }
1081
1082 bool
1083 checkCounting(PublicKey const& validator, bool isCountingState)
1084 {
1085 auto countingState = network_.overlay().isCountingState(validator);
1086 BEAST_EXPECT(countingState == isCountingState);
1087 return countingState == isCountingState;
1088 }
1089
1090 void
1091 doTest(std::string const& msg, bool log, std::function<void(bool)> f)
1092 {
1093 testcase(msg);
1094 f(log);
1095 }
1096
1102 void
1104 {
1105 doTest("Initial Round", log, [this](bool log) { BEAST_EXPECT(propagateAndSquelch(log)); });
1106 }
1107
1111 void
1113 {
1114 doTest("Peer Unsquelched Too Soon", log, [this](bool log) {
1115 BEAST_EXPECT(propagateNoSquelch(log, 1, false, false, false));
1116 });
1117 }
1118
1122 void
1124 {
1125 ManualClock::advance(seconds(601));
1126 doTest("Peer Unsquelched", log, [this](bool log) {
1127 BEAST_EXPECT(propagateNoSquelch(log, 2, true, true, false));
1128 });
1129 }
1130
1132 bool
1133 propagateAndSquelch(bool log, bool purge = true, bool resetClock = true)
1134 {
1135 int n = 0;
1136 network_.propagate(
1137 [&](Link& link, MessageSPtr message) {
1138 std::uint16_t squelched = 0;
1139 link.send(
1140 message,
1141 [&](PublicKey const& key, PeerWPtr const& peerPtr, std::uint32_t duration) {
1142 squelched++;
1143 sendSquelch(key, peerPtr, duration);
1144 });
1145 if (squelched)
1146 {
1147 BEAST_EXPECT(
1148 squelched ==
1149 MAX_PEERS - env_.app().config().VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS);
1150 n++;
1151 }
1152 },
1153 1,
1155 purge,
1156 resetClock);
1157 auto selected = network_.overlay().getSelected(network_.validator(0));
1158 BEAST_EXPECT(
1159 selected.size() == env_.app().config().VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS);
1160 BEAST_EXPECT(n == 1); // only one selection round
1161 auto res = checkCounting(network_.validator(0), false);
1162 BEAST_EXPECT(res);
1163 return n == 1 && res;
1164 }
1165
1167 bool
1169 bool log,
1170 std::uint16_t nMessages,
1171 bool countingState,
1172 bool purge = true,
1173 bool resetClock = true)
1174 {
1175 bool squelched = false;
1176 network_.propagate(
1177 [&](Link& link, MessageSPtr message) {
1178 link.send(
1179 message,
1180 [&](PublicKey const& key, PeerWPtr const& peerPtr, std::uint32_t duration) {
1181 squelched = true;
1182 BEAST_EXPECT(false);
1183 });
1184 },
1185 1,
1186 nMessages,
1187 purge,
1188 resetClock);
1189 auto res = checkCounting(network_.validator(0), countingState);
1190 return !squelched && res;
1191 }
1192
1196 void
1197 testNewPeer(bool log)
1198 {
1199 doTest("New Peer", log, [this](bool log) {
1200 BEAST_EXPECT(propagateAndSquelch(log, true, false));
1201 network_.addPeer();
1202 BEAST_EXPECT(propagateNoSquelch(log, 1, true, false, false));
1203 });
1204 }
1205
1208 void
1210 {
1211 doTest("Selected Peer Disconnects", log, [this](bool log) {
1212 ManualClock::advance(seconds(601));
1213 BEAST_EXPECT(propagateAndSquelch(log, true, false));
1214 auto id = network_.overlay().getSelectedPeer(network_.validator(0));
1215 std::uint16_t unsquelched = 0;
1216 network_.overlay().deletePeer(
1217 id, [&](PublicKey const& key, PeerWPtr const& peer) { unsquelched++; });
1218 BEAST_EXPECT(
1219 unsquelched ==
1220 MAX_PEERS - env_.app().config().VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS);
1221 BEAST_EXPECT(checkCounting(network_.validator(0), true));
1222 });
1223 }
1224
1227 void
1229 {
1230 doTest("Selected Peer Stops Relaying", log, [this](bool log) {
1231 ManualClock::advance(seconds(601));
1232 BEAST_EXPECT(propagateAndSquelch(log, true, false));
1233 ManualClock::advance(reduce_relay::IDLED + seconds(1));
1234 std::uint16_t unsquelched = 0;
1235 network_.overlay().deleteIdlePeers(
1236 [&](PublicKey const& key, PeerWPtr const& peer) { unsquelched++; });
1237 auto peers = network_.overlay().getPeers(network_.validator(0));
1238 BEAST_EXPECT(
1239 unsquelched ==
1240 MAX_PEERS - env_.app().config().VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS);
1241 BEAST_EXPECT(checkCounting(network_.validator(0), true));
1242 });
1243 }
1244
1247 void
1249 {
1250 doTest("Squelched Peer Disconnects", log, [this](bool log) {
1251 ManualClock::advance(seconds(601));
1252 BEAST_EXPECT(propagateAndSquelch(log, true, false));
1253 auto peers = network_.overlay().getPeers(network_.validator(0));
1254 auto it = std::find_if(peers.begin(), peers.end(), [&](auto it) {
1255 return std::get<reduce_relay::PeerState>(it.second) ==
1256 reduce_relay::PeerState::Squelched;
1257 });
1258 assert(it != peers.end());
1259 std::uint16_t unsquelched = 0;
1260 network_.overlay().deletePeer(
1261 it->first, [&](PublicKey const& key, PeerWPtr const& peer) { unsquelched++; });
1262 BEAST_EXPECT(unsquelched == 0);
1263 BEAST_EXPECT(checkCounting(network_.validator(0), false));
1264 });
1265 }
1266
1267 void
1268 testConfig(bool log)
1269 {
1270 doTest("Test Config - squelch enabled (legacy)", log, [&](bool log) {
1271 Config c;
1272
1273 std::string const toLoad(R"rippleConfig(
1274[reduce_relay]
1275vp_enable=1
1276)rippleConfig");
1277
1278 c.loadFromString(toLoad);
1279 BEAST_EXPECT(c.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE == true);
1280 });
1281
1282 doTest("Test Config - squelch disabled (legacy)", log, [&](bool log) {
1283 Config c;
1284
1285 std::string toLoad(R"rippleConfig(
1286[reduce_relay]
1287vp_enable=0
1288)rippleConfig");
1289
1290 c.loadFromString(toLoad);
1291 BEAST_EXPECT(c.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE == false);
1292
1293 Config c1;
1294
1295 toLoad = R"rippleConfig(
1296[reduce_relay]
1297)rippleConfig";
1298
1299 c1.loadFromString(toLoad);
1300 BEAST_EXPECT(c1.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE == false);
1301 });
1302
1303 doTest("Test Config - squelch enabled", log, [&](bool log) {
1304 Config c;
1305
1306 std::string const toLoad(R"rippleConfig(
1307[reduce_relay]
1308vp_base_squelch_enable=1
1309)rippleConfig");
1310
1311 c.loadFromString(toLoad);
1312 BEAST_EXPECT(c.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE == true);
1313 });
1314
1315 doTest("Test Config - squelch disabled", log, [&](bool log) {
1316 Config c;
1317
1318 std::string const toLoad(R"rippleConfig(
1319[reduce_relay]
1320vp_base_squelch_enable=0
1321)rippleConfig");
1322
1323 c.loadFromString(toLoad);
1324 BEAST_EXPECT(c.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE == false);
1325 });
1326
1327 doTest("Test Config - legacy and new", log, [&](bool log) {
1328 Config c;
1329
1330 std::string const toLoad(R"rippleConfig(
1331[reduce_relay]
1332vp_base_squelch_enable=0
1333vp_enable=0
1334)rippleConfig");
1335
1336 std::string error;
1337 auto const expectedError =
1338 "Invalid reduce_relay"
1339 " cannot specify both vp_base_squelch_enable and vp_enable "
1340 "options. "
1341 "vp_enable was deprecated and replaced by "
1342 "vp_base_squelch_enable";
1343
1344 try
1345 {
1346 c.loadFromString(toLoad);
1347 }
1348 catch (std::runtime_error& e)
1349 {
1350 error = e.what();
1351 }
1352
1353 BEAST_EXPECT(error == expectedError);
1354 });
1355
1356 doTest("Test Config - max selected peers", log, [&](bool log) {
1357 Config c;
1358
1359 std::string toLoad(R"rippleConfig(
1360[reduce_relay]
1361)rippleConfig");
1362
1363 c.loadFromString(toLoad);
1364 BEAST_EXPECT(c.VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS == 5);
1365
1366 Config c1;
1367
1368 toLoad = R"rippleConfig(
1369[reduce_relay]
1370vp_base_squelch_max_selected_peers=6
1371)rippleConfig";
1372
1373 c1.loadFromString(toLoad);
1374 BEAST_EXPECT(c1.VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS == 6);
1375
1376 Config c2;
1377
1378 toLoad = R"rippleConfig(
1379[reduce_relay]
1380vp_base_squelch_max_selected_peers=2
1381)rippleConfig";
1382
1383 std::string error;
1384 auto const expectedError =
1385 "Invalid reduce_relay"
1386 " vp_base_squelch_max_selected_peers must be "
1387 "greater than or equal to 3";
1388 try
1389 {
1390 c2.loadFromString(toLoad);
1391 }
1392 catch (std::runtime_error& e)
1393 {
1394 error = e.what();
1395 }
1396
1397 BEAST_EXPECT(error == expectedError);
1398 });
1399 }
1400
1401 void
1403 {
1404 doTest("BaseSquelchReady", log, [&](bool log) {
1405 ManualClock::reset();
1406 auto createSlots = [&](bool baseSquelchEnabled) -> reduce_relay::Slots<ManualClock> {
1407 env_.app().config().VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE = baseSquelchEnabled;
1409 env_.app(), network_.overlay(), env_.app().config());
1410 };
1411 // base squelching must not be ready if squelching is disabled
1412 BEAST_EXPECT(!createSlots(false).baseSquelchReady());
1413
1414 // base squelch must not be ready as not enough time passed from
1415 // bootup
1416 BEAST_EXPECT(!createSlots(true).baseSquelchReady());
1417
1418 ManualClock::advance(reduce_relay::WAIT_ON_BOOTUP + minutes{1});
1419
1420 // base squelch enabled and bootup time passed
1421 BEAST_EXPECT(createSlots(true).baseSquelchReady());
1422
1423 // even if time passed, base squelching must not be ready if turned
1424 // off in the config
1425 BEAST_EXPECT(!createSlots(false).baseSquelchReady());
1426 });
1427 }
1428
1429 void
1431 {
1432 doTest("Duplicate Message", log, [&](bool log) {
1433 network_.reset();
1434 // update message count for the same peer/validator
1435 std::int16_t const nMessages = 5;
1436 for (int i = 0; i < nMessages; i++)
1437 {
1438 uint256 const key(i);
1439 network_.overlay().updateSlotAndSquelch(
1440 key, network_.validator(0), 0, [&](PublicKey const&, PeerWPtr, std::uint32_t) {
1441 });
1442 }
1443 auto peers = network_.overlay().getPeers(network_.validator(0));
1444 // first message changes Slot state to Counting and is not counted,
1445 // hence '-1'.
1446 BEAST_EXPECT(std::get<1>(peers[0]) == (nMessages - 1));
1447 // add duplicate
1448 uint256 const key(nMessages - 1);
1449 network_.overlay().updateSlotAndSquelch(
1450 key, network_.validator(0), 0, [&](PublicKey const&, PeerWPtr, std::uint32_t) {});
1451 // confirm the same number of messages
1452 peers = network_.overlay().getPeers(network_.validator(0));
1453 BEAST_EXPECT(std::get<1>(peers[0]) == (nMessages - 1));
1454 // advance the clock
1455 ManualClock::advance(reduce_relay::IDLED + seconds(1));
1456 network_.overlay().updateSlotAndSquelch(
1457 key, network_.validator(0), 0, [&](PublicKey const&, PeerWPtr, std::uint32_t) {});
1458 peers = network_.overlay().getPeers(network_.validator(0));
1459 // confirm message number increased
1460 BEAST_EXPECT(std::get<1>(peers[0]) == nMessages);
1461 });
1462 }
1463
1465 {
1467 {
1468 }
1469 void
1471 {
1472 maxDuration_ = std::max<uint32_t>(duration, maxDuration_);
1473 }
1474 void
1475 unsquelch(PublicKey const&, Peer::id_t) const override
1476 {
1477 }
1478 mutable int maxDuration_{0};
1479 };
1480
1481 void
1483 {
1484 doTest("Random Squelch", l, [&](bool l) {
1486 Handler handler;
1487
1488 auto run = [&](int npeers) {
1489 handler.maxDuration_ = 0;
1490 reduce_relay::Slots<ManualClock> slots(env_.app(), handler, env_.app().config());
1491 // 1st message from a new peer switches the slot
1492 // to counting state and resets the counts of all peers +
1493 // MAX_MESSAGE_THRESHOLD + 1 messages to reach the threshold
1494 // and switch the slot's state to peer selection.
1495 for (int m = 1; m <= reduce_relay::MAX_MESSAGE_THRESHOLD + 2; m++)
1496 {
1497 for (int peer = 0; peer < npeers; peer++)
1498 {
1499 // make unique message hash to make the
1500 // slot's internal hash router accept the message
1501 std::uint64_t const mid = (m * 1000) + peer;
1502 uint256 const message{mid};
1504 message, validator, peer, protocol::MessageType::mtVALIDATION);
1505 }
1506 }
1507 // make Slot's internal hash router expire all messages
1508 ManualClock::advance(hours(1));
1509 };
1510
1511 using namespace reduce_relay;
1512 // expect max duration less than MAX_UNSQUELCH_EXPIRE_DEFAULT with
1513 // less than or equal to 60 peers
1514 run(20);
1515 BEAST_EXPECT(
1516 handler.maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1517 handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count());
1518 run(60);
1519 BEAST_EXPECT(
1520 handler.maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1521 handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count());
1522 // expect max duration greater than MIN_UNSQUELCH_EXPIRE and less
1523 // than MAX_UNSQUELCH_EXPIRE_PEERS with peers greater than 60
1524 // and less than 360
1525 run(350);
1526 // can't make this condition stronger. squelch
1527 // duration is probabilistic and max condition may still fail.
1528 // log when the value is low
1529 BEAST_EXPECT(
1530 handler.maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1531 handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_PEERS.count());
1532 using namespace beast::unit_test::detail;
1533 if (handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count())
1534 {
1535 log << make_reason("warning: squelch duration is low", __FILE__, __LINE__)
1536 << std::endl
1537 << std::flush;
1538 }
1539 // more than 400 is still less than MAX_UNSQUELCH_EXPIRE_PEERS
1540 run(400);
1541 BEAST_EXPECT(
1542 handler.maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1543 handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_PEERS.count());
1544 if (handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count())
1545 {
1546 log << make_reason("warning: squelch duration is low", __FILE__, __LINE__)
1547 << std::endl
1548 << std::flush;
1549 }
1550 });
1551 }
1552
1553 void
1555 {
1556 doTest("Handshake", log, [&](bool log) {
1557 auto setEnv = [&](bool enable) {
1558 Config c;
1560 str << "[reduce_relay]\n"
1561 << "vp_enable=" << enable << "\n"
1562 << "[compression]\n"
1563 << "1\n";
1564 c.loadFromString(str.str());
1565 env_.app().config().VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE =
1567
1568 env_.app().config().COMPRESSION = c.COMPRESSION;
1569 };
1570 auto handshake = [&](int outboundEnable, int inboundEnable) {
1571 beast::IP::Address const addr = boost::asio::ip::make_address("172.1.1.100");
1572
1573 setEnv(outboundEnable);
1574 auto request = xrpl::makeRequest(
1575 true,
1576 env_.app().config().COMPRESSION,
1577 false,
1578 env_.app().config().TX_REDUCE_RELAY_ENABLE,
1579 env_.app().config().VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE);
1580 http_request_type http_request;
1581 http_request.version(request.version());
1582 http_request.base() = request.base();
1583 // feature enabled on the peer's connection only if both sides
1584 // are enabled
1585 auto const peerEnabled = inboundEnable && outboundEnable;
1586 // inbound is enabled if the request's header has the feature
1587 // enabled and the peer's configuration is enabled
1588 auto const inboundEnabled =
1589 peerFeatureEnabled(http_request, FEATURE_VPRR, inboundEnable);
1590 BEAST_EXPECT(!(peerEnabled ^ inboundEnabled));
1591
1592 setEnv(inboundEnable);
1593 auto http_resp = xrpl::makeResponse(
1594 true, http_request, addr, addr, uint256{1}, 1, {1, 0}, env_.app());
1595 // outbound is enabled if the response's header has the feature
1596 // enabled and the peer's configuration is enabled
1597 auto const outboundEnabled =
1598 peerFeatureEnabled(http_resp, FEATURE_VPRR, outboundEnable);
1599 BEAST_EXPECT(!(peerEnabled ^ outboundEnabled));
1600 };
1601 handshake(1, 1);
1602 handshake(1, 0);
1603 handshake(0, 1);
1604 handshake(0, 0);
1605 });
1606 }
1607
1610
1611public:
1613 : env_(*this, jtx::envconfig([](std::unique_ptr<Config> cfg) {
1614 cfg->VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE = true;
1615 cfg->VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS = 6;
1616 return cfg;
1617 }))
1618 , network_(env_.app())
1619 {
1620 }
1621
1622 void
1623 run() override
1624 {
1625 bool const log = false;
1626 testConfig(log);
1627 testInitialRound(log);
1628 testPeerUnsquelchedTooSoon(log);
1629 testPeerUnsquelched(log);
1630 testNewPeer(log);
1631 testSquelchedPeerDisconnects(log);
1632 testSelectedPeerDisconnects(log);
1633 testSelectedPeerStopsRelaying(log);
1634 testInternalHashRouter(log);
1635 testRandomSquelch(log);
1636 testHandshake(log);
1637 testBaseSquelchReady(log);
1638 }
1639};
1640
1642{
1643 void
1644 testRandom(bool log)
1645 {
1646 doTest("Random Test", log, [&](bool log) { random(log); });
1647 }
1648
1649 void
1650 run() override
1651 {
1652 bool const log = false;
1653 testRandom(log);
1654 }
1655};
1656
1657BEAST_DEFINE_TESTSUITE(reduce_relay, overlay, xrpl);
1658BEAST_DEFINE_TESTSUITE_MANUAL(reduce_relay_simulate, overlay, xrpl);
1659
1660} // namespace test
1661
1662} // namespace xrpl
T back_inserter(T... args)
T begin(T... args)
Represents a JSON value.
Definition json_value.h:130
A version-independent IP address and port combination.
Definition IPEndpoint.h:18
A generic endpoint for log messages.
Definition Journal.h:40
A testsuite class.
Definition suite.h:51
log_os< char > log
Logging output stream.
Definition suite.h:147
virtual Config & config()=0
bool COMPRESSION
Definition Config.h:205
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition Config.cpp:452
bool VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE
Definition Config.h:233
std::size_t VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS
Definition Config.h:239
Represents a peer connection in the overlay.
std::uint32_t id_t
Uniquely identifies a peer.
A public key.
Definition PublicKey.h:42
std::uint8_t const * data() const noexcept
Definition PublicKey.h:67
std::size_t size() const noexcept
Definition PublicKey.h:73
A consumption charge.
Definition Charge.h:10
Service registry for dependency injection.
virtual beast::Journal getJournal(std::string const &name)=0
An immutable linear range of bytes.
Definition Slice.h:26
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:19
Manually advanced clock.
std::chrono::duration< std::uint32_t, period > duration
static void randAdvance(milliseconds min, milliseconds max)
static duration randDuration(milliseconds min, milliseconds max)
static void advance(duration d) noexcept
static void reset() noexcept
static time_point now() noexcept
std::chrono::time_point< ManualClock > time_point
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...
bool isSelected(Peer::id_t id)
Is peer in Selected state in any of the slots.
void enableLink(std::uint16_t validatorId, Peer::id_t peer, bool enable)
std::vector< Validator > validators_
Network(Application &app)
static void for_rand(std::uint32_t min, std::uint32_t max, std::function< void(std::uint32_t)> f)
Validator & validator(std::uint16_t v)
void onDisconnectPeer(Peer::id_t peer)
void propagate(LinkIterCB link, std::uint16_t nValidators=MAX_VALIDATORS, std::uint32_t nMessages=MAX_MESSAGES, bool purge=true, bool resetClock=true)
bool isSelected(PublicKey const &validator, Peer::id_t peer)
std::uint16_t getNumPeers() const
std::optional< Peer::id_t > deleteLastPeer()
std::unordered_map< id_t, std::tuple< reduce_relay::PeerState, std::uint16_t, std::uint32_t, std::uint32_t > > getPeers(PublicKey const &validator)
std::set< id_t > getSelected(PublicKey const &validator)
PeerSPtr addPeer(bool useCache=true)
void squelch(PublicKey const &validator, Peer::id_t id, std::uint32_t squelchDuration) const override
Squelch handler.
void deletePeer(Peer::id_t id, bool useCache=true)
void unsquelch(PublicKey const &validator, Peer::id_t id) const override
Unsquelch handler.
void deleteIdlePeers(UnsquelchCB f) override
void deletePeer(id_t id, UnsquelchCB f) override
id_t getSelectedPeer(PublicKey const &validator)
std::uint16_t inState(PublicKey const &validator, reduce_relay::PeerState state)
bool isCountingState(PublicKey const &validator)
void updateSlotAndSquelch(uint256 const &key, PublicKey const &validator, Peer::id_t id, SquelchCB f, protocol::MessageType type=protocol::mtVALIDATION) override
reduce_relay::Slots< ManualClock > slots_
Simulate server's OverlayImpl.
virtual void deleteIdlePeers(UnsquelchCB)=0
virtual void deletePeer(Peer::id_t, UnsquelchCB)=0
virtual ~Overlay()=default
virtual void updateSlotAndSquelch(uint256 const &key, PublicKey const &validator, Peer::id_t id, SquelchCB f, protocol::MessageType type=protocol::mtVALIDATION)=0
Simulate two entities - peer directly connected to the server (via squelch in PeerSim) and PeerImp (v...
void send(std::shared_ptr< Message > const &m) override
bool hasLedger(uint256 const &hash, std::uint32_t seq) const override
void addTxQueue(uint256 const &) override
Aggregate transaction's hash.
virtual void onMessage(protocol::TMSquelch const &squelch)=0
bool compressionEnabled() const override
virtual void onMessage(MessageSPtr const &m, SquelchCB f)=0
void sendTxQueue() override
Send aggregated transactions' hashes.
void removeTxQueue(uint256 const &) override
Remove hash from the transactions' hashes queue.
std::optional< std::size_t > publisherListSequence(PublicKey const &) const override
bool supportsFeature(ProtocolFeature f) const override
Json::Value json() override
bool hasTxSet(uint256 const &hash) const override
void send(protocol::TMSquelch const &squelch)
void ledgerRange(std::uint32_t &minSeq, std::uint32_t &maxSeq) const override
bool cluster() const override
Returns true if this connection is a member of the cluster.
uint256 const & getClosedLedgerHash() const override
bool hasRange(std::uint32_t uMin, std::uint32_t uMax) 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.
beast::IP::Endpoint getRemoteAddress() const override
bool isHighLatency() const override
PublicKey const & getNodePublic() const override
void setPublisherListSequence(PublicKey const &, std::size_t const) override
bool txReduceRelayEnabled() const override
int getScore(bool) const override
reduce_relay::Squelch< ManualClock > squelch_
std::string const & fingerprint() const override
id_t id() const override
void onMessage(MessageSPtr const &m, SquelchCB f) override
Local Peer (PeerImp)
virtual void onMessage(protocol::TMSquelch const &squelch) override
Remote Peer (Directly connected Peer)
PeerSim(Overlay &overlay, beast::Journal journal)
void addPeer(PeerSPtr peer)
Validator & operator=(Validator &&)=default
void send(std::vector< Peer::id_t > peers, SquelchCB f)
Send to specific peers.
void for_links(LinkIterCB f, bool simulateSlow=false)
void send(SquelchCB f)
Send to all peers.
void linkDown(Peer::id_t id)
Validator(Validator const &)=default
void linkUp(Peer::id_t id)
void deletePeer(Peer::id_t id)
Validator & operator=(Validator const &)=default
std::uint16_t id() const
Validator(Validator &&)=default
static std::uint16_t sid_
PublicKey const & key()
void for_links(std::vector< Peer::id_t > peers, LinkIterCB f)
A transaction testing environment.
Definition Env.h:122
Application & app()
Definition Env.h:259
Set the fee on a JTx.
Definition fee.h:17
void printPeers(std::string const &msg, std::uint16_t validator=0)
void doTest(std::string const &msg, bool log, std::function< void(bool)> f)
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.
bool propagateAndSquelch(bool log, bool purge=true, bool resetClock=true)
Propagate enough messages to generate one squelch event.
static 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 random(bool log)
Randomly brings the link between a validator and a peer down.
void testSquelchedPeerDisconnects(bool log)
Squelched peer disconnects.
void testPeerUnsquelchedTooSoon(bool log)
Receiving message from squelched peer too soon should not 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 testSelectedPeerDisconnects(bool log)
Selected peer disconnects.
void run() override
Runs the suite.
bool checkCounting(PublicKey const &validator, bool isCountingState)
void testPeerUnsquelched(bool log)
Receiving message from squelched peer should change the slot's state to Counting.
void testNewPeer(bool log)
Receiving a message from new peer should change the slot's state to Counting.
T clear(T... args)
T contains(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:19
STL namespace.
static constexpr auto IDLED
static constexpr auto WAIT_ON_BOOTUP
PeerState
Peer's State.
static constexpr uint16_t MAX_MESSAGE_THRESHOLD
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition envconfig.h:34
std::unique_ptr< Config > validator(std::unique_ptr< Config >, std::string const &)
adjust configuration with params needed to be a validator
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:5
KeyType
Definition KeyType.h:8
std::pair< PublicKey, SecretKey > randomKeyPair(KeyType type)
Create a key pair using secure random numbers.
PublicKey derivePublicKey(KeyType type, SecretKey const &sk)
Derive the public key from a secret key.
int run(int argc, char **argv)
Definition Main.cpp:332
T get(Section const &section, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
boost::beast::http::request< boost::beast::http::dynamic_body > http_request_type
Definition Handoff.h:12
std::enable_if_t< std::is_integral< Integral >::value, Integral > rand_int()
auto makeRequest(bool crawlPublic, bool comprEnabled, bool ledgerReplayEnabled, bool txReduceRelayEnabled, bool vpReduceRelayEnabled) -> request_type
Make outbound http request.
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:171
SecretKey randomSecretKey()
Create a secret key using secure random numbers.
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.
constexpr Number squelch(Number const &x, Number const &limit) noexcept
Definition Number.h:750
static constexpr char FEATURE_VPRR[]
Definition Handshake.h:120
T shuffle(T... args)
T size(T... args)
T str(T... args)
Set the sequence number on a JTx.
Definition seq.h:14
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)