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 <chrono>
18#include <iostream>
19#include <numeric>
20#include <optional>
21
22namespace ripple {
23
24namespace test {
25
26using namespace std::chrono;
27
28class Link;
29
34using SquelchCB =
35 std::function<void(PublicKey const&, PeerWPtr const&, std::uint32_t)>;
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:
53
55 virtual ~PeerPartial()
56 {
57 }
58 virtual void
60 virtual void
61 onMessage(protocol::TMSquelch const& squelch) = 0;
62 void
63 send(protocol::TMSquelch const& squelch)
64 {
66 }
67
68 // dummy implementation
69 void
70 send(std::shared_ptr<Message> const& m) override
71 {
72 }
74 getRemoteAddress() const override
75 {
76 return {};
77 }
78 void
79 charge(Resource::Charge const& fee, std::string const& context = {})
80 override
81 {
82 }
83 bool
84 cluster() const override
85 {
86 return false;
87 }
88 bool
89 isHighLatency() const override
90 {
91 return false;
92 }
93 int
94 getScore(bool) const override
95 {
96 return 0;
97 }
98 PublicKey const&
99 getNodePublic() const override
100 {
101 return nodePublicKey_;
102 }
104 json() override
105 {
106 return {};
107 }
108 bool
110 {
111 return false;
112 }
114 publisherListSequence(PublicKey const&) const override
115 {
116 return {};
117 }
118 void
120 {
121 }
122 uint256 const&
123 getClosedLedgerHash() const override
124 {
125 static uint256 hash{};
126 return hash;
127 }
128 bool
129 hasLedger(uint256 const& hash, std::uint32_t seq) const override
130 {
131 return false;
132 }
133 void
134 ledgerRange(std::uint32_t& minSeq, std::uint32_t& maxSeq) const override
135 {
136 }
137 bool
138 hasTxSet(uint256 const& hash) const override
139 {
140 return false;
141 }
142 void
143 cycleStatus() override
144 {
145 }
146 bool
148 {
149 return false;
150 }
151 bool
152 compressionEnabled() const override
153 {
154 return false;
155 }
156 bool
157 txReduceRelayEnabled() const override
158 {
159 return false;
160 }
161 void
162 sendTxQueue() override
163 {
164 }
165 void
166 addTxQueue(uint256 const&) override
167 {
168 }
169 void
170 removeTxQueue(uint256 const&) override
171 {
172 }
173};
174
177{
178public:
179 typedef uint64_t rep;
183 inline static bool const is_steady = false;
184
185 static void
186 advance(duration d) noexcept
187 {
188 now_ += d;
189 }
190
191 static void
193 {
194 now_ += randDuration(min, max);
195 }
196
197 static void
198 reset() noexcept
199 {
200 now_ = time_point(seconds(0));
201 }
202
203 static time_point
204 now() noexcept
205 {
206 return now_;
207 }
208
209 static duration
211 {
212 return duration(milliseconds(rand_int(min.count(), max.count())));
213 }
214
215 explicit ManualClock() = default;
216
217private:
218 inline static time_point now_ = time_point(seconds(0));
219};
220
223{
224public:
225 Overlay() = default;
226 virtual ~Overlay() = default;
227
228 virtual void
230 uint256 const& key,
231 PublicKey const& validator,
232 Peer::id_t id,
233 SquelchCB f,
234 protocol::MessageType type = protocol::mtVALIDATION) = 0;
235
236 virtual void deleteIdlePeers(UnsquelchCB) = 0;
237
239};
240
241class Validator;
242
246class Link
247{
249
250public:
253 PeerSPtr peer,
254 Latency const& latency = {milliseconds(5), milliseconds(15)})
255 : validator_(validator), peer_(peer), latency_(latency), up_(true)
256 {
257 auto sp = peer_.lock();
258 assert(sp);
259 }
260 ~Link() = default;
261 void
263 {
264 if (!up_)
265 return;
266 auto sp = peer_.lock();
267 assert(sp);
269 peer->onMessage(m, f);
270 }
271 Validator&
273 {
274 return validator_;
275 }
276 void
277 up(bool linkUp)
278 {
279 up_ = linkUp;
280 }
283 {
284 auto p = peer_.lock();
285 assert(p);
286 return p->id();
287 }
290 {
291 auto p = peer_.lock();
292 assert(p);
293 return p;
294 }
295
296private:
300 bool up_;
301};
302
305{
307
308public:
310 {
311 protocol::TMValidation v;
312 v.set_validation("validation");
313 message_ = std::make_shared<Message>(v, protocol::mtVALIDATION, pkey_);
314 id_ = sid_++;
315 }
316 Validator(Validator const&) = default;
317 Validator(Validator&&) = default;
318 Validator&
319 operator=(Validator const&) = default;
320 Validator&
321 operator=(Validator&&) = default;
323 {
324 clear();
325 }
326
327 void
329 {
330 links_.clear();
331 }
332
333 static void
335 {
336 sid_ = 0;
337 }
338
339 PublicKey const&
341 {
342 return pkey_;
343 }
344
345 operator PublicKey() const
346 {
347 return pkey_;
348 }
349
350 void
352 {
354 std::make_pair(peer->id(), std::make_shared<Link>(*this, peer)));
355 }
356
357 void
359 {
360 links_.erase(id);
361 }
362
363 void
365 {
366 for (auto id : peers)
367 {
368 assert(links_.find(id) != links_.end());
369 f(*links_[id], message_);
370 }
371 }
372
373 void
374 for_links(LinkIterCB f, bool simulateSlow = false)
375 {
378 links_.begin(), links_.end(), std::back_inserter(v), [](auto& kv) {
379 return kv.second;
380 });
382 std::mt19937 g(d());
383 std::shuffle(v.begin(), v.end(), g);
384
385 for (auto& link : v)
386 {
387 f(*link, message_);
388 }
389 }
390
392 void
394 {
395 for_links(peers, [&](Link& link, MessageSPtr m) { link.send(m, f); });
396 }
397
399 void
401 {
402 for_links([&](Link& link, MessageSPtr m) { link.send(m, f); });
403 }
404
407 {
408 return message_;
409 }
410
413 {
414 return id_;
415 }
416
417 void
419 {
420 auto it = links_.find(id);
421 assert(it != links_.end());
422 it->second->up(true);
423 }
424
425 void
427 {
428 auto it = links_.find(id);
429 assert(it != links_.end());
430 it->second->up(false);
431 }
432
433private:
437 inline static std::uint16_t sid_ = 0;
439};
440
441class PeerSim : public PeerPartial, public std::enable_shared_from_this<PeerSim>
442{
443public:
445 PeerSim(Overlay& overlay, beast::Journal journal)
446 : overlay_(overlay), squelch_(journal)
447 {
448 id_ = sid_++;
449 }
450
451 ~PeerSim() = default;
452
453 id_t
454 id() const override
455 {
456 return id_;
457 }
458
459 std::string const&
460 fingerprint() const override
461 {
462 return fingerprint_;
463 }
464
465 static void
467 {
468 sid_ = 0;
469 }
470
472 void
473 onMessage(MessageSPtr const& m, SquelchCB f) override
474 {
475 auto validator = m->getValidatorKey();
476 assert(validator);
477 if (!squelch_.expireSquelch(*validator))
478 return;
479
481 }
482
484 virtual void
485 onMessage(protocol::TMSquelch const& squelch) override
486 {
487 auto validator = squelch.validatorpubkey();
488 PublicKey key(Slice(validator.data(), validator.size()));
489 if (squelch.squelch())
490 squelch_.addSquelch(
491 key, std::chrono::seconds{squelch.squelchduration()});
492 else
493 squelch_.removeSquelch(key);
494 }
495
496private:
497 inline static id_t sid_ = 0;
502};
503
505{
507
508public:
512 : slots_(app.logs(), *this, app.config()), logs_(app.logs())
513 {
514 }
515
516 ~OverlaySim() = default;
517
518 void
520 {
521 peers_.clear();
523 slots_.deleteIdlePeers();
524 }
525
528 {
529 auto res = slots_.inState(validator, state);
530 return res ? *res : 0;
531 }
532
533 void
535 uint256 const& key,
536 PublicKey const& validator,
537 Peer::id_t id,
538 SquelchCB f,
539 protocol::MessageType type = protocol::mtVALIDATION) override
540 {
541 squelch_ = f;
542 slots_.updateSlotAndSquelch(key, validator, id, type);
543 }
544
545 void
547 {
548 unsquelch_ = f;
549 slots_.deletePeer(id, true);
550 }
551
552 void
554 {
555 unsquelch_ = f;
556 slots_.deleteIdlePeers();
557 }
558
560 addPeer(bool useCache = true)
561 {
562 PeerSPtr peer{};
563 Peer::id_t id;
564 if (peersCache_.empty() || !useCache)
565 {
566 peer = std::make_shared<PeerSim>(*this, logs_.journal("Squelch"));
567 id = peer->id();
568 }
569 else
570 {
571 auto it = peersCache_.begin();
572 peer = it->second;
573 id = it->first;
574 peersCache_.erase(it);
575 }
576 peers_.emplace(std::make_pair(id, peer));
577 return peer;
578 }
579
580 void
581 deletePeer(Peer::id_t id, bool useCache = true)
582 {
583 auto it = peers_.find(id);
584 assert(it != peers_.end());
585 deletePeer(id, [&](PublicKey const&, PeerWPtr) {});
586 if (useCache)
587 peersCache_.emplace(std::make_pair(id, it->second));
588 peers_.erase(it);
589 }
590
591 void
593 {
594 while (!peers_.empty())
595 deletePeer(peers_.begin()->first);
596 while (!peersCache_.empty())
597 addPeer();
598 }
599
602 {
603 if (peers_.empty())
604 return {};
605
606 std::uint8_t maxId = 0;
607
608 for (auto& [id, _] : peers_)
609 {
610 (void)_;
611 if (id > maxId)
612 maxId = id;
613 }
614
615 deletePeer(maxId, false);
616
617 return maxId;
618 }
619
620 bool
625
628 {
629 return slots_.getSelected(validator);
630 }
631
632 bool
634 {
635 auto selected = slots_.getSelected(validator);
636 return selected.find(peer) != selected.end();
637 }
638
639 id_t
641 {
642 auto selected = slots_.getSelected(validator);
643 assert(selected.size());
644 return *selected.begin();
645 }
646
648 id_t,
655 {
656 return slots_.getPeers(validator);
657 }
658
661 {
662 return peers_.size();
663 }
664
665private:
666 void
668 PublicKey const& validator,
669 Peer::id_t id,
670 std::uint32_t squelchDuration) const override
671 {
672 if (auto it = peers_.find(id); it != peers_.end())
673 squelch_(validator, it->second, squelchDuration);
674 }
675 void
676 unsquelch(PublicKey const& validator, Peer::id_t id) const override
677 {
678 if (auto it = peers_.find(id); it != peers_.end())
679 unsquelch_(validator, it->second);
680 }
687};
688
690{
691public:
693 {
694 init();
695 }
696
697 void
699 {
701 for (int p = 0; p < MAX_PEERS; p++)
702 {
703 auto peer = overlay_.addPeer();
704 for (auto& v : validators_)
705 v.addPeer(peer);
706 }
707 }
708
709 ~Network() = default;
710
711 void
713 {
714 validators_.clear();
715 overlay_.clear();
718 init();
719 }
720
723 {
724 auto peer = overlay_.addPeer();
725 for (auto& v : validators_)
726 v.addPeer(peer);
727 return peer->id();
728 }
729
730 void
732 {
733 auto id = overlay_.deleteLastPeer();
734
735 if (!id)
736 return;
737
738 for (auto& validator : validators_)
740 }
741
742 void
744 {
745 while (overlay_.getNumPeers() > MAX_PEERS)
747 }
748
749 Validator&
751 {
752 assert(v < validators_.size());
753 return validators_[v];
754 }
755
758 {
759 return overlay_;
760 }
761
762 void
763 enableLink(std::uint16_t validatorId, Peer::id_t peer, bool enable)
764 {
765 auto it =
766 std::find_if(validators_.begin(), validators_.end(), [&](auto& v) {
767 return v.id() == validatorId;
768 });
769 assert(it != validators_.end());
770 if (enable)
771 it->linkUp(peer);
772 else
773 it->linkDown(peer);
774 }
775
776 void
778 {
779 // Send unsquelch to the Peer on all links. This way when
780 // the Peer "reconnects" it starts sending messages on the link.
781 // We expect that if a Peer disconnects and then reconnects, it's
782 // unsquelched.
783 protocol::TMSquelch squelch;
784 squelch.set_squelch(false);
785 for (auto& v : validators_)
786 {
787 PublicKey key = v;
788 squelch.clear_validatorpubkey();
789 squelch.set_validatorpubkey(key.data(), key.size());
790 v.for_links({peer}, [&](Link& l, MessageSPtr) {
792 });
793 }
794 }
795
796 void
798 std::uint32_t min,
799 std::uint32_t max,
801 {
802 auto size = max - min;
804 std::iota(s.begin(), s.end(), min);
806 std::mt19937 g(d());
807 std::shuffle(s.begin(), s.end(), g);
808 for (auto v : s)
809 f(v);
810 }
811
812 void
814 LinkIterCB link,
815 std::uint16_t nValidators = MAX_VALIDATORS,
816 std::uint32_t nMessages = MAX_MESSAGES,
817 bool purge = true,
818 bool resetClock = true)
819 {
820 if (resetClock)
822
823 if (purge)
824 {
825 purgePeers();
827 }
828
829 for (int m = 0; m < nMessages; ++m)
830 {
832 for_rand(0, nValidators, [&](std::uint32_t v) {
833 validators_[v].for_links(link);
834 });
835 }
836 }
837
839 bool
841 {
842 for (auto& v : validators_)
843 {
844 if (overlay_.isSelected(v, id))
845 return true;
846 }
847 return false;
848 }
849
854 bool
856 {
857 for (auto& v : validators_)
858 {
859 if (!overlay_.isSelected(v, peer))
860 continue;
861 auto peers = overlay_.getPeers(v);
862 for (auto& [_, v] : peers)
863 {
864 (void)_;
867 return false;
868 }
869 }
870 return true;
871 }
872
873private:
876};
877
879{
882
883protected:
884 void
886 {
888 std::cout << msg << " "
889 << "num peers " << (int)network_.overlay().getNumPeers()
890 << std::endl;
891 for (auto& [k, v] : peers)
892 std::cout << k << ":" << (int)std::get<reduce_relay::PeerState>(v)
893 << " ";
895 }
896
900 PublicKey const& validator,
901 PeerWPtr const& peerPtr,
903 {
904 protocol::TMSquelch squelch;
905 bool res = duration ? true : false;
906 squelch.set_squelch(res);
907 squelch.set_validatorpubkey(validator.data(), validator.size());
908 if (res)
909 squelch.set_squelchduration(*duration);
910 auto sp = peerPtr.lock();
911 assert(sp);
913 return sp->id();
914 }
915
916 enum State { On, Off, WaitReset };
918 // Link down or Peer disconnect event
919 // TBD - add new peer event
920 // TBD - add overlapping type of events at any
921 // time in any quantity
934
938 void
940 {
942 {LinkDown, {}}, {PeerDisconnected, {}}};
944
945 network_.reset();
946 network_.propagate([&](Link& link, MessageSPtr m) {
947 auto& validator = link.validator();
948 auto now = ManualClock::now();
949
950 bool squelched = false;
952
953 link.send(
954 m,
955 [&](PublicKey const& key,
956 PeerWPtr const& peerPtr,
958 assert(key == validator);
959 auto p = sendSquelch(key, peerPtr, duration);
960 squelched = true;
961 str << p << " ";
962 });
963
964 if (squelched)
965 {
966 auto selected = network_.overlay().getSelected(validator);
967 str << " selected: ";
968 for (auto s : selected)
969 str << s << " ";
970 if (log)
972 << (double)reduce_relay::epoch<milliseconds>(now)
973 .count() /
974 1000.
975 << " random, squelched, validator: " << validator.id()
976 << " peers: " << str.str() << std::endl;
977 auto countingState =
979 BEAST_EXPECT(
980 countingState == false &&
981 selected.size() ==
982 env_.app()
983 .config()
985 }
986
987 // Trigger Link Down or Peer Disconnect event
988 // Only one Link Down at a time
989 if (events[EventType::LinkDown].state_ == State::Off)
990 {
991 auto update = [&](EventType event) {
992 events[event].cnt_++;
993 events[event].validator_ = validator.id();
994 events[event].key_ = validator;
995 events[event].peer_ = link.peerId();
996 events[event].state_ = State::On;
997 events[event].time_ = now;
998 if (event == EventType::LinkDown)
999 {
1001 validator.id(), link.peerId(), false);
1002 events[event].isSelected_ =
1004 validator, link.peerId());
1005 }
1006 else
1007 events[event].isSelected_ =
1008 network_.isSelected(link.peerId());
1009 };
1010 auto r = rand_int(0, 1000);
1011 if (r == (int)EventType::LinkDown ||
1013 {
1014 update(static_cast<EventType>(r));
1015 }
1016 }
1017
1018 if (events[EventType::PeerDisconnected].state_ == State::On)
1019 {
1020 auto& event = events[EventType::PeerDisconnected];
1021 bool allCounting = network_.allCounting(event.peer_);
1023 event.peer_,
1024 [&](PublicKey const& v, PeerWPtr const& peerPtr) {
1025 if (event.isSelected_)
1026 sendSquelch(v, peerPtr, {});
1027 event.handled_ = true;
1028 });
1029 // Should only be unsquelched if the peer is in Selected state
1030 // If in Selected state it's possible unsquelching didn't
1031 // take place because there is no peers in Squelched state in
1032 // any of the slots where the peer is in Selected state
1033 // (allCounting is true)
1034 bool handled =
1035 (event.isSelected_ == false && !event.handled_) ||
1036 (event.isSelected_ == true &&
1037 (event.handled_ || allCounting));
1038 BEAST_EXPECT(handled);
1039 event.state_ = State::Off;
1040 event.isSelected_ = false;
1041 event.handledCnt_ += handled;
1042 event.handled_ = false;
1043 network_.onDisconnectPeer(event.peer_);
1044 }
1045
1046 auto& event = events[EventType::LinkDown];
1047 // Check every sec for idled peers. Idled peers are
1048 // created by Link Down event.
1049 if (now - lastCheck > milliseconds(1000))
1050 {
1051 lastCheck = now;
1052 // Check if Link Down event must be handled by
1053 // deleteIdlePeer(): 1) the peer is in Selected state;
1054 // 2) the peer has not received any messages for IDLED time;
1055 // 3) there are peers in Squelched state in the slot.
1056 // 4) peer is in Slot's peers_ (if not then it is deleted
1057 // by Slots::deleteIdlePeers())
1058 bool mustHandle = false;
1059 if (event.state_ == State::On && BEAST_EXPECT(event.key_))
1060 {
1061 event.isSelected_ =
1062 network_.overlay().isSelected(*event.key_, event.peer_);
1063 auto peers = network_.overlay().getPeers(*event.key_);
1064 auto d = reduce_relay::epoch<milliseconds>(now).count() -
1065 std::get<3>(peers[event.peer_]);
1066 mustHandle = event.isSelected_ &&
1070 0 &&
1071 peers.find(event.peer_) != peers.end();
1072 }
1074 [&](PublicKey const& v, PeerWPtr const& ptr) {
1075 event.handled_ = true;
1076 if (mustHandle && v == event.key_)
1077 {
1078 event.state_ = State::WaitReset;
1079 sendSquelch(validator, ptr, {});
1080 }
1081 });
1082 bool handled =
1083 (event.handled_ && event.state_ == State::WaitReset) ||
1084 (!event.handled_ && !mustHandle);
1085 BEAST_EXPECT(handled);
1086 }
1087 if (event.state_ == State::WaitReset ||
1088 (event.state_ == State::On &&
1089 (now - event.time_ > (reduce_relay::IDLED + seconds(2)))))
1090 {
1091 bool handled =
1092 event.state_ == State::WaitReset || !event.handled_;
1093 BEAST_EXPECT(handled);
1094 event.state_ = State::Off;
1095 event.isSelected_ = false;
1096 event.handledCnt_ += handled;
1097 event.handled_ = false;
1098 network_.enableLink(event.validator_, event.peer_, true);
1099 }
1100 });
1101
1102 auto& down = events[EventType::LinkDown];
1103 auto& disconnected = events[EventType::PeerDisconnected];
1104 // It's possible the last Down Link event is not handled
1105 BEAST_EXPECT(down.handledCnt_ >= down.cnt_ - 1);
1106 // All Peer Disconnect events must be handled
1107 BEAST_EXPECT(disconnected.cnt_ == disconnected.handledCnt_);
1108 if (log)
1109 std::cout << "link down count: " << down.cnt_ << "/"
1110 << down.handledCnt_
1111 << " peer disconnect count: " << disconnected.cnt_ << "/"
1112 << disconnected.handledCnt_;
1113 }
1114
1115 bool
1116 checkCounting(PublicKey const& validator, bool isCountingState)
1117 {
1118 auto countingState = network_.overlay().isCountingState(validator);
1119 BEAST_EXPECT(countingState == isCountingState);
1120 return countingState == isCountingState;
1121 }
1122
1123 void
1124 doTest(std::string const& msg, bool log, std::function<void(bool)> f)
1125 {
1126 testcase(msg);
1127 f(log);
1128 }
1129
1135 void
1137 {
1138 doTest("Initial Round", log, [this](bool log) {
1139 BEAST_EXPECT(propagateAndSquelch(log));
1140 });
1141 }
1142
1146 void
1148 {
1149 doTest("Peer Unsquelched Too Soon", log, [this](bool log) {
1150 BEAST_EXPECT(propagateNoSquelch(log, 1, false, false, false));
1151 });
1152 }
1153
1157 void
1159 {
1160 ManualClock::advance(seconds(601));
1161 doTest("Peer Unsquelched", log, [this](bool log) {
1162 BEAST_EXPECT(propagateNoSquelch(log, 2, true, true, false));
1163 });
1164 }
1165
1167 bool
1168 propagateAndSquelch(bool log, bool purge = true, bool resetClock = true)
1169 {
1170 int n = 0;
1171 network_.propagate(
1172 [&](Link& link, MessageSPtr message) {
1173 std::uint16_t squelched = 0;
1174 link.send(
1175 message,
1176 [&](PublicKey const& key,
1177 PeerWPtr const& peerPtr,
1179 squelched++;
1180 sendSquelch(key, peerPtr, duration);
1181 });
1182 if (squelched)
1183 {
1184 BEAST_EXPECT(
1185 squelched ==
1186 MAX_PEERS -
1187 env_.app()
1188 .config()
1189 .VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS);
1190 n++;
1191 }
1192 },
1193 1,
1195 purge,
1196 resetClock);
1197 auto selected = network_.overlay().getSelected(network_.validator(0));
1198 BEAST_EXPECT(
1199 selected.size() ==
1200 env_.app().config().VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS);
1201 BEAST_EXPECT(n == 1); // only one selection round
1202 auto res = checkCounting(network_.validator(0), false);
1203 BEAST_EXPECT(res);
1204 return n == 1 && res;
1205 }
1206
1208 bool
1210 bool log,
1211 std::uint16_t nMessages,
1212 bool countingState,
1213 bool purge = true,
1214 bool resetClock = true)
1215 {
1216 bool squelched = false;
1217 network_.propagate(
1218 [&](Link& link, MessageSPtr message) {
1219 link.send(
1220 message,
1221 [&](PublicKey const& key,
1222 PeerWPtr const& peerPtr,
1224 squelched = true;
1225 BEAST_EXPECT(false);
1226 });
1227 },
1228 1,
1229 nMessages,
1230 purge,
1231 resetClock);
1232 auto res = checkCounting(network_.validator(0), countingState);
1233 return !squelched && res;
1234 }
1235
1239 void
1240 testNewPeer(bool log)
1241 {
1242 doTest("New Peer", log, [this](bool log) {
1243 BEAST_EXPECT(propagateAndSquelch(log, true, false));
1244 network_.addPeer();
1245 BEAST_EXPECT(propagateNoSquelch(log, 1, true, false, false));
1246 });
1247 }
1248
1251 void
1253 {
1254 doTest("Selected Peer Disconnects", log, [this](bool log) {
1255 ManualClock::advance(seconds(601));
1256 BEAST_EXPECT(propagateAndSquelch(log, true, false));
1257 auto id = network_.overlay().getSelectedPeer(network_.validator(0));
1258 std::uint16_t unsquelched = 0;
1259 network_.overlay().deletePeer(
1260 id, [&](PublicKey const& key, PeerWPtr const& peer) {
1261 unsquelched++;
1262 });
1263 BEAST_EXPECT(
1264 unsquelched ==
1265 MAX_PEERS -
1266 env_.app()
1267 .config()
1268 .VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS);
1269 BEAST_EXPECT(checkCounting(network_.validator(0), true));
1270 });
1271 }
1272
1275 void
1277 {
1278 doTest("Selected Peer Stops Relaying", log, [this](bool log) {
1279 ManualClock::advance(seconds(601));
1280 BEAST_EXPECT(propagateAndSquelch(log, true, false));
1281 ManualClock::advance(reduce_relay::IDLED + seconds(1));
1282 std::uint16_t unsquelched = 0;
1283 network_.overlay().deleteIdlePeers(
1284 [&](PublicKey const& key, PeerWPtr const& peer) {
1285 unsquelched++;
1286 });
1287 auto peers = network_.overlay().getPeers(network_.validator(0));
1288 BEAST_EXPECT(
1289 unsquelched ==
1290 MAX_PEERS -
1291 env_.app()
1292 .config()
1293 .VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS);
1294 BEAST_EXPECT(checkCounting(network_.validator(0), true));
1295 });
1296 }
1297
1300 void
1302 {
1303 doTest("Squelched Peer Disconnects", log, [this](bool log) {
1304 ManualClock::advance(seconds(601));
1305 BEAST_EXPECT(propagateAndSquelch(log, true, false));
1306 auto peers = network_.overlay().getPeers(network_.validator(0));
1307 auto it = std::find_if(peers.begin(), peers.end(), [&](auto it) {
1308 return std::get<reduce_relay::PeerState>(it.second) ==
1309 reduce_relay::PeerState::Squelched;
1310 });
1311 assert(it != peers.end());
1312 std::uint16_t unsquelched = 0;
1313 network_.overlay().deletePeer(
1314 it->first, [&](PublicKey const& key, PeerWPtr const& peer) {
1315 unsquelched++;
1316 });
1317 BEAST_EXPECT(unsquelched == 0);
1318 BEAST_EXPECT(checkCounting(network_.validator(0), false));
1319 });
1320 }
1321
1322 void
1323 testConfig(bool log)
1324 {
1325 doTest("Test Config - squelch enabled (legacy)", log, [&](bool log) {
1326 Config c;
1327
1328 std::string toLoad(R"rippleConfig(
1329[reduce_relay]
1330vp_enable=1
1331)rippleConfig");
1332
1333 c.loadFromString(toLoad);
1334 BEAST_EXPECT(c.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE == true);
1335 });
1336
1337 doTest("Test Config - squelch disabled (legacy)", log, [&](bool log) {
1338 Config c;
1339
1340 std::string toLoad(R"rippleConfig(
1341[reduce_relay]
1342vp_enable=0
1343)rippleConfig");
1344
1345 c.loadFromString(toLoad);
1346 BEAST_EXPECT(c.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE == false);
1347
1348 Config c1;
1349
1350 toLoad = R"rippleConfig(
1351[reduce_relay]
1352)rippleConfig";
1353
1354 c1.loadFromString(toLoad);
1355 BEAST_EXPECT(c1.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE == false);
1356 });
1357
1358 doTest("Test Config - squelch enabled", log, [&](bool log) {
1359 Config c;
1360
1361 std::string toLoad(R"rippleConfig(
1362[reduce_relay]
1363vp_base_squelch_enable=1
1364)rippleConfig");
1365
1366 c.loadFromString(toLoad);
1367 BEAST_EXPECT(c.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE == true);
1368 });
1369
1370 doTest("Test Config - squelch disabled", log, [&](bool log) {
1371 Config c;
1372
1373 std::string toLoad(R"rippleConfig(
1374[reduce_relay]
1375vp_base_squelch_enable=0
1376)rippleConfig");
1377
1378 c.loadFromString(toLoad);
1379 BEAST_EXPECT(c.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE == false);
1380 });
1381
1382 doTest("Test Config - legacy and new", log, [&](bool log) {
1383 Config c;
1384
1385 std::string toLoad(R"rippleConfig(
1386[reduce_relay]
1387vp_base_squelch_enable=0
1388vp_enable=0
1389)rippleConfig");
1390
1391 std::string error;
1392 auto const expectedError =
1393 "Invalid reduce_relay"
1394 " cannot specify both vp_base_squelch_enable and vp_enable "
1395 "options. "
1396 "vp_enable was deprecated and replaced by "
1397 "vp_base_squelch_enable";
1398
1399 try
1400 {
1401 c.loadFromString(toLoad);
1402 }
1403 catch (std::runtime_error& e)
1404 {
1405 error = e.what();
1406 }
1407
1408 BEAST_EXPECT(error == expectedError);
1409 });
1410
1411 doTest("Test Config - max selected peers", log, [&](bool log) {
1412 Config c;
1413
1414 std::string toLoad(R"rippleConfig(
1415[reduce_relay]
1416)rippleConfig");
1417
1418 c.loadFromString(toLoad);
1419 BEAST_EXPECT(c.VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS == 5);
1420
1421 Config c1;
1422
1423 toLoad = R"rippleConfig(
1424[reduce_relay]
1425vp_base_squelch_max_selected_peers=6
1426)rippleConfig";
1427
1428 c1.loadFromString(toLoad);
1429 BEAST_EXPECT(c1.VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS == 6);
1430
1431 Config c2;
1432
1433 toLoad = R"rippleConfig(
1434[reduce_relay]
1435vp_base_squelch_max_selected_peers=2
1436)rippleConfig";
1437
1438 std::string error;
1439 auto const expectedError =
1440 "Invalid reduce_relay"
1441 " vp_base_squelch_max_selected_peers must be "
1442 "greater than or equal to 3";
1443 try
1444 {
1445 c2.loadFromString(toLoad);
1446 }
1447 catch (std::runtime_error& e)
1448 {
1449 error = e.what();
1450 }
1451
1452 BEAST_EXPECT(error == expectedError);
1453 });
1454 }
1455
1456 void
1458 {
1459 doTest("BaseSquelchReady", log, [&](bool log) {
1460 ManualClock::reset();
1461 auto createSlots = [&](bool baseSquelchEnabled)
1463 env_.app().config().VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE =
1464 baseSquelchEnabled;
1466 env_.app().logs(), network_.overlay(), env_.app().config());
1467 };
1468 // base squelching must not be ready if squelching is disabled
1469 BEAST_EXPECT(!createSlots(false).baseSquelchReady());
1470
1471 // base squelch must not be ready as not enough time passed from
1472 // bootup
1473 BEAST_EXPECT(!createSlots(true).baseSquelchReady());
1474
1475 ManualClock::advance(reduce_relay::WAIT_ON_BOOTUP + minutes{1});
1476
1477 // base squelch enabled and bootup time passed
1478 BEAST_EXPECT(createSlots(true).baseSquelchReady());
1479
1480 // even if time passed, base squelching must not be ready if turned
1481 // off in the config
1482 BEAST_EXPECT(!createSlots(false).baseSquelchReady());
1483 });
1484 }
1485
1486 void
1488 {
1489 doTest("Duplicate Message", log, [&](bool log) {
1490 network_.reset();
1491 // update message count for the same peer/validator
1492 std::int16_t nMessages = 5;
1493 for (int i = 0; i < nMessages; i++)
1494 {
1495 uint256 key(i);
1496 network_.overlay().updateSlotAndSquelch(
1497 key,
1498 network_.validator(0),
1499 0,
1500 [&](PublicKey const&, PeerWPtr, std::uint32_t) {});
1501 }
1502 auto peers = network_.overlay().getPeers(network_.validator(0));
1503 // first message changes Slot state to Counting and is not counted,
1504 // hence '-1'.
1505 BEAST_EXPECT(std::get<1>(peers[0]) == (nMessages - 1));
1506 // add duplicate
1507 uint256 key(nMessages - 1);
1508 network_.overlay().updateSlotAndSquelch(
1509 key,
1510 network_.validator(0),
1511 0,
1512 [&](PublicKey const&, PeerWPtr, std::uint32_t) {});
1513 // confirm the same number of messages
1514 peers = network_.overlay().getPeers(network_.validator(0));
1515 BEAST_EXPECT(std::get<1>(peers[0]) == (nMessages - 1));
1516 // advance the clock
1517 ManualClock::advance(reduce_relay::IDLED + seconds(1));
1518 network_.overlay().updateSlotAndSquelch(
1519 key,
1520 network_.validator(0),
1521 0,
1522 [&](PublicKey const&, PeerWPtr, std::uint32_t) {});
1523 peers = network_.overlay().getPeers(network_.validator(0));
1524 // confirm message number increased
1525 BEAST_EXPECT(std::get<1>(peers[0]) == nMessages);
1526 });
1527 }
1528
1530 {
1531 Handler() : maxDuration_(0)
1532 {
1533 }
1534 void
1536 const override
1537 {
1538 if (duration > maxDuration_)
1539 maxDuration_ = duration;
1540 }
1541 void
1542 unsquelch(PublicKey const&, Peer::id_t) const override
1543 {
1544 }
1545 mutable int maxDuration_;
1546 };
1547
1548 void
1550 {
1551 doTest("Random Squelch", l, [&](bool l) {
1553 Handler handler;
1554
1555 auto run = [&](int npeers) {
1556 handler.maxDuration_ = 0;
1558 env_.app().logs(), handler, env_.app().config());
1559 // 1st message from a new peer switches the slot
1560 // to counting state and resets the counts of all peers +
1561 // MAX_MESSAGE_THRESHOLD + 1 messages to reach the threshold
1562 // and switch the slot's state to peer selection.
1563 for (int m = 1; m <= reduce_relay::MAX_MESSAGE_THRESHOLD + 2;
1564 m++)
1565 {
1566 for (int peer = 0; peer < npeers; peer++)
1567 {
1568 // make unique message hash to make the
1569 // slot's internal hash router accept the message
1570 std::uint64_t mid = m * 1000 + peer;
1571 uint256 const message{mid};
1573 message,
1574 validator,
1575 peer,
1576 protocol::MessageType::mtVALIDATION);
1577 }
1578 }
1579 // make Slot's internal hash router expire all messages
1580 ManualClock::advance(hours(1));
1581 };
1582
1583 using namespace reduce_relay;
1584 // expect max duration less than MAX_UNSQUELCH_EXPIRE_DEFAULT with
1585 // less than or equal to 60 peers
1586 run(20);
1587 BEAST_EXPECT(
1588 handler.maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1589 handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count());
1590 run(60);
1591 BEAST_EXPECT(
1592 handler.maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1593 handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count());
1594 // expect max duration greater than MIN_UNSQUELCH_EXPIRE and less
1595 // than MAX_UNSQUELCH_EXPIRE_PEERS with peers greater than 60
1596 // and less than 360
1597 run(350);
1598 // can't make this condition stronger. squelch
1599 // duration is probabilistic and max condition may still fail.
1600 // log when the value is low
1601 BEAST_EXPECT(
1602 handler.maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1603 handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_PEERS.count());
1604 using namespace beast::unit_test::detail;
1605 if (handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count())
1606 log << make_reason(
1607 "warning: squelch duration is low",
1608 __FILE__,
1609 __LINE__)
1610 << std::endl
1611 << std::flush;
1612 // more than 400 is still less than MAX_UNSQUELCH_EXPIRE_PEERS
1613 run(400);
1614 BEAST_EXPECT(
1615 handler.maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1616 handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_PEERS.count());
1617 if (handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count())
1618 log << make_reason(
1619 "warning: squelch duration is low",
1620 __FILE__,
1621 __LINE__)
1622 << std::endl
1623 << std::flush;
1624 });
1625 }
1626
1627 void
1629 {
1630 doTest("Handshake", log, [&](bool log) {
1631 auto setEnv = [&](bool enable) {
1632 Config c;
1634 str << "[reduce_relay]\n"
1635 << "vp_enable=" << enable << "\n"
1636 << "[compression]\n"
1637 << "1\n";
1638 c.loadFromString(str.str());
1639 env_.app().config().VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE =
1641
1642 env_.app().config().COMPRESSION = c.COMPRESSION;
1643 };
1644 auto handshake = [&](int outboundEnable, int inboundEnable) {
1645 beast::IP::Address addr =
1646 boost::asio::ip::make_address("172.1.1.100");
1647
1648 setEnv(outboundEnable);
1649 auto request = ripple::makeRequest(
1650 true,
1651 env_.app().config().COMPRESSION,
1652 false,
1653 env_.app().config().TX_REDUCE_RELAY_ENABLE,
1654 env_.app().config().VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE);
1655 http_request_type http_request;
1656 http_request.version(request.version());
1657 http_request.base() = request.base();
1658 // feature enabled on the peer's connection only if both sides
1659 // are enabled
1660 auto const peerEnabled = inboundEnable && outboundEnable;
1661 // inbound is enabled if the request's header has the feature
1662 // enabled and the peer's configuration is enabled
1663 auto const inboundEnabled = peerFeatureEnabled(
1664 http_request, FEATURE_VPRR, inboundEnable);
1665 BEAST_EXPECT(!(peerEnabled ^ inboundEnabled));
1666
1667 setEnv(inboundEnable);
1668 auto http_resp = ripple::makeResponse(
1669 true,
1670 http_request,
1671 addr,
1672 addr,
1673 uint256{1},
1674 1,
1675 {1, 0},
1676 env_.app());
1677 // outbound is enabled if the response's header has the feature
1678 // enabled and the peer's configuration is enabled
1679 auto const outboundEnabled =
1680 peerFeatureEnabled(http_resp, FEATURE_VPRR, outboundEnable);
1681 BEAST_EXPECT(!(peerEnabled ^ outboundEnabled));
1682 };
1683 handshake(1, 1);
1684 handshake(1, 0);
1685 handshake(0, 1);
1686 handshake(0, 0);
1687 });
1688 }
1689
1692
1693public:
1695 : env_(*this, jtx::envconfig([](std::unique_ptr<Config> cfg) {
1696 cfg->VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE = true;
1697 cfg->VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS = 6;
1698 return cfg;
1699 }))
1700 , network_(env_.app())
1701 {
1702 }
1703
1704 void
1705 run() override
1706 {
1707 bool log = false;
1708 testConfig(log);
1709 testInitialRound(log);
1710 testPeerUnsquelchedTooSoon(log);
1711 testPeerUnsquelched(log);
1712 testNewPeer(log);
1713 testSquelchedPeerDisconnects(log);
1714 testSelectedPeerDisconnects(log);
1715 testSelectedPeerStopsRelaying(log);
1716 testInternalHashRouter(log);
1717 testRandomSquelch(log);
1718 testHandshake(log);
1719 testBaseSquelchReady(log);
1720 }
1721};
1722
1724{
1725 void
1726 testRandom(bool log)
1727 {
1728 doTest("Random Test", log, [&](bool log) { random(log); });
1729 }
1730
1731 void
1732 run() override
1733 {
1734 bool log = false;
1735 testRandom(log);
1736 }
1737};
1738
1739BEAST_DEFINE_TESTSUITE(reduce_relay, overlay, ripple);
1740BEAST_DEFINE_TESTSUITE_MANUAL(reduce_relay_simulate, overlay, ripple);
1741
1742} // namespace test
1743
1744} // namespace ripple
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:19
A generic endpoint for log messages.
Definition Journal.h:41
A testsuite class.
Definition suite.h:52
log_os< char > log
Logging output stream.
Definition suite.h:149
virtual Config & config()=0
bool VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE
Definition Config.h:229
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition Config.cpp:460
bool COMPRESSION
Definition Config.h:201
std::size_t VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS
Definition Config.h:235
Manages partitions for logging.
Definition Log.h:33
beast::Journal journal(std::string const &name)
Definition Log.cpp:141
Represents a peer connection in the overlay.
std::uint32_t id_t
Uniquely identifies a peer.
A public key.
Definition PublicKey.h:43
std::uint8_t const * data() const noexcept
Definition PublicKey.h:68
std::size_t size() const noexcept
Definition PublicKey.h:74
A consumption charge.
Definition Charge.h:11
An immutable linear range of bytes.
Definition Slice.h:27
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:20
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:102
Application & app()
Definition Env.h:242
Set the fee on a JTx.
Definition fee.h:18
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:20
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
Definition envconfig.cpp:94
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition envconfig.h:35
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:6
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:330
SecretKey randomSecretKey()
Create a secret key using secure random numbers.
KeyType
Definition KeyType.h:9
boost::beast::http::request< boost::beast::http::dynamic_body > http_request_type
Definition Handoff.h:14
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:179
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:362
static constexpr char FEATURE_VPRR[]
Definition Handshake.h:124
STL namespace.
T shuffle(T... args)
T size(T... args)
T str(T... args)
Set the sequence number on a JTx.
Definition seq.h:15
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)