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/optional.hpp>
30 #include <boost/thread.hpp>
68 onMessage(protocol::TMSquelch
const& squelch) = 0;
70 send(protocol::TMSquelch
const& squelch)
120 boost::optional<std::size_t>
178 inline static const bool is_steady =
false;
189 now_ += randDuration(min, max);
224 updateSlotAndSquelch(
229 protocol::MessageType type = protocol::mtVALIDATION) = 0;
250 : validator_(validator), peer_(peer), latency_(latency), up_(
true)
252 auto sp = peer_.lock();
261 auto sp = peer_.lock();
263 auto peer = std::dynamic_pointer_cast<PeerPartial>(sp);
264 peer->onMessage(m, f);
279 auto p = peer_.lock();
286 auto p = peer_.lock();
307 protocol::TMValidation v;
308 v.set_validation(
"validation");
309 message_ = std::make_shared<Message>(v, protocol::mtVALIDATION, pkey_);
362 for (
auto id : peers)
364 assert(links_.find(
id) != links_.end());
365 f(*links_[
id], message_);
416 auto it = links_.find(
id);
417 assert(it != links_.end());
418 it->second->up(
true);
424 auto it = links_.find(
id);
425 assert(it != links_.end());
426 it->second->up(
false);
442 : overlay_(overlay), squelch_(journal)
470 overlay_.updateSlotAndSquelch({}, *
validator, id(), f);
477 auto validator = squelch.validatorpubkey();
479 if (squelch.squelch())
483 squelch_.removeSquelch(key);
511 slots_.deleteIdlePeers();
517 auto res = slots_.inState(
validator, state);
518 return res ? *res : 0;
527 protocol::MessageType type = protocol::mtVALIDATION)
override
530 slots_.updateSlotAndSquelch(key,
validator,
id, type);
537 slots_.deletePeer(
id,
true);
544 slots_.deleteIdlePeers();
552 if (peersCache_.empty() || !useCache)
554 peer = std::make_shared<PeerSim>(*
this, app_.journal(
"Squelch"));
559 auto it = peersCache_.begin();
562 peersCache_.erase(it);
571 auto it = peers_.find(
id);
572 assert(it != peers_.end());
582 while (!peers_.empty())
583 deletePeer(peers_.begin()->first);
584 while (!peersCache_.empty())
596 for (
auto& [
id, _] : peers_)
603 deletePeer(maxId,
false);
623 auto selected = slots_.getSelected(
validator);
624 return selected.find(peer) != selected.end();
630 auto selected = slots_.getSelected(
validator);
631 assert(selected.size());
632 return *selected.begin();
650 return peers_.size();
660 if (
auto it = peers_.find(
id); it != peers_.end())
661 squelch_(
validator, it->second, squelchDuration);
666 if (
auto it = peers_.find(
id); it != peers_.end())
691 auto peer = overlay_.addPeer();
692 for (
auto& v : validators_)
712 auto peer = overlay_.addPeer();
713 for (
auto& v : validators_)
721 auto id = overlay_.deleteLastPeer();
733 while (overlay_.getNumPeers() >
MAX_PEERS)
740 assert(v < validators_.size());
741 return validators_[v];
754 std::find_if(validators_.begin(), validators_.end(), [&](
auto& v) {
755 return v.id() == validatorId;
757 assert(it != validators_.end());
771 protocol::TMSquelch squelch;
772 squelch.set_squelch(
false);
773 for (
auto& v : validators_)
776 squelch.clear_validatorpubkey();
777 squelch.set_validatorpubkey(key.
data(), key.
size());
779 std::dynamic_pointer_cast<PeerSim>(l.
getPeer())->send(squelch);
790 auto size = max - min;
806 bool resetClock =
true)
814 overlay_.resetPeers();
817 for (
int m = 0; m < nMessages; ++m)
821 validators_[v].for_links(link);
830 for (
auto& v : validators_)
832 if (overlay_.isSelected(v,
id))
845 for (
auto& v : validators_)
847 if (!overlay_.isSelected(v, peer))
849 auto peers = overlay_.getPeers(v);
850 for (
auto& [_, v] : peers)
853 if (std::get<reduce_relay::PeerState>(v) ==
875 auto peers = network_.overlay().getPeers(network_.validator(
validator));
877 <<
"num peers " << (int)network_.overlay().getNumPeers()
879 for (
auto& [k, v] : peers)
880 std::cout << k <<
":" << (int)std::get<reduce_relay::PeerState>(v)
892 protocol::TMSquelch squelch;
894 squelch.set_squelch(res);
897 squelch.set_squelchduration(*
duration);
898 auto sp = peerPtr.
lock();
900 std::dynamic_pointer_cast<PeerSim>(sp)->send(squelch);
915 bool isSelected_ =
false;
920 bool handled_ =
false;
930 {LinkDown, {}}, {PeerDisconnected, {}}};
938 bool squelched =
false;
947 auto p = sendSquelch(key, peerPtr,
duration);
954 auto selected = network_.overlay().getSelected(
validator);
955 str <<
" selected: ";
956 for (
auto s : selected)
960 << (double)reduce_relay::epoch<milliseconds>(now)
963 <<
" random, squelched, validator: " <<
validator.id()
966 network_.overlay().isCountingState(
validator);
968 countingState ==
false &&
974 if (events[EventType::LinkDown].state_ == State::Off)
977 events[event].cnt_++;
978 events[event].validator_ =
validator.id();
980 events[event].peer_ = link.
peerId();
981 events[event].state_ = State::On;
982 events[event].time_ = now;
983 if (event == EventType::LinkDown)
987 events[event].isSelected_ =
988 network_.overlay().isSelected(
992 events[event].isSelected_ =
993 network_.isSelected(link.
peerId());
996 if (r == (
int)EventType::LinkDown ||
997 r == (
int)EventType::PeerDisconnected)
1003 if (events[EventType::PeerDisconnected].state_ == State::On)
1005 auto&
event = events[EventType::PeerDisconnected];
1006 bool allCounting = network_.allCounting(event.peer_);
1007 network_.overlay().deletePeer(
1010 if (event.isSelected_)
1011 sendSquelch(v, peerPtr, {});
1012 event.handled_ =
true;
1020 (
event.isSelected_ ==
false && !
event.handled_) ||
1021 (event.isSelected_ ==
true &&
1022 (event.handled_ || allCounting));
1023 BEAST_EXPECT(handled);
1024 event.state_ = State::Off;
1025 event.isSelected_ =
false;
1026 event.handledCnt_ += handled;
1027 event.handled_ =
false;
1028 network_.onDisconnectPeer(event.peer_);
1031 auto&
event = events[EventType::LinkDown];
1043 bool mustHandle =
false;
1044 if (event.state_ == State::On)
1047 network_.overlay().isSelected(event.key_, event.peer_);
1048 auto peers = network_.overlay().getPeers(event.key_);
1049 auto d = reduce_relay::epoch<milliseconds>(now).count() -
1050 std::get<3>(peers[event.peer_]);
1051 mustHandle =
event.isSelected_ &&
1053 network_.overlay().inState(
1056 peers.find(event.peer_) != peers.end();
1058 network_.overlay().deleteIdlePeers(
1060 event.handled_ =
true;
1061 if (mustHandle && v == event.key_)
1063 event.state_ = State::WaitReset;
1064 sendSquelch(validator, ptr, {});
1068 (
event.handled_ &&
event.state_ == State::WaitReset) ||
1069 (!event.handled_ && !mustHandle);
1070 BEAST_EXPECT(handled);
1072 if (event.state_ == State::WaitReset ||
1073 (event.state_ == State::On &&
1077 event.state_ == State::WaitReset || !
event.handled_;
1078 BEAST_EXPECT(handled);
1079 event.state_ = State::Off;
1080 event.isSelected_ =
false;
1081 event.handledCnt_ += handled;
1082 event.handled_ =
false;
1083 network_.enableLink(event.validator_, event.peer_,
true);
1087 auto& down = events[EventType::LinkDown];
1088 auto& disconnected = events[EventType::PeerDisconnected];
1090 BEAST_EXPECT(down.handledCnt_ >= down.cnt_ - 1);
1092 BEAST_EXPECT(disconnected.cnt_ == disconnected.handledCnt_);
1094 std::cout <<
"link down count: " << down.cnt_ <<
"/"
1096 <<
" peer disconnect count: " << disconnected.cnt_ <<
"/"
1097 << disconnected.handledCnt_;
1103 auto countingState = network_.overlay().isCountingState(
validator);
1104 BEAST_EXPECT(countingState == isCountingState);
1105 return countingState == isCountingState;
1123 doTest(
"Initial Round", log, [
this](
bool log) {
1124 BEAST_EXPECT(propagateAndSquelch(log));
1134 doTest(
"Peer Unsquelched Too Soon", log, [
this](
bool log) {
1135 BEAST_EXPECT(propagateNoSquelch(log, 1,
false,
false,
false));
1146 doTest(
"Peer Unsquelched", log, [
this](
bool log) {
1147 BEAST_EXPECT(propagateNoSquelch(log, 2,
true,
true,
false));
1165 sendSquelch(key, peerPtr,
duration);
1179 auto selected = network_.overlay().getSelected(network_.validator(0));
1181 BEAST_EXPECT(n == 1);
1182 auto res = checkCounting(network_.validator(0),
false);
1184 return n == 1 && res;
1194 bool resetClock =
true)
1196 bool squelched =
false;
1205 BEAST_EXPECT(
false);
1212 auto res = checkCounting(network_.validator(0), countingState);
1213 return !squelched && res;
1222 doTest(
"New Peer", log, [
this](
bool log) {
1223 BEAST_EXPECT(propagateAndSquelch(log,
true,
false));
1225 BEAST_EXPECT(propagateNoSquelch(log, 1,
true,
false,
false));
1234 doTest(
"Selected Peer Disconnects", log, [
this](
bool log) {
1236 BEAST_EXPECT(propagateAndSquelch(log,
true,
false));
1237 auto id = network_.overlay().getSelectedPeer(network_.validator(0));
1239 network_.overlay().deletePeer(
1245 BEAST_EXPECT(checkCounting(network_.validator(0),
true));
1254 doTest(
"Selected Peer Stops Relaying", log, [
this](
bool log) {
1256 BEAST_EXPECT(propagateAndSquelch(log,
true,
false));
1259 network_.overlay().deleteIdlePeers(
1263 auto peers = network_.overlay().getPeers(network_.validator(0));
1266 BEAST_EXPECT(checkCounting(network_.validator(0),
true));
1275 doTest(
"Squelched Peer Disconnects", log, [
this](
bool log) {
1277 BEAST_EXPECT(propagateAndSquelch(log,
true,
false));
1278 auto peers = network_.overlay().getPeers(network_.validator(0));
1279 auto it =
std::find_if(peers.begin(), peers.end(), [&](
auto it) {
1280 return std::get<reduce_relay::PeerState>(it.second) ==
1281 reduce_relay::PeerState::Squelched;
1283 assert(it != peers.end());
1285 network_.overlay().deletePeer(
1289 BEAST_EXPECT(unsquelched == 0);
1290 BEAST_EXPECT(checkCounting(network_.validator(0),
false));
1297 doTest(
"Config Test", log, [&](
bool log) {
1312 toLoad = (R
"rippleConfig(
1324 toLoad = R
"rippleConfig(
1339 doTest(
"Duplicate Message", log, [&](
bool log) {
1343 for (
int i = 0; i < nMessages; i++)
1346 network_.overlay().updateSlotAndSquelch(
1348 network_.validator(0),
1352 auto peers = network_.overlay().getPeers(network_.validator(0));
1355 BEAST_EXPECT(std::get<1>(peers[0]) == (nMessages - 1));
1358 network_.overlay().updateSlotAndSquelch(
1360 network_.validator(0),
1364 peers = network_.overlay().getPeers(network_.validator(0));
1365 BEAST_EXPECT(std::get<1>(peers[0]) == (nMessages - 1));
1368 network_.overlay().updateSlotAndSquelch(
1370 network_.validator(0),
1373 peers = network_.overlay().getPeers(network_.validator(0));
1375 BEAST_EXPECT(std::get<1>(peers[0]) == nMessages);
1401 doTest(
"Random Squelch", l, [&](
bool l) {
1405 auto run = [&](
int npeers) {
1415 for (
int peer = 0; peer < npeers; peer++)
1425 protocol::MessageType::mtVALIDATION);
1432 using namespace reduce_relay;
1437 handler.
maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1438 handler.
maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count());
1441 handler.
maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1442 handler.
maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count());
1451 handler.
maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1452 handler.
maxDuration_ <= MAX_UNSQUELCH_EXPIRE_PEERS.count());
1453 using namespace beast::unit_test::detail;
1454 if (handler.
maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count())
1456 "warning: squelch duration is low",
1464 handler.
maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1465 handler.
maxDuration_ <= MAX_UNSQUELCH_EXPIRE_PEERS.count());
1466 if (handler.
maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count())
1468 "warning: squelch duration is low",
1479 doTest(
"Handshake", log, [&](
bool log) {
1480 auto setEnv = [&](
bool enable) {
1483 str <<
"[reduce_relay]\n"
1484 <<
"vp_enable=" << enable <<
"\n"
1485 <<
"vp_squelch=" << enable <<
"\n"
1486 <<
"[compression]\n"
1489 env_.app().config().VP_REDUCE_RELAY_ENABLE =
1491 env_.app().config().VP_REDUCE_RELAY_SQUELCH =
1495 auto handshake = [&](
int outboundEnable,
int inboundEnable) {
1497 boost::asio::ip::address::from_string(
"172.1.1.100");
1499 setEnv(outboundEnable);
1502 env_.app().config().COMPRESSION,
1503 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); });