p2p: first addr self-announcement in separate msg

This makes sure the initial address self-announcement a node sends to
a peer happends in a separate P2P message. This has benefits for both
inbound and outbound connections:

For inbound connections from a peer to us, previously, we might send
the self-announcement along with our response to a GETADDR request.
However, the self-announcement might replace an address from the
GETADDR response. This isn't clean.

For outbound connections from us to a peer, previously, it could have
happend that we send the self-announcement along with other addresses.
Since shortly after connection open, the peer might only have one
rate-limiting token for us, and the addresses are shuffeld on arrival,
it's possible that the self-announcement gets rate-limited. However,
note that these rate-limitings seem to be rare in practice.

This is inspired by and based on https://github.com/bitcoin/bitcoin/pull/33699#issuecomment-3462287763

Co-Authored-By: Anthony Towns <aj@erisian.com.au>
This commit is contained in:
0xb10c
2025-12-01 13:57:45 +01:00
parent d861c38205
commit 792e2edf57
2 changed files with 27 additions and 4 deletions

View File

@@ -5328,7 +5328,20 @@ void PeerManagerImpl::MaybeSendAddr(CNode& node, Peer& peer, std::chrono::micros
}
if (std::optional<CService> local_service = GetLocalAddrForPeer(node)) {
CAddress local_addr{*local_service, peer.m_our_services, Now<NodeSeconds>()};
PushAddress(peer, local_addr);
if (peer.m_next_local_addr_send == 0us) {
// Send the initial self-announcement in its own message. This makes sure
// rate-limiting with limited start-tokens doesn't ignore it if the first
// message ends up containing multiple addresses.
std::vector<CAddress> self_announcement {local_addr};
if (peer.m_wants_addrv2) {
MakeAndPushMessage(node, NetMsgType::ADDRV2, CAddress::V2_NETWORK(self_announcement));
} else {
MakeAndPushMessage(node, NetMsgType::ADDR, CAddress::V1_NETWORK(self_announcement));
}
} else {
// All later self-announcements are sent together with the other addresses.
PushAddress(peer, local_addr);
}
}
peer.m_next_local_addr_send = current_time + m_rng.rand_exp_duration(AVG_LOCAL_ADDRESS_BROADCAST_INTERVAL);
}