Skip to content

Commit ddc9c3f

Browse files
committed
p2p: BIP324 v2.0 clients retry with v1 protocol
1 parent b5809c9 commit ddc9c3f

File tree

2 files changed

+41
-7
lines changed

2 files changed

+41
-7
lines changed

src/net.cpp

Lines changed: 39 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,10 @@ CNode* CConnman::FindNode(const CService& addr)
413413

414414
bool CConnman::AlreadyConnectedToAddress(const CAddress& addr)
415415
{
416-
return FindNode(static_cast<CNetAddr>(addr)) || FindNode(addr.ToStringIPPort());
416+
CNode* found_by_addr = FindNode(static_cast<CNetAddr>(addr));
417+
CNode* found_by_ip_port = FindNode(addr.ToStringIPPort());
418+
return (found_by_addr && !found_by_addr->fDisconnect) ||
419+
(found_by_ip_port && !found_by_ip_port->fDisconnect);
417420
}
418421

419422
bool CConnman::CheckIncomingNonce(uint64_t nonce)
@@ -478,8 +481,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
478481

479482
// Look for an existing connection
480483
CNode* pnode = FindNode(static_cast<CService>(addrConnect));
481-
if (pnode)
482-
{
484+
if (pnode && !pnode->fDisconnect) {
483485
LogPrintf("Failed to open new connection, already connected\n");
484486
return nullptr;
485487
}
@@ -505,7 +507,7 @@ CNode* CConnman::ConnectNode(CAddress addrConnect, const char *pszDest, bool fCo
505507
// In that case, drop the connection that was just created.
506508
LOCK(m_nodes_mutex);
507509
CNode* pnode = FindNode(static_cast<CService>(addrConnect));
508-
if (pnode) {
510+
if (pnode && !pnode->fDisconnect) {
509511
LogPrintf("Failed to open new connection, already connected\n");
510512
return nullptr;
511513
}
@@ -1460,6 +1462,16 @@ bool CConnman::ShouldRunInactivityChecks(const CNode& node, std::chrono::seconds
14601462
return node.m_connected + m_peer_connect_timeout < now;
14611463
}
14621464

1465+
void CConnman::DowngradeToV1Transport(CNode& node)
1466+
{
1467+
AssertLockNotHeld(m_total_bytes_sent_mutex);
1468+
LogPrint(BCLog::NET, "downgrading to v1 transport protocol for peer=%d\n", node.GetId());
1469+
CAddress addr = node.addr;
1470+
addr.nServices = ServiceFlags(addr.nServices & ~NODE_P2P_V2);
1471+
OpenNetworkConnection(addr, false, &node.grantOutbound, addr.ToStringIPPort().c_str(), node.m_conn_type);
1472+
node.m_bip324_shared_state->key_exchange_complete = true;
1473+
}
1474+
14631475
bool CConnman::InactivityCheck(const CNode& node) const
14641476
{
14651477
// Tests that see disconnects after using mocktime can start nodes with a
@@ -1758,6 +1770,14 @@ void CConnman::SocketHandlerConnected(const std::vector<CNode*>& nodes,
17581770
LogPrint(BCLog::NET, "socket closed for peer=%d\n", pnode->GetId());
17591771
}
17601772
pnode->CloseSocketDisconnect();
1773+
1774+
// Downgrade if a v2 outbound connection was met with a disconnection before receiving anything
1775+
if (pnode->PreferV2Conn() &&
1776+
!pnode->IsInboundConn() &&
1777+
(pnode->m_bip324_shared_state->peer_ellswift_buf.empty() &&
1778+
!pnode->m_bip324_node_state->keys_derived)) {
1779+
DowngradeToV1Transport(*pnode);
1780+
}
17611781
} else if (nBytes < 0) {
17621782
// error
17631783
int nErr = WSAGetLastError();
@@ -1777,7 +1797,17 @@ void CConnman::SocketHandlerConnected(const std::vector<CNode*>& nodes,
17771797
if (bytes_sent) RecordBytesSent(bytes_sent);
17781798
}
17791799

1780-
if (InactivityCheck(*pnode)) pnode->fDisconnect = true;
1800+
if (InactivityCheck(*pnode)) {
1801+
pnode->fDisconnect = true;
1802+
// Downgrade if a v2 outbound connection was met with inactivity before receiving anything
1803+
if (pnode->PreferV2Conn() &&
1804+
!pnode->IsInboundConn() &&
1805+
(pnode->m_bip324_shared_state->peer_ellswift_buf.empty() &&
1806+
!pnode->m_bip324_node_state->keys_derived) &&
1807+
pnode->m_last_recv.load().count() == 0) {
1808+
DowngradeToV1Transport(*pnode);
1809+
}
1810+
}
17811811
}
17821812
}
17831813

@@ -2411,8 +2441,10 @@ void CConnman::OpenNetworkConnection(const CAddress& addrConnect, bool fCountFai
24112441
if (IsLocal(addrConnect) || banned_or_discouraged || AlreadyConnectedToAddress(addrConnect)) {
24122442
return;
24132443
}
2414-
} else if (FindNode(std::string(pszDest)))
2415-
return;
2444+
} else {
2445+
auto existing_node = FindNode(std::string(pszDest));
2446+
if (existing_node && !existing_node->fDisconnect) return;
2447+
}
24162448

24172449
CNode* pnode = ConnectNode(addrConnect, pszDest, fCountFailure, conn_type);
24182450

src/net.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1060,6 +1060,8 @@ class CConnman
10601060
void NotifyNumConnectionsChanged();
10611061
/** Return true if the peer is inactive and should be disconnected. */
10621062
bool InactivityCheck(const CNode& node) const;
1063+
void DowngradeToV1Transport(CNode& node)
1064+
EXCLUSIVE_LOCKS_REQUIRED(!m_total_bytes_sent_mutex);
10631065

10641066
/**
10651067
* Generate a collection of sockets to check for IO readiness.

0 commit comments

Comments
 (0)