Skip to content

Commit

Permalink
test: Assumeutxo: import snapshot in a node with a divergent chain
Browse files Browse the repository at this point in the history
  • Loading branch information
alfonsoromanz committed Apr 29, 2024
1 parent 0c45d73 commit 4c07a79
Showing 1 changed file with 37 additions and 7 deletions.
44 changes: 37 additions & 7 deletions test/functional/feature_assumeutxo.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,12 @@
bad other serialization)
- TODO: Valid snapshot file, but referencing a snapshot block that turns out to be
invalid, or has an invalid parent
- TODO: Valid snapshot file and snapshot block, but the block is not on the
most-work chain
Interesting starting states could be loading a snapshot when the current chain tip is:
- TODO: An ancestor of snapshot block
- TODO: Not an ancestor of the snapshot block but has less work
- TODO: The snapshot block
- TODO: A descendant of the snapshot block
- TODO: Not an ancestor or a descendant of the snapshot block and has more work
"""
from shutil import rmtree
Expand Down Expand Up @@ -152,6 +148,38 @@ def test_invalid_mempool_state(self, dump_output_path):

self.restart_node(2, extra_args=self.extra_args[2])

def test_snapshot_in_a_divergent_chain(self, dump_output_path):
# First rollback node2's chain to the pregenerated one, up to height 199
node = self.nodes[2]
current_height = node.getblockcount()
base_height = 199
for block_height in range(current_height, base_height, -1):
block_hash = node.getblockhash(block_height)
node.invalidateblock(block_hash)
assert_equal(node.getblockcount(), START_HEIGHT)

self.log.info(f"Check importing a snapshot where current chain-tip is not an ancestor of the snapshot block but has less work")
# Generate a totally different chain in node2 but with less work compared to the snapshot
self.generate(node, nblocks=99, sync_fun=self.no_op)
assert node.getblockcount() < SNAPSHOT_BASE_HEIGHT
# Try importing the snapshot and assert its success
loaded = node.loadtxoutset(dump_output_path)
assert_equal(loaded['coins_loaded'], SNAPSHOT_BASE_HEIGHT)
assert_equal(loaded['base_height'], SNAPSHOT_BASE_HEIGHT)

# Restart the node and delete the snapshot chainstate.
self.restart_node(2, extra_args=['-reindex-chainstate=1', *self.extra_args[2]])
assert_equal(node.getblockcount(), 298)

self.log.info(f"Check importing a snapshot where current chain-tip is not an ancestor or a descendant of the snapshot block and has more work")
# Generate two extra blocks and make sure node2's chain has more work than the snapshot's chain
# This covers the scenario where the snapshot block is not on the most-work chain
self.generate(node, nblocks=2, sync_fun=self.no_op)
assert node.getblockcount() > SNAPSHOT_BASE_HEIGHT
# Import the snapshot and assert its failure
with node.assert_debug_log(expected_msgs=["[snapshot] activation failed - work does not exceed active chainstate"]):
assert_raises_rpc_error(-32603, "Unable to load UTXO snapshot", node.loadtxoutset, dump_output_path)

def run_test(self):
"""
Bring up two (disconnected) nodes, mine some new blocks on the first,
Expand Down Expand Up @@ -365,10 +393,10 @@ def check_tx_counts(final: bool) -> None:
self.wait_until(lambda: n.getindexinfo() == completed_idx_state)


# Node 2: all indexes + reindex
# -----------------------------
# Node 2: all indexes + reindex + divergent chain
# -----------------------------------------------

self.log.info("-- Testing all indexes + reindex")
self.log.info("-- Testing all indexes + reindex + divergent chain")
assert_equal(n2.getblockcount(), START_HEIGHT)

self.log.info(f"Loading snapshot into third node from {dump_output['path']}")
Expand Down Expand Up @@ -434,6 +462,8 @@ def check_tx_counts(final: bool) -> None:
self.connect_nodes(0, 2)
self.wait_until(lambda: n2.getblockcount() == FINAL_HEIGHT)

self.test_snapshot_in_a_divergent_chain(dump_output['path'])

@dataclass
class Block:
hash: str
Expand Down

0 comments on commit 4c07a79

Please sign in to comment.