#36129 fuzz: reset chainman after external block imports

full analysis

https://github.com/bitcoin/bitcoin/pull/36129 · HowHsu · +23/-2 in 1 files, 1 commits · labels: Fuzzing · draft

Goal

  • Prevent fuzz state contamination across iterations in external block file loading
  • Eliminate order-dependent coverage and non-reproducible fuzz crashes

This pull request resets and re-initializes the chainstate manager after each iteration of the `load_external_block_file` fuzz target. It also disables unused networking setup to prevent `PeerManager` dangling references and resets the deterministic random number generator seed.

Problem: `LoadExternalBlockFile()` adds headers to the block index even when validation fails, contaminating static global state across fuzz iterations and causing order-dependent corpus coverage and non-reproducible fuzz crashes.

Category: Test infrastructure (#6 of 45)

P3 · bug fix

  • P3 because it fixes state leakage across fuzz iterations for a single fuzz harness
  • Improves determinism and crash reproducibility without affecting production code

Fixes state leakage across fuzz iterations in `load_external_block_file`. As the author notes, 'LoadExternalBlockFile() may add headers to the block index even when full block validation fails... making all-corpus coverage order-dependent.' Ensuring test harness determinism improves fuzz signal and reproducibility, though it affects a single fuzz target.

Membership: Modifies `src/test/fuzz/load_external_block_file.cpp` to ensure proper harness isolation and deterministic fuzzing execution.

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

Reviewability: Ready

  • Ready to review now, cleanly merges and passes CI

The patch is small, cleanly merges, passes CI, and the author addressed reviewer feedback with an explanation for why unconditional resets are currently needed.

Author status: active; answered feedback and force-pushed updates

Resolved concerns:

  • maflcko asked whether a dirty-guard would speed up execution by only resetting when chainstate modified; HowHsu answered that tracking all mutated state (like `m_last_notified_header`) is error-prone and proposed the unconditional reset as a baseline step

Agreement: Positive

  • Collaborative discussion with no objections raised
  • Inquired whether a dirty-guard optimization would improve speed (maflcko)
  • Author explained unconditional resets are necessary to catch all internal mutations

Positive; maflcko suggested a performance check and HowHsu explained why full resets are necessary

Reviewer engagement is collaborative with an optimization inquiry that the author addressed; no objections to the approach were raised.

  • maflcko asked if a dirty-guard would be faster
  • HowHsu explained that checking index size is insufficient due to other order-dependent internal variables, proposing unconditional reset first

Review verdicts (DrahtBot): 0

Files

25 lines under test/bench/ci.

  • src/test/fuzz/load_external_block_file.cpp +23/-2

Card

This PR resets the chainstate manager after each input in the `load_external_block_file` fuzz target. It solves an issue where partial imports pollute global chainstate, causing fuzzer corpus execution to be order-dependent. Deterministic test runs verify that all 930 existing corpus inputs now execute consistently in randomized order. Review is active and ready, with only a minor performance discussion on dirty checking raised so far.

Data

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