xrpld
Loading...
Searching...
No Matches
reduce_relay_test.cpp
1#include <test/jtx/Env.h>
2#include <test/jtx/envconfig.h>
3
4#include <xrpld/app/main/Application.h>
5#include <xrpld/overlay/Message.h>
6#include <xrpld/overlay/Peer.h>
7#include <xrpld/overlay/ReduceRelayCommon.h>
8#include <xrpld/overlay/Slot.h>
9#include <xrpld/overlay/Squelch.h>
10#include <xrpld/overlay/detail/Handshake.h>
11
12#include <xrpl/basics/base_uint.h>
13#include <xrpl/basics/random.h>
14#include <xrpl/beast/net/IPAddress.h>
15#include <xrpl/beast/net/IPEndpoint.h>
16#include <xrpl/beast/unit_test/suite.h>
17#include <xrpl/beast/utility/Journal.h>
18#include <xrpl/json/json_value.h>
19#include <xrpl/protocol/KeyType.h>
20#include <xrpl/protocol/PublicKey.h>
21#include <xrpl/protocol/SecretKey.h>
22
23#include <boost/asio/ip/address.hpp>
24
25#include <xrpl.pb.h>
26
27#include <algorithm>
28#include <cassert>
29#include <chrono>
30#include <cstddef>
31#include <cstdint>
32#include <functional>
33#include <iostream>
34#include <iterator>
35#include <memory>
36#include <numeric>
37#include <optional>
38#include <random>
39#include <ratio>
40#include <set>
41#include <sstream>
42#include <stdexcept>
43#include <string>
44#include <tuple>
45#include <unordered_map>
46#include <utility>
47#include <vector>
48
49namespace xrpl::test {
50
51using namespace std::chrono;
52
53class Link;
54
60using UnsquelchCB = std::function<void(PublicKey const&, PeerWPtr const&)>;
62
63static constexpr std::uint32_t kMaxPeers = 10;
64static constexpr std::uint32_t kMaxValidators = 10;
65static constexpr std::uint32_t kMaxMessages = 200000;
66
71class PeerPartial : public Peer
72{
73public:
77
79 ~PeerPartial() override = default;
80 virtual void
82 virtual void
83 onMessage(protocol::TMSquelch const& squelch) = 0;
84 void
85 send(protocol::TMSquelch const& squelch)
86 {
88 }
89
90 // dummy implementation
91 void
92 send(std::shared_ptr<Message> const& m) override
93 {
94 }
95 [[nodiscard]] beast::ip::Endpoint
96 getRemoteAddress() const override
97 {
98 return {};
99 }
100 void
101 charge(resource::Charge const& fee, std::string const& context = {}) override
102 {
103 }
104 [[nodiscard]] bool
105 cluster() const override
106 {
107 return false;
108 }
109 [[nodiscard]] bool
110 isHighLatency() const override
111 {
112 return false;
113 }
114 [[nodiscard]] int
115 getScore(bool) const override
116 {
117 return 0;
118 }
119 [[nodiscard]] PublicKey const&
120 getNodePublic() const override
121 {
122 return nodePublicKey;
123 }
125 json() override
126 {
127 return {};
128 }
129 [[nodiscard]] bool
131 {
132 return false;
133 }
134 [[nodiscard]] std::optional<std::size_t>
135 publisherListSequence(PublicKey const&) const override
136 {
137 return {};
138 }
139 void
141 {
142 }
143 [[nodiscard]] uint256
144 getClosedLedgerHash() const override
145 {
146 static uint256 const kHash{};
147 return kHash;
148 }
149 [[nodiscard]] bool
150 hasLedger(uint256 const& hash, std::uint32_t seq) const override
151 {
152 return false;
153 }
154 void
155 ledgerRange(std::uint32_t& minSeq, std::uint32_t& maxSeq) const override
156 {
157 }
158 [[nodiscard]] bool
159 hasTxSet(uint256 const& hash) const override
160 {
161 return false;
162 }
163 void
164 cycleStatus() override
165 {
166 }
167 bool
169 {
170 return false;
171 }
172 [[nodiscard]] bool
173 compressionEnabled() const override
174 {
175 return false;
176 }
177 [[nodiscard]] bool
178 txReduceRelayEnabled() const override
179 {
180 return false;
181 }
182 void
183 sendTxQueue() override
184 {
185 }
186 void
187 addTxQueue(uint256 const&) override
188 {
189 }
190 void
191 removeTxQueue(uint256 const&) override
192 {
193 }
194};
195
200{
201public:
202 using rep = uint64_t;
206 inline static bool const is_steady = false; // NOLINT(readability-identifier-naming)
207
208 static void
209 advance(duration d) noexcept
210 {
211 kNow += d;
212 }
213
214 static void
219
220 static void
221 reset() noexcept
222 {
223 kNow = time_point(seconds(0));
224 }
225
226 static time_point
227 now() noexcept
228 {
229 return kNow;
230 }
231
232 static duration
234 {
235 return duration(milliseconds(randInt(min.count(), max.count())));
236 }
237
238 explicit ManualClock() = default;
239
240private:
241 inline static time_point kNow = time_point(seconds(0));
242};
243
248{
249public:
250 Overlay() = default;
251 virtual ~Overlay() = default;
252
253 virtual void
255 uint256 const& key,
256 PublicKey const& validator,
257 Peer::id_t id,
258 SquelchCB f,
259 protocol::MessageType type = protocol::mtVALIDATION) = 0;
260
261 virtual void deleteIdlePeers(UnsquelchCB) = 0;
262
264};
265
266class Validator;
267
272class Link
273{
275
276public:
278 : validator_(validator), peer_(peer), latency_(std::move(latency))
279 {
280 auto sp = peer_.lock();
281 assert(sp);
282 }
283 ~Link() = default;
284 void
286 {
287 if (!up_)
288 return;
289 auto sp = peer_.lock();
290 assert(sp);
292 peer->onMessage(m, f);
293 }
294 Validator&
296 {
297 return validator_;
298 }
299 void
300 up(bool linkUp)
301 {
302 up_ = linkUp;
303 }
306 {
307 auto p = peer_.lock();
308 assert(p);
309 return p->id();
310 }
313 {
314 auto p = peer_.lock();
315 assert(p);
316 return p;
317 }
318
319private:
323 bool up_{true};
324};
325
330{
332
333public:
335 {
336 protocol::TMValidation v;
337 v.set_validation("validation");
338 message_ = std::make_shared<Message>(v, protocol::mtVALIDATION, pkey_);
339 }
340 Validator(Validator const&) = default;
341 Validator(Validator&&) = default;
342 Validator&
343 operator=(Validator const&) = default;
344 Validator&
345 operator=(Validator&&) = default;
347 {
348 clear();
349 }
350
351 void
353 {
354 links_.clear();
355 }
356
357 static void
359 {
360 sid = 0;
361 }
362
363 PublicKey const&
365 {
366 return pkey_;
367 }
368
369 operator PublicKey() const
370 {
371 return pkey_;
372 }
373
374 void
376 {
377 links_.emplace(std::make_pair(peer->id(), std::make_shared<Link>(*this, peer)));
378 }
379
380 void
382 {
383 links_.erase(id);
384 }
385
386 void
388 {
389 for (auto id : peers)
390 {
391 assert(links_.contains(id));
392 f(*links_[id], message_);
393 }
394 }
395
396 void
397 forLinks(LinkIterCB f, bool simulateSlow = false)
398 {
400 std::ranges::transform(links_, std::back_inserter(v), [](auto& kv) { return kv.second; });
402 std::mt19937 g(d());
403 std::shuffle(v.begin(), v.end(), g);
404
405 for (auto& link : v)
406 {
407 f(*link, message_);
408 }
409 }
410
414 void
416 {
417 forLinks(peers, [&](Link& link, MessageSPtr m) { link.send(m, f); });
418 }
419
423 void
425 {
426 forLinks([&](Link& link, MessageSPtr m) { link.send(m, f); });
427 }
428
431 {
432 return message_;
433 }
434
435 [[nodiscard]] std::uint16_t
436 id() const
437 {
438 return id_;
439 }
440
441 void
443 {
444 auto it = links_.find(id);
445 assert(it != links_.end());
446 it->second->up(true);
447 }
448
449 void
451 {
452 auto it = links_.find(id);
453 assert(it != links_.end());
454 it->second->up(false);
455 }
456
457private:
461 inline static std::uint16_t sid = 0;
463};
464
465class PeerSim : public PeerPartial, public std::enable_shared_from_this<PeerSim>
466{
467public:
469 PeerSim(Overlay& overlay, beast::Journal journal) : overlay_(overlay), squelch_(journal)
470 {
471 }
472
473 ~PeerSim() override = default;
474
475 id_t
476 id() const override
477 {
478 return id_;
479 }
480
481 std::string const&
482 fingerprint() const override
483 {
484 return fingerprint_;
485 }
486
487 static void
489 {
490 sid = 0;
491 }
492
496 void
497 onMessage(MessageSPtr const& m, SquelchCB f) override
498 {
499 auto validator = m->getValidatorKey();
500 assert(validator);
501 if (!squelch_.expireSquelch(*validator)) // NOLINT(bugprone-unchecked-optional-access)
502 return;
503
504 overlay_.updateSlotAndSquelch(
505 {}, *validator, id(), f); // NOLINT(bugprone-unchecked-optional-access)
506 }
507
511 void
512 onMessage(protocol::TMSquelch const& squelch) override
513 {
514 auto validator = squelch.validatorpubkey();
515 PublicKey const key(Slice(validator.data(), validator.size()));
516 if (squelch.squelch())
517 {
518 squelch_.addSquelch(key, std::chrono::seconds{squelch.squelchduration()});
519 }
520 else
521 {
522 squelch_.removeSquelch(key);
523 }
524 }
525
526private:
527 inline static id_t sid = 0;
532};
533
535{
537
538public:
541 OverlaySim(Application& app) : slots_(app, *this, app.config()), registry_(app)
542 {
543 }
544
545 ~OverlaySim() override = default;
546
547 void
549 {
550 peers_.clear();
552 slots_.deleteIdlePeers();
553 }
554
557 {
558 auto res = slots_.inState(validator, state);
559 return res ? *res : 0;
560 }
561
562 void
564 uint256 const& key,
565 PublicKey const& validator,
566 Peer::id_t id,
567 SquelchCB f,
568 protocol::MessageType type = protocol::mtVALIDATION) override
569 {
570 squelch_ = f;
571 slots_.updateSlotAndSquelch(key, validator, id, type);
572 }
573
574 void
576 {
577 unsquelch_ = f;
578 slots_.deletePeer(id, true);
579 }
580
581 void
583 {
584 unsquelch_ = f;
585 slots_.deleteIdlePeers();
586 }
587
589 addPeer(bool useCache = true)
590 {
591 PeerSPtr peer{};
592 Peer::id_t id = 0;
593 if (peersCache_.empty() || !useCache)
594 {
595 peer = std::make_shared<PeerSim>(*this, registry_.getJournal("Squelch"));
596 id = peer->id();
597 }
598 else
599 {
600 auto it = peersCache_.begin();
601 peer = it->second;
602 id = it->first;
603 peersCache_.erase(it);
604 }
605 peers_.emplace(std::make_pair(id, peer));
606 return peer;
607 }
608
609 void
610 deletePeer(Peer::id_t id, bool useCache = true)
611 {
612 auto it = peers_.find(id);
613 assert(it != peers_.end());
614 deletePeer(id, [&](PublicKey const&, PeerWPtr) {});
615 if (useCache)
616 peersCache_.emplace(std::make_pair(id, it->second));
617 peers_.erase(it);
618 }
619
620 void
622 {
623 while (!peers_.empty())
624 deletePeer(peers_.begin()->first);
625 while (!peersCache_.empty())
626 addPeer();
627 }
628
631 {
632 if (peers_.empty())
633 return {};
634
635 std::uint8_t maxId = 0;
636
637 for (auto& [id, _] : peers_)
638 {
639 (void)_;
640 maxId = std::max<unsigned int>(id, maxId);
641 }
642
643 deletePeer(maxId, false);
644
645 return maxId;
646 }
647
648 bool
653
656 {
657 return slots_.getSelected(validator);
658 }
659
660 bool
662 {
663 auto selected = slots_.getSelected(validator);
664 return selected.contains(peer);
665 }
666
667 id_t
669 {
670 auto selected = slots_.getSelected(validator);
671 assert(!selected.empty());
672 return *selected.begin();
673 }
674
676 id_t,
679 {
680 return slots_.getPeers(validator);
681 }
682
685 {
686 return peers_.size();
687 }
688
689private:
690 void
691 squelch(PublicKey const& validator, Peer::id_t id, std::uint32_t squelchDuration) const override
692 {
693 if (auto it = peers_.find(id); it != peers_.end())
694 squelch_(validator, it->second, squelchDuration);
695 }
696 void
697 unsquelch(PublicKey const& validator, Peer::id_t id) const override
698 {
699 if (auto it = peers_.find(id); it != peers_.end())
700 unsquelch_(validator, it->second);
701 }
708};
709
711{
712public:
714 {
715 init();
716 }
717
718 void
720 {
722 for (int p = 0; p < kMaxPeers; p++)
723 {
724 auto peer = overlay_.addPeer();
725 for (auto& v : validators_)
726 v.addPeer(peer);
727 }
728 }
729
730 ~Network() = default;
731
732 void
734 {
735 validators_.clear();
736 overlay_.clear();
739 init();
740 }
741
744 {
745 auto peer = overlay_.addPeer();
746 for (auto& v : validators_)
747 v.addPeer(peer);
748 return peer->id();
749 }
750
751 void
753 {
754 auto id = overlay_.deleteLastPeer();
755
756 if (!id)
757 return;
758
759 for (auto& validator : validators_)
760 validator.deletePeer(*id);
761 }
762
763 void
765 {
766 while (overlay_.getNumPeers() > kMaxPeers)
768 }
769
770 Validator&
772 {
773 assert(v < validators_.size());
774 return validators_[v];
775 }
776
779 {
780 return overlay_;
781 }
782
783 void
784 enableLink(std::uint16_t validatorId, Peer::id_t peer, bool enable)
785 {
786 auto it = std::ranges::find_if(validators_, [&](auto& v) { return v.id() == validatorId; });
787 assert(it != validators_.end());
788 if (enable)
789 {
790 it->linkUp(peer);
791 }
792 else
793 {
794 it->linkDown(peer);
795 }
796 }
797
798 void
800 {
801 // Send unsquelch to the Peer on all links. This way when
802 // the Peer "reconnects" it starts sending messages on the link.
803 // We expect that if a Peer disconnects and then reconnects, it's
804 // unsquelched.
805 protocol::TMSquelch squelch;
806 squelch.set_squelch(false);
807 for (auto& v : validators_)
808 {
809 PublicKey const key = v;
810 squelch.clear_validatorpubkey();
811 squelch.set_validatorpubkey(key.data(), key.size());
812 v.forLinks({peer}, [&](Link& l, MessageSPtr) {
814 });
815 }
816 }
817
818 static void
820 {
821 auto size = max - min;
823 std::iota(s.begin(), s.end(), min); // NOLINT(modernize-use-ranges)
825 std::mt19937 g(d());
826 std::shuffle(s.begin(), s.end(), g);
827 for (auto v : s)
828 f(v);
829 }
830
831 void
833 LinkIterCB link,
834 std::uint16_t nValidators = kMaxValidators,
835 std::uint32_t nMessages = kMaxMessages,
836 bool purge = true,
837 bool resetClock = true)
838 {
839 if (resetClock)
841
842 if (purge)
843 {
844 purgePeers();
845 overlay_.resetPeers();
846 }
847
848 for (int m = 0; m < nMessages; ++m)
849 {
851 forRand(0, nValidators, [&](std::uint32_t v) { validators_[v].forLinks(link); });
852 }
853 }
854
858 bool
860 {
861 return std::ranges::any_of(
862 validators_, [&](auto& v) { return overlay_.isSelected(v, id); });
863 }
864
870 bool
872 {
873 for (auto& v : validators_)
874 {
875 if (!overlay_.isSelected(v, peer))
876 continue;
877 auto peers = overlay_.getPeers(v);
878 for (auto& [_, v] : peers)
879 {
880 (void)_;
881 if (std::get<reduce_relay::PeerState>(v) == reduce_relay::PeerState::Squelched)
882 return false;
883 }
884 }
885 return true;
886 }
887
888private:
891};
892
894{
897
898protected:
899 void
901 {
902 auto peers = network_.overlay().getPeers(network_.validator(validator));
903 std::cout << msg << " "
904 << "num peers " << (int)network_.overlay().getNumPeers() << std::endl;
905 for (auto& [k, v] : peers)
906 std::cout << k << ":" << (int)std::get<reduce_relay::PeerState>(v) << " ";
908 }
909
913 static Peer::id_t
915 PublicKey const& validator,
916 PeerWPtr const& peerPtr,
918 {
919 protocol::TMSquelch squelch;
920 bool const res = static_cast<bool>(duration);
921 squelch.set_squelch(res);
922 squelch.set_validatorpubkey(validator.data(), validator.size());
923 if (res)
924 squelch.set_squelchduration(*duration);
925 auto sp = peerPtr.lock();
926 assert(sp);
928 return sp->id();
929 }
930
931 enum class State { On, Off, WaitReset };
932 enum class EventType { LinkDown = 0, PeerDisconnected = 1 };
933 // Link down or Peer disconnect event
934 // TBD - add new peer event
935 // TBD - add overlapping type of events at any
936 // time in any quantity
949
954 void
956 {
960
961 network_.reset();
962 network_.propagate([&](Link& link, MessageSPtr m) {
963 auto& validator = link.validator();
964 auto now = ManualClock::now();
965
966 bool squelched = false;
968
969 link.send(
970 m, [&](PublicKey const& key, PeerWPtr const& peerPtr, std::uint32_t duration) {
971 assert(key == validator);
972 auto p = sendSquelch(key, peerPtr, duration);
973 squelched = true;
974 str << p << " ";
975 });
976
977 if (squelched)
978 {
979 auto selected = network_.overlay().getSelected(validator);
980 str << " selected: ";
981 for (auto s : selected)
982 str << s << " ";
983 if (log)
984 {
985 std::cout << (double)reduce_relay::epoch<milliseconds>(now).count() / 1000.
986 << " random, squelched, validator: " << validator.id()
987 << " peers: " << str.str() << std::endl;
988 }
989 auto countingState = network_.overlay().isCountingState(validator);
990 BEAST_EXPECT(
991 countingState == false &&
992 selected.size() == env_.app().config().vpReduceRelaySquelchMaxSelectedPeers);
993 }
994
995 // Trigger Link Down or Peer Disconnect event
996 // Only one Link Down at a time
997 if (events[EventType::LinkDown].state == State::Off)
998 {
999 auto update = [&](EventType event) {
1000 events[event].cnt++;
1001 events[event].validator = validator.id();
1002 events[event].key = validator;
1003 events[event].peer = link.peerId();
1004 events[event].state = State::On;
1005 events[event].time = now;
1006 if (event == EventType::LinkDown)
1007 {
1008 network_.enableLink(validator.id(), link.peerId(), false);
1009 events[event].isSelected =
1010 network_.overlay().isSelected(validator, link.peerId());
1011 }
1012 else
1013 {
1014 events[event].isSelected = network_.isSelected(link.peerId());
1015 }
1016 };
1017 auto r = randInt(0, 1000);
1018 if (r == (int)EventType::LinkDown || r == (int)EventType::PeerDisconnected)
1019 {
1020 update(static_cast<EventType>(r));
1021 }
1022 }
1023
1024 if (events[EventType::PeerDisconnected].state == State::On)
1025 {
1026 auto& event = events[EventType::PeerDisconnected];
1027 bool const allCounting = network_.allCounting(event.peer);
1028 network_.overlay().deletePeer(
1029 event.peer, [&](PublicKey const& v, PeerWPtr const& peerPtr) {
1030 if (event.isSelected)
1031 sendSquelch(v, peerPtr, {});
1032 event.handled = true;
1033 });
1034 // Should only be unsquelched if the peer is in Selected state
1035 // If in Selected state it's possible unsquelching didn't
1036 // take place because there is no peers in Squelched state in
1037 // any of the slots where the peer is in Selected state
1038 // (allCounting is true)
1039 bool const handled = (!event.isSelected && !event.handled) ||
1040 (event.isSelected && (event.handled || allCounting));
1041 BEAST_EXPECT(handled);
1042 event.state = State::Off;
1043 event.isSelected = false;
1044 event.handledCnt += handled;
1045 event.handled = false;
1046 network_.onDisconnectPeer(event.peer);
1047 }
1048
1049 auto& event = events[EventType::LinkDown];
1050 // Check every sec for idled peers. Idled peers are
1051 // created by Link Down event.
1052 if (now - lastCheck > milliseconds(1000))
1053 {
1054 lastCheck = now;
1055 // Check if Link Down event must be handled by
1056 // deleteIdlePeer(): 1) the peer is in Selected state;
1057 // 2) the peer has not received any messages for IDLED time;
1058 // 3) there are peers in Squelched state in the slot.
1059 // 4) peer is in Slot's peers_ (if not then it is deleted
1060 // by Slots::deleteIdlePeers())
1061 bool mustHandle = false;
1062 if (event.state == State::On && BEAST_EXPECT(event.key))
1063 {
1064 event.isSelected = network_.overlay().isSelected(*event.key, event.peer);
1065 auto peers = network_.overlay().getPeers(*event.key);
1066 auto d = reduce_relay::epoch<milliseconds>(now).count() -
1067 std::get<3>(peers[event.peer]);
1068 mustHandle = event.isSelected &&
1070 network_.overlay().inState(*event.key, reduce_relay::PeerState::Squelched) >
1071 0 &&
1072 peers.contains(event.peer);
1073 }
1074 network_.overlay().deleteIdlePeers([&](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 const handled = (event.handled && event.state == State::WaitReset) ||
1083 (!event.handled && !mustHandle);
1084 BEAST_EXPECT(handled);
1085 }
1086 if (event.state == State::WaitReset ||
1087 (event.state == State::On &&
1088 (now - event.time > (reduce_relay::kIdled + seconds(2)))))
1089 {
1090 bool const handled = event.state == State::WaitReset || !event.handled;
1091 BEAST_EXPECT(handled);
1092 event.state = State::Off;
1093 event.isSelected = false;
1094 event.handledCnt += handled;
1095 event.handled = false;
1096 network_.enableLink(event.validator, event.peer, true);
1097 }
1098 });
1099
1100 auto& down = events[EventType::LinkDown];
1101 auto& disconnected = events[EventType::PeerDisconnected];
1102 // It's possible the last Down Link event is not handled
1103 BEAST_EXPECT(down.handledCnt >= down.cnt - 1);
1104 // All Peer Disconnect events must be handled
1105 BEAST_EXPECT(disconnected.cnt == disconnected.handledCnt);
1106 if (log)
1107 {
1108 std::cout << "link down count: " << down.cnt << "/" << down.handledCnt
1109 << " peer disconnect count: " << disconnected.cnt << "/"
1110 << disconnected.handledCnt;
1111 }
1112 }
1113
1114 bool
1115 checkCounting(PublicKey const& validator, bool isCountingState)
1116 {
1117 auto countingState = network_.overlay().isCountingState(validator);
1118 BEAST_EXPECT(countingState == isCountingState);
1119 return countingState == isCountingState;
1120 }
1121
1122 void
1123 doTest(std::string const& msg, bool log, std::function<void(bool)> f)
1124 {
1125 testcase(msg);
1126 f(log);
1127 }
1128
1135 void
1137 {
1138 doTest("Initial Round", log, [this](bool log) { BEAST_EXPECT(propagateAndSquelch(log)); });
1139 }
1140
1145 void
1147 {
1148 doTest("Peer Unsquelched Too Soon", log, [this](bool log) {
1149 BEAST_EXPECT(propagateNoSquelch(log, 1, false, false, false));
1150 });
1151 }
1152
1157 void
1159 {
1161 doTest("Peer Unsquelched", log, [this](bool log) {
1162 BEAST_EXPECT(propagateNoSquelch(log, 2, true, true, false));
1163 });
1164 }
1165
1169 bool
1170 propagateAndSquelch(bool log, bool purge = true, bool resetClock = true)
1171 {
1172 int n = 0;
1173 network_.propagate(
1174 [&](Link& link, MessageSPtr message) {
1175 std::uint16_t squelched = 0;
1176 link.send(
1177 message,
1178 [&](PublicKey const& key, PeerWPtr const& peerPtr, std::uint32_t duration) {
1179 squelched++;
1180 sendSquelch(key, peerPtr, duration);
1181 });
1182 if (squelched)
1183 {
1184 BEAST_EXPECT(
1185 squelched ==
1186 kMaxPeers - env_.app().config().vpReduceRelaySquelchMaxSelectedPeers);
1187 n++;
1188 }
1189 },
1190 1,
1192 purge,
1193 resetClock);
1194 auto selected = network_.overlay().getSelected(network_.validator(0));
1195 BEAST_EXPECT(selected.size() == env_.app().config().vpReduceRelaySquelchMaxSelectedPeers);
1196 BEAST_EXPECT(n == 1); // only one selection round
1197 auto res = checkCounting(network_.validator(0), false);
1198 BEAST_EXPECT(res);
1199 return n == 1 && res;
1200 }
1201
1205 bool
1207 bool log,
1208 std::uint16_t nMessages,
1209 bool countingState,
1210 bool purge = true,
1211 bool resetClock = true)
1212 {
1213 bool squelched = false;
1214 network_.propagate(
1215 [&](Link& link, MessageSPtr message) {
1216 link.send(
1217 message,
1218 [&](PublicKey const& key, PeerWPtr const& peerPtr, std::uint32_t duration) {
1219 squelched = true;
1220 BEAST_EXPECT(false);
1221 });
1222 },
1223 1,
1224 nMessages,
1225 purge,
1226 resetClock);
1227 auto res = checkCounting(network_.validator(0), countingState);
1228 return !squelched && res;
1229 }
1230
1235 void
1237 {
1238 doTest("New Peer", log, [this](bool log) {
1239 BEAST_EXPECT(propagateAndSquelch(log, true, false));
1240 network_.addPeer();
1241 BEAST_EXPECT(propagateNoSquelch(log, 1, true, false, false));
1242 });
1243 }
1244
1249 void
1251 {
1252 doTest("Selected Peer Disconnects", log, [this](bool log) {
1254 BEAST_EXPECT(propagateAndSquelch(log, true, false));
1255 auto id = network_.overlay().getSelectedPeer(network_.validator(0));
1256 std::uint16_t unsquelched = 0;
1257 network_.overlay().deletePeer(
1258 id, [&](PublicKey const& key, PeerWPtr const& peer) { unsquelched++; });
1259 BEAST_EXPECT(
1260 unsquelched ==
1261 kMaxPeers - env_.app().config().vpReduceRelaySquelchMaxSelectedPeers);
1262 BEAST_EXPECT(checkCounting(network_.validator(0), true));
1263 });
1264 }
1265
1270 void
1272 {
1273 doTest("Selected Peer Stops Relaying", log, [this](bool log) {
1275 BEAST_EXPECT(propagateAndSquelch(log, true, false));
1277 std::uint16_t unsquelched = 0;
1278 network_.overlay().deleteIdlePeers(
1279 [&](PublicKey const& key, PeerWPtr const& peer) { unsquelched++; });
1280 auto peers = network_.overlay().getPeers(network_.validator(0));
1281 BEAST_EXPECT(
1282 unsquelched ==
1283 kMaxPeers - env_.app().config().vpReduceRelaySquelchMaxSelectedPeers);
1284 BEAST_EXPECT(checkCounting(network_.validator(0), true));
1285 });
1286 }
1287
1291 void
1293 {
1294 doTest("Squelched Peer Disconnects", log, [this](bool log) {
1296 BEAST_EXPECT(propagateAndSquelch(log, true, false));
1297 auto peers = network_.overlay().getPeers(network_.validator(0));
1298 auto it = std::ranges::find_if(peers, [&](auto it) {
1299 return std::get<reduce_relay::PeerState>(it.second) ==
1301 });
1302 assert(it != peers.end());
1303 std::uint16_t unsquelched = 0;
1304 network_.overlay().deletePeer(
1305 it->first, [&](PublicKey const& key, PeerWPtr const& peer) { unsquelched++; });
1306 BEAST_EXPECT(unsquelched == 0);
1307 BEAST_EXPECT(checkCounting(network_.validator(0), false));
1308 });
1309 }
1310
1311 void
1313 {
1314 doTest("Test Config - squelch enabled (legacy)", log, [&](bool log) {
1315 Config c;
1316
1317 std::string const toLoad(R"xrpldConfig(
1318[reduce_relay]
1319vp_enable=1
1320)xrpldConfig");
1321
1322 c.loadFromString(toLoad);
1323 BEAST_EXPECT(c.vpReduceRelayBaseSquelchEnable == true);
1324 });
1325
1326 doTest("Test Config - squelch disabled (legacy)", log, [&](bool log) {
1327 Config c;
1328
1329 std::string toLoad(R"xrpldConfig(
1330[reduce_relay]
1331vp_enable=0
1332)xrpldConfig");
1333
1334 c.loadFromString(toLoad);
1335 BEAST_EXPECT(c.vpReduceRelayBaseSquelchEnable == false);
1336
1337 Config c1;
1338
1339 toLoad = R"xrpldConfig(
1340[reduce_relay]
1341)xrpldConfig";
1342
1343 c1.loadFromString(toLoad);
1344 BEAST_EXPECT(c1.vpReduceRelayBaseSquelchEnable == false);
1345 });
1346
1347 doTest("Test Config - squelch enabled", log, [&](bool log) {
1348 Config c;
1349
1350 std::string const toLoad(R"xrpldConfig(
1351[reduce_relay]
1352vp_base_squelch_enable=1
1353)xrpldConfig");
1354
1355 c.loadFromString(toLoad);
1356 BEAST_EXPECT(c.vpReduceRelayBaseSquelchEnable == true);
1357 });
1358
1359 doTest("Test Config - squelch disabled", log, [&](bool log) {
1360 Config c;
1361
1362 std::string const toLoad(R"xrpldConfig(
1363[reduce_relay]
1364vp_base_squelch_enable=0
1365)xrpldConfig");
1366
1367 c.loadFromString(toLoad);
1368 BEAST_EXPECT(c.vpReduceRelayBaseSquelchEnable == false);
1369 });
1370
1371 doTest("Test Config - legacy and new", log, [&](bool log) {
1372 Config c;
1373
1374 std::string const toLoad(R"xrpldConfig(
1375[reduce_relay]
1376vp_base_squelch_enable=0
1377vp_enable=0
1378)xrpldConfig");
1379
1380 std::string error;
1381 auto const expectedError =
1382 "Invalid reduce_relay"
1383 " cannot specify both vp_base_squelch_enable and vp_enable "
1384 "options. "
1385 "vp_enable was deprecated and replaced by "
1386 "vp_base_squelch_enable";
1387
1388 try
1389 {
1390 c.loadFromString(toLoad);
1391 }
1392 catch (std::runtime_error const& e)
1393 {
1394 error = e.what();
1395 }
1396
1397 BEAST_EXPECT(error == expectedError);
1398 });
1399
1400 doTest("Test Config - max selected peers", log, [&](bool log) {
1401 Config c;
1402
1403 std::string toLoad(R"xrpldConfig(
1404[reduce_relay]
1405)xrpldConfig");
1406
1407 c.loadFromString(toLoad);
1408 BEAST_EXPECT(c.vpReduceRelaySquelchMaxSelectedPeers == 5);
1409
1410 Config c1;
1411
1412 toLoad = R"xrpldConfig(
1413[reduce_relay]
1414vp_base_squelch_max_selected_peers=6
1415)xrpldConfig";
1416
1417 c1.loadFromString(toLoad);
1418 BEAST_EXPECT(c1.vpReduceRelaySquelchMaxSelectedPeers == 6);
1419
1421
1422 toLoad = R"xrpldConfig(
1423[reduce_relay]
1424vp_base_squelch_max_selected_peers=2
1425)xrpldConfig";
1426
1427 std::string error;
1428 auto const expectedError =
1429 "Invalid reduce_relay"
1430 " vp_base_squelch_max_selected_peers must be "
1431 "greater than or equal to 3";
1432 try
1433 {
1434 c2.loadFromString(toLoad);
1435 }
1436 catch (std::runtime_error const& e)
1437 {
1438 error = e.what();
1439 }
1440
1441 BEAST_EXPECT(error == expectedError);
1442 });
1443 }
1444
1445 void
1446 testBaseSquelchReady(bool log)
1447 {
1448 doTest("BaseSquelchReady", log, [&](bool log) {
1450 auto createSlots = [&](bool baseSquelchEnabled) -> reduce_relay::Slots<ManualClock> {
1451 env_.app().config().vpReduceRelayBaseSquelchEnable = baseSquelchEnabled;
1453 env_.app(), network_.overlay(), env_.app().config());
1454 };
1455 // base squelching must not be ready if squelching is disabled
1456 BEAST_EXPECT(!createSlots(false).baseSquelchReady());
1457
1458 // base squelch must not be ready as not enough time passed from
1459 // bootup
1460 BEAST_EXPECT(!createSlots(true).baseSquelchReady());
1461
1463
1464 // base squelch enabled and bootup time passed
1465 BEAST_EXPECT(createSlots(true).baseSquelchReady());
1466
1467 // even if time passed, base squelching must not be ready if turned
1468 // off in the config
1469 BEAST_EXPECT(!createSlots(false).baseSquelchReady());
1470 });
1471 }
1472
1473 void
1474 testInternalHashRouter(bool log)
1475 {
1476 doTest("Duplicate Message", log, [&](bool log) {
1477 network_.reset();
1478 // update message count for the same peer/validator
1479 std::int16_t const nMessages = 5;
1480 for (int i = 0; i < nMessages; i++)
1481 {
1482 uint256 const key(i);
1483 network_.overlay().updateSlotAndSquelch(
1484 key, network_.validator(0), 0, [&](PublicKey const&, PeerWPtr, std::uint32_t) {
1485 });
1487 auto peers = network_.overlay().getPeers(network_.validator(0));
1488 // first message changes Slot state to Counting and is not counted,
1489 // hence '-1'.
1490 BEAST_EXPECT(std::get<1>(peers[0]) == (nMessages - 1));
1491 // add duplicate
1492 uint256 const key(nMessages - 1);
1493 network_.overlay().updateSlotAndSquelch(
1494 key, network_.validator(0), 0, [&](PublicKey const&, PeerWPtr, std::uint32_t) {});
1495 // confirm the same number of messages
1496 peers = network_.overlay().getPeers(network_.validator(0));
1497 BEAST_EXPECT(std::get<1>(peers[0]) == (nMessages - 1));
1498 // advance the clock
1500 network_.overlay().updateSlotAndSquelch(
1501 key, network_.validator(0), 0, [&](PublicKey const&, PeerWPtr, std::uint32_t) {});
1502 peers = network_.overlay().getPeers(network_.validator(0));
1503 // confirm message number increased
1504 BEAST_EXPECT(std::get<1>(peers[0]) == nMessages);
1505 });
1506 }
1507
1508 struct Handler : public reduce_relay::SquelchHandler
1509 {
1510 Handler() = default;
1511 void
1512 squelch(PublicKey const&, Peer::id_t, std::uint32_t duration) const override
1513 {
1514 maxDuration = std::max<uint32_t>(duration, maxDuration);
1515 }
1516 void
1517 unsquelch(PublicKey const&, Peer::id_t) const override
1518 {
1519 }
1520 mutable int maxDuration{0};
1521 };
1522
1523 void
1524 testRandomSquelch(bool l)
1525 {
1526 doTest("Random Squelch", l, [&](bool l) {
1527 PublicKey validator = std::get<0>(randomKeyPair(KeyType::Ed25519));
1528 Handler handler;
1529
1530 auto run = [&](int npeers) {
1531 handler.maxDuration = 0;
1532 reduce_relay::Slots<ManualClock> slots(env_.app(), handler, env_.app().config());
1533 // 1st message from a new peer switches the slot
1534 // to counting state and resets the counts of all peers +
1535 // MAX_MESSAGE_THRESHOLD + 1 messages to reach the threshold
1536 // and switch the slot's state to peer selection.
1537 for (int m = 1; m <= reduce_relay::kMaxMessageThreshold + 2; m++)
1538 {
1539 for (int peer = 0; peer < npeers; peer++)
1540 {
1541 // make unique message hash to make the
1542 // slot's internal hash router accept the message
1543 std::uint64_t const mid = (m * 1000) + peer;
1544 uint256 const message{mid};
1545 slots.updateSlotAndSquelch(
1546 message, validator, peer, protocol::MessageType::mtVALIDATION);
1547 }
1548 }
1549 // make Slot's internal hash router expire all messages
1551 };
1552
1553 using namespace reduce_relay;
1554 // expect max duration less than kMaxUnsquelchExpireDefault with
1555 // less than or equal to 60 peers
1556 run(20);
1557 BEAST_EXPECT(
1558 handler.maxDuration >= kMinUnsquelchExpire.count() &&
1559 handler.maxDuration <= kMaxUnsquelchExpireDefault.count());
1560 run(60);
1561 BEAST_EXPECT(
1562 handler.maxDuration >= kMinUnsquelchExpire.count() &&
1563 handler.maxDuration <= kMaxUnsquelchExpireDefault.count());
1564 // expect max duration greater than kMinUnsquelchExpire and less
1565 // than kMaxUnsquelchExpirePeers with peers greater than 60
1566 // and less than 360
1567 run(350);
1568 // can't make this condition stronger. squelch
1569 // duration is probabilistic and max condition may still fail.
1570 // log when the value is low
1571 BEAST_EXPECT(
1572 handler.maxDuration >= kMinUnsquelchExpire.count() &&
1573 handler.maxDuration <= kMaxUnsquelchExpirePeers.count());
1574 using namespace beast::unit_test::detail;
1575 if (handler.maxDuration <= kMaxUnsquelchExpireDefault.count())
1576 {
1577 log << makeReason("warning: squelch duration is low", __FILE__, __LINE__)
1578 << std::endl
1579 << std::flush;
1580 }
1581 // more than 400 is still less than kMaxUnsquelchExpirePeers
1582 run(400);
1583 BEAST_EXPECT(
1584 handler.maxDuration >= kMinUnsquelchExpire.count() &&
1585 handler.maxDuration <= kMaxUnsquelchExpirePeers.count());
1586 if (handler.maxDuration <= kMaxUnsquelchExpireDefault.count())
1587 {
1588 log << makeReason("warning: squelch duration is low", __FILE__, __LINE__)
1589 << std::endl
1590 << std::flush;
1591 }
1592 });
1593 }
1594
1595 void
1596 testHandshake(bool log)
1597 {
1598 doTest("Handshake", log, [&](bool log) {
1599 auto setEnv = [&](bool enable) {
1600 Config c;
1601 std::stringstream str;
1602 str << "[reduce_relay]\n"
1603 << "vp_enable=" << enable << "\n"
1604 << "[compression]\n"
1605 << "1\n";
1606 c.loadFromString(str.str());
1607 env_.app().config().vpReduceRelayBaseSquelchEnable =
1608 c.vpReduceRelayBaseSquelchEnable;
1609
1610 env_.app().config().compression = c.compression;
1611 };
1612 auto handshake = [&](int outboundEnable, int inboundEnable) {
1613 beast::ip::Address const addr = boost::asio::ip::make_address("172.1.1.100");
1614
1615 setEnv(outboundEnable);
1616 auto request = xrpl::makeRequest(
1617 true,
1618 env_.app().config().compression,
1619 false,
1620 env_.app().config().txReduceRelayEnable,
1621 env_.app().config().vpReduceRelayBaseSquelchEnable);
1622 http_request_type httpRequest;
1623 httpRequest.version(request.version());
1624 httpRequest.base() = request.base();
1625 // feature enabled on the peer's connection only if both sides
1626 // are enabled
1627 auto const peerEnabled = inboundEnable && outboundEnable;
1628 // inbound is enabled if the request's header has the feature
1629 // enabled and the peer's configuration is enabled
1630 auto const inboundEnabled =
1631 peerFeatureEnabled(httpRequest, kFeatureVprr, inboundEnable);
1632 BEAST_EXPECT(!(peerEnabled ^ inboundEnabled));
1633
1634 setEnv(inboundEnable);
1635 auto httpResp = xrpl::makeResponse(
1636 true, httpRequest, addr, addr, uint256{1}, 1, {1, 0}, env_.app());
1637 // outbound is enabled if the response's header has the feature
1638 // enabled and the peer's configuration is enabled
1639 auto const outboundEnabled =
1640 peerFeatureEnabled(httpResp, kFeatureVprr, outboundEnable);
1641 BEAST_EXPECT(!(peerEnabled ^ outboundEnabled));
1642 };
1643 handshake(1, 1);
1644 handshake(1, 0);
1645 handshake(0, 1);
1646 handshake(0, 0);
1647 });
1648 }
1649
1650 jtx::Env env_;
1651 Network network_;
1652
1653public:
1654 reduce_relay_test()
1655 : env_(*this, jtx::envconfig([](std::unique_ptr<Config> cfg) {
1656 cfg->vpReduceRelayBaseSquelchEnable = true;
1657 cfg->vpReduceRelaySquelchMaxSelectedPeers = 6;
1658 return cfg;
1659 }))
1660 , network_(env_.app())
1661 {
1662 }
1663
1664 void
1665 run() override
1666 {
1667 bool const log = false;
1668 testConfig(log);
1669 testInitialRound(log);
1670 testPeerUnsquelchedTooSoon(log);
1671 testPeerUnsquelched(log);
1672 testNewPeer(log);
1673 testSquelchedPeerDisconnects(log);
1674 testSelectedPeerDisconnects(log);
1675 testSelectedPeerStopsRelaying(log);
1676 testInternalHashRouter(log);
1677 testRandomSquelch(log);
1678 testHandshake(log);
1679 testBaseSquelchReady(log);
1680 }
1681};
1682
1684{
1685 void
1687 {
1688 doTest("Random Test", log, [&](bool log) { random(log); });
1689 }
1690
1691 void
1692 run() override
1693 {
1694 bool const log = false;
1695 testRandom(log);
1696 }
1697};
1698
1700BEAST_DEFINE_TESTSUITE_MANUAL(reduce_relay_simulate, overlay, xrpl);
1701
1702} // namespace xrpl::test
T any_of(T... args)
T back_inserter(T... args)
T begin(T... args)
A generic endpoint for log messages.
Definition Journal.h:44
A version-independent IP address and port combination.
Definition IPEndpoint.h:24
A testsuite class.
Definition suite.h:52
LogOs< char > log
Logging output stream.
Definition suite.h:150
TestcaseT testcase
Memberspace for declaring test cases.
Definition suite.h:155
Represents a JSON value.
Definition json_value.h:117
std::size_t vpReduceRelaySquelchMaxSelectedPeers
////////////////// !
void loadFromString(std::string const &fileContents)
Load the config from the contents of the string.
std::uint32_t id_t
Uniquely identifies a peer.
A public key.
Definition PublicKey.h:53
std::uint8_t const * data() const noexcept
Definition PublicKey.h:79
static std::size_t size() noexcept
Definition PublicKey.h:85
Service registry for dependency injection.
An immutable linear range of bytes.
Definition Slice.h:28
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...
Maintains squelching of relaying messages from validators.
Definition Squelch.h:19
A consumption charge.
Definition Charge.h:13
Manually advanced clock.
static void randAdvance(milliseconds min, milliseconds max)
static duration randDuration(milliseconds min, milliseconds max)
static void advance(duration d) noexcept
std::chrono::time_point< ManualClock > time_point
static void reset() noexcept
static time_point now() noexcept
std::chrono::duration< std::uint32_t, period > duration
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...
static void forRand(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)
void propagate(LinkIterCB link, std::uint16_t nValidators=kMaxValidators, std::uint32_t nMessages=kMaxMessages, bool purge=true, bool resetClock=true)
std::vector< Validator > validators_
Network(Application &app)
Validator & validator(std::uint16_t v)
void onDisconnectPeer(Peer::id_t peer)
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)
std::unordered_map< Peer::id_t, PeerSPtr > Peers
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)
~OverlaySim() override=default
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
uint256 getClosedLedgerHash() const override
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
beast::ip::Endpoint getRemoteAddress() const override
virtual void onMessage(protocol::TMSquelch const &squelch)=0
bool compressionEnabled() const override
virtual void onMessage(MessageSPtr const &m, SquelchCB f)=0
void removeTxQueue(uint256 const &) override
json::Value json() override
std::optional< std::size_t > publisherListSequence(PublicKey const &) const override
bool supportsFeature(ProtocolFeature f) const 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
~PeerPartial() override=default
bool cluster() const override
void charge(resource::Charge const &fee, std::string const &context={}) override
bool hasRange(std::uint32_t uMin, std::uint32_t uMax) 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
~PeerSim() override=default
void onMessage(protocol::TMSquelch const &squelch) override
Remote Peer (Directly connected Peer).
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).
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 send(SquelchCB f)
Send to all peers.
void forLinks(LinkIterCB f, bool simulateSlow=false)
void linkDown(Peer::id_t id)
Validator(Validator const &)=default
void linkUp(Peer::id_t id)
void deletePeer(Peer::id_t id)
void forLinks(std::vector< Peer::id_t > peers, LinkIterCB f)
Validator & operator=(Validator const &)=default
std::unordered_map< Peer::id_t, LinkSPtr > Links
std::uint16_t id() const
Validator(Validator &&)=default
static std::uint16_t sid
PublicKey const & key()
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.
reduce_relay::Slot< ManualClock > Slot
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.
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 end(T... args)
T endl(T... args)
T find_if(T... args)
T flush(T... args)
T iota(T... args)
T lock(T... args)
T log(T... args)
T make_pair(T... args)
T make_shared(T... args)
T max(T... args)
T min(T... args)
boost::asio::ip::address Address
Definition IPAddress.h:20
static std::string makeReason(String const &reason, char const *file, int line)
Definition suite.h:24
STL namespace.
static constexpr uint16_t kMaxMessageThreshold
static constexpr auto kWaitOnBootup
static constexpr auto kIdled
std::unique_ptr< Config > envconfig()
creates and initializes a default configuration for jtx::Env
Definition envconfig.h:37
std::unique_ptr< Config > validator(std::unique_ptr< Config >, std::string const &)
adjust configuration with params needed to be a validator
static constexpr std::uint32_t kMaxMessages
std::function< void(Link &, MessageSPtr)> LinkIterCB
BEAST_DEFINE_TESTSUITE(AMMClawback, app, xrpl)
std::shared_ptr< Peer > PeerSPtr
static constexpr std::uint32_t kMaxPeers
BEAST_DEFINE_TESTSUITE_MANUAL(AMMCalc, app, xrpl)
std::shared_ptr< Message > MessageSPtr
static constexpr std::uint32_t kMaxValidators
std::shared_ptr< Link > LinkSPtr
std::weak_ptr< Peer > PeerWPtr
std::function< void(PublicKey const &, PeerWPtr const &)> UnsquelchCB
std::function< void(PublicKey const &, PeerWPtr const &, std::uint32_t)> SquelchCB
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:354
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.
SecretKey randomSecretKey()
Create a secret key using secure random numbers.
http_response_type makeResponse(bool crawlPublic, http_request_type const &req, beast::ip::Address publicIp, beast::ip::Address remoteIp, uint256 const &sharedValue, std::optional< std::uint32_t > networkID, ProtocolVersion protocol, Application &app)
Make http response.
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:182
constexpr Number squelch(Number const &x, Number const &limit) noexcept
Definition Number.h:907
boost::beast::http::request< boost::beast::http::dynamic_body > http_request_type
Definition Handoff.h:12
BaseUInt< 256 > uint256
Definition base_uint.h:580
static constexpr char kFeatureVprr[]
Definition Handshake.h:127
T dynamic_pointer_cast(T... args)
T shuffle(T... args)
T size(T... args)
T str(T... args)
T transform(T... args)
T what(T... args)