19 #include <ripple/basics/random.h>
20 #include <ripple/beast/unit_test.h>
21 #include <ripple/overlay/Message.h>
22 #include <ripple/overlay/Peer.h>
23 #include <ripple/overlay/Slot.h>
24 #include <ripple/overlay/impl/Handshake.h>
25 #include <ripple/protocol/SecretKey.h>
26 #include <ripple.pb.h>
27 #include <test/jtx/Env.h>
29 #include <boost/thread.hpp>
67 onMessage(protocol::TMSquelch
const& squelch) = 0;
69 send(protocol::TMSquelch
const& squelch)
177 inline static const bool is_steady =
false;
188 now_ += randDuration(min, max);
223 updateSlotAndSquelch(
228 protocol::MessageType type = protocol::mtVALIDATION) = 0;
249 : validator_(validator), peer_(peer), latency_(latency), up_(
true)
251 auto sp = peer_.lock();
260 auto sp = peer_.lock();
262 auto peer = std::dynamic_pointer_cast<PeerPartial>(sp);
263 peer->onMessage(m, f);
278 auto p = peer_.lock();
285 auto p = peer_.lock();
306 protocol::TMValidation v;
307 v.set_validation(
"validation");
308 message_ = std::make_shared<Message>(v, protocol::mtVALIDATION, pkey_);
361 for (
auto id : peers)
363 assert(links_.find(
id) != links_.end());
364 f(*links_[
id], message_);
415 auto it = links_.find(
id);
416 assert(it != links_.end());
417 it->second->up(
true);
423 auto it = links_.find(
id);
424 assert(it != links_.end());
425 it->second->up(
false);
441 : overlay_(overlay), squelch_(journal)
469 overlay_.updateSlotAndSquelch({}, *
validator, id(), f);
476 auto validator = squelch.validatorpubkey();
478 if (squelch.squelch())
482 squelch_.removeSquelch(key);
510 slots_.deleteIdlePeers();
516 auto res = slots_.inState(
validator, state);
517 return res ? *res : 0;
526 protocol::MessageType type = protocol::mtVALIDATION)
override
529 slots_.updateSlotAndSquelch(key,
validator,
id, type);
536 slots_.deletePeer(
id,
true);
543 slots_.deleteIdlePeers();
551 if (peersCache_.empty() || !useCache)
553 peer = std::make_shared<PeerSim>(*
this, app_.journal(
"Squelch"));
558 auto it = peersCache_.begin();
561 peersCache_.erase(it);
570 auto it = peers_.find(
id);
571 assert(it != peers_.end());
581 while (!peers_.empty())
582 deletePeer(peers_.begin()->first);
583 while (!peersCache_.empty())
595 for (
auto& [
id, _] : peers_)
602 deletePeer(maxId,
false);
622 auto selected = slots_.getSelected(
validator);
623 return selected.find(peer) != selected.end();
629 auto selected = slots_.getSelected(
validator);
630 assert(selected.size());
631 return *selected.begin();
649 return peers_.size();
659 if (
auto it = peers_.find(
id); it != peers_.end())
660 squelch_(
validator, it->second, squelchDuration);
665 if (
auto it = peers_.find(
id); it != peers_.end())
690 auto peer = overlay_.addPeer();
691 for (
auto& v : validators_)
711 auto peer = overlay_.addPeer();
712 for (
auto& v : validators_)
720 auto id = overlay_.deleteLastPeer();
732 while (overlay_.getNumPeers() >
MAX_PEERS)
739 assert(v < validators_.size());
740 return validators_[v];
753 std::find_if(validators_.begin(), validators_.end(), [&](
auto& v) {
754 return v.id() == validatorId;
756 assert(it != validators_.end());
770 protocol::TMSquelch squelch;
771 squelch.set_squelch(
false);
772 for (
auto& v : validators_)
775 squelch.clear_validatorpubkey();
776 squelch.set_validatorpubkey(key.
data(), key.
size());
778 std::dynamic_pointer_cast<PeerSim>(l.
getPeer())->send(squelch);
789 auto size = max - min;
805 bool resetClock =
true)
813 overlay_.resetPeers();
816 for (
int m = 0; m < nMessages; ++m)
820 validators_[v].for_links(link);
829 for (
auto& v : validators_)
831 if (overlay_.isSelected(v,
id))
844 for (
auto& v : validators_)
846 if (!overlay_.isSelected(v, peer))
848 auto peers = overlay_.getPeers(v);
849 for (
auto& [_, v] : peers)
852 if (std::get<reduce_relay::PeerState>(v) ==
874 auto peers = network_.overlay().getPeers(network_.validator(
validator));
876 <<
"num peers " << (int)network_.overlay().getNumPeers()
878 for (
auto& [k, v] : peers)
879 std::cout << k <<
":" << (int)std::get<reduce_relay::PeerState>(v)
891 protocol::TMSquelch squelch;
893 squelch.set_squelch(res);
896 squelch.set_squelchduration(*
duration);
897 auto sp = peerPtr.
lock();
899 std::dynamic_pointer_cast<PeerSim>(sp)->send(squelch);
914 bool isSelected_ =
false;
919 bool handled_ =
false;
929 {LinkDown, {}}, {PeerDisconnected, {}}};
937 bool squelched =
false;
946 auto p = sendSquelch(key, peerPtr,
duration);
953 auto selected = network_.overlay().getSelected(
validator);
954 str <<
" selected: ";
955 for (
auto s : selected)
959 << (double)reduce_relay::epoch<milliseconds>(now)
962 <<
" random, squelched, validator: " <<
validator.id()
965 network_.overlay().isCountingState(
validator);
967 countingState ==
false &&
973 if (events[EventType::LinkDown].state_ == State::Off)
976 events[event].cnt_++;
977 events[event].validator_ =
validator.id();
979 events[event].peer_ = link.
peerId();
980 events[event].state_ = State::On;
981 events[event].time_ = now;
982 if (event == EventType::LinkDown)
986 events[event].isSelected_ =
987 network_.overlay().isSelected(
991 events[event].isSelected_ =
992 network_.isSelected(link.
peerId());
995 if (r == (
int)EventType::LinkDown ||
996 r == (
int)EventType::PeerDisconnected)
1002 if (events[EventType::PeerDisconnected].state_ == State::On)
1004 auto&
event = events[EventType::PeerDisconnected];
1005 bool allCounting = network_.allCounting(event.peer_);
1006 network_.overlay().deletePeer(
1009 if (event.isSelected_)
1010 sendSquelch(v, peerPtr, {});
1011 event.handled_ =
true;
1019 (
event.isSelected_ ==
false && !
event.handled_) ||
1020 (event.isSelected_ ==
true &&
1021 (event.handled_ || allCounting));
1022 BEAST_EXPECT(handled);
1023 event.state_ = State::Off;
1024 event.isSelected_ =
false;
1025 event.handledCnt_ += handled;
1026 event.handled_ =
false;
1027 network_.onDisconnectPeer(event.peer_);
1030 auto&
event = events[EventType::LinkDown];
1042 bool mustHandle =
false;
1043 if (event.state_ == State::On)
1046 network_.overlay().isSelected(event.key_, event.peer_);
1047 auto peers = network_.overlay().getPeers(event.key_);
1048 auto d = reduce_relay::epoch<milliseconds>(now).count() -
1049 std::get<3>(peers[event.peer_]);
1050 mustHandle =
event.isSelected_ &&
1052 network_.overlay().inState(
1055 peers.find(event.peer_) != peers.end();
1057 network_.overlay().deleteIdlePeers(
1059 event.handled_ =
true;
1060 if (mustHandle && v == event.key_)
1062 event.state_ = State::WaitReset;
1063 sendSquelch(validator, ptr, {});
1067 (
event.handled_ &&
event.state_ == State::WaitReset) ||
1068 (!event.handled_ && !mustHandle);
1069 BEAST_EXPECT(handled);
1071 if (event.state_ == State::WaitReset ||
1072 (event.state_ == State::On &&
1076 event.state_ == State::WaitReset || !
event.handled_;
1077 BEAST_EXPECT(handled);
1078 event.state_ = State::Off;
1079 event.isSelected_ =
false;
1080 event.handledCnt_ += handled;
1081 event.handled_ =
false;
1082 network_.enableLink(event.validator_, event.peer_,
true);
1086 auto& down = events[EventType::LinkDown];
1087 auto& disconnected = events[EventType::PeerDisconnected];
1089 BEAST_EXPECT(down.handledCnt_ >= down.cnt_ - 1);
1091 BEAST_EXPECT(disconnected.cnt_ == disconnected.handledCnt_);
1093 std::cout <<
"link down count: " << down.cnt_ <<
"/"
1095 <<
" peer disconnect count: " << disconnected.cnt_ <<
"/"
1096 << disconnected.handledCnt_;
1102 auto countingState = network_.overlay().isCountingState(
validator);
1103 BEAST_EXPECT(countingState == isCountingState);
1104 return countingState == isCountingState;
1122 doTest(
"Initial Round", log, [
this](
bool log) {
1123 BEAST_EXPECT(propagateAndSquelch(log));
1133 doTest(
"Peer Unsquelched Too Soon", log, [
this](
bool log) {
1134 BEAST_EXPECT(propagateNoSquelch(log, 1,
false,
false,
false));
1145 doTest(
"Peer Unsquelched", log, [
this](
bool log) {
1146 BEAST_EXPECT(propagateNoSquelch(log, 2,
true,
true,
false));
1164 sendSquelch(key, peerPtr,
duration);
1178 auto selected = network_.overlay().getSelected(network_.validator(0));
1180 BEAST_EXPECT(n == 1);
1181 auto res = checkCounting(network_.validator(0),
false);
1183 return n == 1 && res;
1193 bool resetClock =
true)
1195 bool squelched =
false;
1204 BEAST_EXPECT(
false);
1211 auto res = checkCounting(network_.validator(0), countingState);
1212 return !squelched && res;
1221 doTest(
"New Peer", log, [
this](
bool log) {
1222 BEAST_EXPECT(propagateAndSquelch(log,
true,
false));
1224 BEAST_EXPECT(propagateNoSquelch(log, 1,
true,
false,
false));
1233 doTest(
"Selected Peer Disconnects", log, [
this](
bool log) {
1235 BEAST_EXPECT(propagateAndSquelch(log,
true,
false));
1236 auto id = network_.overlay().getSelectedPeer(network_.validator(0));
1238 network_.overlay().deletePeer(
1244 BEAST_EXPECT(checkCounting(network_.validator(0),
true));
1253 doTest(
"Selected Peer Stops Relaying", log, [
this](
bool log) {
1255 BEAST_EXPECT(propagateAndSquelch(log,
true,
false));
1258 network_.overlay().deleteIdlePeers(
1262 auto peers = network_.overlay().getPeers(network_.validator(0));
1265 BEAST_EXPECT(checkCounting(network_.validator(0),
true));
1274 doTest(
"Squelched Peer Disconnects", log, [
this](
bool log) {
1276 BEAST_EXPECT(propagateAndSquelch(log,
true,
false));
1277 auto peers = network_.overlay().getPeers(network_.validator(0));
1278 auto it =
std::find_if(peers.begin(), peers.end(), [&](
auto it) {
1279 return std::get<reduce_relay::PeerState>(it.second) ==
1280 reduce_relay::PeerState::Squelched;
1282 assert(it != peers.end());
1284 network_.overlay().deletePeer(
1288 BEAST_EXPECT(unsquelched == 0);
1289 BEAST_EXPECT(checkCounting(network_.validator(0),
false));
1296 doTest(
"Config Test", log, [&](
bool log) {
1311 toLoad = (R
"rippleConfig(
1323 toLoad = R
"rippleConfig(
1338 doTest(
"Duplicate Message", log, [&](
bool log) {
1342 for (
int i = 0; i < nMessages; i++)
1345 network_.overlay().updateSlotAndSquelch(
1347 network_.validator(0),
1351 auto peers = network_.overlay().getPeers(network_.validator(0));
1354 BEAST_EXPECT(std::get<1>(peers[0]) == (nMessages - 1));
1357 network_.overlay().updateSlotAndSquelch(
1359 network_.validator(0),
1363 peers = network_.overlay().getPeers(network_.validator(0));
1364 BEAST_EXPECT(std::get<1>(peers[0]) == (nMessages - 1));
1367 network_.overlay().updateSlotAndSquelch(
1369 network_.validator(0),
1372 peers = network_.overlay().getPeers(network_.validator(0));
1374 BEAST_EXPECT(std::get<1>(peers[0]) == nMessages);
1400 doTest(
"Random Squelch", l, [&](
bool l) {
1404 auto run = [&](
int npeers) {
1414 for (
int peer = 0; peer < npeers; peer++)
1424 protocol::MessageType::mtVALIDATION);
1431 using namespace reduce_relay;
1436 handler.
maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1437 handler.
maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count());
1440 handler.
maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1441 handler.
maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count());
1450 handler.
maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1451 handler.
maxDuration_ <= MAX_UNSQUELCH_EXPIRE_PEERS.count());
1452 using namespace beast::unit_test::detail;
1453 if (handler.
maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count())
1455 "warning: squelch duration is low",
1463 handler.
maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1464 handler.
maxDuration_ <= MAX_UNSQUELCH_EXPIRE_PEERS.count());
1465 if (handler.
maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count())
1467 "warning: squelch duration is low",
1478 doTest(
"Handshake", log, [&](
bool log) {
1479 auto setEnv = [&](
bool enable) {
1482 str <<
"[reduce_relay]\n"
1483 <<
"vp_enable=" << enable <<
"\n"
1484 <<
"vp_squelch=" << enable <<
"\n"
1485 <<
"[compression]\n"
1488 env_.app().config().VP_REDUCE_RELAY_ENABLE =
1490 env_.app().config().VP_REDUCE_RELAY_SQUELCH =
1494 auto handshake = [&](
int outboundEnable,
int inboundEnable) {
1496 boost::asio::ip::address::from_string(
"172.1.1.100");
1498 setEnv(outboundEnable);
1501 env_.app().config().COMPRESSION,
1502 env_.app().config().VP_REDUCE_RELAY_ENABLE,
1505 http_request.version(request.version());
1506 http_request.base() = request.base();
1509 auto const peerEnabled = inboundEnable && outboundEnable;
1514 BEAST_EXPECT(!(peerEnabled ^ inboundEnabled));
1516 setEnv(inboundEnable);
1528 auto const outboundEnabled =
1530 BEAST_EXPECT(!(peerEnabled ^ outboundEnabled));
1552 testInitialRound(log);
1553 testPeerUnsquelchedTooSoon(log);
1554 testPeerUnsquelched(log);
1556 testSquelchedPeerDisconnects(log);
1557 testSelectedPeerDisconnects(log);
1558 testSelectedPeerStopsRelaying(log);
1559 testInternalHashRouter(log);
1560 testRandomSquelch(log);
1570 doTest(
"Random Test", log, [&](
bool log) {
random(log); });