24
24
25
25
class GetBlockFromPeerTest (BitcoinTestFramework ):
26
26
def set_test_params (self ):
27
- self .num_nodes = 2
27
+ self .num_nodes = 3
28
+ self .extra_args = [
29
+ [],
30
+ [],
31
+ ["-fastprune" , "-prune=1" ]
32
+ ]
28
33
29
34
def setup_network (self ):
30
35
self .setup_nodes ()
31
36
32
- def check_for_block (self , hash ):
37
+ def check_for_block (self , node , hash ):
33
38
try :
34
- self .nodes [0 ].getblock (hash )
39
+ self .nodes [node ].getblock (hash )
35
40
return True
36
41
except JSONRPCException :
37
42
return False
@@ -48,7 +53,7 @@ def run_test(self):
48
53
49
54
self .log .info ("Connect nodes to sync headers" )
50
55
self .connect_nodes (0 , 1 )
51
- self .sync_blocks ()
56
+ self .sync_blocks (self . nodes [ 0 : 2 ] )
52
57
53
58
self .log .info ("Node 0 should only have the header for node 1's block 3" )
54
59
x = next (filter (lambda x : x ['hash' ] == short_tip , self .nodes [0 ].getchaintips ()))
@@ -81,7 +86,7 @@ def run_test(self):
81
86
82
87
self .log .info ("Successful fetch" )
83
88
result = self .nodes [0 ].getblockfrompeer (short_tip , peer_0_peer_1_id )
84
- self .wait_until (lambda : self .check_for_block (short_tip ), timeout = 1 )
89
+ self .wait_until (lambda : self .check_for_block (node = 0 , hash = short_tip ), timeout = 1 )
85
90
assert_equal (result , {})
86
91
87
92
self .log .info ("Don't fetch blocks we already have" )
@@ -111,6 +116,40 @@ def run_test(self):
111
116
error_msg = "In prune mode, only blocks that the node has already synced previously can be fetched from a peer"
112
117
assert_raises_rpc_error (- 1 , error_msg , self .nodes [1 ].getblockfrompeer , blockhash , node1_interface_id )
113
118
119
+ self .log .info ("Connect pruned node" )
120
+ # We need to generate more blocks to be able to prune
121
+ self .connect_nodes (0 , 2 )
122
+ pruned_node = self .nodes [2 ]
123
+ self .generate (self .nodes [0 ], 400 , sync_fun = self .no_op )
124
+ self .sync_blocks ([self .nodes [0 ], pruned_node ])
125
+ pruneheight = pruned_node .pruneblockchain (300 )
126
+ assert_equal (pruneheight , 248 )
127
+ # Ensure the block is actually pruned
128
+ pruned_block = self .nodes [0 ].getblockhash (2 )
129
+ assert_raises_rpc_error (- 1 , "Block not available (pruned data)" , pruned_node .getblock , pruned_block )
130
+
131
+ self .log .info ("Fetch pruned block" )
132
+ peers = pruned_node .getpeerinfo ()
133
+ assert_equal (len (peers ), 1 )
134
+ pruned_node_peer_0_id = peers [0 ]["id" ]
135
+ result = pruned_node .getblockfrompeer (pruned_block , pruned_node_peer_0_id )
136
+ self .wait_until (lambda : self .check_for_block (node = 2 , hash = pruned_block ), timeout = 1 )
137
+ assert_equal (result , {})
138
+
139
+ self .log .info ("Fetched block persists after next pruning event" )
140
+ self .generate (self .nodes [0 ], 250 , sync_fun = self .no_op )
141
+ self .sync_blocks ([self .nodes [0 ], pruned_node ])
142
+ pruneheight += 251
143
+ assert_equal (pruned_node .pruneblockchain (700 ), pruneheight )
144
+ assert_equal (pruned_node .getblock (pruned_block )["hash" ], "36c56c5b5ebbaf90d76b0d1a074dcb32d42abab75b7ec6fa0ffd9b4fbce8f0f7" )
145
+
146
+ self .log .info ("Fetched block can be pruned again when prune height exceeds the height of the tip at the time when the block was fetched" )
147
+ self .generate (self .nodes [0 ], 250 , sync_fun = self .no_op )
148
+ self .sync_blocks ([self .nodes [0 ], pruned_node ])
149
+ pruneheight += 250
150
+ assert_equal (pruned_node .pruneblockchain (1000 ), pruneheight )
151
+ assert_raises_rpc_error (- 1 , "Block not available (pruned data)" , pruned_node .getblock , pruned_block )
152
+
114
153
115
154
if __name__ == '__main__' :
116
155
GetBlockFromPeerTest ().main ()
0 commit comments