Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions bip-0440.mediawiki
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
License: BSD-3-Clause
Discussion: https://groups.google.com/g/bitcoindev/c/GisTcPb8Jco/m/8znWcWwKAQAJ
https://delvingbitcoin.org/t/benchmarking-bitcoin-script-evaluation-for-the-varops-budget-great-script-restoration/2094
Version: 0.2.1
Version: 0.2.3
</pre>

==Introduction==
Expand Down Expand Up @@ -51,7 +51,9 @@ The last two assumptions make a large difference in practice: normal usage on sm

A per-transaction integer "varops budget" is determined by multiplying the total transaction weight by the fixed factor 10,000 (chosen to make operation costs all integer values). The budget is transaction-wide (rather than per-input) to allow for cross-input introspection: a small input may reasonably access larger inputs.

Opcodes consume budget as they are executed, based on the length (not generally the value) of their parameters as detailed below. A transaction which exceeds its budget fails to validate.
Opcodes evaluated under Tapscript v2 and later participating leaf versions consume budget based on the lengths (not generally the values) of their parameters, as detailed below. Because a linear operation determines its exact cost as it executes, that cost may be deducted afterward instead of being calculated in a separate pass; exceeding the remaining budget invalidates the script before the next opcode. Superlinear operations and signature checks must instead be charged before execution because they could otherwise perform disproportionately expensive work before an overrun is detected.

Earlier script versions retain their existing resource limits and do not consume the varops budget. An adversarial mixed-version transaction can therefore combine both workloads, requiring up to twice the validation work of the more expensive regime alone. This is accepted to avoid making budget funding depend on input-version composition, or retrofitting varops accounting into existing script versions and transaction tooling.

===Derivation of Costs===

Expand All @@ -75,13 +77,13 @@ The costs were validated by constructing maximally expensive scripts for every o

Apple M1 Pro, Apple M2, Apple M4 Pro (macOS + Linux/Docker), AMD Ryzen 5 3600, AMD Ryzen 7 5800U, AMD Ryzen 9 9950X, Intel i5-12500, Intel i7-7700, Intel i7-8700, Intel i9-9900K, Intel N150 (Umbrel), Raspberry Pi 5.

For each machine, the ratio of the GSR worst-case block time to the existing (pre-GSR) worst-case block time was computed. A ratio below 1.0 means GSR does not introduce a new worst case. On all 14 tested machines, the ratio is below 1.0.
For each machine, we compared the worst-case block time under Tapscript v2 alone with the worst-case block time under existing script versions. The resulting ratio was below 1.0 on all 14 tested machines.

Without GSR, the slowest blocks are dominated by:
Under existing script versions, the slowest blocks are dominated by:
* Schnorr signature validation (80,000 signatures per block)
* Repeated hashing of 520-byte elements (3DUP + HASH256, 3DUP + RIPEMD160)

With GSR enabled, the slowest blocks restricted by the varops budget depend on the machine but usually include:
Under Tapscript v2, the slowest blocks permitted by the varops budget depend on the machine but usually include:
* Schnorr signature validation (80,000 signatures per block)
* Repeated hashing of 520-byte elements (3DUP + HASH256, 3DUP + RIPEMD160)
* Small-element multiplication (MUL on 1-byte operands)
Expand All @@ -106,7 +108,7 @@ We divided operations into six speed categories:

Each class then has the following costs.

# Signature operations cost 500,000 (10,000 * 50) units each, this resembles the cost of the existing sigops budget.
# Signature operations with a nonempty signature operand cost 500,000 (10,000 * 50) units each; signature operations with an empty signature operand have no SIGCHECK cost. This resembles the existing sigops budget and applies to unknown nonzero-length public-key types as well.
# Hashing costs 50 units per byte hashed.
# OP_ROLL costs an additional 48 units (24 bytes per std::vector * 2 units per byte) per stack entry moved (i.e. the value of its operand).
# Fast operations cost 2 units per byte output.
Expand All @@ -131,7 +133,7 @@ We use the following annotations to indicate the derivation for each opcode:
;ARITH
: Arithmetic operations which have carry operations: cost = 6 per byte examined.
;SIGCHECK
: Checking a signature is a flat cost: cost = 500,000.
: A signature operation with a nonempty signature operand has a flat cost of 500,000; an empty signature operand has a cost of 0.
;HASH
: cost = 50 per byte hashed.
;ROLL
Expand Down Expand Up @@ -348,6 +350,8 @@ Work in progress:

==Changelog==

* 0.2.3: 2026-08-11: clarify conditional SIGCHECK charging and charging order for linear and superlinear operations.
* 0.2.2: 2026-08-05: document mixed-version resource limits.
* 0.2.1: 2026-06-15: define wordspan notation and clarify byte-length versus word-span costs.
* 0.2.0: 2026-02-21: increase in cost for hashing and copying based on benchmark results.
* 0.1.0: 2025-09-27: first public posting
Expand Down
17 changes: 10 additions & 7 deletions bip-0441.mediawiki
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
Assigned: 2026-03-25
License: BSD-3-Clause
Discussion: https://groups.google.com/g/bitcoindev/c/GisTcPb8Jco/m/8znWcWwKAQAJ
Version: 0.2.2
Version: 0.2.3
Requires: 440
</pre>

Expand Down Expand Up @@ -567,6 +567,8 @@ failure, as mathematicians agree the result would not be natural.

The following opcodes have costs below:

In this table, <code>sigcheck_cost(signature)</code> is 500,000 if the signature operand is nonempty, and 0 otherwise. This rule also applies to unknown nonzero-length public-key types.

{|
! Opcode
! Varops Budget Cost
Expand All @@ -581,22 +583,21 @@ The following opcodes have costs below:
| LENGTHCONV
|-
| OP_CHECKSIGADD
| MAX(wordspan(1), wordspan(number operand)) * 9 + 500,000
| MAX(wordspan(1), wordspan(number operand)) * 9 + sigcheck_cost(signature)
| ARITH + COPYING + SIGCHECK
|-
| OP_CHECKSIG
| 500,000
| sigcheck_cost(signature)
| SIGCHECK
|-
| OP_CHECKSIGVERIFY
| 500,000
| sigcheck_cost(signature)
| SIGCHECK
|}

====Rationale====

OP_CHECKSIGADD does an OP_1ADD on success, so we use the same cost as that.
For simplicity, this is charged whether the OP_CHECKSIGADD succeeds or not.
The arithmetic and copying component of OP_CHECKSIGADD uses the OP_1ADD cost and is charged whether or not the signature is empty or valid. Its SIGCHECK component is charged only for a nonempty signature.

===Other Operators===

Expand All @@ -617,6 +618,7 @@ The varops costs of the following opcodes are defined in
* OP_PICK
* OP_TUCK
* OP_ROLL
* OP_BOOLAND
* OP_BOOLOR
* OP_NUMEQUAL
* OP_NUMEQUALVERIFY
Expand Down Expand Up @@ -644,10 +646,11 @@ version, for backwards compatibility.

Work in progress:

https://github.com/jmoik/bitcoin/tree/gsr
https://github.com/jmoik/bitcoin/tree/gsr-core

==Changelog==

* 0.2.3: 2026-08-11: clarify that SIGCHECK cost applies only to nonempty signature operands.
* 0.2.2: 2026-06-15: clarify wordspan costs, OP_RIGHT semantics, OP_UPSHIFT unaligned cost, CLTV/CSV bounds, and final success-check cost.
* 0.2.1: 2023-03-27: fix OP_MUL cost to round length(B) up
* 0.2.0: 2025-02-21: change costs to match those in varops budget
Expand Down