@@ -25,7 +25,7 @@ class PruneTest(BitcoinTestFramework):
25
25
def __init__ (self ):
26
26
super ().__init__ ()
27
27
self .setup_clean_chain = True
28
- self .num_nodes = 5
28
+ self .num_nodes = 6
29
29
30
30
# Cache for utxos, as the listunspent may take a long time later in the test
31
31
self .utxo_cache_0 = []
@@ -43,12 +43,12 @@ def setup_network(self):
43
43
self .nodes .append (start_node (2 , self .options .tmpdir , ["-debug" ,"-maxreceivebuffer=20000" ,"-prune=550" ], timewait = 900 ))
44
44
self .prunedir = self .options .tmpdir + "/node2/regtest/blocks/"
45
45
46
- # Create node 3 to test manual pruning (it will be re-started with manual pruning later)
46
+ # Create nodes 3 and 4 to test manual pruning (they will be re-started with manual pruning later)
47
47
self .nodes .append (start_node (3 , self .options .tmpdir , ["-debug=0" ,"-maxreceivebuffer=20000" ,"-blockmaxsize=999000" ], timewait = 900 ))
48
- self .manualdir = self .options .tmpdir + "/node3/regtest/blocks/"
48
+ self .nodes . append ( start_node ( 4 , self .options .tmpdir , [ "-debug=0" , "-maxreceivebuffer=20000" , "-blockmaxsize=999000" ], timewait = 900 ))
49
49
50
- # Create node 4 to test wallet in prune mode, but do not connect
51
- self .nodes .append (start_node (4 , self .options .tmpdir , ["-debug=0" , "-prune=550" ]))
50
+ # Create nodes 5 to test wallet in prune mode, but do not connect
51
+ self .nodes .append (start_node (5 , self .options .tmpdir , ["-debug=0" , "-prune=550" ]))
52
52
53
53
# Determine default relay fee
54
54
self .relayfee = self .nodes [0 ].getnetworkinfo ()["relayfee" ]
@@ -57,7 +57,8 @@ def setup_network(self):
57
57
connect_nodes (self .nodes [1 ], 2 )
58
58
connect_nodes (self .nodes [2 ], 0 )
59
59
connect_nodes (self .nodes [0 ], 3 )
60
- sync_blocks (self .nodes [0 :4 ])
60
+ connect_nodes (self .nodes [0 ], 4 )
61
+ sync_blocks (self .nodes [0 :5 ])
61
62
62
63
def create_big_chain (self ):
63
64
# Start by creating some coinbases we can spend later
@@ -68,7 +69,7 @@ def create_big_chain(self):
68
69
for i in range (645 ):
69
70
mine_large_block (self .nodes [0 ], self .utxo_cache_0 )
70
71
71
- sync_blocks (self .nodes [0 :4 ])
72
+ sync_blocks (self .nodes [0 :5 ])
72
73
73
74
def test_height_min (self ):
74
75
if not os .path .isfile (self .prunedir + "blk00000.dat" ):
@@ -223,68 +224,78 @@ def reorg_back(self):
223
224
# Verify we can now have the data for a block previously pruned
224
225
assert (self .nodes [2 ].getblock (self .forkhash )["height" ] == self .forkheight )
225
226
226
- def manual_test (self ):
227
- # at this point, node3 has 995 blocks and has not yet run in prune mode
228
- self .nodes [3 ] = start_node (3 , self .options .tmpdir , ["-debug=0" ], timewait = 900 )
229
- assert_raises_message (JSONRPCException , "not in prune mode" , self .nodes [3 ].pruneblockchain , 500 )
230
- stop_node (self .nodes [3 ],3 )
227
+ def manual_test (self , node_number , use_timestamp ):
228
+ # at this point, node has 995 blocks and has not yet run in prune mode
229
+ node = self .nodes [node_number ] = start_node (node_number , self .options .tmpdir , ["-debug=0" ], timewait = 900 )
230
+ assert_equal (node .getblockcount (), 995 )
231
+ assert_raises_message (JSONRPCException , "not in prune mode" , node .pruneblockchain , 500 )
232
+ stop_node (node , node_number )
231
233
232
234
# now re-start in manual pruning mode
233
- self .nodes [3 ] = start_node (3 , self .options .tmpdir , ["-debug=0" ,"-prune=1" ], timewait = 900 )
234
- assert_equal (self .nodes [3 ].getblockcount (), 995 )
235
+ node = self .nodes [node_number ] = start_node (node_number , self .options .tmpdir , ["-debug=0" ,"-prune=1" ], timewait = 900 )
236
+ assert_equal (node .getblockcount (), 995 )
237
+
238
+ def height (index ):
239
+ if use_timestamp :
240
+ return node .getblockheader (node .getblockhash (index ))["time" ]
241
+ else :
242
+ return index
243
+
244
+ def has_block (index ):
245
+ return os .path .isfile (self .options .tmpdir + "/node{}/regtest/blocks/blk{:05}.dat" .format (node_number , index ))
235
246
236
247
# should not prune because chain tip of node 3 (995) < PruneAfterHeight (1000)
237
- assert_raises_message (JSONRPCException , "Blockchain is too short for pruning" , self . nodes [ 3 ]. pruneblockchain , 500 )
248
+ assert_raises_message (JSONRPCException , "Blockchain is too short for pruning" , node . pruneblockchain , height ( 500 ) )
238
249
239
250
# mine 6 blocks so we are at height 1001 (i.e., above PruneAfterHeight)
240
- self . nodes [ 3 ] .generate (6 )
251
+ node .generate (6 )
241
252
242
253
# negative and zero inputs should raise an exception
243
254
try :
244
- self . nodes [ 3 ] .pruneblockchain (- 10 )
255
+ node .pruneblockchain (- 10 )
245
256
raise AssertionError ("pruneblockchain(-10) should have failed." )
246
257
except :
247
258
pass
248
259
249
260
try :
250
- self . nodes [ 3 ] .pruneblockchain (0 )
261
+ node .pruneblockchain (0 )
251
262
raise AssertionError ("pruneblockchain(0) should have failed." )
252
263
except :
253
264
pass
254
265
255
266
# height=100 too low to prune first block file so this is a no-op
256
- self . nodes [ 3 ]. pruneblockchain (100 )
257
- if not os . path . isfile ( self . manualdir + "blk00000.dat" ):
267
+ node . pruneblockchain (height ( 100 ) )
268
+ if not has_block ( 0 ):
258
269
raise AssertionError ("blk00000.dat is missing when should still be there" )
259
270
260
271
# height=500 should prune first file
261
- self . nodes [ 3 ]. pruneblockchain (500 )
262
- if os . path . isfile ( self . manualdir + "blk00000.dat" ):
272
+ node . pruneblockchain (height ( 500 ) )
273
+ if has_block ( 0 ):
263
274
raise AssertionError ("blk00000.dat is still there, should be pruned by now" )
264
- if not os . path . isfile ( self . manualdir + "blk00001.dat" ):
275
+ if not has_block ( 1 ):
265
276
raise AssertionError ("blk00001.dat is missing when should still be there" )
266
277
267
278
# height=650 should prune second file
268
- self . nodes [ 3 ]. pruneblockchain (650 )
269
- if os . path . isfile ( self . manualdir + "blk00001.dat" ):
279
+ node . pruneblockchain (height ( 650 ) )
280
+ if has_block ( 1 ):
270
281
raise AssertionError ("blk00001.dat is still there, should be pruned by now" )
271
282
272
283
# height=1000 should not prune anything more, because tip-288 is in blk00002.dat.
273
- self . nodes [ 3 ]. pruneblockchain (1000 )
274
- if not os . path . isfile ( self . manualdir + "blk00002.dat" ):
284
+ node . pruneblockchain (height ( 1000 ) )
285
+ if not has_block ( 2 ):
275
286
raise AssertionError ("blk00002.dat is still there, should be pruned by now" )
276
287
277
288
# advance the tip so blk00002.dat and blk00003.dat can be pruned (the last 288 blocks should now be in blk00004.dat)
278
- self . nodes [ 3 ] .generate (288 )
279
- self . nodes [ 3 ]. pruneblockchain (1000 )
280
- if os . path . isfile ( self . manualdir + "blk00002.dat" ):
289
+ node .generate (288 )
290
+ node . pruneblockchain (height ( 1000 ) )
291
+ if has_block ( 2 ):
281
292
raise AssertionError ("blk00002.dat is still there, should be pruned by now" )
282
- if os . path . isfile ( self . manualdir + "blk00003.dat" ):
293
+ if has_block ( 3 ):
283
294
raise AssertionError ("blk00003.dat is still there, should be pruned by now" )
284
295
285
296
# stop node, start back up with auto-prune at 550MB, make sure still runs
286
- stop_node (self . nodes [ 3 ], 3 )
287
- self .nodes [3 ] = start_node (3 , self .options .tmpdir , ["-debug=0" ,"-prune=550" ], timewait = 900 )
297
+ stop_node (node , node_number )
298
+ self .nodes [node_number ] = start_node (node_number , self .options .tmpdir , ["-debug=0" ,"-prune=550" ], timewait = 900 )
288
299
289
300
print ("Success" )
290
301
@@ -300,16 +311,16 @@ def wallet_test(self):
300
311
301
312
# check that wallet loads loads successfully when restarting a pruned node after IBD.
302
313
# this was reported to fail in #7494.
303
- print ("Syncing node 4 to test wallet" )
304
- connect_nodes (self .nodes [0 ], 4 )
305
- nds = [self .nodes [0 ], self .nodes [4 ]]
314
+ print ("Syncing node 5 to test wallet" )
315
+ connect_nodes (self .nodes [0 ], 5 )
316
+ nds = [self .nodes [0 ], self .nodes [5 ]]
306
317
sync_blocks (nds )
307
318
try :
308
- stop_node (self .nodes [4 ], 4 ) #stop and start to trigger rescan
309
- start_node (4 , self .options .tmpdir , ["-debug=1" ,"-prune=550" ])
319
+ stop_node (self .nodes [5 ], 5 ) #stop and start to trigger rescan
320
+ start_node (5 , self .options .tmpdir , ["-debug=1" ,"-prune=550" ])
310
321
print ("Success" )
311
322
except Exception as detail :
312
- raise AssertionError ("Wallet test: unable to re-start node4 " )
323
+ raise AssertionError ("Wallet test: unable to re-start node5 " )
313
324
314
325
def run_test (self ):
315
326
print ("Warning! This test requires 4GB of disk space and takes over 30 mins (up to 2 hours)" )
@@ -326,6 +337,7 @@ def run_test(self):
326
337
327
338
# stop manual-pruning node with 995 blocks
328
339
stop_node (self .nodes [3 ],3 )
340
+ stop_node (self .nodes [4 ],4 )
329
341
330
342
print ("Check that we haven't started pruning yet because we're below PruneAfterHeight" )
331
343
self .test_height_min ()
@@ -409,8 +421,11 @@ def run_test(self):
409
421
#
410
422
# N1 doesn't change because 1033 on main chain (*) is invalid
411
423
412
- print ("Test manual pruning" )
413
- self .manual_test ()
424
+ print ("Test manual pruning with block indices" )
425
+ self .manual_test (3 , use_timestamp = False )
426
+
427
+ print ("Test manual pruning with timestamps" )
428
+ self .manual_test (4 , use_timestamp = True )
414
429
415
430
print ("Test wallet re-scan" )
416
431
self .wallet_test ()
0 commit comments