mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-20 14:05:23 +01:00
[net_processing] Defer initializing m_addr_known
Use SetupAddressRelay to only initialize `m_addr_known` as needed. For outbound peers, we initialize the filter before sending our self announcement (not applicable for block-relay-only connections). For inbound peers, we initialize the filter when we get an addr related message (ADDR, ADDRV2, GETADDR). These changes intend to mitigate address blackholes. Since an inbound peer has to send us an addr related message to become eligible as a candidate for addr relay, this should reduce our likelihood of sending them self-announcements.
This commit is contained in:
parent
6653fa3328
commit
1d1ef2db7e
3 changed files with 22 additions and 11 deletions
|
@ -224,8 +224,13 @@ struct Peer {
|
|||
|
||||
/** A vector of addresses to send to the peer, limited to MAX_ADDR_TO_SEND. */
|
||||
std::vector<CAddress> m_addrs_to_send;
|
||||
/** Probabilistic filter of addresses that this peer already knows.
|
||||
* Used to avoid relaying addresses to this peer more than once. */
|
||||
/** Probabilistic filter to track recent addr messages relayed with this
|
||||
* peer. Used to avoid relaying redundant addresses to this peer.
|
||||
*
|
||||
* We initialize this filter for outbound peers (other than
|
||||
* block-relay-only connections) or when an inbound peer sends us an
|
||||
* address related message (ADDR, ADDRV2, GETADDR).
|
||||
**/
|
||||
std::unique_ptr<CRollingBloomFilter> m_addr_known;
|
||||
/** Whether a getaddr request to this peer is outstanding. */
|
||||
bool m_getaddr_sent{false};
|
||||
|
@ -258,9 +263,8 @@ struct Peer {
|
|||
/** Work queue of items requested by this peer **/
|
||||
std::deque<CInv> m_getdata_requests GUARDED_BY(m_getdata_requests_mutex);
|
||||
|
||||
explicit Peer(NodeId id, bool addr_relay)
|
||||
explicit Peer(NodeId id)
|
||||
: m_id(id)
|
||||
, m_addr_known{addr_relay ? std::make_unique<CRollingBloomFilter>(5000, 0.001) : nullptr}
|
||||
{}
|
||||
};
|
||||
|
||||
|
@ -1125,9 +1129,7 @@ void PeerManagerImpl::InitializeNode(CNode *pnode)
|
|||
assert(m_txrequest.Count(nodeid) == 0);
|
||||
}
|
||||
{
|
||||
// Addr relay is disabled for outbound block-relay-only peers to
|
||||
// prevent adversaries from inferring these links from addr traffic.
|
||||
PeerRef peer = std::make_shared<Peer>(nodeid, /* addr_relay = */ !pnode->IsBlockOnlyConn());
|
||||
PeerRef peer = std::make_shared<Peer>(nodeid);
|
||||
LOCK(m_peer_mutex);
|
||||
m_peer_map.emplace_hint(m_peer_map.end(), nodeid, std::move(peer));
|
||||
}
|
||||
|
@ -2580,7 +2582,8 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||
UpdatePreferredDownload(pfrom, State(pfrom.GetId()));
|
||||
}
|
||||
|
||||
if (!pfrom.IsInboundConn() && !pfrom.IsBlockOnlyConn()) {
|
||||
// Self advertisement & GETADDR logic
|
||||
if (!pfrom.IsInboundConn() && SetupAddressRelay(pfrom, *peer)) {
|
||||
// For outbound peers, we try to relay our address (so that other
|
||||
// nodes can try to find us more quickly, as we have no guarantee
|
||||
// that an outbound peer is even aware of how to reach us) and do a
|
||||
|
@ -2589,8 +2592,9 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||
// empty and no one will know who we are, so these mechanisms are
|
||||
// important to help us connect to the network.
|
||||
//
|
||||
// We skip this for block-relay-only peers to avoid potentially leaking
|
||||
// information about our block-relay-only connections via address relay.
|
||||
// We skip this for block-relay-only peers. We want to avoid
|
||||
// potentially leaking addr information and we do not want to
|
||||
// indicate to the peer that we will participate in addr relay.
|
||||
if (fListen && !m_chainman.ActiveChainstate().IsInitialBlockDownload())
|
||||
{
|
||||
CAddress addr = GetLocalAddress(&pfrom.addr, pfrom.GetLocalServices());
|
||||
|
@ -2788,10 +2792,11 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||
|
||||
s >> vAddr;
|
||||
|
||||
if (!RelayAddrsWithPeer(*peer)) {
|
||||
if (!SetupAddressRelay(pfrom, *peer)) {
|
||||
LogPrint(BCLog::NET, "ignoring %s message from %s peer=%d\n", msg_type, pfrom.ConnectionTypeAsString(), pfrom.GetId());
|
||||
return;
|
||||
}
|
||||
|
||||
if (vAddr.size() > MAX_ADDR_TO_SEND)
|
||||
{
|
||||
Misbehaving(pfrom.GetId(), 20, strprintf("%s message size = %u", msg_type, vAddr.size()));
|
||||
|
@ -3725,6 +3730,8 @@ void PeerManagerImpl::ProcessMessage(CNode& pfrom, const std::string& msg_type,
|
|||
return;
|
||||
}
|
||||
|
||||
SetupAddressRelay(pfrom, *peer);
|
||||
|
||||
// Only send one GetAddr response per connection to reduce resource waste
|
||||
// and discourage addr stamping of INV announcements.
|
||||
if (peer->m_getaddr_recvd) {
|
||||
|
|
|
@ -175,6 +175,9 @@ class AddrTest(BitcoinTestFramework):
|
|||
# of the outbound peer which is often sent before the GETADDR response.
|
||||
assert_equal(inbound_peer.num_ipv4_received, 0)
|
||||
|
||||
# Send an empty ADDR message to intialize address relay on this connection.
|
||||
inbound_peer.send_and_ping(msg_addr())
|
||||
|
||||
self.log.info('Check that subsequent addr messages sent from an outbound peer are relayed')
|
||||
msg2 = self.setup_addr_msg(2)
|
||||
self.send_addr_msg(full_outbound_peer, msg2, [inbound_peer])
|
||||
|
|
|
@ -438,6 +438,7 @@ class P2PInterface(P2PConnection):
|
|||
self.send_message(msg_sendaddrv2())
|
||||
self.send_message(msg_verack())
|
||||
self.nServices = message.nServices
|
||||
self.send_message(msg_getaddr())
|
||||
|
||||
# Connection helper methods
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue