|
2 | 2 | # Copyright (c) 2017 The Bitcoin Core developers
|
3 | 3 | # Distributed under the MIT software license, see the accompanying
|
4 | 4 | # file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
| 5 | +"""Tests NODE_NETWORK_LIMITED. |
| 6 | +
|
| 7 | +Tests that a node configured with -prune=550 signals NODE_NETWORK_LIMITED correctly |
| 8 | +and that it responds to getdata requests for blocks correctly: |
| 9 | + - send a block within 288 + 2 of the tip |
| 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 |
5 | 13 | from test_framework.test_framework import BitcoinTestFramework
|
6 |
| -from test_framework.util import * |
7 |
| -from test_framework.mininode import * |
| 14 | +from test_framework.util import assert_equal |
8 | 15 |
|
9 |
| -class BaseNode(P2PInterface): |
10 |
| - nServices = 0 |
11 |
| - def on_version(self, message): |
12 |
| - self.nServices = message.nServices |
| 16 | +class P2PIgnoreInv(P2PInterface): |
| 17 | + def on_inv(self, message): |
| 18 | + # The node will send us invs for other blocks. Ignore them. |
| 19 | + pass |
| 20 | + |
| 21 | + def send_getdata_for_block(self, blockhash): |
| 22 | + getdata_request = msg_getdata() |
| 23 | + getdata_request.inv.append(CInv(2, int(blockhash, 16))) |
| 24 | + self.send_message(getdata_request) |
13 | 25 |
|
14 | 26 | class NodeNetworkLimitedTest(BitcoinTestFramework):
|
15 | 27 | def set_test_params(self):
|
16 | 28 | self.setup_clean_chain = True
|
17 | 29 | self.num_nodes = 1
|
18 | 30 | self.extra_args = [['-prune=550']]
|
19 | 31 |
|
20 |
| - def getSignaledServiceFlags(self): |
21 |
| - node = self.nodes[0].add_p2p_connection(BaseNode()) |
| 32 | + def run_test(self): |
| 33 | + node = self.nodes[0].add_p2p_connection(P2PIgnoreInv()) |
22 | 34 | NetworkThread().start()
|
23 | 35 | node.wait_for_verack()
|
24 |
| - services = node.nServices |
25 |
| - self.nodes[0].disconnect_p2ps() |
26 |
| - node.wait_for_disconnect() |
27 |
| - return services |
28 | 36 |
|
29 |
| - def tryGetBlockViaGetData(self, blockhash, must_disconnect): |
30 |
| - node = self.nodes[0].add_p2p_connection(BaseNode()) |
31 |
| - NetworkThread().start() |
32 |
| - node.wait_for_verack() |
33 |
| - node.send_message(msg_verack()) |
34 |
| - getdata_request = msg_getdata() |
35 |
| - getdata_request.inv.append(CInv(2, int(blockhash, 16))) |
36 |
| - node.send_message(getdata_request) |
| 37 | + expected_services = NODE_BLOOM | NODE_WITNESS | NODE_NETWORK_LIMITED |
37 | 38 |
|
38 |
| - if (must_disconnect): |
39 |
| - #ensure we get disconnected |
40 |
| - node.wait_for_disconnect(5) |
41 |
| - else: |
42 |
| - # check if the peer sends us the requested block |
43 |
| - node.wait_for_block(int(blockhash, 16), 3) |
44 |
| - self.nodes[0].disconnect_p2ps() |
45 |
| - node.wait_for_disconnect() |
| 39 | + self.log.info("Check that node has signalled expected services.") |
| 40 | + assert_equal(node.nServices, expected_services) |
46 | 41 |
|
47 |
| - def run_test(self): |
48 |
| - #NODE_BLOOM & NODE_WITNESS & NODE_NETWORK_LIMITED must now be signaled |
49 |
| - assert_equal(self.getSignaledServiceFlags(), 1036) #1036 == 0x40C == 0100 0000 1100 |
50 |
| -# | || |
51 |
| -# | |^--- NODE_BLOOM |
52 |
| -# | ^---- NODE_WITNESS |
53 |
| -# ^-- NODE_NETWORK_LIMITED |
| 42 | + self.log.info("Check that the localservices is as expected.") |
| 43 | + assert_equal(int(self.nodes[0].getnetworkinfo()['localservices'], 16), expected_services) |
54 | 44 |
|
55 |
| - #now mine some blocks over the NODE_NETWORK_LIMITED + 2(racy buffer ext.) target |
56 |
| - firstblock = self.nodes[0].generate(1)[0] |
| 45 | + self.log.info("Mine enough blocks to reach the NODE_NETWORK_LIMITED range.") |
57 | 46 | blocks = self.nodes[0].generate(292)
|
58 |
| - blockWithinLimitedRange = blocks[-1] |
59 |
| - |
60 |
| - #make sure we can max retrive block at tip-288 |
61 |
| - #requesting block at height 2 (tip-289) must fail (ignored) |
62 |
| - self.tryGetBlockViaGetData(firstblock, True) #first block must lead to disconnect |
63 |
| - self.tryGetBlockViaGetData(blocks[1], False) #last block in valid range |
64 |
| - self.tryGetBlockViaGetData(blocks[0], True) #first block outside of the 288+2 limit |
65 |
| - |
66 |
| - #NODE_NETWORK_LIMITED must still be signaled after restart |
67 |
| - self.restart_node(0) |
68 |
| - assert_equal(self.getSignaledServiceFlags(), 1036) |
69 |
| - |
70 |
| - #test the RPC service flags |
71 |
| - assert_equal(self.nodes[0].getnetworkinfo()['localservices'], "000000000000040c") |
72 | 47 |
|
73 |
| - # getdata a block above the NODE_NETWORK_LIMITED threshold must be possible |
74 |
| - self.tryGetBlockViaGetData(blockWithinLimitedRange, False) |
| 48 | + self.log.info("Make sure we can max retrive block at tip-288.") |
| 49 | + node.send_getdata_for_block(blocks[1]) # last block in valid range |
| 50 | + node.wait_for_block(int(blocks[1], 16), timeout=3) |
75 | 51 |
|
76 |
| - # getdata a block below the NODE_NETWORK_LIMITED threshold must be ignored |
77 |
| - self.tryGetBlockViaGetData(firstblock, True) |
| 52 | + self.log.info("Requesting block at height 2 (tip-289) must fail (ignored).") |
| 53 | + node.send_getdata_for_block(blocks[0]) # first block outside of the 288+2 limit |
| 54 | + node.wait_for_disconnect(5) |
78 | 55 |
|
79 | 56 | if __name__ == '__main__':
|
80 | 57 | NodeNetworkLimitedTest().main()
|
0 commit comments