Skip to content

Commit a3cc1ff

Browse files
authored
Merge pull request #46 from antonyip/master
Update p2p_* tests from bitcoin core
2 parents ceb5ec3 + ac14939 commit a3cc1ff

24 files changed

+740
-262
lines changed

test/functional/p2p_addr_relay.py

+122-36
Original file line numberDiff line numberDiff line change
@@ -13,53 +13,72 @@
1313
msg_addr,
1414
msg_getaddr
1515
)
16-
from test_framework.p2p import P2PInterface
17-
from test_framework.test_framework import BGLTestFramework
18-
from test_framework.util import (
19-
assert_equal,
16+
from test_framework.p2p import (
17+
P2PInterface,
18+
p2p_lock,
2019
)
20+
from test_framework.test_framework import BGLTestFramework
21+
from test_framework.util import assert_equal
22+
import random
2123
import time
2224

2325

2426
class AddrReceiver(P2PInterface):
2527
num_ipv4_received = 0
28+
test_addr_contents = False
29+
_tokens = 1
30+
31+
def __init__(self, test_addr_contents=False):
32+
super().__init__()
33+
self.test_addr_contents = test_addr_contents
2634

2735
def on_addr(self, message):
2836
for addr in message.addrs:
29-
assert_equal(addr.nServices, 9)
30-
if not 8333 <= addr.port < 8343:
31-
raise AssertionError("Invalid addr.port of {} (8333-8342 expected)".format(addr.port))
32-
assert addr.ip.startswith('123.123.123.')
3337
self.num_ipv4_received += 1
34-
35-
36-
class GetAddrStore(P2PInterface):
37-
getaddr_received = False
38-
num_ipv4_received = 0
38+
if(self.test_addr_contents):
39+
# relay_tests checks the content of the addr messages match
40+
# expectations based on the message creation in setup_addr_msg
41+
assert_equal(addr.nServices, 9)
42+
if not 8333 <= addr.port < 8343:
43+
raise AssertionError("Invalid addr.port of {} (8333-8342 expected)".format(addr.port))
44+
assert addr.ip.startswith('123.123.123.')
3945

4046
def on_getaddr(self, message):
41-
self.getaddr_received = True
47+
# When the node sends us a getaddr, it increments the addr relay tokens for the connection by 1000
48+
self._tokens += 1000
4249

43-
def on_addr(self, message):
44-
for addr in message.addrs:
45-
self.num_ipv4_received += 1
50+
@property
51+
def tokens(self):
52+
with p2p_lock:
53+
return self._tokens
54+
55+
def increment_tokens(self, n):
56+
# When we move mocktime forward, the node increments the addr relay tokens for its peers
57+
with p2p_lock:
58+
self._tokens += n
4659

4760
def addr_received(self):
4861
return self.num_ipv4_received != 0
4962

63+
def getaddr_received(self):
64+
return self.message_count['getaddr'] > 0
65+
5066

5167
class AddrTest(BGLTestFramework):
5268
counter = 0
5369
mocktime = int(time.time())
5470

5571
def set_test_params(self):
5672
self.num_nodes = 1
73+
self.extra_args = [["[email protected]"]]
5774

5875
def run_test(self):
5976
self.oversized_addr_test()
6077
self.relay_tests()
6178
self.getaddr_tests()
6279
self.blocksonly_mode_tests()
80+
# Not sure if supported by BGL
81+
#self.rate_limit_tests()
6382

6483
def setup_addr_msg(self, num):
6584
addrs = []
@@ -76,13 +95,26 @@ def setup_addr_msg(self, num):
7695
msg.addrs = addrs
7796
return msg
7897

98+
def setup_rand_addr_msg(self, num):
99+
addrs = []
100+
for i in range(num):
101+
addr = CAddress()
102+
addr.time = self.mocktime + i
103+
addr.nServices = NODE_NETWORK | NODE_WITNESS
104+
addr.ip = f"{random.randrange(128,169)}.{random.randrange(1,255)}.{random.randrange(1,255)}.{random.randrange(1,255)}"
105+
addr.port = 8333
106+
addrs.append(addr)
107+
msg = msg_addr()
108+
msg.addrs = addrs
109+
return msg
110+
79111
def send_addr_msg(self, source, msg, receivers):
80112
source.send_and_ping(msg)
81113
# pop m_next_addr_send timer
82-
self.mocktime += 5 * 60
114+
self.mocktime += 10 * 60
83115
self.nodes[0].setmocktime(self.mocktime)
84116
for peer in receivers:
85-
peer.sync_with_ping()
117+
peer.sync_send_with_ping()
86118

87119
def oversized_addr_test(self):
88120
self.log.info('Send an addr message that is too large')
@@ -101,7 +133,7 @@ def relay_tests(self):
101133
num_receivers = 7
102134
receivers = []
103135
for _ in range(num_receivers):
104-
receivers.append(self.nodes[0].add_p2p_connection(AddrReceiver()))
136+
receivers.append(self.nodes[0].add_p2p_connection(AddrReceiver(test_addr_contents=True)))
105137

106138
# Keep this with length <= 10. Addresses from larger messages are not
107139
# relayed.
@@ -125,8 +157,8 @@ def relay_tests(self):
125157
self.nodes[0].disconnect_p2ps()
126158

127159
self.log.info('Check relay of addresses received from outbound peers')
128-
inbound_peer = self.nodes[0].add_p2p_connection(AddrReceiver())
129-
full_outbound_peer = self.nodes[0].add_outbound_p2p_connection(GetAddrStore(), p2p_idx=0, connection_type="outbound-full-relay")
160+
inbound_peer = self.nodes[0].add_p2p_connection(AddrReceiver(test_addr_contents=True))
161+
full_outbound_peer = self.nodes[0].add_outbound_p2p_connection(AddrReceiver(), p2p_idx=0, connection_type="outbound-full-relay")
130162
msg = self.setup_addr_msg(2)
131163
self.send_addr_msg(full_outbound_peer, msg, [inbound_peer])
132164
self.log.info('Check that the first addr message received from an outbound peer is not relayed')
@@ -142,7 +174,7 @@ def relay_tests(self):
142174
assert_equal(inbound_peer.num_ipv4_received, 2)
143175

144176
self.log.info('Check address relay to outbound peers')
145-
block_relay_peer = self.nodes[0].add_outbound_p2p_connection(GetAddrStore(), p2p_idx=1, connection_type="block-relay-only")
177+
block_relay_peer = self.nodes[0].add_outbound_p2p_connection(AddrReceiver(), p2p_idx=1, connection_type="block-relay-only")
146178
msg3 = self.setup_addr_msg(2)
147179
self.send_addr_msg(inbound_peer, msg3, [full_outbound_peer, block_relay_peer])
148180

@@ -156,17 +188,17 @@ def relay_tests(self):
156188
def getaddr_tests(self):
157189
self.log.info('Test getaddr behavior')
158190
self.log.info('Check that we send a getaddr message upon connecting to an outbound-full-relay peer')
159-
full_outbound_peer = self.nodes[0].add_outbound_p2p_connection(GetAddrStore(), p2p_idx=0, connection_type="outbound-full-relay")
191+
full_outbound_peer = self.nodes[0].add_outbound_p2p_connection(AddrReceiver(), p2p_idx=0, connection_type="outbound-full-relay")
160192
full_outbound_peer.sync_with_ping()
161-
assert full_outbound_peer.getaddr_received
193+
assert full_outbound_peer.getaddr_received()
162194

163195
self.log.info('Check that we do not send a getaddr message upon connecting to a block-relay-only peer')
164-
block_relay_peer = self.nodes[0].add_outbound_p2p_connection(GetAddrStore(), p2p_idx=1, connection_type="block-relay-only")
196+
block_relay_peer = self.nodes[0].add_outbound_p2p_connection(AddrReceiver(), p2p_idx=1, connection_type="block-relay-only")
165197
block_relay_peer.sync_with_ping()
166-
assert_equal(block_relay_peer.getaddr_received, False)
198+
assert_equal(block_relay_peer.getaddr_received(), False)
167199

168200
self.log.info('Check that we answer getaddr messages only from inbound peers')
169-
inbound_peer = self.nodes[0].add_p2p_connection(GetAddrStore())
201+
inbound_peer = self.nodes[0].add_p2p_connection(AddrReceiver())
170202
inbound_peer.sync_with_ping()
171203

172204
# Add some addresses to addrman
@@ -182,7 +214,7 @@ def getaddr_tests(self):
182214

183215
self.mocktime += 5 * 60
184216
self.nodes[0].setmocktime(self.mocktime)
185-
inbound_peer.wait_until(inbound_peer.addr_received)
217+
inbound_peer.wait_until(lambda: inbound_peer.addr_received() is True)
186218

187219
assert_equal(full_outbound_peer.num_ipv4_received, 0)
188220
assert_equal(block_relay_peer.num_ipv4_received, 0)
@@ -192,25 +224,79 @@ def getaddr_tests(self):
192224

193225
def blocksonly_mode_tests(self):
194226
self.log.info('Test addr relay in -blocksonly mode')
195-
self.restart_node(0, ["-blocksonly"])
227+
self.restart_node(0, ["-blocksonly", "[email protected]"])
196228
self.mocktime = int(time.time())
197229

198230
self.log.info('Check that we send getaddr messages')
199-
full_outbound_peer = self.nodes[0].add_outbound_p2p_connection(GetAddrStore(), p2p_idx=0, connection_type="outbound-full-relay")
231+
full_outbound_peer = self.nodes[0].add_outbound_p2p_connection(AddrReceiver(), p2p_idx=0, connection_type="outbound-full-relay")
200232
full_outbound_peer.sync_with_ping()
201-
assert full_outbound_peer.getaddr_received
233+
assert full_outbound_peer.getaddr_received()
202234

203235
self.log.info('Check that we relay address messages')
204236
addr_source = self.nodes[0].add_p2p_connection(P2PInterface())
205237
msg = self.setup_addr_msg(2)
206-
addr_source.send_and_ping(msg)
207-
self.mocktime += 5 * 60
208-
self.nodes[0].setmocktime(self.mocktime)
209-
full_outbound_peer.sync_with_ping()
238+
self.send_addr_msg(addr_source, msg, [full_outbound_peer])
210239
assert_equal(full_outbound_peer.num_ipv4_received, 2)
211240

212241
self.nodes[0].disconnect_p2ps()
213242

243+
def send_addrs_and_test_rate_limiting(self, peer, no_relay, new_addrs, total_addrs):
244+
"""Send an addr message and check that the number of addresses processed and rate-limited is as expected"""
245+
246+
peer.send_and_ping(self.setup_rand_addr_msg(new_addrs))
247+
248+
peerinfo = self.nodes[0].getpeerinfo()[0]
249+
addrs_processed = peerinfo['addr_processed']
250+
addrs_rate_limited = peerinfo['addr_rate_limited']
251+
self.log.debug(f"addrs_processed = {addrs_processed}, addrs_rate_limited = {addrs_rate_limited}")
252+
253+
if no_relay:
254+
assert_equal(addrs_processed, 0)
255+
assert_equal(addrs_rate_limited, 0)
256+
else:
257+
assert_equal(addrs_processed, min(total_addrs, peer.tokens))
258+
assert_equal(addrs_rate_limited, max(0, total_addrs - peer.tokens))
259+
260+
def rate_limit_tests(self):
261+
262+
self.mocktime = int(time.time())
263+
self.restart_node(0, [])
264+
self.nodes[0].setmocktime(self.mocktime)
265+
266+
for contype, no_relay in [("outbound-full-relay", False), ("block-relay-only", True), ("inbound", False)]:
267+
self.log.info(f'Test rate limiting of addr processing for {contype} peers')
268+
if contype == "inbound":
269+
peer = self.nodes[0].add_p2p_connection(AddrReceiver())
270+
else:
271+
peer = self.nodes[0].add_outbound_p2p_connection(AddrReceiver(), p2p_idx=0, connection_type=contype)
272+
273+
# Send 600 addresses. For all but the block-relay-only peer this should result in addresses being processed.
274+
self.send_addrs_and_test_rate_limiting(peer, no_relay, 600, 600)
275+
276+
# Send 600 more addresses. For the outbound-full-relay peer (which we send a GETADDR, and thus will
277+
# process up to 1001 incoming addresses), this means more addresses will be processed.
278+
self.send_addrs_and_test_rate_limiting(peer, no_relay, 600, 1200)
279+
280+
# Send 10 more. As we reached the processing limit for all nodes, no more addresses should be procesesd.
281+
self.send_addrs_and_test_rate_limiting(peer, no_relay, 10, 1210)
282+
283+
# Advance the time by 100 seconds, permitting the processing of 10 more addresses.
284+
# Send 200 and verify that 10 are processed.
285+
self.mocktime += 100
286+
self.nodes[0].setmocktime(self.mocktime)
287+
peer.increment_tokens(10)
288+
289+
self.send_addrs_and_test_rate_limiting(peer, no_relay, 200, 1410)
290+
291+
# Advance the time by 1000 seconds, permitting the processing of 100 more addresses.
292+
# Send 200 and verify that 100 are processed.
293+
self.mocktime += 1000
294+
self.nodes[0].setmocktime(self.mocktime)
295+
peer.increment_tokens(100)
296+
297+
self.send_addrs_and_test_rate_limiting(peer, no_relay, 200, 1610)
298+
299+
self.nodes[0].disconnect_p2ps()
214300

215301
if __name__ == '__main__':
216302
AddrTest().main()

test/functional/p2p_addrfetch.py

+62
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) 2021 The Bitcoin Core developers
3+
# Distributed under the MIT software license, see the accompanying
4+
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
5+
"""
6+
Test p2p addr-fetch connections
7+
"""
8+
9+
import time
10+
11+
from test_framework.messages import msg_addr, CAddress, NODE_NETWORK, NODE_WITNESS
12+
from test_framework.p2p import P2PInterface, p2p_lock
13+
from test_framework.test_framework import BGLTestFramework
14+
from test_framework.util import assert_equal
15+
16+
ADDR = CAddress()
17+
ADDR.time = int(time.time())
18+
ADDR.nServices = NODE_NETWORK | NODE_WITNESS
19+
ADDR.ip = "192.0.0.8"
20+
ADDR.port = 18444
21+
22+
23+
class P2PAddrFetch(BGLTestFramework):
24+
25+
def set_test_params(self):
26+
self.setup_clean_chain = True
27+
self.num_nodes = 1
28+
29+
def run_test(self):
30+
node = self.nodes[0]
31+
self.log.info("Connect to an addr-fetch peer")
32+
peer = node.add_outbound_p2p_connection(P2PInterface(), p2p_idx=0, connection_type="addr-fetch")
33+
info = node.getpeerinfo()
34+
assert_equal(len(info), 1)
35+
assert_equal(info[0]['connection_type'], 'addr-fetch')
36+
37+
self.log.info("Check that we send getaddr but don't try to sync headers with the addr-fetch peer")
38+
peer.sync_send_with_ping()
39+
with p2p_lock:
40+
assert peer.message_count['getaddr'] == 1
41+
assert peer.message_count['getheaders'] == 0
42+
43+
self.log.info("Check that answering the getaddr with a single address does not lead to disconnect")
44+
# This prevents disconnecting on self-announcements
45+
msg = msg_addr()
46+
msg.addrs = [ADDR]
47+
peer.send_and_ping(msg)
48+
assert_equal(len(node.getpeerinfo()), 1)
49+
50+
self.log.info("Check that answering with larger addr messages leads to disconnect")
51+
msg.addrs = [ADDR] * 2
52+
peer.send_message(msg)
53+
peer.wait_for_disconnect(timeout=5)
54+
55+
self.log.info("Check timeout for addr-fetch peer that does not send addrs")
56+
peer = node.add_outbound_p2p_connection(P2PInterface(), p2p_idx=1, connection_type="addr-fetch")
57+
node.setmocktime(int(time.time()) + 301) # Timeout: 5 minutes
58+
peer.wait_for_disconnect(timeout=5)
59+
60+
61+
if __name__ == '__main__':
62+
P2PAddrFetch().main()

test/functional/p2p_addrv2_relay.py

+9-7
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
addr = CAddress()
2424
addr.time = int(time.time()) + i
2525
addr.nServices = NODE_NETWORK | NODE_WITNESS
26-
addr.ip = "123.123.123.{}".format(i % 256)
26+
addr.ip = f"123.123.123.{i % 256}"
2727
addr.port = 8333 + i
2828
ADDRS.append(addr)
2929

@@ -35,11 +35,10 @@ def __init__(self):
3535
super().__init__(support_addrv2 = True)
3636

3737
def on_addrv2(self, message):
38-
for addr in message.addrs:
39-
assert_equal(addr.nServices, 9)
40-
assert addr.ip.startswith('123.123.123.')
41-
assert (8333 <= addr.port < 8343)
42-
self.addrv2_received_and_checked = True
38+
expected_set = set((addr.ip, addr.port) for addr in ADDRS)
39+
received_set = set((addr.ip, addr.port) for addr in message.addrs)
40+
if expected_set == received_set:
41+
self.addrv2_received_and_checked = True
4342

4443
def wait_for_addrv2(self):
4544
self.wait_until(lambda: "addrv2" in self.last_message)
@@ -49,6 +48,7 @@ class AddrTest(BGLTestFramework):
4948
def set_test_params(self):
5049
self.setup_clean_chain = True
5150
self.num_nodes = 1
51+
self.extra_args = [["[email protected]"]]
5252

5353
def run_test(self):
5454
self.log.info('Create connection that sends addrv2 messages')
@@ -64,8 +64,10 @@ def run_test(self):
6464
addr_receiver = self.nodes[0].add_p2p_connection(AddrReceiver())
6565
msg.addrs = ADDRS
6666
with self.nodes[0].assert_debug_log([
67+
# The I2P address is not added to node's own addrman because it has no
68+
# I2P reachability (thus 10 - 1 = 9).
6769
'Added 10 addresses from 127.0.0.1: 0 tried',
68-
'received: addrv2 (131 bytes) peer=0',
70+
#'received: addrv2 (159 bytes) peer=0',
6971
'sending addrv2 (131 bytes) peer=1',
7072
]):
7173
addr_source.send_and_ping(msg)

0 commit comments

Comments
 (0)