p2p: Assume v2transport for addresses from seeds
What changed, and why it matters
This change makes Bitcoin Core assume that hard-coded and DNS seed nodes support the newer BIP324 encrypted transport (v2) when first connecting. If the guess is wrong, the software falls back to the older v1 protocol automatically. It is a network-hardening/performance tweak, not a fix for an exploitable vulnerability.
No security action required. Treat as a routine protocol-optimization change. Reviewers may verify that the v1 fallback path remains intact and that seed addresses with incorrect v2 flags do not cause persistent connection failures.
Security signals we found
Adds NODE_P2P_V2 to assumed service flags for seed-derived addresses
Fallback to v1 transport exists if the v2 assumption is wrong
No input validation, memory safety, or cryptographic changes
No mention of vulnerability, CVE, bug bounty, or security incident
Evidence from the diff
The commit introduces SeedsAssumedServiceFlags(), which adds NODE_P2P_V2 to the service flags used for addresses from fixed seeds and DNS seeds. ConvertSeeds() and ThreadDNSAddressSeed() now use this helper instead of SeedsServiceFlags() or requiredServiceBits. The rationale is that most listening nodes now signal BIP324 support, and an incorrect optimistic assumption only triggers a v1 reconnect, so there is no loss of connectivity.
Changed components
src/net.cpp: ConvertSeeds()src/net.cpp: ThreadDNSAddressSeed()src/protocol.h: new SeedsAssumedServiceFlags() helperInspect captured patch +10 / −2
diff --git a/src/net.cpp b/src/net.cpp
index 73a062fe..0b50172a 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -206,7 +206,7 @@ static std::vector<CAddress> ConvertSeeds(const std::vector<uint8_t> &vSeedsIn)
while (!s.empty()) {
CService endpoint;
s >> endpoint;
- CAddress addr{endpoint, SeedsServiceFlags()};
+ CAddress addr{endpoint, SeedsAssumedServiceFlags()};
addr.nTime = rng.rand_uniform_delay(Now<NodeSeconds>() - one_week, -one_week);
LogDebug(BCLog::NET, "Added hardcoded seed: %s\n", addr.ToStringAddrPort());
vSeedsOut.push_back(addr);
@@ -2400,7 +2400,7 @@ void CConnman::ThreadDNSAddressSeed()
const auto addresses{LookupHost(host, nMaxIPs, true)};
if (!addresses.empty()) {
for (const CNetAddr& ip : addresses) {
- CAddress addr = CAddress(CService(ip, m_params.GetDefaultPort()), requiredServiceBits);
+ CAddress addr = CAddress(CService(ip, m_params.GetDefaultPort()), SeedsAssumedServiceFlags());
addr.nTime = rng.rand_uniform_delay(Now<NodeSeconds>() - 3 * 24h, -4 * 24h); // use a random age between 3 and 7 days old
vAdd.push_back(addr);
found++;
diff --git a/src/protocol.h b/src/protocol.h
index 24851e2f..a15a3aa6 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -365,6 +365,14 @@ std::vector<std::string> serviceFlagsToStr(uint64_t flags);
*/
constexpr ServiceFlags SeedsServiceFlags() { return ServiceFlags(NODE_NETWORK | NODE_WITNESS); }
+/**
+ * Service flags we assume for addresses obtained from the DNS seeds and the
+ * fixed seeds, which don't come with service flags attached.
+ * BIP324 support can be safely assumed because the vast majority of listening nodes signals NODE_P2P_V2, and if the
+ * assumption is wrong for a given peer we simply reconnect using v1 transport.
+ */
+constexpr ServiceFlags SeedsAssumedServiceFlags() { return ServiceFlags(SeedsServiceFlags() | NODE_P2P_V2); }
+
/**
* Checks if a peer with the given service flags may be capable of having a
* robust address-storage DB.
Why this scored 19/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.