Skip to content

Commit 3018d88

Browse files
committed
Aggressive peer discovery for direct qset peers
1 parent ac66a2c commit 3018d88

6 files changed

Lines changed: 357 additions & 10 deletions

File tree

src/overlay/OverlayManager.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ class OverlayManager
143143

144144
virtual bool isPreferred(Peer* peer) const = 0;
145145
virtual bool isDirectQsetPeer(NodeID const& nodeID) const = 0;
146+
virtual void recordProbedNonQsetAddress(PeerBareAddress const& address) = 0;
146147
virtual bool isPossiblyPreferred(std::string const& ip) const = 0;
147148
virtual bool haveSpaceForConnection(std::string const& ip) const = 0;
148149

src/overlay/OverlayManagerImpl.cpp

Lines changed: 90 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -214,6 +214,13 @@ OverlayManagerImpl::PeersList::acceptAuthenticatedPeer(Peer::pointer peer)
214214
ZoneScoped;
215215
releaseAssert(threadIsMain());
216216

217+
if (peer->isMutualQsetPeer())
218+
{
219+
// Mutual direct-qset peers are operator-bounded by QUORUM_SET and must
220+
// not consume ordinary inbound/outbound authenticated capacity.
221+
return moveToAuthenticated(peer);
222+
}
223+
217224
CLOG_TRACE(Overlay, "Trying to promote peer to authenticated {}",
218225
peer->toString());
219226
if (mOverlayManager.isPreferred(peer.get()))
@@ -679,6 +686,70 @@ OverlayManagerImpl::connectTo(std::vector<PeerBareAddress> const& peers,
679686
return count;
680687
}
681688

689+
void
690+
OverlayManagerImpl::connectToQsetPeers(int& availablePendingSlots)
691+
{
692+
ZoneScoped;
693+
releaseAssert(availablePendingSlots >= 0);
694+
if (availablePendingSlots == 0)
695+
{
696+
return;
697+
}
698+
699+
auto missing = mDirectQsetPeers;
700+
missing.erase(mApp.getConfig().NODE_SEED.getPublicKey());
701+
for (auto const& peer : getAuthenticatedPeers())
702+
{
703+
missing.erase(peer.first);
704+
}
705+
for (auto it = missing.begin(); it != missing.end();)
706+
{
707+
auto info = mQuorumPeerState.getInfo(*it);
708+
if (info && info->remoteRole == RemoteQsetRole::None)
709+
{
710+
it = missing.erase(it);
711+
}
712+
else
713+
{
714+
++it;
715+
}
716+
}
717+
718+
if (missing.empty())
719+
{
720+
return;
721+
}
722+
723+
constexpr auto QSET_PROBE_BATCH_SIZE = 4;
724+
std::vector<PeerBareAddress> candidates;
725+
auto appendCandidates = [&](PeerType peerType) {
726+
auto peers = getPeersToConnectTo(QSET_PROBE_BATCH_SIZE, peerType);
727+
candidates.insert(std::end(candidates), std::begin(peers),
728+
std::end(peers));
729+
};
730+
appendCandidates(PeerType::INBOUND);
731+
appendCandidates(PeerType::OUTBOUND);
732+
733+
std::set<PeerBareAddress> tried;
734+
for (auto const& address : candidates)
735+
{
736+
if (availablePendingSlots == 0)
737+
{
738+
return;
739+
}
740+
if (mProbedNonQset.find(address) != std::end(mProbedNonQset) ||
741+
getConnectedPeer(address) || !tried.insert(address).second)
742+
{
743+
continue;
744+
}
745+
746+
if (connectToImpl(address, false))
747+
{
748+
--availablePendingSlots;
749+
}
750+
}
751+
}
752+
682753
void
683754
OverlayManagerImpl::updateTimerAndMaybeDropRandomPeer(bool shouldDrop)
684755
{
@@ -867,6 +938,8 @@ OverlayManagerImpl::tick()
867938
availablePendingSlots -= pendingUsedByOutbound;
868939
}
869940

941+
connectToQsetPeers(availablePendingSlots);
942+
870943
// Finally, attempt to promote some inbound connections to outbound
871944
if (availablePendingSlots > 0)
872945
{
@@ -900,10 +973,16 @@ OverlayManagerImpl::availableOutboundAuthenticatedSlots() const
900973
? OverlayManager::MIN_INBOUND_FACTOR
901974
: mApp.getConfig().TARGET_PEER_CONNECTIONS;
902975

903-
if (mOutboundPeers.mAuthenticated.size() < adjustedTarget)
976+
auto mutualQsetCount = std::count_if(
977+
std::begin(mOutboundPeers.mAuthenticated),
978+
std::end(mOutboundPeers.mAuthenticated),
979+
[](auto const& peer) { return peer.second->isMutualQsetPeer(); });
980+
auto ordinaryOutboundCount =
981+
mOutboundPeers.mAuthenticated.size() - mutualQsetCount;
982+
983+
if (ordinaryOutboundCount < adjustedTarget)
904984
{
905-
return static_cast<int>(adjustedTarget -
906-
mOutboundPeers.mAuthenticated.size());
985+
return static_cast<int>(adjustedTarget - ordinaryOutboundCount);
907986
}
908987
else
909988
{
@@ -1191,6 +1270,14 @@ OverlayManagerImpl::isDirectQsetPeer(NodeID const& nodeID) const
11911270
return mDirectQsetPeers.count(nodeID) != 0;
11921271
}
11931272

1273+
void
1274+
OverlayManagerImpl::recordProbedNonQsetAddress(PeerBareAddress const& address)
1275+
{
1276+
releaseAssert(threadIsMain());
1277+
releaseAssert(!address.isEmpty());
1278+
mProbedNonQset.insert(address);
1279+
}
1280+
11941281
static xdr::opaque_array<32> const TX_BATCH_HASH = [] {
11951282
xdr::opaque_array<32> bytes{};
11961283
for (auto& b : bytes)

src/overlay/OverlayManagerImpl.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ class OverlayManagerImpl : public OverlayManager
4343
Application& mApp;
4444
std::set<PeerBareAddress> mConfigurationPreferredPeers;
4545
std::set<NodeID> mDirectQsetPeers;
46+
// Addresses that were proactively probed while searching for direct-qset
47+
// peers and authenticated as non-qset peers. This is intentionally
48+
// in-memory only; next-attempt backoff limits churn until restart.
49+
std::set<PeerBareAddress> mProbedNonQset;
4650
QuorumPeerState mQuorumPeerState;
4751

4852
struct PeersList
@@ -137,6 +141,7 @@ class OverlayManagerImpl : public OverlayManager
137141
bool acceptAuthenticatedPeer(Peer::pointer peer) override;
138142
bool isPreferred(Peer* peer) const override;
139143
bool isDirectQsetPeer(NodeID const& nodeID) const override;
144+
void recordProbedNonQsetAddress(PeerBareAddress const& address) override;
140145
std::vector<Peer::pointer> const& getInboundPendingPeers() const override;
141146
std::vector<Peer::pointer> const& getOutboundPendingPeers() const override;
142147
std::vector<Peer::pointer> getPendingPeers() const override;
@@ -208,6 +213,7 @@ class OverlayManagerImpl : public OverlayManager
208213
int connectTo(int maxNum, PeerType peerType);
209214
int connectTo(std::vector<PeerBareAddress> const& peers,
210215
bool forceoutbound);
216+
void connectToQsetPeers(int& availablePendingSlots);
211217
std::vector<PeerBareAddress> getPeersToConnectTo(int maxNum,
212218
PeerType peerType);
213219

src/overlay/Peer.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1802,6 +1802,10 @@ Peer::updatePeerRecordAfterAuthentication()
18021802
/* preferredTypeKnown */ true);
18031803
}
18041804
}
1805+
else
1806+
{
1807+
overlayManager.recordProbedNonQsetAddress(getAddress());
1808+
}
18051809

18061810
CLOG_DEBUG(Overlay, "successful handshake with {}@{}",
18071811
mAppConnector.getConfig().toShortString(mPeerID), toString());

0 commit comments

Comments
 (0)