#35788 bitcoin-util: Add evalscript subcommand

ReviewabilityReviewsAgreementSize
#35788 ajtowns bitcoin-util: Add evalscript subcommandWaiting on author0 (+1)Strong325 + 294 tests
  • Allow developers and researchers to execute and inspect script fragments directly via the CLI
  • Validates script behavior and signatures against Core's consensus interpreter without custom tests
  • Ready to review
  • Strong support with extensive testing and no open objections
  • Verified by running script tests and 90k random scripts against an external interpreter (fametrano)
  • Verified across taproot tests, script unit tests, and CLI examples (jeanpablojp)
  • Open suggestion to clarify raw hex handling in help or require a 0x prefix (fametrano)
  • 325 lines added or modified outside tests
  • 294 lines added or modified in tests
  • 17 lines removed in total
  • 15 files, 4 commits
Tools and scripts#9 of 16
P3 · new feature
  • P3 because it adds a developer productivity tool to test script fragments against consensus logic
  • Helps developers and researchers validate scripts without building custom test harnesses
  • Ranking pass: Moved down: a useful developer/researcher convenience tool with no existing breakage behind it, so it ranks below the tool bugs and the dev-time-saving automation in the same band.
Reviewability: ReadyStalePaused
Agreement: StrongPositivePositive w/ caveatsNeutralMildDisputedBlockedCrickets
Reviews: current code-review ACKs, then (+stale ACKs) and -NACKs; greener = more ACKs.
Size: lines added or modified outside tests, then in tests; greener = smaller.

Goal

Adds an `evalscript` subcommand to the `bitcoin-util` CLI tool, allowing standalone execution and inspection of script fragments using Bitcoin Core's consensus script interpreter. It exposes interpreter helper functions `CastToBool` and `CheckTapscriptOpSuccess` in `src/script/interpreter.h` to support standalone evaluation. Users can configure signature versions, script verify flags, initial stack arguments, and optional transaction context to test opcodes like CHECKSIG, CSV, and CLTV.

Problem: Developers and protocol researchers lack a built-in CLI tool to execute and inspect arbitrary script fragments directly against Core's consensus logic. They must rely on custom unit tests or third-party interpreters that may diverge from Core's consensus rules.

Evidence of importance:

  • The PR description states it is 'Intended for debugging and development' to 'check a script fragment's behaviour' and 'validate a real signature' against Core's consensus logic directly from the command line.

Scope: Refactors `ExecuteWitnessScript` in `src/script/interpreter.cpp` to extract tapscript `OP_SUCCESS` parsing into an exported `CheckTapscriptOpSuccess` helper function.

Risk of a mistake: medium (consensus, tooling). A mistake when extracting the CheckTapscriptOpSuccess helper from ExecuteWitnessScript could subtly alter tapscript evaluation and cause a consensus fork.

Changed since the previous assessment: Rebased without substantive changes to the approach or interface.

Reviewability

Paused · Waiting on author

Open objection from fametrano with no author reply for 30 days; review would repeat what has been asked.

Waiting on (from the thread read):

  • author: fametrano's suggestion regarding hex parsing vs opcode trap in help or CLI syntax 2026-10-02
  • author: response to fametrano's suggestion about hex script argument parsing 2026-10-02

Agreement

Strong

substantive support, no open objection (jeanpablojp, fametrano)

Thread notes: Added jeanpablojp's suggestion about -tx test coverage (fixed by ajtowns), and fametrano's Tested ACK and open suggestion on raw hex argument parsing. / Added jeanpablojp's test suggestion (fixed by ajtowns in c:5922856288) and fametrano's testing report and suggestion regarding raw hex script argument handling.

Objections, suggestions, and questions:

ReviewerTypeHarm, request, or questionStatusMust beAuthor repliedQuote
jeanpablojp (contributor)suggestion, correctnessadd test coverage for -tx in bitcoin-util-test.jsonfixed · fix pushed · author rebased and added a test covering -txansweredyes2026-08-19: 'The PR description mentions `-tx`, but I noticed no case in bitcoin-util-test.json uses `-tx`, so that path goes uncovered. To confirm, I disabled the `-input` range check and the suite still passes. Would it be worth adding a case like that?'
Status from: 2026-10-01: ajtowns: 'Rebased, added a test that uses `-tx`'
fametrano (contributor)suggestion, interfacedocument in help that valid hex script arguments are read as raw bytes, or require a 0x prefix for raw hexopenansweredno2026-10-02: 'One trap: a script argument that is valid hex is read as raw bytes. `evalscript 16` runs the byte 0x16 and fails with "Opcode missing or not understood", while `evalscript '16 '` runs OP_16. Could the help say so, or raw hex need a `0x` prefix?'

Support:

  • jeanpablojp (contributor) (Tested ACK, 2026-08-19) [tested: feature_taproot, script unit tests, tool_utils]: Ran tool_utils, script unit tests, feature_taproot, and reproduced description examples
  • fametrano (contributor) (Tested ACK, 2026-10-02) [tested: script_tests.json]: Ran 1214 script_tests.json rows and 90,000 random script runs compared with btclib interpreter without crashes

Participants:

  • jeanpablojp (contributor, support, 1 statements 2026-08-19 to 2026-08-19): Tested ACK; tested examples and suggested adding test coverage for -tx
  • fametrano (contributor, support, 1 statements 2026-10-02 to 2026-10-02): Tested ACK; tested script_tests and 90k random scripts; suggested documenting hex argument parsing or requiring 0x prefix

Files

296 lines under test/bench/ci.

  • src/bitcoin-util.cpp +290/-0
  • test/functional/data/util/bitcoin-util-test.json +78/-0
  • src/script/interpreter.cpp +24/-15
  • test/functional/data/util/evalscript-tapscript.json +24/-0
  • test/functional/data/util/evalscript-tx-checksig-badsig.json +24/-0
  • test/functional/data/util/evalscript-add.json +23/-0
  • test/functional/data/util/evalscript-empty.json +23/-0
  • test/functional/data/util/evalscript-op1.json +23/-0
  • test/functional/data/util/evalscript-opsuccess.json +23/-0
  • test/functional/data/util/evalscript-tx-checksig.json +23/-0
  • test/functional/data/util/evalscript-customflags.json +18/-0
  • test/functional/data/util/evalscript-opsuccess-discouraged.json +18/-0
  • test/functional/data/util/evalscript-base-noflags.json +17/-0
  • src/script/interpreter.h +11/-0
  • src/test/fuzz/script_interpreter.cpp +0/-2

Card

The short text the ranking pass compares across PRs.

Adds an evalscript subcommand to bitcoin-util to execute and debug arbitrary script fragments using Bitcoin Core's consensus interpreter. This provides script authors and protocol researchers a native CLI tool to inspect script results, error codes, and resulting stack states across different sigversions and verification flags without writing dedicated test code. It also supports optional transaction and spent output inputs to validate contextual opcodes such as CHECKSIG, CSV, and CLTV. Output is returned as structured JSON detailing execution success, errors, and sigop costs.

Data

dossier JSON · extract JSON · model ledger, generated 2026-10-03T01:20, confidence high, input hash 59e9e50ccddffac2
thread read through 2026-10-02 (4 statements), head 598427fd07
labels: none

Categories

Tools and scripts

P3 · new feature (ranking pass: Moved down: a useful developer/researcher convenience tool with no existing breakage behind it, so it ranks below the tool bugs and the dev-time-saving automation in the same band.)

Adds a CLI tool allowing developers and researchers to evaluate script fragments against Bitcoin Core's consensus interpreter directly. This provides a clear developer productivity utility to 'check a script fragment's behaviour' and validate signatures without bespoke test harnesses.

Membership: Adds an `evalscript` subcommand to `src/bitcoin-util.cpp`.

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