Repository navigation
consensus: script corpus checked against Core v31.1 VerifyScript - #1057
Merged
Merged
Conversation
The corpus uses Core script_tests.json row form. Our interpreter runs every row, and script-oracle compiles VerifyScript from the v31.1 submodule. The first row is an empty scriptSig and OP_1; both engines accept it.
Legacy, witness v0, and tapscript rows cover the 10,000-byte script cap, the 520-byte element cap (including an unexecuted IF), the 201-opcode cap, truncated PUSHDATA, and IF/ELSE/ENDIF structure. OP_VERIF and OP_VERNOTIF reject even when unexecuted. Tapscript OP_SUCCESS still accepts before the initial stack and element checks. script-oracle assembles the rows with the Core script assembler and checks them with v31.1 VerifyScript.
Each legacy disabled opcode rejects inside an unexecuted IF on legacy and witness v0, and accepts as OP_SUCCESS in tapscript. OP_RESERVED, OP_VER, the reserved opcodes, and both ends of the 187..254 success range reject when executed outside tapscript. Opcode 0xff and OP_RETURN reject only when executed. An OP_SUCCESS byte hidden inside a push does not succeed.
Arithmetic accepts a sum that does not fit in 4 bytes and rejects that value when a later numeric opcode decodes it. A 5-byte input rejects. 0 and negative zero match under NUMEQUAL and differ under EQUAL. WITHIN is inclusive of the low bound. Tapscript MINIMALIF rejects every IF argument except an empty vector or a single 0x01. Witness v0 does that only when the flag is on. A bare script ignores the flag. Both engines agree, including Bitcoin Core v31.1 VerifyScript.
Core script_tests.json already accepts and rejects each listed stack opcode. This corpus names the empty-stack pop, 2ROT at five versus six items, and FROMALTSTACK on an empty altstack.
Witness v0 NULLDUMMY follows SCRIPT_VERIFY_NULLDUMMY. Core v31.1 VerifyScript accepts a non-empty dummy when that flag is off. Confirm still sets the flag on every segwit block.
P2SH execution, witness program lengths, unknown tapleaf versions, and the P2PKH, P2WPKH, and key-path verifiers. Typed checks use the same credit and spend as the corpus rows.
Unknown tapleaf versions follow DISCOURAGE_UPGRADABLE_TAPROOT_VERSION. DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM still rejects unknown witness programs and does not reject an unknown leaf. The script corpus and Core's JSON take the remaining consensus lines. secp256k1 stays out of scope.
Unknown leaf versions succeed. That discourage bit is standardness, and confirm never sets it. Unknown witness programs still follow the witness-program flag.
Master moved TxPrecompute and shared prevouts into this crate. The coverage tests that build a wire prevout on an owned job follow that.
rearden-grok
Bot
force-pushed
the
consensus/script-corpus
branch
from
October 17, 2026 23:10
5ec17c4 to
c96038e
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
A script corpus runs beside Bitcoin Core's JSON. Both the shipped verifier and Core v31.1
VerifyScript(the pinned submodule, not crates.iobitcoinconsensus) accept or reject every row the same way. secp256k1 stays the shared library.Unknown tapleaf versions succeed.
DISCOURAGE_UPGRADABLE_TAPROOT_VERSIONis standardness, and confirm never sets it. Unknown witness programs still followDISCOURAGE_UPGRADABLE_WITNESS_PROGRAM.Core files these rows would append to
The checked-in rows use Core's existing JSON dialects. A later Core PR can append them. No runner change is required for the rows that are already in
script_tests.jsonform ([scriptSig, scriptPubKey, flags, result]or the witness form).script_tests.json— the script, flag, and witness rows, including stack, numbers, conditionals, checksig, CLTV/CSV, P2SH, witness programs, tapleaf, and the fast-path credits.tx_valid.json/tx_invalid.json— no new transaction-structure rows. Spend shape stays inside the script-test credit/spend builder.sighash.json— the past-endSIGHASH_SINGLErows (sighash-single-past-legacy,sighash-single-past-v0,sighash-single-past-tap).script_testscannot express a transaction with zero outputs, so those rows carry"spend": { "n_outputs": 0 }here and belong insighash.jsonupstream.Test plan
cargo test -p rbitcoin-consensus --lib -- script_corpus_rows_match_our_interpreter core_script_tests_all_rowscargo test --manifest-path script-oracle/Cargo.toml -- script_corpus_matches_core_verify_scriptscript::(Core JSON plus this corpus)../scripts/coverage.shis not run on this VM.qc,test,windows,macos, andcoverage