Skip to content

Commit faa1b9b

Browse files
committed
test: add functional test for XORed block/undo files (-blocksxor)
1 parent 6b3676b commit faa1b9b

File tree

2 files changed

+66
-0
lines changed

2 files changed

+66
-0
lines changed

test/functional/feature_blocksxor.py

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
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()

test/functional/test_runner.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,7 @@
284284
'mempool_package_limits.py',
285285
'mempool_package_rbf.py',
286286
'feature_versionbits_warning.py',
287+
'feature_blocksxor.py',
287288
'rpc_preciousblock.py',
288289
'wallet_importprunedfunds.py --legacy-wallet',
289290
'wallet_importprunedfunds.py --descriptors',

0 commit comments

Comments
 (0)