Skip to content

Commit c5b5843

Browse files
committed
test: avoid requesting blocks beyond limited peer threshold
Even when the node believes it completed IBD, need to avoid requesting historical blocks from network-limited peers. Otherwise, the limited peer will disconnect right away.
1 parent 2f6a055 commit c5b5843

File tree

1 file changed

+63
-0
lines changed

1 file changed

+63
-0
lines changed

test/functional/p2p_node_network_limited.py

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,12 @@
2121
from test_framework.test_framework import BitcoinTestFramework
2222
from test_framework.util import (
2323
assert_equal,
24+
assert_raises_rpc_error,
25+
try_rpc
2426
)
2527

28+
# Minimum blocks required to signal NODE_NETWORK_LIMITED #
29+
NODE_NETWORK_LIMITED_MIN_BLOCKS = 288
2630

2731
class P2PIgnoreInv(P2PInterface):
2832
firstAddrnServices = 0
@@ -54,6 +58,63 @@ def setup_network(self):
5458
self.add_nodes(self.num_nodes, self.extra_args)
5559
self.start_nodes()
5660

61+
def test_avoid_requesting_historical_blocks(self):
62+
self.log.info("Test full node does not request blocks beyond the limited peer threshold")
63+
pruned_node = self.nodes[0]
64+
miner = self.nodes[1]
65+
full_node = self.nodes[2]
66+
67+
# Connect and generate block to ensure IBD=false
68+
self.connect_nodes(1, 0)
69+
self.connect_nodes(1, 2)
70+
self.generate(miner, 1)
71+
72+
# Verify peers are out of IBD
73+
for node in self.nodes:
74+
assert not node.getblockchaininfo()['initialblockdownload']
75+
76+
# Isolate full_node (the node will remain out of IBD)
77+
full_node.setnetworkactive(False)
78+
self.wait_until(lambda: len(full_node.getpeerinfo()) == 0)
79+
80+
# Mine blocks and sync the pruned node. Surpass the NETWORK_NODE_LIMITED threshold.
81+
# Blocks deeper than the threshold are considered "historical blocks"
82+
num_historial_blocks = 12
83+
self.generate(miner, NODE_NETWORK_LIMITED_MIN_BLOCKS + num_historial_blocks, sync_fun=self.no_op)
84+
self.sync_blocks([miner, pruned_node])
85+
86+
# Connect full_node to prune_node and check peers don't disconnect right away.
87+
# (they will disconnect if full_node, which is chain-wise behind, request blocks
88+
# older than NODE_NETWORK_LIMITED_MIN_BLOCKS)
89+
start_height_full_node = full_node.getblockcount()
90+
full_node.setnetworkactive(True)
91+
self.connect_nodes(2, 0)
92+
assert_equal(len(full_node.getpeerinfo()), 1)
93+
94+
# Wait until the full_node is headers-wise sync
95+
best_block_hash = pruned_node.getbestblockhash()
96+
self.wait_until(lambda: next(filter(lambda x: x['hash'] == best_block_hash, full_node.getchaintips()))['status'] == "headers-only")
97+
98+
# Now, since the node aims to download a window of 1024 blocks,
99+
# ensure it requests the blocks below the threshold only (with a
100+
# 2-block buffer). And also, ensure it does not request any
101+
# historical block.
102+
tip_height = pruned_node.getblockcount()
103+
limit_buffer = 2
104+
# Prevent races by waiting for the tip to arrive first
105+
self.wait_until(lambda: not try_rpc(-1, "Block not found", full_node.getblock, pruned_node.getbestblockhash()))
106+
for height in range(start_height_full_node + 1, tip_height + 1):
107+
if height <= tip_height - (NODE_NETWORK_LIMITED_MIN_BLOCKS - limit_buffer):
108+
assert_raises_rpc_error(-1, "Block not found on disk", full_node.getblock, pruned_node.getblockhash(height))
109+
else:
110+
full_node.getblock(pruned_node.getblockhash(height)) # just assert it does not throw an exception
111+
112+
# Lastly, ensure the full_node is not sync and verify it can get synced by
113+
# establishing a connection with another full node capable of providing them.
114+
assert_equal(full_node.getblockcount(), start_height_full_node)
115+
self.connect_nodes(2, 1)
116+
self.sync_blocks([miner, full_node])
117+
57118
def run_test(self):
58119
node = self.nodes[0].add_p2p_connection(P2PIgnoreInv())
59120

@@ -118,5 +179,7 @@ def run_test(self):
118179
# sync must be possible, node 1 is no longer in IBD and should therefore connect to node 0 (NODE_NETWORK_LIMITED)
119180
self.sync_blocks([self.nodes[0], self.nodes[1]])
120181

182+
self.test_avoid_requesting_historical_blocks()
183+
121184
if __name__ == '__main__':
122185
NodeNetworkLimitedTest().main()

0 commit comments

Comments
 (0)