8
8
and that it responds to getdata requests for blocks correctly:
9
9
- send a block within 288 + 2 of the tip
10
10
- disconnect peers who request blocks older than that."""
11
- from test_framework .messages import CInv , msg_getdata
12
- from test_framework .mininode import NODE_BLOOM , NODE_NETWORK_LIMITED , NODE_WITNESS , NetworkThread , P2PInterface
11
+ from test_framework .messages import CInv , msg_getdata , msg_verack
12
+ from test_framework .mininode import NODE_BLOOM , NODE_NETWORK_LIMITED , NODE_WITNESS , P2PInterface , wait_until , mininode_lock , network_thread_start , network_thread_join
13
13
from test_framework .test_framework import BitcoinTestFramework
14
- from test_framework .util import assert_equal
14
+ from test_framework .util import assert_equal , disconnect_nodes , connect_nodes_bi , sync_blocks
15
15
16
16
class P2PIgnoreInv (P2PInterface ):
17
+ firstAddrnServices = 0
17
18
def on_inv (self , message ):
18
19
# The node will send us invs for other blocks. Ignore them.
19
20
pass
20
-
21
+ def on_addr (self , message ):
22
+ self .firstAddrnServices = message .addrs [0 ].nServices
23
+ def wait_for_addr (self , timeout = 5 ):
24
+ test_function = lambda : self .last_message .get ("addr" )
25
+ wait_until (test_function , timeout = timeout , lock = mininode_lock )
21
26
def send_getdata_for_block (self , blockhash ):
22
27
getdata_request = msg_getdata ()
23
28
getdata_request .inv .append (CInv (2 , int (blockhash , 16 )))
@@ -26,12 +31,24 @@ def send_getdata_for_block(self, blockhash):
26
31
class NodeNetworkLimitedTest (BitcoinTestFramework ):
27
32
def set_test_params (self ):
28
33
self .setup_clean_chain = True
29
- self .num_nodes = 1
30
- self .extra_args = [['-prune=550' ]]
34
+ self .num_nodes = 3
35
+ self .extra_args = [['-prune=550' , '-addrmantest' ], [], []]
36
+
37
+ def disconnect_all (self ):
38
+ disconnect_nodes (self .nodes [0 ], 1 )
39
+ disconnect_nodes (self .nodes [1 ], 0 )
40
+ disconnect_nodes (self .nodes [2 ], 1 )
41
+ disconnect_nodes (self .nodes [2 ], 0 )
42
+ disconnect_nodes (self .nodes [0 ], 2 )
43
+ disconnect_nodes (self .nodes [1 ], 2 )
44
+
45
+ def setup_network (self ):
46
+ super (NodeNetworkLimitedTest , self ).setup_network ()
47
+ self .disconnect_all ()
31
48
32
49
def run_test (self ):
33
50
node = self .nodes [0 ].add_p2p_connection (P2PIgnoreInv ())
34
- NetworkThread (). start ()
51
+ network_thread_start ()
35
52
node .wait_for_verack ()
36
53
37
54
expected_services = NODE_BLOOM | NODE_WITNESS | NODE_NETWORK_LIMITED
@@ -43,7 +60,9 @@ def run_test(self):
43
60
assert_equal (int (self .nodes [0 ].getnetworkinfo ()['localservices' ], 16 ), expected_services )
44
61
45
62
self .log .info ("Mine enough blocks to reach the NODE_NETWORK_LIMITED range." )
46
- blocks = self .nodes [0 ].generate (292 )
63
+ connect_nodes_bi (self .nodes , 0 , 1 )
64
+ blocks = self .nodes [1 ].generate (292 )
65
+ sync_blocks ([self .nodes [0 ], self .nodes [1 ]])
47
66
48
67
self .log .info ("Make sure we can max retrive block at tip-288." )
49
68
node .send_getdata_for_block (blocks [1 ]) # last block in valid range
@@ -53,5 +72,48 @@ def run_test(self):
53
72
node .send_getdata_for_block (blocks [0 ]) # first block outside of the 288+2 limit
54
73
node .wait_for_disconnect (5 )
55
74
75
+ self .log .info ("Check local address relay, do a fresh connection." )
76
+ self .nodes [0 ].disconnect_p2ps ()
77
+ network_thread_join ()
78
+ node1 = self .nodes [0 ].add_p2p_connection (P2PIgnoreInv ())
79
+ network_thread_start ()
80
+ node1 .wait_for_verack ()
81
+ node1 .send_message (msg_verack ())
82
+
83
+ node1 .wait_for_addr ()
84
+ #must relay address with NODE_NETWORK_LIMITED
85
+ assert_equal (node1 .firstAddrnServices , 1036 )
86
+
87
+ self .nodes [0 ].disconnect_p2ps ()
88
+ node1 .wait_for_disconnect ()
89
+
90
+ # connect unsynced node 2 with pruned NODE_NETWORK_LIMITED peer
91
+ # because node 2 is in IBD and node 0 is a NODE_NETWORK_LIMITED peer, sync must not be possible
92
+ connect_nodes_bi (self .nodes , 0 , 2 )
93
+ try :
94
+ sync_blocks ([self .nodes [0 ], self .nodes [2 ]], timeout = 5 )
95
+ except :
96
+ pass
97
+ # node2 must remain at heigh 0
98
+ assert_equal (self .nodes [2 ].getblockheader (self .nodes [2 ].getbestblockhash ())['height' ], 0 )
99
+
100
+ # now connect also to node 1 (non pruned)
101
+ connect_nodes_bi (self .nodes , 1 , 2 )
102
+
103
+ # sync must be possible
104
+ sync_blocks (self .nodes )
105
+
106
+ # disconnect all peers
107
+ self .disconnect_all ()
108
+
109
+ # mine 10 blocks on node 0 (pruned node)
110
+ self .nodes [0 ].generate (10 )
111
+
112
+ # connect node1 (non pruned) with node0 (pruned) and check if the can sync
113
+ connect_nodes_bi (self .nodes , 0 , 1 )
114
+
115
+ # sync must be possible, node 1 is no longer in IBD and should therefore connect to node 0 (NODE_NETWORK_LIMITED)
116
+ sync_blocks ([self .nodes [0 ], self .nodes [1 ]])
117
+
56
118
if __name__ == '__main__' :
57
119
NodeNetworkLimitedTest ().main ()
0 commit comments