21
21
Interesting starting states could be loading a snapshot when the current chain tip is:
22
22
23
23
- TODO: An ancestor of snapshot block
24
- - TODO: Not an ancestor of the snapshot block but has less work
25
24
- TODO: The snapshot block
26
25
- TODO: A descendant of the snapshot block
27
26
- TODO: Not an ancestor or a descendant of the snapshot block and has more work
@@ -51,18 +50,19 @@ class AssumeutxoTest(BitcoinTestFramework):
51
50
52
51
def set_test_params (self ):
53
52
"""Use the pregenerated, deterministic chain up to height 199."""
54
- self .num_nodes = 3
53
+ self .num_nodes = 4
55
54
self .rpc_timeout = 120
56
55
self .extra_args = [
57
56
[],
58
57
["-fastprune" , "-prune=1" , "-blockfilterindex=1" , "-coinstatsindex=1" ],
59
58
["-persistmempool=0" ,"-txindex=1" , "-blockfilterindex=1" , "-coinstatsindex=1" ],
59
+ []
60
60
]
61
61
62
62
def setup_network (self ):
63
63
"""Start with the nodes disconnected so that one can generate a snapshot
64
64
including blocks the other hasn't yet seen."""
65
- self .add_nodes (3 )
65
+ self .add_nodes (4 )
66
66
self .start_nodes (extra_args = self .extra_args )
67
67
68
68
def test_invalid_snapshot_scenarios (self , valid_snapshot_path ):
@@ -204,6 +204,29 @@ def test_snapshot_with_less_work(self, dump_output_path):
204
204
assert_raises_rpc_error (- 32603 , "Unable to load UTXO snapshot" , node .loadtxoutset , dump_output_path )
205
205
self .restart_node (0 , extra_args = self .extra_args [0 ])
206
206
207
+ def test_snapshot_in_a_divergent_chain (self , dump_output_path ):
208
+ n0 = self .nodes [0 ]
209
+ n3 = self .nodes [3 ]
210
+ assert_equal (n0 .getblockcount (), FINAL_HEIGHT )
211
+ assert_equal (n3 .getblockcount (), START_HEIGHT )
212
+
213
+ self .log .info ("Check importing a snapshot where current chain-tip is not an ancestor of the snapshot block but has less work" )
214
+ # Generate a divergent chain in n3 up to 298
215
+ self .generate (n3 , nblocks = 99 , sync_fun = self .no_op )
216
+ assert_equal (n3 .getblockcount (), SNAPSHOT_BASE_HEIGHT - 1 )
217
+
218
+ # Try importing the snapshot and assert its success
219
+ loaded = n3 .loadtxoutset (dump_output_path )
220
+ assert_equal (loaded ['base_height' ], SNAPSHOT_BASE_HEIGHT )
221
+ normal , snapshot = n3 .getchainstates ()["chainstates" ]
222
+ assert_equal (normal ['blocks' ], START_HEIGHT + 99 )
223
+ assert_equal (snapshot ['blocks' ], SNAPSHOT_BASE_HEIGHT )
224
+
225
+ # Now lets sync the nodes and wait for the background validation to finish
226
+ self .connect_nodes (0 , 3 )
227
+ self .sync_blocks (nodes = (n0 , n3 ))
228
+ self .wait_until (lambda : len (n3 .getchainstates ()['chainstates' ]) == 1 )
229
+
207
230
def run_test (self ):
208
231
"""
209
232
Bring up two (disconnected) nodes, mine some new blocks on the first,
@@ -215,6 +238,7 @@ def run_test(self):
215
238
n0 = self .nodes [0 ]
216
239
n1 = self .nodes [1 ]
217
240
n2 = self .nodes [2 ]
241
+ n3 = self .nodes [3 ]
218
242
219
243
self .mini_wallet = MiniWallet (n0 )
220
244
@@ -265,6 +289,7 @@ def run_test(self):
265
289
# block.
266
290
n1 .submitheader (block )
267
291
n2 .submitheader (block )
292
+ n3 .submitheader (block )
268
293
269
294
# Ensure everyone is seeing the same headers.
270
295
for n in self .nodes :
@@ -455,7 +480,7 @@ def check_tx_counts(final: bool) -> None:
455
480
456
481
self .connect_nodes (0 , 2 )
457
482
self .wait_until (lambda : n2 .getchainstates ()['chainstates' ][- 1 ]['blocks' ] == FINAL_HEIGHT )
458
- self .sync_blocks ()
483
+ self .sync_blocks (nodes = ( n0 , n2 ) )
459
484
460
485
self .log .info ("Ensuring background validation completes" )
461
486
self .wait_until (lambda : len (n2 .getchainstates ()['chainstates' ]) == 1 )
@@ -492,6 +517,8 @@ def check_tx_counts(final: bool) -> None:
492
517
self .connect_nodes (0 , 2 )
493
518
self .wait_until (lambda : n2 .getblockcount () == FINAL_HEIGHT )
494
519
520
+ self .test_snapshot_in_a_divergent_chain (dump_output ['path' ])
521
+
495
522
@dataclass
496
523
class Block :
497
524
hash : str
0 commit comments