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)
172 inline static const bool is_steady =
false;
183 now_ += randDuration(min, max);
218 updateSlotAndSquelch(
223 protocol::MessageType type = protocol::mtVALIDATION) = 0;
244 : validator_(validator), peer_(peer), latency_(latency), up_(
true)
246 auto sp = peer_.lock();
255 auto sp = peer_.lock();
257 auto peer = std::dynamic_pointer_cast<PeerPartial>(sp);
258 peer->onMessage(m, f);
273 auto p = peer_.lock();
280 auto p = peer_.lock();
301 protocol::TMValidation v;
302 v.set_validation(
"validation");
303 message_ = std::make_shared<Message>(v, protocol::mtVALIDATION, pkey_);
356 for (
auto id : peers)
358 assert(links_.find(
id) != links_.end());
359 f(*links_[
id], message_);
410 auto it = links_.find(
id);
411 assert(it != links_.end());
412 it->second->up(
true);
418 auto it = links_.find(
id);
419 assert(it != links_.end());
420 it->second->up(
false);
436 : overlay_(overlay), squelch_(journal)
464 overlay_.updateSlotAndSquelch({}, *
validator, id(), f);
471 auto validator = squelch.validatorpubkey();
473 if (squelch.squelch())
477 squelch_.removeSquelch(key);
505 slots_.deleteIdlePeers();
511 auto res = slots_.inState(
validator, state);
512 return res ? *res : 0;
521 protocol::MessageType type = protocol::mtVALIDATION)
override
524 slots_.updateSlotAndSquelch(key,
validator,
id, type);
531 slots_.deletePeer(
id,
true);
538 slots_.deleteIdlePeers();
546 if (peersCache_.empty() || !useCache)
548 peer = std::make_shared<PeerSim>(*
this, app_.journal(
"Squelch"));
553 auto it = peersCache_.begin();
556 peersCache_.erase(it);
565 auto it = peers_.find(
id);
566 assert(it != peers_.end());
576 while (!peers_.empty())
577 deletePeer(peers_.begin()->first);
578 while (!peersCache_.empty())
590 for (
auto& [
id, _] : peers_)
597 deletePeer(maxId,
false);
617 auto selected = slots_.getSelected(
validator);
618 return selected.find(peer) != selected.end();
624 auto selected = slots_.getSelected(
validator);
625 assert(selected.size());
626 return *selected.begin();
644 return peers_.size();
654 if (
auto it = peers_.find(
id); it != peers_.end())
655 squelch_(
validator, it->second, squelchDuration);
660 if (
auto it = peers_.find(
id); it != peers_.end())
685 auto peer = overlay_.addPeer();
686 for (
auto& v : validators_)
706 auto peer = overlay_.addPeer();
707 for (
auto& v : validators_)
715 auto id = overlay_.deleteLastPeer();
727 while (overlay_.getNumPeers() >
MAX_PEERS)
734 assert(v < validators_.size());
735 return validators_[v];
748 std::find_if(validators_.begin(), validators_.end(), [&](
auto& v) {
749 return v.id() == validatorId;
751 assert(it != validators_.end());
765 protocol::TMSquelch squelch;
766 squelch.set_squelch(
false);
767 for (
auto& v : validators_)
770 squelch.clear_validatorpubkey();
771 squelch.set_validatorpubkey(key.
data(), key.
size());
773 std::dynamic_pointer_cast<PeerSim>(l.
getPeer())->send(squelch);
784 auto size = max - min;
800 bool resetClock =
true)
808 overlay_.resetPeers();
811 for (
int m = 0; m < nMessages; ++m)
815 validators_[v].for_links(link);
824 for (
auto& v : validators_)
826 if (overlay_.isSelected(v,
id))
839 for (
auto& v : validators_)
841 if (!overlay_.isSelected(v, peer))
843 auto peers = overlay_.getPeers(v);
844 for (
auto& [_, v] : peers)
847 if (std::get<reduce_relay::PeerState>(v) ==
869 auto peers = network_.overlay().getPeers(network_.validator(
validator));
871 <<
"num peers " << (int)network_.overlay().getNumPeers()
873 for (
auto& [k, v] : peers)
874 std::cout << k <<
":" << (int)std::get<reduce_relay::PeerState>(v)
886 protocol::TMSquelch squelch;
888 squelch.set_squelch(res);
891 squelch.set_squelchduration(*
duration);
892 auto sp = peerPtr.
lock();
894 std::dynamic_pointer_cast<PeerSim>(sp)->send(squelch);
909 bool isSelected_ =
false;
914 bool handled_ =
false;
924 {LinkDown, {}}, {PeerDisconnected, {}}};
932 bool squelched =
false;
941 auto p = sendSquelch(key, peerPtr,
duration);
948 auto selected = network_.overlay().getSelected(
validator);
949 str <<
" selected: ";
950 for (
auto s : selected)
954 << (double)reduce_relay::epoch<milliseconds>(now)
957 <<
" random, squelched, validator: " <<
validator.id()
960 network_.overlay().isCountingState(
validator);
962 countingState ==
false &&
968 if (events[EventType::LinkDown].state_ == State::Off)
971 events[event].cnt_++;
972 events[event].validator_ =
validator.id();
974 events[event].peer_ = link.
peerId();
975 events[event].state_ = State::On;
976 events[event].time_ = now;
977 if (event == EventType::LinkDown)
981 events[event].isSelected_ =
982 network_.overlay().isSelected(
986 events[event].isSelected_ =
987 network_.isSelected(link.
peerId());
990 if (r == (
int)EventType::LinkDown ||
991 r == (
int)EventType::PeerDisconnected)
997 if (events[EventType::PeerDisconnected].state_ == State::On)
999 auto&
event = events[EventType::PeerDisconnected];
1000 bool allCounting = network_.allCounting(event.peer_);
1001 network_.overlay().deletePeer(
1004 if (event.isSelected_)
1005 sendSquelch(v, peerPtr, {});
1006 event.handled_ =
true;
1014 (
event.isSelected_ ==
false && !
event.handled_) ||
1015 (event.isSelected_ ==
true &&
1016 (event.handled_ || allCounting));
1017 BEAST_EXPECT(handled);
1018 event.state_ = State::Off;
1019 event.isSelected_ =
false;
1020 event.handledCnt_ += handled;
1021 event.handled_ =
false;
1022 network_.onDisconnectPeer(event.peer_);
1025 auto&
event = events[EventType::LinkDown];
1037 bool mustHandle =
false;
1038 if (event.state_ == State::On)
1041 network_.overlay().isSelected(event.key_, event.peer_);
1042 auto peers = network_.overlay().getPeers(event.key_);
1043 auto d = reduce_relay::epoch<milliseconds>(now).count() -
1044 std::get<3>(peers[event.peer_]);
1045 mustHandle =
event.isSelected_ &&
1047 network_.overlay().inState(
1050 peers.find(event.peer_) != peers.end();
1052 network_.overlay().deleteIdlePeers(
1054 event.handled_ =
true;
1055 if (mustHandle && v == event.key_)
1057 event.state_ = State::WaitReset;
1058 sendSquelch(validator, ptr, {});
1062 (
event.handled_ &&
event.state_ == State::WaitReset) ||
1063 (!event.handled_ && !mustHandle);
1064 BEAST_EXPECT(handled);
1066 if (event.state_ == State::WaitReset ||
1067 (event.state_ == State::On &&
1071 event.state_ == State::WaitReset || !
event.handled_;
1072 BEAST_EXPECT(handled);
1073 event.state_ = State::Off;
1074 event.isSelected_ =
false;
1075 event.handledCnt_ += handled;
1076 event.handled_ =
false;
1077 network_.enableLink(event.validator_, event.peer_,
true);
1081 auto& down = events[EventType::LinkDown];
1082 auto& disconnected = events[EventType::PeerDisconnected];
1084 BEAST_EXPECT(down.handledCnt_ >= down.cnt_ - 1);
1086 BEAST_EXPECT(disconnected.cnt_ == disconnected.handledCnt_);
1088 std::cout <<
"link down count: " << down.cnt_ <<
"/"
1090 <<
" peer disconnect count: " << disconnected.cnt_ <<
"/"
1091 << disconnected.handledCnt_;
1097 auto countingState = network_.overlay().isCountingState(
validator);
1098 BEAST_EXPECT(countingState == isCountingState);
1099 return countingState == isCountingState;
1117 doTest(
"Initial Round", log, [
this](
bool log) {
1118 BEAST_EXPECT(propagateAndSquelch(log));
1128 doTest(
"Peer Unsquelched Too Soon", log, [
this](
bool log) {
1129 BEAST_EXPECT(propagateNoSquelch(log, 1,
false,
false,
false));
1140 doTest(
"Peer Unsquelched", log, [
this](
bool log) {
1141 BEAST_EXPECT(propagateNoSquelch(log, 2,
true,
true,
false));
1159 sendSquelch(key, peerPtr,
duration);
1173 auto selected = network_.overlay().getSelected(network_.validator(0));
1175 BEAST_EXPECT(n == 1);
1176 auto res = checkCounting(network_.validator(0),
false);
1178 return n == 1 && res;
1188 bool resetClock =
true)
1190 bool squelched =
false;
1199 BEAST_EXPECT(
false);
1206 auto res = checkCounting(network_.validator(0), countingState);
1207 return !squelched && res;
1216 doTest(
"New Peer", log, [
this](
bool log) {
1217 BEAST_EXPECT(propagateAndSquelch(log,
true,
false));
1219 BEAST_EXPECT(propagateNoSquelch(log, 1,
true,
false,
false));
1228 doTest(
"Selected Peer Disconnects", log, [
this](
bool log) {
1230 BEAST_EXPECT(propagateAndSquelch(log,
true,
false));
1231 auto id = network_.overlay().getSelectedPeer(network_.validator(0));
1233 network_.overlay().deletePeer(
1239 BEAST_EXPECT(checkCounting(network_.validator(0),
true));
1248 doTest(
"Selected Peer Stops Relaying", log, [
this](
bool log) {
1250 BEAST_EXPECT(propagateAndSquelch(log,
true,
false));
1253 network_.overlay().deleteIdlePeers(
1257 auto peers = network_.overlay().getPeers(network_.validator(0));
1260 BEAST_EXPECT(checkCounting(network_.validator(0),
true));
1269 doTest(
"Squelched Peer Disconnects", log, [
this](
bool log) {
1271 BEAST_EXPECT(propagateAndSquelch(log,
true,
false));
1272 auto peers = network_.overlay().getPeers(network_.validator(0));
1273 auto it =
std::find_if(peers.begin(), peers.end(), [&](
auto it) {
1274 return std::get<reduce_relay::PeerState>(it.second) ==
1275 reduce_relay::PeerState::Squelched;
1277 assert(it != peers.end());
1279 network_.overlay().deletePeer(
1283 BEAST_EXPECT(unsquelched == 0);
1284 BEAST_EXPECT(checkCounting(network_.validator(0),
false));
1291 doTest(
"Config Test", log, [&](
bool log) {
1306 toLoad = (R
"rippleConfig(
1318 toLoad = R
"rippleConfig(
1333 doTest(
"Duplicate Message", log, [&](
bool log) {
1337 for (
int i = 0; i < nMessages; i++)
1340 network_.overlay().updateSlotAndSquelch(
1342 network_.validator(0),
1346 auto peers = network_.overlay().getPeers(network_.validator(0));
1349 BEAST_EXPECT(std::get<1>(peers[0]) == (nMessages - 1));
1352 network_.overlay().updateSlotAndSquelch(
1354 network_.validator(0),
1358 peers = network_.overlay().getPeers(network_.validator(0));
1359 BEAST_EXPECT(std::get<1>(peers[0]) == (nMessages - 1));
1362 network_.overlay().updateSlotAndSquelch(
1364 network_.validator(0),
1367 peers = network_.overlay().getPeers(network_.validator(0));
1369 BEAST_EXPECT(std::get<1>(peers[0]) == nMessages);
1395 doTest(
"Random Squelch", l, [&](
bool l) {
1399 auto run = [&](
int npeers) {
1409 for (
int peer = 0; peer < npeers; peer++)
1419 protocol::MessageType::mtVALIDATION);
1426 using namespace reduce_relay;
1431 handler.
maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1432 handler.
maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count());
1435 handler.
maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1436 handler.
maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count());
1445 handler.
maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1446 handler.
maxDuration_ <= MAX_UNSQUELCH_EXPIRE_PEERS.count());
1447 using namespace beast::unit_test::detail;
1448 if (handler.
maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count())
1450 "warning: squelch duration is low",
1458 handler.
maxDuration_ >= MIN_UNSQUELCH_EXPIRE.count() &&
1459 handler.
maxDuration_ <= MAX_UNSQUELCH_EXPIRE_PEERS.count());
1460 if (handler.
maxDuration_ <= MAX_UNSQUELCH_EXPIRE_DEFAULT.count())
1462 "warning: squelch duration is low",
1473 doTest(
"Handshake", log, [&](
bool log) {
1474 auto setEnv = [&](
bool enable) {
1477 str <<
"[reduce_relay]\n"
1478 <<
"vp_enable=" << enable <<
"\n"
1479 <<
"vp_squelch=" << enable <<
"\n"
1480 <<
"[compression]\n"
1483 env_.app().config().VP_REDUCE_RELAY_ENABLE =
1485 env_.app().config().VP_REDUCE_RELAY_SQUELCH =
1489 auto handshake = [&](
int outboundEnable,
int inboundEnable) {
1491 boost::asio::ip::address::from_string(
"172.1.1.100");
1493 setEnv(outboundEnable);
1496 env_.app().config().COMPRESSION,
1497 env_.app().config().VP_REDUCE_RELAY_ENABLE,
1500 http_request.version(request.version());
1501 http_request.base() = request.base();
1504 auto const peerEnabled = inboundEnable && outboundEnable;
1509 BEAST_EXPECT(!(peerEnabled ^ inboundEnabled));
1511 setEnv(inboundEnable);
1523 auto const outboundEnabled =
1525 BEAST_EXPECT(!(peerEnabled ^ outboundEnabled));
1547 testInitialRound(log);
1548 testPeerUnsquelchedTooSoon(log);
1549 testPeerUnsquelched(log);
1551 testSquelchedPeerDisconnects(log);
1552 testSelectedPeerDisconnects(log);
1553 testSelectedPeerStopsRelaying(log);
1554 testInternalHashRouter(log);
1555 testRandomSquelch(log);
1565 doTest(
"Random Test", log, [&](
bool log) {
random(log); });