bitcoin/test/functional/rpc_dumptxoutset.py

93 lines
3.6 KiB
Python
Executable File

#!/usr/bin/env python3
# Copyright (c) 2019-2022 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the generation of UTXO snapshots using `dumptxoutset`.
"""
from test_framework.blocktools import COINBASE_MATURITY
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
assert_raises_rpc_error,
sha256sum_file,
)
class DumptxoutsetTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 1
def test_dumptxoutset_with_fork(self):
node = self.nodes[0]
tip = node.getbestblockhash()
target_height = node.getblockcount() - 10
target_hash = node.getblockhash(target_height)
# Create a fork of two blocks at the target height
invalid_block = node.getblockhash(target_height + 1)
node.invalidateblock(invalid_block)
# Reset mocktime to not regenerate the same blockhash
node.setmocktime(0)
self.generate(node, 2)
# Move back on to actual main chain
node.reconsiderblock(invalid_block)
self.wait_until(lambda: node.getbestblockhash() == tip)
# Use dumptxoutset at the forked height
out = node.dumptxoutset("txoutset_fork.dat", "rollback", {"rollback": target_height})
# Verify the snapshot was created at the target height and not the fork tip
assert_equal(out['base_height'], target_height)
assert_equal(out['base_hash'], target_hash)
def run_test(self):
"""Test a trivial usage of the dumptxoutset RPC command."""
node = self.nodes[0]
mocktime = node.getblockheader(node.getblockhash(0))['time'] + 1
node.setmocktime(mocktime)
self.generate(node, COINBASE_MATURITY)
FILENAME = 'txoutset.dat'
out = node.dumptxoutset(FILENAME, "latest")
expected_path = node.chain_path / FILENAME
assert expected_path.is_file()
assert_equal(out['coins_written'], 100)
assert_equal(out['base_height'], 100)
assert_equal(out['path'], str(expected_path))
# Blockhash should be deterministic based on mocked time.
assert_equal(
out['base_hash'],
'6885775faa46290bedfa071f22d0598c93f1d7e01f24607c4dedd69b9baa4a8f')
# UTXO snapshot hash should be deterministic based on mocked time.
assert_equal(
sha256sum_file(str(expected_path)).hex(),
'd9506d541437f5e2892d6b6ea173f55233de11601650c157a27d8f2b9d08cb6f')
assert_equal(
out['txoutset_hash'], 'd4453995f4f20db7bb3a604afd10d7128e8ee11159cde56d5b2fd7f55be7c74c')
assert_equal(out['nchaintx'], 101)
# Specifying a path to an existing or invalid file will fail.
assert_raises_rpc_error(
-8, '{} already exists'.format(FILENAME), node.dumptxoutset, FILENAME, "latest")
invalid_path = node.datadir_path / "invalid" / "path"
assert_raises_rpc_error(
-8, "Couldn't open file {}.incomplete for writing".format(invalid_path), node.dumptxoutset, invalid_path, "latest")
self.log.info("Test that dumptxoutset with unknown dump type fails")
assert_raises_rpc_error(
-8, 'Invalid snapshot type "bogus" specified. Please specify "rollback" or "latest"', node.dumptxoutset, 'utxos.dat', "bogus")
self.log.info("Testing dumptxoutset with chain fork at target height")
self.test_dumptxoutset_with_fork()
if __name__ == '__main__':
DumptxoutsetTest(__file__).main()