Skip to content

Implement BIP 440 & 441 (Script Restoration in new Tapleaf 0xc2) - #119

Draft
jmoik wants to merge 14 commits into
bitcoin-inquisition:29.xfrom
jmoik:gsr-inquisition
Draft

Implement BIP 440 & 441 (Script Restoration in new Tapleaf 0xc2)#119
jmoik wants to merge 14 commits into
bitcoin-inquisition:29.xfrom
jmoik:gsr-inquisition

Conversation

@jmoik

@jmoik jmoik commented Jul 30, 2026

Copy link
Copy Markdown

Implement BIP 440 & BIP 441

Summary

This PR implements BIP 440 — Varops Budget For Script Runtime Constraint
and BIP 441 — Restoration of disabled script (Tapleaf 0xC2)
on Bitcoin Inquisition 29.x.

BIP 440 introduces a transaction-wide varops budget. BIP 441 uses that budget
to restore Script functionality in tapleaf version 0xc2.

Deployment

The rules are registered as BIN-2026-0441-000 /
SCRIPT_RESTORATION.

On signet, signalling has been permitted since 2026-01-01. The deployment
times out on 2036-01-01 and uses 432-block periods.

Before activation, 0xc2 retains unknown-tapleaf behavior. After activation,
it is evaluated as Tapscript v2.

Implementation structure

  1. (Consensus) Define BIP 440 budgets and cost formulas in a new varops class
  2. (Consensus) Add arbitrary-length unsigned arithmetic with the Val64 class
  3. (Tests) Add Val64 conversion vectors and unit coverage
  4. (Consensus) Add Tapscript-v2 stack accounting with the ValtypeStack class
  5. (Consensus) Define Tapscript-v2 limits and opcode classification
  6. (Consensus) Plumb the transaction-wide budget through validation
  7. (Consensus) Mechanically copy EvalScript for the new script evaluator
  8. (Deployment) Add the SCRIPT_RESTORATION deployment
  9. (Consensus) Implement the BIP 440/441 evaluator semantics
  10. (Integration) Add Tapscript-v2 support to signing, PSBT, RPC, wallet, and utility code
  11. (Unit and JSON tests) Add BIP 440/441 unit and JSON coverage
  12. (Functional tests) Add Tapscript-v2 functional coverage
  13. (Fuzz testing) Add Tapscript-v2 and Val64 fuzz targets
  14. (Benchmark) Add the varops calibration benchmark

Notes

  • Existing Inquisition Script opcode additions are intentionally not automatically
    enabled in Tapscript v2. OP_CHECKTEMPLATEVERIFY remains an upgradable NOP in 0xc2, while
    OP_CHECKSIGFROMSTACK, OP_INTERNALKEY, and OP_TEMPLATEHASH retain
    OP_SUCCESS semantics. ANYPREVOUT-prefixed public keys similarly remain
    unknown public-key types. OP_CAT is the exception: it is enabled directly
    by BIP 441 with the Tapscript-v2 semantics defined there.
  • boost-multiprecision is used only as an independent oracle in Val64 unit
    and fuzz tests. It is not used by production consensus code.
  • bench_varops is included so the cost calibration and worst-case scripts
    can be tested on additional hardware. Existing results are collected in
    varopsData.

Testing

Coverage includes varops accounting, Val64 arithmetic, restored opcodes,
stack-resource boundaries, activation behavior, transaction-wide budgeting,
signatures and timelocks, policy boundaries, functional tests and fuzz targets.

Frontier LLMs were also used to independently verify the test structure and expected results against the BIP 440 and BIP 441 specifications.

Julian Moik added 5 commits July 29, 2026 10:54
Add the transaction-wide budget carrier and BIP 440 and BIP 441 cost helpers used by tapscript v2 execution.

Include focused unit coverage for the budget carrier and cost formulas. Execution plumbing and opcode charging follow in later commits.
Add the Bitcoin-specific arbitrary-length unsigned value type used by tapscript v2 arithmetic and bit operations.

Use little-endian logical values and aligned 64-bit words while accounting for operation costs through the varops helpers.
Add conversion vectors and deterministic coverage for Val64 arithmetic, representation invariants, portable wide arithmetic, and edge cases. Use Boost multiprecision as an independent test oracle.
Add ValtypeStack, a const-access stack wrapper that tracks element sizes across every mutation.

Wire the stack into the production targets; evaluator integration follows later.
Add the 0xc2 leaf version, TAPSCRIPT_V2 sigversion, resource limits,
and script errors used by tapscript v2 execution.

Move SigVersion to script.h and add IsTapscript() so shared callers can
classify both script-path versions.

Make OP_SUCCESS classification sigversion-aware, restoring the BIP 441
opcodes for 0xc2 without changing BIP 342 behavior. Add compile-time
proofs that maximum-size varops cost expressions fit in uint64_t.
@DrahtBot

Copy link
Copy Markdown
Collaborator

The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.

Conflicts

Reviewers, this pull request conflicts with the following ones:

  • #115 (Binana 2026-0003 Simplicity implementation by delta1)
  • #108 (PoC: tooling for OP_TEMPLATEHASH by darosior)
  • #102 (BIP-443 "OP_CHECKCONTRACTVERIFY" implementation by bigspider)

If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.

Julian Moik added 4 commits August 11, 2026 23:19
Add an explicit-budget VerifyScript overload and thread the budget
through witness execution and CScriptCheck. Give all checks for one
transaction a shared atomic budget derived from its weight.

Retain the existing unlimited-budget overload for compatibility. Give
each standalone PSBT input check a fresh budget derived from finalized
transaction weight.
Copy the existing EvalScript() body into an overload that takes an
explicit varops budget. Keep the function bodies byte-for-byte
identical so this commit remains a mechanical review checkpoint.
Semantic changes follow in a later commit.

Verify the copy with:

    ./contrib/devtools/verify-evalscript-copy.sh <this-commit>
Register BIN-2026-0441-000 as SCRIPT_RESTORATION with consensus and policy verification gating. This gives signet the 2026 deployment window and keeps the deployment always active on regtest through the generated Inquisition parameters.
Route activated 0xc2 leaves through a dedicated evaluator while leaving
legacy script and BIP 342 paths unchanged.

Implement the BIP 441 restored opcodes and unsigned numeric semantics,
enforce the expanded stack resource limits, and charge BIP 440 varops
before costly operations. Apply tapscript v2 signature hashing,
OP_SUCCESS handling, and final cleanstack and truthiness rules.
Julian Moik added 5 commits August 12, 2026 17:13
Propagate the 0xc2 leaf version and TAPSCRIPT_V2 sigversion through
Schnorr signing, PSBT, RPC, wallet, and bitcoin-util paths.

Verify finalized transactions under one transaction-wide varops budget.
Let bitcoin-util evalscript accept an explicit budget and report the
remaining amount.
- Add JSON vectors and unit coverage for ValtypeStack, varops, restored opcodes, and edge cases.

- Add bitcoin-util fixtures for Tapscript v2 evaluation paths.

- Migrate existing tests to the explicit varops-budget API.
- Add SCRIPT_RESTORATION activation coverage and focused Tapscript v2 spend tests.

- Replay shared Taproot mechanics under 0xc2 leaves while filtering semantics that intentionally diverge from c0/APO.

- Register the focused functional tests with the test runner.
Exercise budget accounting, evaluator invariants, stack programs and
resource limits, and signature and timelock behavior against independent
expected results.

Check Val64 arithmetic, predicates, bitwise shifts, and large multiply,
divide, and modulo operations against Boost multiprecision.
Add a standalone bench_varops executable that materializes and
preflights a declarative corpus of opcode saturation and budget-boundary
cases, then measures it against a raw Schnorr baseline.

Use deterministic discovery and stable-measurement rounds, support
filtered and validation-only runs, and atomically write summary and
sample data to CSV. Add CTest coverage for invalid opcodes and output
failures.
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.

2 participants