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 xrpl {
23
24namespace test {
25
26using namespace std::chrono;
27
28class Link;
29
35using UnsquelchCB = std::function<void(PublicKey const&, PeerWPtr const&)>;
37
38static constexpr std::uint32_t MAX_PEERS = 10;
39static constexpr std::uint32_t MAX_VALIDATORS = 10;
40static constexpr std::uint32_t MAX_MESSAGES = 200000;
41
45class PeerPartial : public Peer
46{
47public:
51
53 virtual ~PeerPartial()
54 {
55 }
56 virtual void
58 virtual void
59 onMessage(protocol::TMSquelch const& squelch) = 0;
60 void
61 send(protocol::TMSquelch const& squelch)
62 {
64 }
65
66 // dummy implementation
67 void
68 send(std::shared_ptr<Message> const& m) override
69 {
70 }
72 getRemoteAddress() const override
73 {
74 return {};
75 }
76 void
77 charge(Resource::Charge const& fee, std::string const& context = {}) override
78 {
79 }
80 bool
81 cluster() const override
82 {
83 return false;
84 }
85 bool
86 isHighLatency() const override
87 {
88 return false;
89 }
90 int
91 getScore(bool) const override
92 {
93 return 0;
94 }
95 PublicKey const&
96 getNodePublic() const override
97 {
98 return nodePublicKey_;
99 }
101 json() override
102 {
103 return {};
104 }
105 bool
107 {
108 return false;
109 }
111 publisherListSequence(PublicKey const&) const override
112 {
113 return {};
114 }
115 void
117 {
118 }
119 uint256 const&
120 getClosedLedgerHash() const override
121 {
122 static uint256 hash{};
123 return hash;
124 }
125 bool
126 hasLedger(uint256 const& hash, std::uint32_t seq) const override
127 {
128 return false;
129 }
130 void
131 ledgerRange(std::uint32_t& minSeq, std::uint32_t& maxSeq) const override
132 {
133 }
134 bool
135 hasTxSet(uint256 const& hash) const override
136 {
137 return false;
138 }
139 void
140 cycleStatus() override
141 {
142 }
143 bool
145 {
146 return false;
147 }
148 bool
149 compressionEnabled() const override
150 {
151 return false;
152 }
153 bool
154 txReduceRelayEnabled() const override
155 {
156 return false;
157 }
158 void
159 sendTxQueue() override
160 {
161 }
162 void
163 addTxQueue(uint256 const&) override
164 {
165 }
166 void
167 removeTxQueue(uint256 const&) override
168 {
169 }
170};
171
174{
175public:
176 typedef uint64_t rep;
180 inline static bool const is_steady = false;
181
182 static void
183 advance(duration d) noexcept
184 {
185 now_ += d;
186 }
187
188 static void
190 {
191 now_ += randDuration(min, max);
192 }
193
194 static void
195 reset() noexcept
196 {
197 now_ = time_point(seconds(0));
198 }
199
200 static time_point
201 now() noexcept
202 {
203 return now_;
204 }
205
206 static duration
208 {
209 return duration(milliseconds(rand_int(min.count(), max.count())));
210 }
211
212 explicit ManualClock() = default;
213
214private:
215 inline static time_point now_ = time_point(seconds(0));
216};
217
220{
221public:
222 Overlay() = default;
223 virtual ~Overlay() = default;
224
225 virtual void
227 uint256 const& key,
228 PublicKey const& validator,
229 Peer::id_t id,
230 SquelchCB f,
231 protocol::MessageType type = protocol::mtVALIDATION) = 0;
232
233 virtual void deleteIdlePeers(UnsquelchCB) = 0;
234
236};
237
238class Validator;
239
243class Link
244{
246
247public:
249 : validator_(validator), peer_(peer), latency_(latency), up_(true)
250 {
251 auto sp = peer_.lock();
252 assert(sp);
253 }
254 ~Link() = default;
255 void
257 {
258 if (!up_)
259 return;
260 auto sp = peer_.lock();
261 assert(sp);
263 peer->onMessage(m, f);
264 }
265 Validator&
267 {
268 return validator_;
269 }
270 void
271 up(bool linkUp)
272 {
273 up_ = linkUp;
274 }
277 {
278 auto p = peer_.lock();
279 assert(p);
280 return p->id();
281 }
284 {
285 auto p = peer_.lock();
286 assert(p);
287 return p;
288 }
289
290private:
294 bool up_;
295};
296
299{
301
302public:
304 {
305 protocol::TMValidation v;
306 v.set_validation("validation");
307 message_ = std::make_shared<Message>(v, protocol::mtVALIDATION, pkey_);
308 id_ = sid_++;
309 }
310 Validator(Validator const&) = default;
311 Validator(Validator&&) = default;
312 Validator&
313 operator=(Validator const&) = default;
314 Validator&
315 operator=(Validator&&) = default;
317 {
318 clear();
319 }
320
321 void
323 {
324 links_.clear();
325 }
326
327 static void
329 {
330 sid_ = 0;
331 }
332
333 PublicKey const&
335 {
336 return pkey_;
337 }
338
339 operator PublicKey() const
340 {
341 return pkey_;
342 }
343
344 void
346 {
347 links_.emplace(std::make_pair(peer->id(), std::make_shared<Link>(*this, peer)));
348 }
349
350 void
352 {
353 links_.erase(id);
354 }
355
356 void
358 {
359 for (auto id : peers)
360 {
361 assert(links_.find(id) != links_.end());
362 f(*links_[id], message_);
363 }
364 }
365
366 void
367 for_links(LinkIterCB f, bool simulateSlow = false)
368 {
370 std::transform(links_.begin(), links_.end(), std::back_inserter(v), [](auto& kv) { return kv.second; });
372 std::mt19937 g(d());
373 std::shuffle(v.begin(), v.end(), g);
374
375 for (auto& link : v)
376 {
377 f(*link, message_);
378 }
379 }
380
382 void
384 {
385 for_links(peers, [&](Link& link, MessageSPtr m) { link.send(m, f); });
386 }
387
389 void
391 {
392 for_links([&](Link& link, MessageSPtr m) { link.send(m, f); });
393 }
394
397 {
398 return message_;
399 }
400
403 {
404 return id_;
405 }
406
407 void
409 {
410 auto it = links_.find(id);
411 assert(it != links_.end());
412 it->second->up(true);
413 }
414
415 void
417 {
418 auto it = links_.find(id);
419 assert(it != links_.end());
420 it->second->up(false);
421 }
422
423private:
427 inline static std::uint16_t sid_ = 0;
429};
430
431class PeerSim : public PeerPartial, public std::enable_shared_from_this<PeerSim>
432{
433public:
435 PeerSim(Overlay& overlay, beast::Journal journal) : overlay_(overlay), squelch_(journal)
436 {
437 id_ = sid_++;
438 }
439
440 ~PeerSim() = default;
441
442 id_t
443 id() const override
444 {
445 return id_;
446 }
447
448 std::string const&
449 fingerprint() const override
450 {
451 return fingerprint_;
452 }
453
454 static void
456 {
457 sid_ = 0;
458 }
459
461 void
462 onMessage(MessageSPtr const& m, SquelchCB f) override
463 {
464 auto validator = m->getValidatorKey();
465 assert(validator);
466 if (!squelch_.expireSquelch(*validator))
467 return;
468
470 }
471
473 virtual void
474 onMessage(protocol::TMSquelch const& squelch) override
475 {
476 auto validator = squelch.validatorpubkey();
477 PublicKey key(Slice(validator.data(), validator.size()));
478 if (squelch.squelch())
479 squelch_.addSquelch(key, std::chrono::seconds{squelch.squelchduration()});
480 else
481 squelch_.removeSquelch(key);
482 }
483
484private:
485 inline static id_t sid_ = 0;
490};
491
493{
495
496public:
499 OverlaySim(Application& app) : slots_(app.logs(), *this, app.config()), logs_(app.logs())
500 {
501 }
502
503 ~OverlaySim() = default;
504
505 void
507 {
508 peers_.clear();
510 slots_.deleteIdlePeers();
511 }
512
515 {
516 auto res = slots_.inState(validator, state);
517 return res ? *res : 0;
518 }
519
520 void
522 uint256 const& key,
523 PublicKey const& validator,
524 Peer::id_t id,
525 SquelchCB f,
526 protocol::MessageType type = protocol::mtVALIDATION) override
527 {
528 squelch_ = f;
529 slots_.updateSlotAndSquelch(key, validator, id, type);
530 }
531
532 void
534 {
535 unsquelch_ = f;
536 slots_.deletePeer(id, true);
537 }
538
539 void
541 {
542 unsquelch_ = f;
543 slots_.deleteIdlePeers();
544 }
545
547 addPeer(bool useCache = true)
548 {
549 PeerSPtr peer{};
550 Peer::id_t id;
551 if (peersCache_.empty() || !useCache)
552 {
553 peer = std::make_shared<PeerSim>(*this, logs_.journal("Squelch"));
554 id = peer->id();
555 }
556 else
557 {
558 auto it = peersCache_.begin();
559 peer = it->second;
560 id = it->first;
561 peersCache_.erase(it);
562 }
563 peers_.emplace(std::make_pair(id, peer));
564 return peer;
565 }
566
567 void
568 deletePeer(Peer::id_t id, bool useCache = true)
569 {
570 auto it = peers_.find(id);
571 assert(it != peers_.end());
572 deletePeer(id, [&](PublicKey const&, PeerWPtr) {});
573 if (useCache)
574 peersCache_.emplace(std::make_pair(id, it->second));
575 peers_.erase(it);
576 }
577
578 void
580 {
581 while (!peers_.empty())
582 deletePeer(peers_.begin()->first);
583 while (!peersCache_.empty())
584 addPeer();
585 }
586
589 {
590 if (peers_.empty())
591 return {};
592
593 std::uint8_t maxId = 0;
594
595 for (auto& [id, _] : peers_)
596 {
597 (void)_;
598 if (id > maxId)
599 maxId = id;
600 }
601
602 deletePeer(maxId, false);
603
604 return maxId;
605 }
606
607 bool
612
615 {
616 return slots_.getSelected(validator);
617 }
618
619 bool
621 {
622 auto selected = slots_.getSelected(validator);
623 return selected.find(peer) != selected.end();
624 }
625
626 id_t
628 {
629 auto selected = slots_.getSelected(validator);
630 assert(selected.size());
631 return *selected.begin();
632 }
633
636 {
637 return slots_.getPeers(validator);
638 }
639
642 {
643 return peers_.size();
644 }
645
646private:
647 void
648 squelch(PublicKey const& validator, Peer::id_t id, std::uint32_t squelchDuration) const override
649 {
650 if (auto it = peers_.find(id); it != peers_.end())
651 squelch_(validator, it->second, squelchDuration);
652 }
653 void
654 unsquelch(PublicKey const& validator, Peer::id_t id) const override
655 {
656 if (auto it = peers_.find(id); it != peers_.end())
657 unsquelch_(validator, it->second);
658 }
665};
666
668{
669public:
671 {
672 init();
673 }
674
675 void
677 {
679 for (int p = 0; p < MAX_PEERS; p++)
680 {
681 auto peer = overlay_.addPeer();
682 for (auto& v : validators_)
683 v.addPeer(peer);
684 }
685 }
686
687 ~Network() = default;
688
689 void
691 {
692 validators_.clear();
693 overlay_.clear();
696 init();
697 }
698
701 {
702 auto peer = overlay_.addPeer();
703 for (auto& v : validators_)
704 v.addPeer(peer);
705 return peer->id();
706 }
707
708 void
710 {
711 auto id = overlay_.deleteLastPeer();
712
713 if (!id)
714 return;
715
716 for (auto& validator : validators_)
718 }
719
720 void
722 {
723 while (overlay_.getNumPeers() > MAX_PEERS)
725 }
726
727 Validator&
729 {
730 assert(v < validators_.size());
731 return validators_[v];
732 }
733
736 {
737 return overlay_;
738 }
739
740 void
741 enableLink(std::uint16_t validatorId, Peer::id_t peer, bool enable)
742 {
743 auto it = std::find_if(validators_.begin(), validators_.end(), [&](auto& v) { return v.id() == validatorId; });
744 assert(it != validators_.end());
745 if (enable)
746 it->linkUp(peer);
747 else
748 it->linkDown(peer);
749 }
750
751 void
753 {
754 // Send unsquelch to the Peer on all links. This way when
755 // the Peer "reconnects" it starts sending messages on the link.
756 // We expect that if a Peer disconnects and then reconnects, it's
757 // unsquelched.
758 protocol::TMSquelch squelch;
759 squelch.set_squelch(false);
760 for (auto& v : validators_)
761 {
762 PublicKey key = v;
763 squelch.clear_validatorpubkey();
764 squelch.set_validatorpubkey(key.data(), key.size());
765 v.for_links(
766 {peer}, [&](Link& l, MessageSPtr) { std::dynamic_pointer_cast<PeerSim>(l.getPeer())->send(squelch); });
767 }
768 }
769
770 void
772 {
773 auto size = max - min;
775 std::iota(s.begin(), s.end(), min);
777 std::mt19937 g(d());
778 std::shuffle(s.begin(), s.end(), g);
779 for (auto v : s)
780 f(v);
781 }
782
783 void
785 LinkIterCB link,
786 std::uint16_t nValidators = MAX_VALIDATORS,
787 std::uint32_t nMessages = MAX_MESSAGES,
788 bool purge = true,
789 bool resetClock = true)
790 {
791 if (resetClock)
793
794 if (purge)
795 {
796 purgePeers();
798 }
799
800 for (int m = 0; m < nMessages; ++m)
801 {
803 for_rand(0, nValidators, [&](std::uint32_t v) { validators_[v].for_links(link); });
804 }
805 }
806
808 bool
810 {
811 for (auto& v : validators_)
812 {
813 if (overlay_.isSelected(v, id))
814 return true;
815 }
816 return false;
817 }
818
823 bool
825 {
826 for (auto& v : validators_)
827 {
828 if (!overlay_.isSelected(v, peer))
829 continue;
830 auto peers = overlay_.getPeers(v);
831 for (auto& [_, v] : peers)
832 {
833 (void)_;
835 return false;
836 }
837 }
838 return true;
839 }
840
841private:
844};
845
847{
850
851protected:
852 void
854 {
856 std::cout << msg << " "
857 << "num peers " << (int)network_.overlay().getNumPeers() << std::endl;
858 for (auto& [k, v] : peers)
859 std::cout << k << ":" << (int)std::get<reduce_relay::PeerState>(v) << " ";
861 }
862
866 {
867 protocol::TMSquelch squelch;
868 bool res = duration ? true : false;
869 squelch.set_squelch(res);
870 squelch.set_validatorpubkey(validator.data(), validator.size());
871 if (res)
872 squelch.set_squelchduration(*duration);
873 auto sp = peerPtr.lock();
874 assert(sp);
876 return sp->id();
877 }
878
879 enum State { On, Off, WaitReset };
881 // Link down or Peer disconnect event
882 // TBD - add new peer event
883 // TBD - add overlapping type of events at any
884 // time in any quantity
897
901 void
903 {
906
907 network_.reset();
908 network_.propagate([&](Link& link, MessageSPtr m) {
909 auto& validator = link.validator();
910 auto now = ManualClock::now();
911
912 bool squelched = false;
914
915 link.send(m, [&](PublicKey const& key, PeerWPtr const& peerPtr, std::uint32_t duration) {
916 assert(key == validator);
917 auto p = sendSquelch(key, peerPtr, duration);
918 squelched = true;
919 str << p << " ";
920 });
921
922 if (squelched)
923 {
924 auto selected = network_.overlay().getSelected(validator);
925 str << " selected: ";
926 for (auto s : selected)
927 str << s << " ";
928 if (log)
930 << " random, squelched, validator: " << validator.id() << " peers: " << str.str()
931 << std::endl;
932 auto countingState = network_.overlay().isCountingState(validator);
933 BEAST_EXPECT(
934 countingState == false &&
936 }
937
938 // Trigger Link Down or Peer Disconnect event
939 // Only one Link Down at a time
940 if (events[EventType::LinkDown].state_ == State::Off)
941 {
942 auto update = [&](EventType event) {
943 events[event].cnt_++;
944 events[event].validator_ = validator.id();
945 events[event].key_ = validator;
946 events[event].peer_ = link.peerId();
947 events[event].state_ = State::On;
948 events[event].time_ = now;
949 if (event == EventType::LinkDown)
950 {
951 network_.enableLink(validator.id(), link.peerId(), false);
952 events[event].isSelected_ = network_.overlay().isSelected(validator, link.peerId());
953 }
954 else
955 events[event].isSelected_ = network_.isSelected(link.peerId());
956 };
957 auto r = rand_int(0, 1000);
958 if (r == (int)EventType::LinkDown || r == (int)EventType::PeerDisconnected)
959 {
960 update(static_cast<EventType>(r));
961 }
962 }
963
964 if (events[EventType::PeerDisconnected].state_ == State::On)
965 {
966 auto& event = events[EventType::PeerDisconnected];
967 bool allCounting = network_.allCounting(event.peer_);
968 network_.overlay().deletePeer(event.peer_, [&](PublicKey const& v, PeerWPtr const& peerPtr) {
969 if (event.isSelected_)
970 sendSquelch(v, peerPtr, {});
971 event.handled_ = true;
972 });
973 // Should only be unsquelched if the peer is in Selected state
974 // If in Selected state it's possible unsquelching didn't
975 // take place because there is no peers in Squelched state in
976 // any of the slots where the peer is in Selected state
977 // (allCounting is true)
978 bool handled = (event.isSelected_ == false && !event.handled_) ||
979 (event.isSelected_ == true && (event.handled_ || allCounting));
980 BEAST_EXPECT(handled);
981 event.state_ = State::Off;
982 event.isSelected_ = false;
983 event.handledCnt_ += handled;
984 event.handled_ = false;
985 network_.onDisconnectPeer(event.peer_);
986 }
987
988 auto& event = events[EventType::LinkDown];
989 // Check every sec for idled peers. Idled peers are
990 // created by Link Down event.
991 if (now - lastCheck > milliseconds(1000))
992 {
993 lastCheck = now;
994 // Check if Link Down event must be handled by
995 // deleteIdlePeer(): 1) the peer is in Selected state;
996 // 2) the peer has not received any messages for IDLED time;
997 // 3) there are peers in Squelched state in the slot.
998 // 4) peer is in Slot's peers_ (if not then it is deleted
999 // by Slots::deleteIdlePeers())
1000 bool mustHandle = false;
1001 if (event.state_ == State::On && BEAST_EXPECT(event.key_))
1002 {
1003 event.isSelected_ = network_.overlay().isSelected(*event.key_, event.peer_);
1004 auto peers = network_.overlay().getPeers(*event.key_);
1005 auto d = reduce_relay::epoch<milliseconds>(now).count() - std::get<3>(peers[event.peer_]);
1006 mustHandle = event.isSelected_ && d > milliseconds(reduce_relay::IDLED).count() &&
1008 peers.find(event.peer_) != peers.end();
1009 }
1010 network_.overlay().deleteIdlePeers([&](PublicKey const& v, PeerWPtr const& ptr) {
1011 event.handled_ = true;
1012 if (mustHandle && v == event.key_)
1013 {
1014 event.state_ = State::WaitReset;
1015 sendSquelch(validator, ptr, {});
1016 }
1017 });
1018 bool handled = (event.handled_ && event.state_ == State::WaitReset) || (!event.handled_ && !mustHandle);
1019 BEAST_EXPECT(handled);
1020 }
1021 if (event.state_ == State::WaitReset ||
1022 (event.state_ == State::On && (now - event.time_ > (reduce_relay::IDLED + seconds(2)))))
1023 {
1024 bool handled = event.state_ == State::WaitReset || !event.handled_;
1025 BEAST_EXPECT(handled);
1026 event.state_ = State::Off;
1027 event.isSelected_ = false;
1028 event.handledCnt_ += handled;
1029 event.handled_ = false;
1030 network_.enableLink(event.validator_, event.peer_, true);
1031 }
1032 });
1033
1034 auto& down = events[EventType::LinkDown];
1035 auto& disconnected = events[EventType::PeerDisconnected];
1036 // It's possible the last Down Link event is not handled
1037 BEAST_EXPECT(down.handledCnt_ >= down.cnt_ - 1);
1038 // All Peer Disconnect events must be handled
1039 BEAST_EXPECT(disconnected.cnt_ == disconnected.handledCnt_);
1040 if (log)
1041 std::cout << "link down count: " << down.cnt_ << "/" << down.handledCnt_
1042 << " peer disconnect count: " << disconnected.cnt_ << "/" << disconnected.handledCnt_;
1043 }
1044
1045 bool
1046 checkCounting(PublicKey const& validator, bool isCountingState)
1047 {
1048 auto countingState = network_.overlay().isCountingState(validator);
1049 BEAST_EXPECT(countingState == isCountingState);
1050 return countingState == isCountingState;
1051 }
1052
1053 void
1054 doTest(std::string const& msg, bool log, std::function<void(bool)> f)
1055 {
1056 testcase(msg);
1057 f(log);
1058 }
1059
1065 void
1067 {
1068 doTest("Initial Round", log, [this](bool log) { BEAST_EXPECT(propagateAndSquelch(log)); });
1069 }
1070
1074 void
1076 {
1077 doTest("Peer Unsquelched Too Soon", log, [this](bool log) {
1078 BEAST_EXPECT(propagateNoSquelch(log, 1, false, false, false));
1079 });
1080 }
1081
1085 void
1087 {
1088 ManualClock::advance(seconds(601));
1089 doTest(
1090 "Peer Unsquelched", log, [this](bool log) { BEAST_EXPECT(propagateNoSquelch(log, 2, true, true, false)); });
1091 }
1092
1094 bool
1095 propagateAndSquelch(bool log, bool purge = true, bool resetClock = true)
1096 {
1097 int n = 0;
1098 network_.propagate(
1099 [&](Link& link, MessageSPtr message) {
1100 std::uint16_t squelched = 0;
1101 link.send(message, [&](PublicKey const& key, PeerWPtr const& peerPtr, std::uint32_t duration) {
1102 squelched++;
1103 sendSquelch(key, peerPtr, duration);
1104 });
1105 if (squelched)
1106 {
1107 BEAST_EXPECT(
1108 squelched == MAX_PEERS - env_.app().config().VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS);
1109 n++;
1110 }
1111 },
1112 1,
1114 purge,
1115 resetClock);
1116 auto selected = network_.overlay().getSelected(network_.validator(0));
1117 BEAST_EXPECT(selected.size() == env_.app().config().VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS);
1118 BEAST_EXPECT(n == 1); // only one selection round
1119 auto res = checkCounting(network_.validator(0), false);
1120 BEAST_EXPECT(res);
1121 return n == 1 && res;
1122 }
1123
1125 bool
1126 propagateNoSquelch(bool log, std::uint16_t nMessages, bool countingState, bool purge = true, bool resetClock = true)
1127 {
1128 bool squelched = false;
1129 network_.propagate(
1130 [&](Link& link, MessageSPtr message) {
1131 link.send(message, [&](PublicKey const& key, PeerWPtr const& peerPtr, std::uint32_t duration) {
1132 squelched = true;
1133 BEAST_EXPECT(false);
1134 });
1135 },
1136 1,
1137 nMessages,
1138 purge,
1139 resetClock);
1140 auto res = checkCounting(network_.validator(0), countingState);
1141 return !squelched && res;
1142 }
1143
1147 void
1148 testNewPeer(bool log)
1149 {
1150 doTest("New Peer", log, [this](bool log) {
1151 BEAST_EXPECT(propagateAndSquelch(log, true, false));
1152 network_.addPeer();
1153 BEAST_EXPECT(propagateNoSquelch(log, 1, true, false, false));
1154 });
1155 }
1156
1159 void
1161 {
1162 doTest("Selected Peer Disconnects", log, [this](bool log) {
1163 ManualClock::advance(seconds(601));
1164 BEAST_EXPECT(propagateAndSquelch(log, true, false));
1165 auto id = network_.overlay().getSelectedPeer(network_.validator(0));
1166 std::uint16_t unsquelched = 0;
1167 network_.overlay().deletePeer(id, [&](PublicKey const& key, PeerWPtr const& peer) { unsquelched++; });
1168 BEAST_EXPECT(unsquelched == MAX_PEERS - env_.app().config().VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS);
1169 BEAST_EXPECT(checkCounting(network_.validator(0), true));
1170 });
1171 }
1172
1175 void
1177 {
1178 doTest("Selected Peer Stops Relaying", log, [this](bool log) {
1179 ManualClock::advance(seconds(601));
1180 BEAST_EXPECT(propagateAndSquelch(log, true, false));
1181 ManualClock::advance(reduce_relay::IDLED + seconds(1));
1182 std::uint16_t unsquelched = 0;
1183 network_.overlay().deleteIdlePeers([&](PublicKey const& key, PeerWPtr const& peer) { unsquelched++; });
1184 auto peers = network_.overlay().getPeers(network_.validator(0));
1185 BEAST_EXPECT(unsquelched == MAX_PEERS - env_.app().config().VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS);
1186 BEAST_EXPECT(checkCounting(network_.validator(0), true));
1187 });
1188 }
1189
1192 void
1194 {
1195 doTest("Squelched Peer Disconnects", log, [this](bool log) {
1196 ManualClock::advance(seconds(601));
1197 BEAST_EXPECT(propagateAndSquelch(log, true, false));
1198 auto peers = network_.overlay().getPeers(network_.validator(0));
1199 auto it = std::find_if(peers.begin(), peers.end(), [&](auto it) {
1200 return std::get<reduce_relay::PeerState>(it.second) == reduce_relay::PeerState::Squelched;
1201 });
1202 assert(it != peers.end());
1203 std::uint16_t unsquelched = 0;
1204 network_.overlay().deletePeer(
1205 it->first, [&](PublicKey const& key, PeerWPtr const& peer) { unsquelched++; });
1206 BEAST_EXPECT(unsquelched == 0);
1207 BEAST_EXPECT(checkCounting(network_.validator(0), false));
1208 });
1209 }
1210
1211 void
1212 testConfig(bool log)
1213 {
1214 doTest("Test Config - squelch enabled (legacy)", log, [&](bool log) {
1215 Config c;
1216
1217 std::string toLoad(R"rippleConfig(
1218[reduce_relay]
1219vp_enable=1
1220)rippleConfig");
1221
1222 c.loadFromString(toLoad);
1223 BEAST_EXPECT(c.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE == true);
1224 });
1225
1226 doTest("Test Config - squelch disabled (legacy)", log, [&](bool log) {
1227 Config c;
1228
1229 std::string toLoad(R"rippleConfig(
1230[reduce_relay]
1231vp_enable=0
1232)rippleConfig");
1233
1234 c.loadFromString(toLoad);
1235 BEAST_EXPECT(c.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE == false);
1236
1237 Config c1;
1238
1239 toLoad = R"rippleConfig(
1240[reduce_relay]
1241)rippleConfig";
1242
1243 c1.loadFromString(toLoad);
1244 BEAST_EXPECT(c1.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE == false);
1245 });
1246
1247 doTest("Test Config - squelch enabled", log, [&](bool log) {
1248 Config c;
1249
1250 std::string toLoad(R"rippleConfig(
1251[reduce_relay]
1252vp_base_squelch_enable=1
1253)rippleConfig");
1254
1255 c.loadFromString(toLoad);
1256 BEAST_EXPECT(c.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE == true);
1257 });
1258
1259 doTest("Test Config - squelch disabled", log, [&](bool log) {
1260 Config c;
1261
1262 std::string toLoad(R"rippleConfig(
1263[reduce_relay]
1264vp_base_squelch_enable=0
1265)rippleConfig");
1266
1267 c.loadFromString(toLoad);
1268 BEAST_EXPECT(c.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE == false);
1269 });
1270
1271 doTest("Test Config - legacy and new", log, [&](bool log) {
1272 Config c;
1273
1274 std::string toLoad(R"rippleConfig(
1275[reduce_relay]
1276vp_base_squelch_enable=0
1277vp_enable=0
1278)rippleConfig");
1279
1280 std::string error;
1281 auto const expectedError =
1282 "Invalid reduce_relay"
1283 " cannot specify both vp_base_squelch_enable and vp_enable "
1284 "options. "
1285 "vp_enable was deprecated and replaced by "
1286 "vp_base_squelch_enable";
1287
1288 try
1289 {
1290 c.loadFromString(toLoad);
1291 }
1292 catch (std::runtime_error& e)
1293 {
1294 error = e.what();
1295 }
1296
1297 BEAST_EXPECT(error == expectedError);
1298 });
1299
1300 doTest("Test Config - max selected peers", log, [&](bool log) {
1301 Config c;
1302
1303 std::string toLoad(R"rippleConfig(
1304[reduce_relay]
1305)rippleConfig");
1306
1307 c.loadFromString(toLoad);
1308 BEAST_EXPECT(c.VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS == 5);
1309
1310 Config c1;
1311
1312 toLoad = R"rippleConfig(
1313[reduce_relay]
1314vp_base_squelch_max_selected_peers=6
1315)rippleConfig";
1316
1317 c1.loadFromString(toLoad);
1318 BEAST_EXPECT(c1.VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS == 6);
1319
1320 Config c2;
1321
1322 toLoad = R"rippleConfig(
1323[reduce_relay]
1324vp_base_squelch_max_selected_peers=2
1325)rippleConfig";
1326
1327 std::string error;
1328 auto const expectedError =
1329 "Invalid reduce_relay"
1330 " vp_base_squelch_max_selected_peers must be "
1331 "greater than or equal to 3";
1332 try
1333 {
1334 c2.loadFromString(toLoad);
1335 }
1336 catch (std::runtime_error& e)
1337 {
1338 error = e.what();
1339 }
1340
1341 BEAST_EXPECT(error == expectedError);
1342 });
1343 }
1344
1345 void
1347 {
1348 doTest("BaseSquelchReady", log, [&](bool log) {
1349 ManualClock::reset();
1350 auto createSlots = [&](bool baseSquelchEnabled) -> reduce_relay::Slots<ManualClock> {
1351 env_.app().config().VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE = baseSquelchEnabled;
1352 return reduce_relay::Slots<ManualClock>(env_.app().logs(), network_.overlay(), env_.app().config());
1353 };
1354 // base squelching must not be ready if squelching is disabled
1355 BEAST_EXPECT(!createSlots(false).baseSquelchReady());
1356
1357 // base squelch must not be ready as not enough time passed from
1358 // bootup
1359 BEAST_EXPECT(!createSlots(true).baseSquelchReady());
1360
1361 ManualClock::advance(reduce_relay::WAIT_ON_BOOTUP + minutes{1});
1362
1363 // base squelch enabled and bootup time passed
1364 BEAST_EXPECT(createSlots(true).baseSquelchReady());
1365
1366 // even if time passed, base squelching must not be ready if turned
1367 // off in the config
1368 BEAST_EXPECT(!createSlots(false).baseSquelchReady());
1369 });
1370 }
1371
1372 void
1374 {
1375 doTest("Duplicate Message", log, [&](bool log) {
1376 network_.reset();
1377 // update message count for the same peer/validator
1378 std::int16_t nMessages = 5;
1379 for (int i = 0; i < nMessages; i++)
1380 {
1381 uint256 key(i);
1382 network_.overlay().updateSlotAndSquelch(
1383 key, network_.validator(0), 0, [&](PublicKey const&, PeerWPtr, std::uint32_t) {});
1384 }
1385 auto peers = network_.overlay().getPeers(network_.validator(0));
1386 // first message changes Slot state to Counting and is not counted,
1387 // hence '-1'.
1388 BEAST_EXPECT(std::get<1>(peers[0]) == (nMessages - 1));
1389 // add duplicate
1390 uint256 key(nMessages - 1);
1391 network_.overlay().updateSlotAndSquelch(
1392 key, network_.validator(0), 0, [&](PublicKey const&, PeerWPtr, std::uint32_t) {});
1393 // confirm the same number of messages
1394 peers = network_.overlay().getPeers(network_.validator(0));
1395 BEAST_EXPECT(std::get<1>(peers[0]) == (nMessages - 1));
1396 // advance the clock
1397 ManualClock::advance(reduce_relay::IDLED + seconds(1));
1398 network_.overlay().updateSlotAndSquelch(
1399 key, network_.validator(0), 0, [&](PublicKey const&, PeerWPtr, std::uint32_t) {});
1400 peers = network_.overlay().getPeers(network_.validator(0));
1401 // confirm message number increased
1402 BEAST_EXPECT(std::get<1>(peers[0]) == nMessages);
1403 });
1404 }
1405
1407 {
1408 Handler() : maxDuration_(0)
1409 {
1410 }
1411 void
1413 {
1414 if (duration > maxDuration_)
1415 maxDuration_ = duration;
1416 }
1417 void
1418 unsquelch(PublicKey const&, Peer::id_t) const override
1419 {
1420 }
1421 mutable int maxDuration_;
1422 };
1423
1424 void
1426 {
1427 doTest("Random Squelch", l, [&](bool l) {
1429 Handler handler;
1430
1431 auto run = [&](int npeers) {
1432 handler.maxDuration_ = 0;
1433 reduce_relay::Slots<ManualClock> slots(env_.app().logs(), handler, env_.app().config());
1434 // 1st message from a new peer switches the slot
1435 // to counting state and resets the counts of all peers +
1436 // MAX_MESSAGE_THRESHOLD + 1 messages to reach the threshold
1437 // and switch the slot's state to peer selection.
1438 for (int m = 1; m <= reduce_relay::MAX_MESSAGE_THRESHOLD + 2; m++)
1439 {
1440 for (int peer = 0; peer < npeers; peer++)
1441 {
1442 // make unique message hash to make the
1443 // slot's internal hash router accept the message
1444 std::uint64_t mid = m * 1000 + peer;
1445 uint256 const message{mid};
1446 slots.updateSlotAndSquelch(message, validator, peer, protocol::MessageType::mtVALIDATION);
1447 }
1448 }
1449 // make Slot's internal hash router expire all messages
1450 ManualClock::advance(hours(1));
1451 };
1452
1453 using namespace reduce_relay;
1454 // expect max duration less than MAX_UNSQUELCH_EXPIRE_DEFAULT with
1455 // less than or equal to 60 peers
1456 run(20);
1457 BEAST_EXPECT(
1458 handler.maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1459 handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count());
1460 run(60);
1461 BEAST_EXPECT(
1462 handler.maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1463 handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count());
1464 // expect max duration greater than MIN_UNSQUELCH_EXPIRE and less
1465 // than MAX_UNSQUELCH_EXPIRE_PEERS with peers greater than 60
1466 // and less than 360
1467 run(350);
1468 // can't make this condition stronger. squelch
1469 // duration is probabilistic and max condition may still fail.
1470 // log when the value is low
1471 BEAST_EXPECT(
1472 handler.maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1473 handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_PEERS.count());
1474 using namespace beast::unit_test::detail;
1475 if (handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count())
1476 log << make_reason("warning: squelch duration is low", __FILE__, __LINE__) << std::endl << std::flush;
1477 // more than 400 is still less than MAX_UNSQUELCH_EXPIRE_PEERS
1478 run(400);
1479 BEAST_EXPECT(
1480 handler.maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1481 handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_PEERS.count());
1482 if (handler.maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count())
1483 log << make_reason("warning: squelch duration is low", __FILE__, __LINE__) << std::endl << std::flush;
1484 });
1485 }
1486
1487 void
1489 {
1490 doTest("Handshake", log, [&](bool log) {
1491 auto setEnv = [&](bool enable) {
1492 Config c;
1494 str << "[reduce_relay]\n"
1495 << "vp_enable=" << enable << "\n"
1496 << "[compression]\n"
1497 << "1\n";
1498 c.loadFromString(str.str());
1499 env_.app().config().VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE = c.VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE;
1500
1501 env_.app().config().COMPRESSION = c.COMPRESSION;
1502 };
1503 auto handshake = [&](int outboundEnable, int inboundEnable) {
1504 beast::IP::Address addr = boost::asio::ip::make_address("172.1.1.100");
1505
1506 setEnv(outboundEnable);
1507 auto request = xrpl::makeRequest(
1508 true,
1509 env_.app().config().COMPRESSION,
1510 false,
1511 env_.app().config().TX_REDUCE_RELAY_ENABLE,
1512 env_.app().config().VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE);
1513 http_request_type http_request;
1514 http_request.version(request.version());
1515 http_request.base() = request.base();
1516 // feature enabled on the peer's connection only if both sides
1517 // are enabled
1518 auto const peerEnabled = inboundEnable && outboundEnable;
1519 // inbound is enabled if the request's header has the feature
1520 // enabled and the peer's configuration is enabled
1521 auto const inboundEnabled = peerFeatureEnabled(http_request, FEATURE_VPRR, inboundEnable);
1522 BEAST_EXPECT(!(peerEnabled ^ inboundEnabled));
1523
1524 setEnv(inboundEnable);
1525 auto http_resp = xrpl::makeResponse(true, http_request, addr, addr, uint256{1}, 1, {1, 0}, env_.app());
1526 // outbound is enabled if the response's header has the feature
1527 // enabled and the peer's configuration is enabled
1528 auto const outboundEnabled = peerFeatureEnabled(http_resp, FEATURE_VPRR, outboundEnable);
1529 BEAST_EXPECT(!(peerEnabled ^ outboundEnabled));
1530 };
1531 handshake(1, 1);
1532 handshake(1, 0);
1533 handshake(0, 1);
1534 handshake(0, 0);
1535 });
1536 }
1537
1540
1541public:
1543 : env_(*this, jtx::envconfig([](std::unique_ptr<Config> cfg) {
1544 cfg->VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE = true;
1545 cfg->VP_REDUCE_RELAY_SQUELCH_MAX_SELECTED_PEERS = 6;
1546 return cfg;
1547 }))
1548 , network_(env_.app())
1549 {
1550 }
1551
1552 void
1553 run() override
1554 {
1555 bool log = false;
1556 testConfig(log);
1557 testInitialRound(log);
1558 testPeerUnsquelchedTooSoon(log);
1559 testPeerUnsquelched(log);
1560 testNewPeer(log);
1561 testSquelchedPeerDisconnects(log);
1562 testSelectedPeerDisconnects(log);
1563 testSelectedPeerStopsRelaying(log);
1564 testInternalHashRouter(log);
1565 testRandomSquelch(log);
1566 testHandshake(log);
1567 testBaseSquelchReady(log);
1568 }
1569};
1570
1572{
1573 void
1574 testRandom(bool log)
1575 {
1576 doTest("Random Test", log, [&](bool log) { random(log); });
1577 }
1578
1579 void
1580 run() override
1581 {
1582 bool log = false;
1583 testRandom(log);
1584 }
1585};
1586
1587BEAST_DEFINE_TESTSUITE(reduce_relay, overlay, xrpl);
1588BEAST_DEFINE_TESTSUITE_MANUAL(reduce_relay_simulate, overlay, xrpl);
1589
1590} // namespace test
1591
1592} // namespace xrpl
T back_inserter(T... args)
T begin(T... args)
Represents a JSON value.
Definition json_value.h:131
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:145
virtual Config & config()=0
bool COMPRESSION
Definition Config.h:201
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
Definition Config.cpp:440
bool VP_REDUCE_RELAY_BASE_SQUELCH_ENABLE
Definition Config.h:229
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:134
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.
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...
void for_rand(std::uint32_t min, std::uint32_t max, std::function< void(std::uint32_t)> f)
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)
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
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:98
Application & app()
Definition Env.h:230
Set the fee on a JTx.
Definition fee.h:18
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.
void random(bool log)
Randomly brings the link between a validator and a peer down.
void testSquelchedPeerDisconnects(bool log)
Squelched peer disconnects.
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 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 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
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:35
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::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
KeyType
Definition KeyType.h:9
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:322
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:13
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:169
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:738
static constexpr char FEATURE_VPRR[]
Definition Handshake.h:121
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)