@@ -264,9 +264,31 @@ struct Peer {
264264
265265 /* * A vector of addresses to send to the peer, limited to MAX_ADDR_TO_SEND. */
266266 std::vector<CAddress> m_addrs_to_send;
267- /* * Probabilistic filter of addresses that this peer already knows.
268- * Used to avoid relaying addresses to this peer more than once. */
269- const std::unique_ptr<CRollingBloomFilter> m_addr_known;
267+ /* * Probabilistic filter to track recent addr messages relayed with this
268+ * peer. Used to avoid relaying redundant addresses to this peer.
269+ *
270+ * We initialize this filter for outbound peers (other than
271+ * block-relay-only connections) or when an inbound peer sends us an
272+ * address related message (ADDR, ADDRV2, GETADDR).
273+ *
274+ * Presence of this filter must correlate with m_addr_relay_enabled.
275+ **/
276+ std::unique_ptr<CRollingBloomFilter> m_addr_known;
277+ /* * Whether we are participating in address relay with this connection.
278+ *
279+ * We set this bool to true for outbound peers (other than
280+ * block-relay-only connections), or when an inbound peer sends us an
281+ * address related message (ADDR, ADDRV2, GETADDR).
282+ *
283+ * We use this bool to decide whether a peer is eligible for gossiping
284+ * addr messages. This avoids relaying to peers that are unlikely to
285+ * forward them, effectively blackholing self announcements. Reasons
286+ * peers might support addr relay on the link include that they connected
287+ * to us as a block-relay-only peer or they are a light client.
288+ *
289+ * This field must correlate with whether m_addr_known has been
290+ * initialized.*/
291+ std::atomic_bool m_addr_relay_enabled{false };
270292 /* * Whether a getaddr request to this peer is outstanding. */
271293 bool m_getaddr_sent{false };
272294 /* * Guards address sending timers. */
@@ -298,9 +320,8 @@ struct Peer {
298320 /* * Work queue of items requested by this peer **/
299321 std::deque<CInv> m_getdata_requests GUARDED_BY (m_getdata_requests_mutex);
300322
301- explicit Peer (NodeId id, bool addr_relay )
323+ explicit Peer (NodeId id)
302324 : m_id(id)
303- , m_addr_known{addr_relay ? std::make_unique<CRollingBloomFilter>(5000 , 0.001 ) : nullptr }
304325 {}
305326};
306327
@@ -523,6 +544,14 @@ class PeerManagerImpl final : public PeerManager
523544 */
524545 void ProcessGetCFCheckPt (CNode& peer, CDataStream& vRecv);
525546
547+ /* * Checks if address relay is permitted with peer. If needed, initializes
548+ * the m_addr_known bloom filter and sets m_addr_relay_enabled to true.
549+ *
550+ * @return True if address relay is enabled with peer
551+ * False if address relay is disallowed
552+ */
553+ bool SetupAddressRelay (CNode& node, Peer& peer);
554+
526555 /* * Number of nodes with fSyncStarted. */
527556 int nSyncStarted GUARDED_BY (cs_main) = 0;
528557
@@ -852,11 +881,6 @@ static CNodeState *State(NodeId pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
852881 return &it->second ;
853882}
854883
855- static bool RelayAddrsWithPeer (const Peer& peer)
856- {
857- return peer.m_addr_known != nullptr ;
858- }
859-
860884/* *
861885 * Whether the peer supports the address. For example, a peer that does not
862886 * implement BIP155 cannot receive Tor v3 addresses because it requires
@@ -1330,9 +1354,7 @@ void PeerManagerImpl::InitializeNode(CNode *pnode) {
13301354 mapNodeState.emplace_hint (mapNodeState.end (), std::piecewise_construct, std::forward_as_tuple (nodeid), std::forward_as_tuple (addr, pnode->IsInboundConn ()));
13311355 }
13321356 {
1333- // Addr relay is disabled for outbound block-relay-only peers to
1334- // prevent adversaries from inferring these links from addr traffic.
1335- PeerRef peer = std::make_shared<Peer>(nodeid, /* addr_relay = */ !pnode->IsBlockOnlyConn ());
1357+ PeerRef peer = std::make_shared<Peer>(nodeid);
13361358 LOCK (m_peer_mutex);
13371359 m_peer_map.emplace_hint (m_peer_map.end (), nodeid, std::move (peer));
13381360 }
@@ -1465,6 +1487,7 @@ bool PeerManagerImpl::GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats)
14651487 stats.m_ping_wait = ping_wait;
14661488 stats.m_addr_processed = peer->m_addr_processed .load ();
14671489 stats.m_addr_rate_limited = peer->m_addr_rate_limited .load ();
1490+ stats.m_addr_relay_enabled = peer->m_addr_relay_enabled .load ();
14681491
14691492 return true ;
14701493}
@@ -1654,7 +1677,7 @@ bool PeerManagerImpl::CanRelayAddrs(NodeId pnode) const
16541677 PeerRef peer = GetPeerRef (pnode);
16551678 if (peer == nullptr )
16561679 return false ;
1657- return RelayAddrsWithPeer (* peer) ;
1680+ return peer-> m_addr_relay_enabled ;
16581681}
16591682
16601683bool PeerManagerImpl::MaybePunishNodeForBlock (NodeId nodeid, const BlockValidationState& state,
@@ -2128,7 +2151,7 @@ void PeerManagerImpl::RelayAddress(NodeId originator,
21282151 LOCK (m_peer_mutex);
21292152
21302153 for (auto & [id, peer] : m_peer_map) {
2131- if (RelayAddrsWithPeer (* peer) && id != originator && IsAddrCompatible (*peer, addr)) {
2154+ if (peer-> m_addr_relay_enabled && id != originator && IsAddrCompatible (*peer, addr)) {
21322155 uint64_t hashKey = CSipHasher (hasher).Write (id).Finalize ();
21332156 for (unsigned int i = 0 ; i < nRelayNodes; i++) {
21342157 if (hashKey > best[i].first ) {
@@ -2354,7 +2377,7 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic
23542377 }
23552378 ++it;
23562379
2357- if (!RelayAddrsWithPeer ( peer) && NetMessageViolatesBlocksOnly (inv.GetCommand ())) {
2380+ if (!peer. m_addr_relay_enabled && NetMessageViolatesBlocksOnly (inv.GetCommand ())) {
23582381 // Note that if we receive a getdata for non-block messages
23592382 // from a block-relay-only outbound peer that violate the policy,
23602383 // we skip such getdata messages from this peer
@@ -3208,7 +3231,8 @@ void PeerManagerImpl::ProcessMessage(
32083231 UpdatePreferredDownload (pfrom, State (pfrom.GetId ()));
32093232 }
32103233
3211- if (!pfrom.IsInboundConn () && !pfrom.IsBlockOnlyConn ()) {
3234+ // Self advertisement & GETADDR logic
3235+ if (!pfrom.IsInboundConn () && SetupAddressRelay (pfrom, *peer)) {
32123236 // For outbound peers, we try to relay our address (so that other
32133237 // nodes can try to find us more quickly, as we have no guarantee
32143238 // that an outbound peer is even aware of how to reach us) and do a
@@ -3217,8 +3241,9 @@ void PeerManagerImpl::ProcessMessage(
32173241 // empty and no one will know who we are, so these mechanisms are
32183242 // important to help us connect to the network.
32193243 //
3220- // We skip this for block-relay-only peers to avoid potentially leaking
3221- // information about our block-relay-only connections via address relay.
3244+ // We skip this for block-relay-only peers. We want to avoid
3245+ // potentially leaking addr information and we do not want to
3246+ // indicate to the peer that we will participate in addr relay.
32223247 if (fListen && !m_chainman.ActiveChainstate ().IsInitialBlockDownload ())
32233248 {
32243249 CAddress addr = GetLocalAddress (&pfrom.addr , pfrom.GetLocalServices ());
@@ -3394,10 +3419,11 @@ void PeerManagerImpl::ProcessMessage(
33943419
33953420 s >> vAddr;
33963421
3397- if (!RelayAddrsWithPeer ( *peer)) {
3422+ if (!SetupAddressRelay (pfrom, *peer)) {
33983423 LogPrint (BCLog::NET, " ignoring %s message from %s peer=%d\n " , msg_type, pfrom.ConnectionTypeAsString (), pfrom.GetId ());
33993424 return ;
34003425 }
3426+
34013427 if (vAddr.size () > MAX_ADDR_TO_SEND)
34023428 {
34033429 Misbehaving (pfrom.GetId (), 20 , strprintf (" %s message size = %u" , msg_type, vAddr.size ()));
@@ -4371,6 +4397,8 @@ void PeerManagerImpl::ProcessMessage(
43714397 return ;
43724398 }
43734399
4400+ SetupAddressRelay (pfrom, *peer);
4401+
43744402 // Only send one GetAddr response per connection to reduce resource waste
43754403 // and discourage addr stamping of INV announcements.
43764404 if (peer->m_getaddr_recvd ) {
@@ -5025,7 +5053,7 @@ void PeerManagerImpl::MaybeSendPing(CNode& node_to, Peer& peer, std::chrono::mic
50255053void PeerManagerImpl::MaybeSendAddr (CNode& node, Peer& peer, std::chrono::microseconds current_time)
50265054{
50275055 // Nothing to do for non-address-relay peers
5028- if (!RelayAddrsWithPeer ( peer) ) return ;
5056+ if (!peer. m_addr_relay_enabled ) return ;
50295057
50305058 LOCK (peer.m_addr_send_times_mutex );
50315059 // Periodically advertise our local address to the peer.
@@ -5108,6 +5136,22 @@ class CompareInvMempoolOrder
51085136};
51095137}
51105138
5139+ bool PeerManagerImpl::SetupAddressRelay (CNode& node, Peer& peer)
5140+ {
5141+ // We don't participate in addr relay with outbound block-relay-only
5142+ // connections to prevent providing adversaries with the additional
5143+ // information of addr traffic to infer the link.
5144+ if (node.IsBlockOnlyConn ()) return false ;
5145+
5146+ if (!peer.m_addr_relay_enabled .exchange (true )) {
5147+ // First addr message we have received from the peer, initialize
5148+ // m_addr_known
5149+ peer.m_addr_known = std::make_unique<CRollingBloomFilter>(5000 , 0.001 );
5150+ }
5151+
5152+ return true ;
5153+ }
5154+
51115155bool PeerManagerImpl::SendMessages (CNode* pto)
51125156{
51135157 assert (m_llmq_ctx);
0 commit comments