From 2fcaec7bbb96d6fe72a7e3a5744b0c35c79733e8 Mon Sep 17 00:00:00 2001 From: Amiti Uttarwar Date: Mon, 22 Mar 2021 15:48:17 -0700 Subject: [PATCH 1/8] [net_processing] Introduce SetupAddressRelay Idempotent function that initializes m_addr_known for connections that support address relay (anything other than block-relay-only). Unused until the next commit. --- src/net_processing.cpp | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index a0c346b99f..1d53d1a1b7 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -226,7 +226,7 @@ struct Peer { std::vector m_addrs_to_send; /** Probabilistic filter of addresses that this peer already knows. * Used to avoid relaying addresses to this peer more than once. */ - const std::unique_ptr m_addr_known; + std::unique_ptr m_addr_known; /** Whether a getaddr request to this peer is outstanding. */ bool m_getaddr_sent{false}; /** Guards address sending timers. */ @@ -612,6 +612,14 @@ private: * @param[in] vRecv The raw message received */ void ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv); + + /** Checks if address relay is permitted with peer. Initializes + * `m_addr_known` bloom filter if needed. + * + * @return True if address relay is enabled with peer + * False if address relay is disallowed + */ + bool SetupAddressRelay(CNode& node, Peer& peer); }; } // namespace @@ -4423,6 +4431,22 @@ public: }; } +bool PeerManagerImpl::SetupAddressRelay(CNode& node, Peer& peer) +{ + // We don't participate in addr relay with outbound block-relay-only + // connections to prevent providing adversaries with the additional + // information of addr traffic to infer the link. + if (node.IsBlockOnlyConn()) return false; + + if (!RelayAddrsWithPeer(peer)) { + // First addr message we have received from the peer, initialize + // m_addr_known + peer.m_addr_known = std::make_unique(5000, 0.001); + } + + return true; +} + bool PeerManagerImpl::SendMessages(CNode* pto) { PeerRef peer = GetPeerRef(pto->GetId()); From 6653fa3328b5608fcceda1c6ea8e68c5d58739ec Mon Sep 17 00:00:00 2001 From: Amiti Uttarwar Date: Mon, 21 Jun 2021 19:15:07 -0700 Subject: [PATCH 2/8] [test] Update p2p_addr_relay test to prepare Use an init param to make clear whether a getaddr message should be sent when the P2PConnection receives a version message. These changes are in preparation for upcoming commits that modify the behavior of a bitcoind node and the test framework. --- test/functional/p2p_addr_relay.py | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/test/functional/p2p_addr_relay.py b/test/functional/p2p_addr_relay.py index ff1d85a9be..7b7bcfc917 100755 --- a/test/functional/p2p_addr_relay.py +++ b/test/functional/p2p_addr_relay.py @@ -11,7 +11,8 @@ from test_framework.messages import ( NODE_NETWORK, NODE_WITNESS, msg_addr, - msg_getaddr + msg_getaddr, + msg_verack ) from test_framework.p2p import ( P2PInterface, @@ -27,10 +28,12 @@ class AddrReceiver(P2PInterface): num_ipv4_received = 0 test_addr_contents = False _tokens = 1 + send_getaddr = True - def __init__(self, test_addr_contents=False): + def __init__(self, test_addr_contents=False, send_getaddr=True): super().__init__() self.test_addr_contents = test_addr_contents + self.send_getaddr = send_getaddr def on_addr(self, message): for addr in message.addrs: @@ -60,6 +63,11 @@ class AddrReceiver(P2PInterface): def addr_received(self): return self.num_ipv4_received != 0 + def on_version(self, message): + self.send_message(msg_verack()) + if (self.send_getaddr): + self.send_message(msg_getaddr()) + def getaddr_received(self): return self.message_count['getaddr'] > 0 @@ -156,7 +164,7 @@ class AddrTest(BitcoinTestFramework): self.nodes[0].disconnect_p2ps() self.log.info('Check relay of addresses received from outbound peers') - inbound_peer = self.nodes[0].add_p2p_connection(AddrReceiver(test_addr_contents=True)) + inbound_peer = self.nodes[0].add_p2p_connection(AddrReceiver(test_addr_contents=True, send_getaddr=False)) full_outbound_peer = self.nodes[0].add_outbound_p2p_connection(AddrReceiver(), p2p_idx=0, connection_type="outbound-full-relay") msg = self.setup_addr_msg(2) self.send_addr_msg(full_outbound_peer, msg, [inbound_peer]) @@ -185,6 +193,12 @@ class AddrTest(BitcoinTestFramework): self.nodes[0].disconnect_p2ps() def getaddr_tests(self): + # In the previous tests, the node answered GETADDR requests with an + # empty addrman. Due to GETADDR response caching (see + # CConnman::GetAddresses), the node would continue to provide 0 addrs + # in response until enough time has passed or the node is restarted. + self.restart_node(0) + self.log.info('Test getaddr behavior') self.log.info('Check that we send a getaddr message upon connecting to an outbound-full-relay peer') full_outbound_peer = self.nodes[0].add_outbound_p2p_connection(AddrReceiver(), p2p_idx=0, connection_type="outbound-full-relay") @@ -197,7 +211,7 @@ class AddrTest(BitcoinTestFramework): assert_equal(block_relay_peer.getaddr_received(), False) self.log.info('Check that we answer getaddr messages only from inbound peers') - inbound_peer = self.nodes[0].add_p2p_connection(AddrReceiver()) + inbound_peer = self.nodes[0].add_p2p_connection(AddrReceiver(send_getaddr=False)) inbound_peer.sync_with_ping() # Add some addresses to addrman From 1d1ef2db7ea0d93c7dab4a9800ec74afa7a019eb Mon Sep 17 00:00:00 2001 From: Amiti Uttarwar Date: Wed, 24 Mar 2021 15:01:05 -0700 Subject: [PATCH 3/8] [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. --- src/net_processing.cpp | 29 +++++++++++++++++---------- test/functional/p2p_addr_relay.py | 3 +++ test/functional/test_framework/p2p.py | 1 + 3 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 1d53d1a1b7..fe20421a21 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -224,8 +224,13 @@ struct Peer { /** A vector of addresses to send to the peer, limited to MAX_ADDR_TO_SEND. */ std::vector 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 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 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(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(nodeid, /* addr_relay = */ !pnode->IsBlockOnlyConn()); + PeerRef peer = std::make_shared(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) { diff --git a/test/functional/p2p_addr_relay.py b/test/functional/p2p_addr_relay.py index 7b7bcfc917..c8c1120462 100755 --- a/test/functional/p2p_addr_relay.py +++ b/test/functional/p2p_addr_relay.py @@ -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]) diff --git a/test/functional/test_framework/p2p.py b/test/functional/test_framework/p2p.py index cc80b543cd..b7d5bd8fab 100755 --- a/test/functional/test_framework/p2p.py +++ b/test/functional/test_framework/p2p.py @@ -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 From 201e4964816f8896cfe7b4f6d8ddbfffe7102f87 Mon Sep 17 00:00:00 2001 From: Amiti Uttarwar Date: Mon, 26 Jul 2021 11:48:58 -0700 Subject: [PATCH 4/8] [net_processing] Introduce new field to indicate if addr relay is enabled --- src/net_processing.cpp | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index fe20421a21..e9bb4f2211 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -230,8 +230,25 @@ struct 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). + * + * Presence of this filter must correlate with m_addr_relay_enabled. **/ std::unique_ptr m_addr_known; + /** Whether we are participating in address relay with this connection. + * + * We set this bool to true for outbound peers (other than + * block-relay-only connections), or when an inbound peer sends us an + * address related message (ADDR, ADDRV2, GETADDR). + * + * We use this bool to decide whether a peer is eligible for gossiping + * addr messages. This avoids relaying to peers that are unlikely to + * forward them, effectively blackholing self announcements. Reasons + * peers might support addr relay on the link include that they connected + * to us as a block-relay-only peer or they are a light client. + * + * This field must correlate with whether m_addr_known has been + * initialized.*/ + std::atomic_bool m_addr_relay_enabled{false}; /** Whether a getaddr request to this peer is outstanding. */ bool m_getaddr_sent{false}; /** Guards address sending timers. */ @@ -617,8 +634,8 @@ private: */ void ProcessGetCFCheckPt(CNode& peer, CDataStream& vRecv); - /** Checks if address relay is permitted with peer. Initializes - * `m_addr_known` bloom filter if needed. + /** Checks if address relay is permitted with peer. If needed, initializes + * the m_addr_known bloom filter and sets m_addr_relay_enabled to true. * * @return True if address relay is enabled with peer * False if address relay is disallowed @@ -746,7 +763,7 @@ static CNodeState *State(NodeId pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { static bool RelayAddrsWithPeer(const Peer& peer) { - return peer.m_addr_known != nullptr; + return peer.m_addr_relay_enabled; } /** @@ -4449,6 +4466,7 @@ bool PeerManagerImpl::SetupAddressRelay(CNode& node, Peer& peer) // First addr message we have received from the peer, initialize // m_addr_known peer.m_addr_known = std::make_unique(5000, 0.001); + peer.m_addr_relay_enabled = true; } return true; From c061599e40dc3d379c10b914765061a7a8449dd7 Mon Sep 17 00:00:00 2001 From: Amiti Uttarwar Date: Mon, 26 Jul 2021 11:54:07 -0700 Subject: [PATCH 5/8] [net_processing] Remove RelayAddrsWithPeer function Now that we have a simple boolean stored on the field, the wrapper function is no longer necessary. --- src/net_processing.cpp | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index e9bb4f2211..5103824ee1 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -761,11 +761,6 @@ static CNodeState *State(NodeId pnode) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return &it->second; } -static bool RelayAddrsWithPeer(const Peer& peer) -{ - return peer.m_addr_relay_enabled; -} - /** * Whether the peer supports the address. For example, a peer that does not * implement BIP155 cannot receive Tor v3 addresses because it requires @@ -1708,7 +1703,7 @@ void PeerManagerImpl::RelayAddress(NodeId originator, LOCK(m_peer_mutex); for (auto& [id, peer] : m_peer_map) { - if (RelayAddrsWithPeer(*peer) && id != originator && IsAddrCompatible(*peer, addr)) { + if (peer->m_addr_relay_enabled && id != originator && IsAddrCompatible(*peer, addr)) { uint64_t hashKey = CSipHasher(hasher).Write(id).Finalize(); for (unsigned int i = 0; i < nRelayNodes; i++) { if (hashKey > best[i].first) { @@ -4327,7 +4322,7 @@ void PeerManagerImpl::MaybeSendPing(CNode& node_to, Peer& peer, std::chrono::mic void PeerManagerImpl::MaybeSendAddr(CNode& node, Peer& peer, std::chrono::microseconds current_time) { // Nothing to do for non-address-relay peers - if (!RelayAddrsWithPeer(peer)) return; + if (!peer.m_addr_relay_enabled) return; LOCK(peer.m_addr_send_times_mutex); // Periodically advertise our local address to the peer. @@ -4462,11 +4457,10 @@ bool PeerManagerImpl::SetupAddressRelay(CNode& node, Peer& peer) // information of addr traffic to infer the link. if (node.IsBlockOnlyConn()) return false; - if (!RelayAddrsWithPeer(peer)) { + if (!peer.m_addr_relay_enabled.exchange(true)) { // First addr message we have received from the peer, initialize // m_addr_known peer.m_addr_known = std::make_unique(5000, 0.001); - peer.m_addr_relay_enabled = true; } return true; From 0980ca78cd930a00c9985d7f00083a3b8e8be89e Mon Sep 17 00:00:00 2001 From: Amiti Uttarwar Date: Sun, 13 Jun 2021 22:08:54 -0700 Subject: [PATCH 6/8] [test] Test that we intentionally select addr relay peers. This test checks that we only relay addresses with inbound peers who have sent us an addr related message. Uses a combination of GETADDR and ADDR to verify when peers are eligible. --- test/functional/p2p_addr_relay.py | 49 ++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) diff --git a/test/functional/p2p_addr_relay.py b/test/functional/p2p_addr_relay.py index c8c1120462..4233d8d010 100755 --- a/test/functional/p2p_addr_relay.py +++ b/test/functional/p2p_addr_relay.py @@ -19,7 +19,7 @@ from test_framework.p2p import ( p2p_lock, ) from test_framework.test_framework import BitcoinTestFramework -from test_framework.util import assert_equal +from test_framework.util import assert_equal, assert_greater_than import random import time @@ -83,6 +83,10 @@ class AddrTest(BitcoinTestFramework): def run_test(self): self.oversized_addr_test() self.relay_tests() + self.inbound_blackhole_tests() + + # This test populates the addrman, which can impact the node's behavior + # in subsequent tests self.getaddr_tests() self.blocksonly_mode_tests() self.rate_limit_tests() @@ -195,6 +199,49 @@ class AddrTest(BitcoinTestFramework): self.nodes[0].disconnect_p2ps() + def sum_addr_messages(self, msgs_dict): + return sum(bytes_received for (msg, bytes_received) in msgs_dict.items() if msg in ['addr', 'addrv2', 'getaddr']) + + def inbound_blackhole_tests(self): + self.log.info('Check that we only relay addresses to inbound peers who have previously sent us addr related messages') + + addr_source = self.nodes[0].add_p2p_connection(P2PInterface()) + receiver_peer = self.nodes[0].add_p2p_connection(AddrReceiver()) + blackhole_peer = self.nodes[0].add_p2p_connection(AddrReceiver(send_getaddr=False)) + initial_addrs_received = receiver_peer.num_ipv4_received + + # addr_source sends 2 addresses to node0 + msg = self.setup_addr_msg(2) + addr_source.send_and_ping(msg) + self.mocktime += 30 * 60 + self.nodes[0].setmocktime(self.mocktime) + receiver_peer.sync_with_ping() + blackhole_peer.sync_with_ping() + + peerinfo = self.nodes[0].getpeerinfo() + + # Confirm node received addr-related messages from receiver peer + assert_greater_than(self.sum_addr_messages(peerinfo[1]['bytesrecv_per_msg']), 0) + # And that peer received addresses + assert_equal(receiver_peer.num_ipv4_received - initial_addrs_received, 2) + + # Confirm node has not received addr-related messages from blackhole peer + assert_equal(self.sum_addr_messages(peerinfo[2]['bytesrecv_per_msg']), 0) + # And that peer did not receive addresses + assert_equal(blackhole_peer.num_ipv4_received, 0) + + self.log.info("After blackhole peer sends addr message, it becomes eligible for addr gossip") + blackhole_peer.send_and_ping(msg_addr()) + msg = self.setup_addr_msg(2) + self.send_addr_msg(addr_source, msg, [receiver_peer, blackhole_peer]) + + # Confirm node has now received addr-related messages from blackhole peer + assert_greater_than(self.sum_addr_messages(peerinfo[1]['bytesrecv_per_msg']), 0) + # And that peer received addresses + assert_equal(blackhole_peer.num_ipv4_received, 2) + + self.nodes[0].disconnect_p2ps() + def getaddr_tests(self): # In the previous tests, the node answered GETADDR requests with an # empty addrman. Due to GETADDR response caching (see From 3893da06db1eb622f540605700f8663f8d87b2df Mon Sep 17 00:00:00 2001 From: Amiti Uttarwar Date: Mon, 26 Jul 2021 12:08:07 -0700 Subject: [PATCH 7/8] [RPC] Add field to getpeerinfo to indicate if addr relay is enabled --- src/net_processing.cpp | 1 + src/net_processing.h | 1 + src/rpc/net.cpp | 2 ++ 3 files changed, 4 insertions(+) diff --git a/src/net_processing.cpp b/src/net_processing.cpp index 5103824ee1..24b55eb5cf 100644 --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -1279,6 +1279,7 @@ bool PeerManagerImpl::GetNodeStateStats(NodeId nodeid, CNodeStateStats& stats) c stats.m_ping_wait = ping_wait; stats.m_addr_processed = peer->m_addr_processed.load(); stats.m_addr_rate_limited = peer->m_addr_rate_limited.load(); + stats.m_addr_relay_enabled = peer->m_addr_relay_enabled.load(); return true; } diff --git a/src/net_processing.h b/src/net_processing.h index c537efb5db..4532a0505e 100644 --- a/src/net_processing.h +++ b/src/net_processing.h @@ -31,6 +31,7 @@ struct CNodeStateStats { std::vector vHeightInFlight; uint64_t m_addr_processed = 0; uint64_t m_addr_rate_limited = 0; + bool m_addr_relay_enabled{false}; }; class PeerManager : public CValidationInterface, public NetEventsInterface diff --git a/src/rpc/net.cpp b/src/rpc/net.cpp index dba0f971b2..3962a13924 100644 --- a/src/rpc/net.cpp +++ b/src/rpc/net.cpp @@ -118,6 +118,7 @@ static RPCHelpMan getpeerinfo() {RPCResult::Type::STR, "addr", "(host:port) The IP address and port of the peer"}, {RPCResult::Type::STR, "addrbind", "(ip:port) Bind address of the connection to the peer"}, {RPCResult::Type::STR, "addrlocal", "(ip:port) Local address as reported by the peer"}, + {RPCResult::Type::BOOL, "addr_relay_enabled", "Whether we participate in address relay with this peer"}, {RPCResult::Type::STR, "network", "Network (" + Join(GetNetworkNames(/* append_unroutable */ true), ", ") + ")"}, {RPCResult::Type::NUM, "mapped_as", "The AS in the BGP route to the peer used for diversifying\n" "peer selection (only available if the asmap config flag is set)"}, @@ -201,6 +202,7 @@ static RPCHelpMan getpeerinfo() if (!(stats.addrLocal.empty())) { obj.pushKV("addrlocal", stats.addrLocal); } + obj.pushKV("addr_relay_enabled", statestats.m_addr_relay_enabled); obj.pushKV("network", GetNetworkName(stats.m_network)); if (stats.m_mapped_as != 0) { obj.pushKV("mapped_as", uint64_t(stats.m_mapped_as)); From 3f7250b328b8b2f5d63f323702445ac5c989b73d Mon Sep 17 00:00:00 2001 From: Amiti Uttarwar Date: Fri, 23 Jul 2021 18:19:32 -0700 Subject: [PATCH 8/8] [test] Use the new endpoint to improve tests --- test/functional/p2p_addr_relay.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/test/functional/p2p_addr_relay.py b/test/functional/p2p_addr_relay.py index 4233d8d010..95743a1bf5 100755 --- a/test/functional/p2p_addr_relay.py +++ b/test/functional/p2p_addr_relay.py @@ -210,6 +210,11 @@ class AddrTest(BitcoinTestFramework): blackhole_peer = self.nodes[0].add_p2p_connection(AddrReceiver(send_getaddr=False)) initial_addrs_received = receiver_peer.num_ipv4_received + peerinfo = self.nodes[0].getpeerinfo() + assert_equal(peerinfo[0]['addr_relay_enabled'], True) # addr_source + assert_equal(peerinfo[1]['addr_relay_enabled'], True) # receiver_peer + assert_equal(peerinfo[2]['addr_relay_enabled'], False) # blackhole_peer + # addr_source sends 2 addresses to node0 msg = self.setup_addr_msg(2) addr_source.send_and_ping(msg) @@ -232,11 +237,14 @@ class AddrTest(BitcoinTestFramework): self.log.info("After blackhole peer sends addr message, it becomes eligible for addr gossip") blackhole_peer.send_and_ping(msg_addr()) - msg = self.setup_addr_msg(2) - self.send_addr_msg(addr_source, msg, [receiver_peer, blackhole_peer]) # Confirm node has now received addr-related messages from blackhole peer assert_greater_than(self.sum_addr_messages(peerinfo[1]['bytesrecv_per_msg']), 0) + assert_equal(self.nodes[0].getpeerinfo()[2]['addr_relay_enabled'], True) + + msg = self.setup_addr_msg(2) + self.send_addr_msg(addr_source, msg, [receiver_peer, blackhole_peer]) + # And that peer received addresses assert_equal(blackhole_peer.num_ipv4_received, 2)