aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/net.cpp5
-rwxr-xr-xtest/functional/p2p_getaddr_caching.py66
2 files changed, 57 insertions, 14 deletions
diff --git a/src/net.cpp b/src/net.cpp
index 00f2136f4a..82b5a69eb5 100644
--- a/src/net.cpp
+++ b/src/net.cpp
@@ -2814,8 +2814,11 @@ std::vector<CAddress> CConnman::GetAddresses(CNode& requestor, size_t max_addres
{
auto local_socket_bytes = requestor.addrBind.GetAddrBytes();
uint64_t cache_id = GetDeterministicRandomizer(RANDOMIZER_ID_ADDRCACHE)
- .Write(requestor.addr.GetNetwork())
+ .Write(requestor.ConnectedThroughNetwork())
.Write(local_socket_bytes.data(), local_socket_bytes.size())
+ // For outbound connections, the port of the bound address is randomly
+ // assigned by the OS and would therefore not be useful for seeding.
+ .Write(requestor.IsInboundConn() ? requestor.addrBind.GetPort() : 0)
.Finalize();
const auto current_time = GetTime<std::chrono::microseconds>();
auto r = m_addr_response_caches.emplace(cache_id, CachedAddrResponse{});
diff --git a/test/functional/p2p_getaddr_caching.py b/test/functional/p2p_getaddr_caching.py
index d375af6fe1..c934a97729 100755
--- a/test/functional/p2p_getaddr_caching.py
+++ b/test/functional/p2p_getaddr_caching.py
@@ -14,6 +14,8 @@ from test_framework.p2p import (
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
+ PORT_MIN,
+ PORT_RANGE,
)
# As defined in net_processing.
@@ -42,6 +44,13 @@ class AddrReceiver(P2PInterface):
class AddrTest(BitcoinTestFramework):
def set_test_params(self):
self.num_nodes = 1
+ # Start onion ports after p2p and rpc ports.
+ port = PORT_MIN + 2 * PORT_RANGE
+ self.onion_port1 = port
+ self.onion_port2 = port + 1
+ self.extra_args = [
+ [f"-bind=127.0.0.1:{self.onion_port1}=onion", f"-bind=127.0.0.1:{self.onion_port2}=onion"],
+ ]
def run_test(self):
self.log.info('Fill peer AddrMan with a lot of records')
@@ -55,35 +64,66 @@ class AddrTest(BitcoinTestFramework):
# only a fraction of all known addresses can be cached and returned.
assert(len(self.nodes[0].getnodeaddresses(0)) > int(MAX_ADDR_TO_SEND / (MAX_PCT_ADDR_TO_SEND / 100)))
- responses = []
+ last_response_on_local_bind = None
+ last_response_on_onion_bind1 = None
+ last_response_on_onion_bind2 = None
self.log.info('Send many addr requests within short time to receive same response')
N = 5
cur_mock_time = int(time.time())
for i in range(N):
- addr_receiver = self.nodes[0].add_p2p_connection(AddrReceiver())
- addr_receiver.send_and_ping(msg_getaddr())
+ addr_receiver_local = self.nodes[0].add_p2p_connection(AddrReceiver())
+ addr_receiver_local.send_and_ping(msg_getaddr())
+ addr_receiver_onion1 = self.nodes[0].add_p2p_connection(AddrReceiver(), dstport=self.onion_port1)
+ addr_receiver_onion1.send_and_ping(msg_getaddr())
+ addr_receiver_onion2 = self.nodes[0].add_p2p_connection(AddrReceiver(), dstport=self.onion_port2)
+ addr_receiver_onion2.send_and_ping(msg_getaddr())
+
# Trigger response
cur_mock_time += 5 * 60
self.nodes[0].setmocktime(cur_mock_time)
- addr_receiver.wait_until(addr_receiver.addr_received)
- responses.append(addr_receiver.get_received_addrs())
- for response in responses[1:]:
- assert_equal(response, responses[0])
- assert(len(response) == MAX_ADDR_TO_SEND)
+ addr_receiver_local.wait_until(addr_receiver_local.addr_received)
+ addr_receiver_onion1.wait_until(addr_receiver_onion1.addr_received)
+ addr_receiver_onion2.wait_until(addr_receiver_onion2.addr_received)
+
+ if i > 0:
+ # Responses from different binds should be unique
+ assert(last_response_on_local_bind != addr_receiver_onion1.get_received_addrs())
+ assert(last_response_on_local_bind != addr_receiver_onion2.get_received_addrs())
+ assert(last_response_on_onion_bind1 != addr_receiver_onion2.get_received_addrs())
+ # Responses on from the same bind should be the same
+ assert_equal(last_response_on_local_bind, addr_receiver_local.get_received_addrs())
+ assert_equal(last_response_on_onion_bind1, addr_receiver_onion1.get_received_addrs())
+ assert_equal(last_response_on_onion_bind2, addr_receiver_onion2.get_received_addrs())
+
+ last_response_on_local_bind = addr_receiver_local.get_received_addrs()
+ last_response_on_onion_bind1 = addr_receiver_onion1.get_received_addrs()
+ last_response_on_onion_bind2 = addr_receiver_onion2.get_received_addrs()
+
+ for response in [last_response_on_local_bind, last_response_on_onion_bind1, last_response_on_onion_bind2]:
+ assert_equal(len(response), MAX_ADDR_TO_SEND)
cur_mock_time += 3 * 24 * 60 * 60
self.nodes[0].setmocktime(cur_mock_time)
self.log.info('After time passed, see a new response to addr request')
- last_addr_receiver = self.nodes[0].add_p2p_connection(AddrReceiver())
- last_addr_receiver.send_and_ping(msg_getaddr())
+ addr_receiver_local = self.nodes[0].add_p2p_connection(AddrReceiver())
+ addr_receiver_local.send_and_ping(msg_getaddr())
+ addr_receiver_onion1 = self.nodes[0].add_p2p_connection(AddrReceiver(), dstport=self.onion_port1)
+ addr_receiver_onion1.send_and_ping(msg_getaddr())
+ addr_receiver_onion2 = self.nodes[0].add_p2p_connection(AddrReceiver(), dstport=self.onion_port2)
+ addr_receiver_onion2.send_and_ping(msg_getaddr())
+
# Trigger response
cur_mock_time += 5 * 60
self.nodes[0].setmocktime(cur_mock_time)
- last_addr_receiver.wait_until(last_addr_receiver.addr_received)
- # new response is different
- assert(set(responses[0]) != set(last_addr_receiver.get_received_addrs()))
+ addr_receiver_local.wait_until(addr_receiver_local.addr_received)
+ addr_receiver_onion1.wait_until(addr_receiver_onion1.addr_received)
+ addr_receiver_onion2.wait_until(addr_receiver_onion2.addr_received)
+ # new response is different
+ assert(set(last_response_on_local_bind) != set(addr_receiver_local.get_received_addrs()))
+ assert(set(last_response_on_onion_bind1) != set(addr_receiver_onion1.get_received_addrs()))
+ assert(set(last_response_on_onion_bind2) != set(addr_receiver_onion2.get_received_addrs()))
if __name__ == '__main__':
AddrTest().main()