|
| 1 | +#!/usr/bin/env python3 |
| 2 | +# Copyright (c) 2024 The Bitcoin Core developers |
| 3 | +# Distributed under the MIT software license, see the accompanying |
| 4 | +# file COPYING or http://www.opensource.org/licenses/mit-license.php. |
| 5 | +"""Test support for XORed block data and undo files (`-blocksxor` option).""" |
| 6 | +import os |
| 7 | + |
| 8 | +from test_framework.test_framework import BitcoinTestFramework |
| 9 | +from test_framework.test_node import ErrorMatch |
| 10 | +from test_framework.util import ( |
| 11 | + assert_equal, |
| 12 | + assert_greater_than, |
| 13 | + read_xor_key, |
| 14 | + util_xor, |
| 15 | +) |
| 16 | +from test_framework.wallet import MiniWallet |
| 17 | + |
| 18 | + |
| 19 | +class BlocksXORTest(BitcoinTestFramework): |
| 20 | + def set_test_params(self): |
| 21 | + self.num_nodes = 1 |
| 22 | + self.extra_args = [[ |
| 23 | + '-blocksxor=1', |
| 24 | + '-fastprune=1', # use smaller block files |
| 25 | + '-datacarriersize=100000', # needed to pad transaction with MiniWallet |
| 26 | + ]] |
| 27 | + |
| 28 | + def run_test(self): |
| 29 | + self.log.info("Mine some blocks, to create multiple blk*.dat/rev*.dat files") |
| 30 | + node = self.nodes[0] |
| 31 | + wallet = MiniWallet(node) |
| 32 | + for _ in range(5): |
| 33 | + wallet.send_self_transfer(from_node=node, target_weight=80000) |
| 34 | + self.generate(wallet, 1) |
| 35 | + |
| 36 | + block_files = list(node.blocks_path.glob('blk[0-9][0-9][0-9][0-9][0-9].dat')) |
| 37 | + undo_files = list(node.blocks_path.glob('rev[0-9][0-9][0-9][0-9][0-9].dat')) |
| 38 | + assert_equal(len(block_files), len(undo_files)) |
| 39 | + assert_greater_than(len(block_files), 1) # we want at least one full block file |
| 40 | + |
| 41 | + self.log.info("Shut down node and un-XOR block/undo files manually") |
| 42 | + self.stop_node(0) |
| 43 | + xor_key = read_xor_key(node=node) |
| 44 | + for data_file in sorted(block_files + undo_files): |
| 45 | + self.log.debug(f"Rewriting file {data_file}...") |
| 46 | + with open(data_file, 'rb+') as f: |
| 47 | + xored_data = f.read() |
| 48 | + f.seek(0) |
| 49 | + f.write(util_xor(xored_data, xor_key, offset=0)) |
| 50 | + |
| 51 | + self.log.info("Check that restarting with 'blocksxor=0' fails if XOR key is present") |
| 52 | + node.assert_start_raises_init_error(['-blocksxor=0'], |
| 53 | + 'The blocksdir XOR-key can not be disabled when a random key was already stored!', |
| 54 | + match=ErrorMatch.PARTIAL_REGEX) |
| 55 | + |
| 56 | + self.log.info("Delete XOR key, restart node with '-blocksxor=0', check blk*.dat/rev*.dat file integrity") |
| 57 | + os.remove(node.blocks_path / 'xor.dat') |
| 58 | + self.start_node(0, extra_args=['-blocksxor=0']) |
| 59 | + # checklevel=2 -> verify block validity + undo data |
| 60 | + # nblocks=0 -> verify all blocks |
| 61 | + node.verifychain(checklevel=2, nblocks=0) |
| 62 | + |
| 63 | + |
| 64 | +if __name__ == '__main__': |
| 65 | + BlocksXORTest(__file__).main() |
0 commit comments