test: loadtxoutset in divergent chain with less work

This commit is contained in:
Alfonso Roman Zubeldia 2024-06-19 15:07:55 +02:00
parent d35efe1efc
commit 5b7f70ba26

View file

@ -21,7 +21,6 @@ Interesting test cases could be loading an assumeutxo snapshot file with:
Interesting starting states could be loading a snapshot when the current chain tip is: Interesting starting states could be loading a snapshot when the current chain tip is:
- TODO: An ancestor of snapshot block - TODO: An ancestor of snapshot block
- TODO: Not an ancestor of the snapshot block but has less work
- TODO: The snapshot block - TODO: The snapshot block
- TODO: A descendant of 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 - TODO: Not an ancestor or a descendant of the snapshot block and has more work
@ -51,18 +50,19 @@ class AssumeutxoTest(BitcoinTestFramework):
def set_test_params(self): def set_test_params(self):
"""Use the pregenerated, deterministic chain up to height 199.""" """Use the pregenerated, deterministic chain up to height 199."""
self.num_nodes = 3 self.num_nodes = 4
self.rpc_timeout = 120 self.rpc_timeout = 120
self.extra_args = [ self.extra_args = [
[], [],
["-fastprune", "-prune=1", "-blockfilterindex=1", "-coinstatsindex=1"], ["-fastprune", "-prune=1", "-blockfilterindex=1", "-coinstatsindex=1"],
["-persistmempool=0","-txindex=1", "-blockfilterindex=1", "-coinstatsindex=1"], ["-persistmempool=0","-txindex=1", "-blockfilterindex=1", "-coinstatsindex=1"],
[]
] ]
def setup_network(self): def setup_network(self):
"""Start with the nodes disconnected so that one can generate a snapshot """Start with the nodes disconnected so that one can generate a snapshot
including blocks the other hasn't yet seen.""" including blocks the other hasn't yet seen."""
self.add_nodes(3) self.add_nodes(4)
self.start_nodes(extra_args=self.extra_args) self.start_nodes(extra_args=self.extra_args)
def test_invalid_snapshot_scenarios(self, valid_snapshot_path): def test_invalid_snapshot_scenarios(self, valid_snapshot_path):
@ -204,6 +204,29 @@ class AssumeutxoTest(BitcoinTestFramework):
assert_raises_rpc_error(-32603, "Unable to load UTXO snapshot", node.loadtxoutset, dump_output_path) assert_raises_rpc_error(-32603, "Unable to load UTXO snapshot", node.loadtxoutset, dump_output_path)
self.restart_node(0, extra_args=self.extra_args[0]) self.restart_node(0, extra_args=self.extra_args[0])
def test_snapshot_in_a_divergent_chain(self, dump_output_path):
n0 = self.nodes[0]
n3 = self.nodes[3]
assert_equal(n0.getblockcount(), FINAL_HEIGHT)
assert_equal(n3.getblockcount(), START_HEIGHT)
self.log.info("Check importing a snapshot where current chain-tip is not an ancestor of the snapshot block but has less work")
# Generate a divergent chain in n3 up to 298
self.generate(n3, nblocks=99, sync_fun=self.no_op)
assert_equal(n3.getblockcount(), SNAPSHOT_BASE_HEIGHT - 1)
# Try importing the snapshot and assert its success
loaded = n3.loadtxoutset(dump_output_path)
assert_equal(loaded['base_height'], SNAPSHOT_BASE_HEIGHT)
normal, snapshot = n3.getchainstates()["chainstates"]
assert_equal(normal['blocks'], START_HEIGHT + 99)
assert_equal(snapshot['blocks'], SNAPSHOT_BASE_HEIGHT)
# Now lets sync the nodes and wait for the background validation to finish
self.connect_nodes(0, 3)
self.sync_blocks(nodes=(n0, n3))
self.wait_until(lambda: len(n3.getchainstates()['chainstates']) == 1)
def run_test(self): def run_test(self):
""" """
Bring up two (disconnected) nodes, mine some new blocks on the first, Bring up two (disconnected) nodes, mine some new blocks on the first,
@ -215,6 +238,7 @@ class AssumeutxoTest(BitcoinTestFramework):
n0 = self.nodes[0] n0 = self.nodes[0]
n1 = self.nodes[1] n1 = self.nodes[1]
n2 = self.nodes[2] n2 = self.nodes[2]
n3 = self.nodes[3]
self.mini_wallet = MiniWallet(n0) self.mini_wallet = MiniWallet(n0)
@ -265,6 +289,7 @@ class AssumeutxoTest(BitcoinTestFramework):
# block. # block.
n1.submitheader(block) n1.submitheader(block)
n2.submitheader(block) n2.submitheader(block)
n3.submitheader(block)
# Ensure everyone is seeing the same headers. # Ensure everyone is seeing the same headers.
for n in self.nodes: for n in self.nodes:
@ -455,7 +480,7 @@ class AssumeutxoTest(BitcoinTestFramework):
self.connect_nodes(0, 2) self.connect_nodes(0, 2)
self.wait_until(lambda: n2.getchainstates()['chainstates'][-1]['blocks'] == FINAL_HEIGHT) self.wait_until(lambda: n2.getchainstates()['chainstates'][-1]['blocks'] == FINAL_HEIGHT)
self.sync_blocks() self.sync_blocks(nodes=(n0, n2))
self.log.info("Ensuring background validation completes") self.log.info("Ensuring background validation completes")
self.wait_until(lambda: len(n2.getchainstates()['chainstates']) == 1) self.wait_until(lambda: len(n2.getchainstates()['chainstates']) == 1)
@ -492,6 +517,8 @@ class AssumeutxoTest(BitcoinTestFramework):
self.connect_nodes(0, 2) self.connect_nodes(0, 2)
self.wait_until(lambda: n2.getblockcount() == FINAL_HEIGHT) self.wait_until(lambda: n2.getblockcount() == FINAL_HEIGHT)
self.test_snapshot_in_a_divergent_chain(dump_output['path'])
@dataclass @dataclass
class Block: class Block:
hash: str hash: str