#33324 blocks: add resumable reobfuscation for existing block files

full analysis

https://github.com/bitcoin/bitcoin/pull/33324 · l0rinc · +451/-43 in 15 files, 9 commits · labels: Needs rebase

Goal

  • Allow node operators to obfuscate existing block files or rotate keys without redownloading the chain
  • Protects pre-v28 datadirs from false-positive antivirus scanner deletion or quarantine

This pull request introduces the `-reobfuscate-blocks` startup option to migrate existing block and undo files (`blk*.dat` and `rev*.dat`) under a new or random XOR obfuscation key. The migration rewrites files in fixed-size chunks to temporary staged files, preserves file timestamps, commits directory changes to disk for crash safety, and is resumable if interrupted. It also adds progress reporting through kernel notifications and tests covering key rotation and interruption recovery.

Problem: Nodes that were synced prior to Bitcoin Core v28 store block and undo files without XOR obfuscation using a zero key, leaving them susceptible to false-positive deletion or quarantine by antivirus scanners. Currently, node operators cannot obfuscate existing block files or rotate XOR keys without redownloading the entire blockchain.

Category: Validation (#28 of 48)

P3 · new feature

  • P3 because it helps operators with pre-v28 datadirs protect block files from antivirus false positives
  • Avoids having to redownload the entire blockchain to obfuscate or rotate keys
  • It is an optional one-off migration and existing nodes run fine without it

Provides a useful maintenance feature allowing node operators with pre-v28 datadirs to obfuscate their block files against antivirus interference without resyncing from scratch. Because this is an optional one-off migration and existing nodes run fine without it, it is worthwhile but reasonably deferrable.

Membership: Substantially modifies block and undo file storage and initialization logic in src/node/blockstorage.cpp and src/init.cpp.

Factors: security/stability 1, bug 0, performance 0, user value 2, leverage 0

Reviewability: Stale: Needs rebase

  • Needs rebase against master due to merge conflicts

The PR has merge conflicts with master and carries the Needs rebase label.

Author status: Active; rebased and pushed I/O error-handling hardening recently, but the PR has since developed merge conflicts.

Open concerns:

  • Whether block reobfuscation should be a bitcoind startup flag or a separate CLI utility binary such as part of bitcoin-util

Resolved concerns:

  • Reading entire block files into memory at once was replaced with chunked 1 MiB stream processing
  • Preserving block file modification timestamps across the rewrite
  • Handling pruned node datadirs where early block files are missing
  • Replacing filesystem assertion aborts with recoverable runtime error handling
  • Restricting argument parsing so invalid hex keys fail immediately on startup

Agreement: Positive w/ caveats

  • General support for the migration feature, but architectural debate remains on the interface
  • Approval after hardening error handling and argument parsing (sedited)
  • Prefers an external CLI tool rather than adding another daemon startup option (stickies-v, luke-jr)
  • Contributed improvements for streaming chunks and timestamp preservation (ajtowns)

sedited approved after hardening; stickies-v and luke-jr questioned in-node startup flag versus a separate tool

Reviewers support the functionality and have contributed improvements, with sedited approving the code after extensive iteration. However, multiple contributors noted an architectural preference for an external CLI tool rather than adding another one-off startup option to the daemon, though sedited accepted shipping it in the node first.

  • sedited approved the PR (ACK 181753328a8e27c7fac5300a44885843c3b6855f) after review iterations on startup parsing and error handling
  • ajtowns suggested chunking, timestamp preservation, and benchmarked multi-threading options, co-authoring commits
  • stickies-v gave Concept ACK but suggested bundling into a utility like bitcoin-util instead of a startup flag
  • luke-jr agreed that a separate standalone utility would be cleaner than daemon startup code

Review verdicts (DrahtBot): 0 (+1)

Files

176 lines under test/bench/ci.

  • src/node/blockstorage.cpp +194/-30
  • test/functional/feature_reobfuscation.py +136/-0
  • src/init.cpp +34/-0
  • src/test/streams_tests.cpp +27/-1
  • src/util/obfuscation.h +21/-0
  • src/node/blockstorage.h +12/-0
  • src/util/fs_helpers.cpp +7/-5
  • src/test/fs_tests.cpp +11/-0
  • src/util/fs_helpers.h +3/-1
  • src/index/base.cpp +1/-2
  • src/index/base.h +1/-1
  • src/index/txindex.cpp +1/-1
  • src/index/txospenderindex.cpp +1/-1
  • src/streams.h +1/-1
  • test/functional/test_runner.py +1/-0

Card

Adds a -reobfuscate-blocks startup option to bitcoind to rewrite existing block and undo files with a random or user-specified XOR key in a crash-safe, resumable manner. This solves the problem where datadirs synced before v28 remain unobfuscated and subject to antivirus false-positive file corruption unless the user completely redownloads the blockchain. The PR has seen active review and approval from sedited with contributions from ajtowns, though stickies-v and luke-jr raised design questions regarding whether this belongs in the daemon or as an external utility. It currently needs a rebase to resolve merge conflicts with master.

Data

dossier JSON · extract JSON · model openrouter/google/gemini-3.8-flash, generated 2026-09-17T16:16, confidence high, input hash 6161573b6aab69bd