bitcoin/test/functional/feature_reindex_readonly.py
Martin Zumsande bf4e919811 test: Disable tests for cli that make large RPC calls
These tests send off large rpc calls (e.g.by submitting large txns or blocks)
that exceed the limit of execve (128kb on many systems) when using cli.
2025-04-25 11:24:55 -04:00

91 lines
4 KiB
Python
Executable file

#!/usr/bin/env python3
# Copyright (c) 2023-present 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 running bitcoind with -reindex from a read-only blockstore
- Start a node, generate blocks, then restart with -reindex after setting blk files to read-only
"""
import os
import stat
import subprocess
from test_framework.test_framework import BitcoinTestFramework
class BlockstoreReindexTest(BitcoinTestFramework):
def set_test_params(self):
self.setup_clean_chain = True
self.num_nodes = 1
self.extra_args = [["-fastprune"]]
self.supports_cli = False
def reindex_readonly(self):
self.log.debug("Generate block big enough to start second block file")
fastprune_blockfile_size = 0x10000
opreturn = "6a"
nulldata = fastprune_blockfile_size * "ff"
self.generateblock(self.nodes[0], output=f"raw({opreturn}{nulldata})", transactions=[])
block_count = self.nodes[0].getblockcount()
self.stop_node(0)
assert (self.nodes[0].chain_path / "blocks" / "blk00000.dat").exists()
assert (self.nodes[0].chain_path / "blocks" / "blk00001.dat").exists()
self.log.debug("Make the first block file read-only")
filename = self.nodes[0].chain_path / "blocks" / "blk00000.dat"
filename.chmod(stat.S_IREAD)
undo_immutable = lambda: None
# Linux
try:
subprocess.run(['chattr'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
try:
subprocess.run(['chattr', '+i', filename], capture_output=True, check=True)
undo_immutable = lambda: subprocess.check_call(['chattr', '-i', filename])
self.log.info("Made file immutable with chattr")
except subprocess.CalledProcessError as e:
self.log.warning(str(e))
if e.stdout:
self.log.warning(f"stdout: {e.stdout}")
if e.stderr:
self.log.warning(f"stderr: {e.stderr}")
if os.getuid() == 0:
self.log.warning("Return early on Linux under root, because chattr failed.")
self.log.warning("This should only happen due to missing capabilities in a container.")
self.log.warning("Make sure to --cap-add LINUX_IMMUTABLE if you want to run this test.")
undo_immutable = False
except Exception:
# macOS, and *BSD
try:
subprocess.run(['chflags'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
try:
subprocess.run(['chflags', 'uchg', filename], capture_output=True, check=True)
undo_immutable = lambda: subprocess.check_call(['chflags', 'nouchg', filename])
self.log.info("Made file immutable with chflags")
except subprocess.CalledProcessError as e:
self.log.warning(str(e))
if e.stdout:
self.log.warning(f"stdout: {e.stdout}")
if e.stderr:
self.log.warning(f"stderr: {e.stderr}")
if os.getuid() == 0:
self.log.warning("Return early on BSD under root, because chflags failed.")
undo_immutable = False
except Exception:
pass
if undo_immutable:
self.log.debug("Attempt to restart and reindex the node with the unwritable block file")
with self.nodes[0].assert_debug_log(["Reindexing finished"], timeout=60):
self.start_node(0, extra_args=['-reindex', '-fastprune'])
assert block_count == self.nodes[0].getblockcount()
undo_immutable()
filename.chmod(0o777)
def run_test(self):
self.reindex_readonly()
if __name__ == '__main__':
BlockstoreReindexTest(__file__).main()