Inside Bitcoin
Opening the selected file…
Inside Bitcoin
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1#!/usr/bin/env python32# Copyright (c) 2023-present The Bitcoin Core developers3# Distributed under the MIT software license, see the accompanying4# file COPYING or http://www.opensource.org/licenses/mit-license.php.5"""Test running bitcoind with -reindex from a read-only blockstore6- Start a node, generate blocks, then restart with -reindex after setting blk files to read-only7"""9import os10import stat11import subprocess12from test_framework.test_framework import BitcoinTestFramework13from test_framework.util import assert_equal16class BlockstoreReindexTest(BitcoinTestFramework):17def set_test_params(self):18self.setup_clean_chain = True19self.num_nodes = 120self.extra_args = [["-fastprune"]]22def reindex_readonly(self):23self.log.debug("Generate block big enough to start second block file")24fastprune_blockfile_size = 0x1000025opreturn = "6a"26nulldata = fastprune_blockfile_size * "ff"27self.generateblock(self.nodes[0], output=f"raw({opreturn}{nulldata})", transactions=[])28block_count = self.nodes[0].getblockcount()29self.stop_node(0)31assert (self.nodes[0].chain_path / "blocks" / "blk00000.dat").exists()32assert (self.nodes[0].chain_path / "blocks" / "blk00001.dat").exists()34self.log.debug("Make the first block file read-only")35filename = self.nodes[0].chain_path / "blocks" / "blk00000.dat"36filename.chmod(stat.S_IREAD)38undo_immutable_cmd = None39should_reindex = True40# Linux41try:42subprocess.run(['chattr'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)43try:44subprocess.run(['chattr', '+i', filename], capture_output=True, check=True)45undo_immutable_cmd = ['chattr', '-i', filename]46self.log.info("Made file immutable with chattr")47except subprocess.CalledProcessError as e:48self.log.warning(str(e))49if e.stdout:50self.log.warning(f"stdout: {e.stdout}")51if e.stderr:52self.log.warning(f"stderr: {e.stderr}")53if os.getuid() == 0:54self.log.warning("Return early on Linux under root, because chattr failed.")55self.log.warning("This should only happen due to missing capabilities in a container.")56self.log.warning("Make sure to --cap-add LINUX_IMMUTABLE if you want to run this test.")57should_reindex = False58except Exception:59# macOS, and *BSD60try:61subprocess.run(['chflags'], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)62try:63subprocess.run(['chflags', 'uchg', filename], capture_output=True, check=True)64undo_immutable_cmd = ['chflags', 'nouchg', filename]65self.log.info("Made file immutable with chflags")66except subprocess.CalledProcessError as e:67self.log.warning(str(e))68if e.stdout:69self.log.warning(f"stdout: {e.stdout}")70if e.stderr:71self.log.warning(f"stderr: {e.stderr}")72if os.getuid() == 0:73self.log.warning("Return early on BSD under root, because chflags failed.")74should_reindex = False75except Exception:76pass78if should_reindex:79self.log.debug("Attempt to restart and reindex the node with the unwritable block file")80with self.nodes[0].assert_debug_log(["Reindexing finished"], timeout=60):81self.start_node(0, extra_args=['-reindex', '-fastprune'])82assert_equal(block_count, self.nodes[0].getblockcount())83if undo_immutable_cmd is not None:84subprocess.check_call(undo_immutable_cmd)86filename.chmod(0o777)88def run_test(self):89self.reindex_readonly()92if __name__ == '__main__':93BlockstoreReindexTest(__file__).main()
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.