@@ -264,9 +264,31 @@ struct Peer {
264
264
265
265
/* * A vector of addresses to send to the peer, limited to MAX_ADDR_TO_SEND. */
266
266
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 };
270
292
/* * Whether a getaddr request to this peer is outstanding. */
271
293
bool m_getaddr_sent{false };
272
294
/* * Guards address sending timers. */
@@ -298,9 +320,8 @@ struct Peer {
298
320
/* * Work queue of items requested by this peer **/
299
321
std::deque<CInv> m_getdata_requests GUARDED_BY (m_getdata_requests_mutex);
300
322
301
- explicit Peer (NodeId id, bool addr_relay )
323
+ explicit Peer (NodeId id)
302
324
: m_id(id)
303
- , m_addr_known{addr_relay ? std::make_unique<CRollingBloomFilter>(5000 , 0.001 ) : nullptr }
304
325
{}
305
326
};
306
327
@@ -523,6 +544,14 @@ class PeerManagerImpl final : public PeerManager
523
544
*/
524
545
void ProcessGetCFCheckPt (CNode& peer, CDataStream& vRecv);
525
546
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
+
526
555
/* * Number of nodes with fSyncStarted. */
527
556
int nSyncStarted GUARDED_BY (cs_main) = 0;
528
557
@@ -852,11 +881,6 @@ static CNodeState *State(NodeId pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main) {
852
881
return &it->second ;
853
882
}
854
883
855
- static bool RelayAddrsWithPeer (const Peer& peer)
856
- {
857
- return peer.m_addr_known != nullptr ;
858
- }
859
-
860
884
/* *
861
885
* Whether the peer supports the address. For example, a peer that does not
862
886
* implement BIP155 cannot receive Tor v3 addresses because it requires
@@ -1330,9 +1354,7 @@ void PeerManagerImpl::InitializeNode(CNode *pnode) {
1330
1354
mapNodeState.emplace_hint (mapNodeState.end (), std::piecewise_construct, std::forward_as_tuple (nodeid), std::forward_as_tuple (addr, pnode->IsInboundConn ()));
1331
1355
}
1332
1356
{
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);
1336
1358
LOCK (m_peer_mutex);
1337
1359
m_peer_map.emplace_hint (m_peer_map.end (), nodeid, std::move (peer));
1338
1360
}
@@ -1465,6 +1487,7 @@ bool PeerManagerImpl::GetNodeStateStats(NodeId nodeid, CNodeStateStats &stats)
1465
1487
stats.m_ping_wait = ping_wait;
1466
1488
stats.m_addr_processed = peer->m_addr_processed .load ();
1467
1489
stats.m_addr_rate_limited = peer->m_addr_rate_limited .load ();
1490
+ stats.m_addr_relay_enabled = peer->m_addr_relay_enabled .load ();
1468
1491
1469
1492
return true ;
1470
1493
}
@@ -1654,7 +1677,7 @@ bool PeerManagerImpl::CanRelayAddrs(NodeId pnode) const
1654
1677
PeerRef peer = GetPeerRef (pnode);
1655
1678
if (peer == nullptr )
1656
1679
return false ;
1657
- return RelayAddrsWithPeer (* peer) ;
1680
+ return peer-> m_addr_relay_enabled ;
1658
1681
}
1659
1682
1660
1683
bool PeerManagerImpl::MaybePunishNodeForBlock (NodeId nodeid, const BlockValidationState& state,
@@ -2128,7 +2151,7 @@ void PeerManagerImpl::RelayAddress(NodeId originator,
2128
2151
LOCK (m_peer_mutex);
2129
2152
2130
2153
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)) {
2132
2155
uint64_t hashKey = CSipHasher (hasher).Write (id).Finalize ();
2133
2156
for (unsigned int i = 0 ; i < nRelayNodes; i++) {
2134
2157
if (hashKey > best[i].first ) {
@@ -2354,7 +2377,7 @@ void PeerManagerImpl::ProcessGetData(CNode& pfrom, Peer& peer, const std::atomic
2354
2377
}
2355
2378
++it;
2356
2379
2357
- if (!RelayAddrsWithPeer ( peer) && NetMessageViolatesBlocksOnly (inv.GetCommand ())) {
2380
+ if (!peer. m_addr_relay_enabled && NetMessageViolatesBlocksOnly (inv.GetCommand ())) {
2358
2381
// Note that if we receive a getdata for non-block messages
2359
2382
// from a block-relay-only outbound peer that violate the policy,
2360
2383
// we skip such getdata messages from this peer
@@ -3208,7 +3231,8 @@ void PeerManagerImpl::ProcessMessage(
3208
3231
UpdatePreferredDownload (pfrom, State (pfrom.GetId ()));
3209
3232
}
3210
3233
3211
- if (!pfrom.IsInboundConn () && !pfrom.IsBlockOnlyConn ()) {
3234
+ // Self advertisement & GETADDR logic
3235
+ if (!pfrom.IsInboundConn () && SetupAddressRelay (pfrom, *peer)) {
3212
3236
// For outbound peers, we try to relay our address (so that other
3213
3237
// nodes can try to find us more quickly, as we have no guarantee
3214
3238
// that an outbound peer is even aware of how to reach us) and do a
@@ -3217,8 +3241,9 @@ void PeerManagerImpl::ProcessMessage(
3217
3241
// empty and no one will know who we are, so these mechanisms are
3218
3242
// important to help us connect to the network.
3219
3243
//
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.
3222
3247
if (fListen && !m_chainman.ActiveChainstate ().IsInitialBlockDownload ())
3223
3248
{
3224
3249
CAddress addr = GetLocalAddress (&pfrom.addr , pfrom.GetLocalServices ());
@@ -3394,10 +3419,11 @@ void PeerManagerImpl::ProcessMessage(
3394
3419
3395
3420
s >> vAddr;
3396
3421
3397
- if (!RelayAddrsWithPeer ( *peer)) {
3422
+ if (!SetupAddressRelay (pfrom, *peer)) {
3398
3423
LogPrint (BCLog::NET, " ignoring %s message from %s peer=%d\n " , msg_type, pfrom.ConnectionTypeAsString (), pfrom.GetId ());
3399
3424
return ;
3400
3425
}
3426
+
3401
3427
if (vAddr.size () > MAX_ADDR_TO_SEND)
3402
3428
{
3403
3429
Misbehaving (pfrom.GetId (), 20 , strprintf (" %s message size = %u" , msg_type, vAddr.size ()));
@@ -4371,6 +4397,8 @@ void PeerManagerImpl::ProcessMessage(
4371
4397
return ;
4372
4398
}
4373
4399
4400
+ SetupAddressRelay (pfrom, *peer);
4401
+
4374
4402
// Only send one GetAddr response per connection to reduce resource waste
4375
4403
// and discourage addr stamping of INV announcements.
4376
4404
if (peer->m_getaddr_recvd ) {
@@ -5025,7 +5053,7 @@ void PeerManagerImpl::MaybeSendPing(CNode& node_to, Peer& peer, std::chrono::mic
5025
5053
void PeerManagerImpl::MaybeSendAddr (CNode& node, Peer& peer, std::chrono::microseconds current_time)
5026
5054
{
5027
5055
// Nothing to do for non-address-relay peers
5028
- if (!RelayAddrsWithPeer ( peer) ) return ;
5056
+ if (!peer. m_addr_relay_enabled ) return ;
5029
5057
5030
5058
LOCK (peer.m_addr_send_times_mutex );
5031
5059
// Periodically advertise our local address to the peer.
@@ -5108,6 +5136,22 @@ class CompareInvMempoolOrder
5108
5136
};
5109
5137
}
5110
5138
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
+
5111
5155
bool PeerManagerImpl::SendMessages (CNode* pto)
5112
5156
{
5113
5157
assert (m_llmq_ctx);
0 commit comments