test: Core v31.1 verdict-only height-1 block differential fuzz (Q-30) - #323
Merged
Conversation
added 9 commits
September 4, 2026 10:16
Differential fuzz needs the same Core release as the sparse submodule without building bitcoind from it. Record official linux tarball SHA256s in inventory.toml [release] and print them via release_pin.py (no network). Required CI already runs fuzz-run.test.sh; hook the new pin test there so it is gated before the operator workflow commit.
Download the inventory-pinned Core v31.1 tarball, verify SHA256, and extract only bin/bitcoind into ~/.cache/rbitcoin/core-bitcoind. Tests use a file:// stub tarball so default CI never hits the network.
Extract nonce-only regtest PoW grind from mine_regtest_paying so the differential harness can fix prev/bits/time/merkle/nonce without rewriting fuzzer-owned version or txdata. Commit a height-1 seed for the fuzz corpus.
Add block_diff: Core submitblock JSON/skip map, accept_received_block verdict mapping, compare_one with rewind_to_height(0), BIP34 overlay on the diff hub only, env/cookie/HTTP helpers. Pins use a mock oracle so default cargo test never fetches Core or binds RPC.
Isolated cargo-fuzz bin calls compare_one against a spawned official bitcoind. Env gates HEAD_SCALE/IO/CORE_BITCOIND before opening the store. Not a workspace member; default cargo test does not compile it.
Add block_differential: fetch bitcoind, --sanitizer none, -jobs=1, tee a log and fail if comparisons=0. Unset CARGO_TARGET_DIR around cargo-fuzz so worktree target/dev does not steal fuzz/target. block_wire path unchanged.
TESTING.md owns how to run height-1 verdict-only fuzz vs official Core v31.1 bitcoind. Q-30 stays Open. Default cargo test does not fetch Core.
Hash/OutPoint/ScriptBuf are test-only; clippy -D warnings failed on the lib graph. Keep Hash in the test module for from_byte_array.
Second fuzz.yml job: no CARGO_TARGET_DIR, rust-cache fuzz/target, cache the v31.1 tarball, --sanitizer none via fuzz-run.sh. Required test job runs pin/fetch script tests; fmt also checks the fuzz workspace. Not a required check. Operator may need to push this workflow commit.
reardencode
force-pushed
the
test/core-diff-fuzz
branch
from
September 4, 2026 17:20
1b6b789 to
a56fe0b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
First meaningful in-tree differential fuzz (Q-30): libFuzzer mutates a height-1 regtest block, runs in-process
ChainHub::accept_received_block, andsubmitblocks the same bytes to official Bitcoin Core v31.1bitcoind(downloaded tarball, SHA256 pinned ininventory.toml[release]). Compare accept vs reject only.Default
cargo test --workspacedoes not download Core, bind RPC, or compilefuzz/. Fuzz is not a required PR check.Why download, not build
third_party/bitcoinis a sparse clone (src/test/data+test). It cannot producebitcoind. Official tarball hashes:b80d9c3e04da78fb6f0569685673418cf686fadba9042d926d13fb87ff503f9edcf1873f2208ba4f962f3398d47e154c39c0084be8f4553e05c940d0ace3d004Harness vs finding
panic!(libFuzzercrash-*) →docs/external_findings/+ named regression. Do not churn production in this PR to silence it.comparisons==0→ exit 2, no crash artifact.rewind_to_height(0)on us; Coreinvalidateblockuntilgetblockcount==0. Diff hub overlaysbip34@1only (globalChainParams::regtest()unchanged).Operator: workflow commit
The GitHub App cannot push
.github/workflows/*. Local tip ontest/core-diff-fuzzhas one extra commit after this PR head:Please push it from a machine with
workflowspermission:That commit adds the nightly
block_differentialjob (timeout-minutes: 50, tarball cache, rust-cachefuzz -> fuzz/target, no job-levelCARGO_TARGET_DIR) and required-CI hooks for pin/fetch tests + fuzz workspacefmt. Preferworkflow_dispatchonfuzzonce after that push.Pin/fetch tests are already hooked from
scripts/fuzz-run.test.sh(requiredtestjob) so they run before the workflow commit.Nightly command (after workflow lands)
Q-30 stays Open (spend-pad / script-wire / BIP324 later).