Skip to content

fix(node): anchor assume-valid per network with Core's hash and minimum work - #31

Open
MeABzZz wants to merge 3 commits into
BTCDecoded:mainfrom
MeABzZz:criticals/assume-valid-anchor
Open

MeABzZz wants to merge 3 commits into
BTCDecoded:mainfrom
MeABzZz:criticals/assume-valid-anchor

Conversation

@MeABzZz

@MeABzZz MeABzZz commented Oct 21, 2026 •

Copy link
Copy Markdown

What remains after main

Josh's main fixed the dangerous part of this a different way:

  • bbdaccb (consensus): a script skip below assume_valid_height now requires an assume-valid hash.
  • blvm 19da720: the blvm binary no longer seeds a hashless height.

Together these mean main never skips scripts by default, so the "height with no hash and minimum work 0" critical is closed on main. No code from this PR is duplicated there, so nothing was dropped in the merge.

This PR now does something different: it restores Core-anchored assume-valid. Each network gets Bitcoin Core v31.1's defaultAssumeValid height and hash, plus its nMinimumChainWork. Values come from https://github.com/bitcoin/bitcoin/blob/v31.1/src/kernel/chainparams.cpp:

Network Height Hash (display) Min work
mainnet 938343 00000000000000000000ccebd6…1ba5ac 0x1128750f82f4c366153a3a030
testnet3 4842348 000000007a61e423…6505b67f4 0x17dde1c649f3708d14b6
testnet4 0 (full verification kept; Core has 123613) none 0x9a0fe15d0177d086304
signet (default) 293175 00000008414aab61…01ff5c329 0xb463ea0a4b8
regtest, custom signet 0 none 0

resolve_assume_valid picks the height in this order: BLVM_ASSUME_VALID_HEIGHT, then the config file, then the network default.

  • A configured height equal to the network's keeps the network's hash. That covers old config files and pre-19da720 binaries that wrote only the height.
  • Minimum work always comes from the network.
  • -noassumevalid still turns the skip off.
  • The startup log prints min_chain_work.

Commits since the original: 8f658e3 merges node main 4f1be96, and 8ac954c updates a test doc comment to describe the height-only seed after 19da720.

Verification (Rust 1.88.0, branch head 8ac954c)

  • tests/assumevalid_tests.rs: 10 passed. The tests check every value against Core's display hex and cover:

    • the height-only seed
    • zero-config mainnet and regtest
    • custom height
    • env and noassumevalid
    • custom signet

    Against main's src/ these tests don't compile (core_assume_valid_for_network and resolve_assume_valid don't exist there). Main's defaults are height-only (912683 / 4550000 / 267665) with no hash or minimum work, which since bbdaccb means no skip at all.

  • config_parsing_tests: 44 passed. lib config::: 16 passed.

  • Full cargo test --no-fail-fast: 3022 passed / 0 failed / 26 ignored (main 4f1be96: 3016 / 0 / 26; +6 new tests)

  • cargo clippy --all-targets: the same 90 diagnostics as main, with 0 new. The 2 nonminimal_bool errors in chunk_assigner_tests.rs are already on main.

  • rustfmt --check on the touched files: clean. Main's existing fmt failure is in tests/feature_flags_reflection_tests.rs:7.

Review notes

  • Builds on: blvm-consensus bbdaccb (the skip needs a hash), blvm 19da720 (no hashless seed), and node main 4f1be96.
  • Merge order:
  • Open decisions:
    1. Should mainnet skip scripts by default at all? On main today it doesn't (full verification). This PR turns Core's skip back on, behind the hash and minimum-work floor. If full verification is the intended default, close this PR.
    2. Checkpoint vs Core semantics. Today's consensus rejects any block at the assume-valid height whose hash differs, so setting the hash by default makes 938343 behave like a hard checkpoint. Core never rejects a chain for this. blvm-consensus#24 + blvm-node#39 (drafts) implement Core semantics: skip only ancestors of the assume-valid block, never reject.
    3. testnet4 stays at 0 rather than Core's 123613.

…um work

Startup gave consensus assume_valid_height with hash none and
n_minimum_chain_work 0. Connect skips scripts when
height < assume_valid_height && chainwork >= n_minimum_chain_work, so with
a floor of 0 any header chain skipped every script below the height. On
mainnet the blvm binary seeds height 912683 (Core v30) with no hash; on a
zero-config regtest start the library default height 938343 applied to
regtest.

Add core_assume_valid_for_network with Bitcoin Core v31.1 chainparams
(defaultAssumeValid height and hash, nMinimumChainWork) for mainnet,
testnet3 and default signet. Testnet4 keeps height 0 (full verification,
as before) and takes Core's minimum work. Regtest and custom signet get
none. resolve_assume_valid picks the height from env, then config, then
network; a configured height equal to the network's keeps the network's
hash, so the binary's height-only seed keeps the anchor. Minimum work
always comes from the network. The startup log prints it.

Tests: tests/assumevalid_tests.rs checks every value against Core v31.1
display hex, and that the binary seed, zero-config, custom-height, env
and custom-signet cases resolve as described.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant