BIP440: Varops Budget for Script Runtime Constraint, BIP441: Restoration of disabled Script (tapleaf 0xc2)#2118
BIP440: Varops Budget for Script Runtime Constraint, BIP441: Restoration of disabled Script (tapleaf 0xc2)#2118rustyrussell wants to merge 3 commits intobitcoin:masterfrom
Conversation
|
to fix the CI we should add |
murchandamus
left a comment
There was a problem hiding this comment.
I only made it to the Multiply and Divide Opcodes in this first read. I suspect that I’m missing something about how you are describing the opcodes. Please see my comments for details.
c4572fe to
7d29c19
Compare
|
@murchandamus thankyou for your detailed review. Here's the comment on the fixup commit which I hope addresses it: |
murchandamus
left a comment
There was a problem hiding this comment.
Thanks, the additional explanation and additions to the abstract helped.
My first impression from the document titles was that "Restoration of disabled script functionality (Tapscript v2)" would be focused on explaining the functionality of the restored opcodes (and perhaps only maybe mention costs), whereas "Varops Budget For Script Runtime Constraint" would expound on the budget and how the costs were found. It seemed to me that you were splitting the content for users of script from the content for the implementers.
In hindsight, I should have first read "Varops Budget For Script Runtime Constraint", I think "Restoration of disabled script functionality (Tapscript v2)" would have made more sense to me after that. Either way, the title "Restoration of disabled script functionality (Tapscript v2)" does not set the expectation that the main focus of the document would be to provide Rationale for the costs of the restored opcodes.
Yes, the split is kind of awkward :(
If we were to put restoration first, that BIP would become trivial. But, also, kinda useless? The varops budget BIP would then have to re-describe the restored opcodes in precise detail, in order to derive their costs. I guess there are three parts:
Happy to do this. If so, would number 3 be a separate BIP, or a giant appendix? I think I'm too close to it to see it through fresh eyes, so I'll take your advice here? Help! |
0c7e36a to
1093247
Compare
murchandamus
left a comment
There was a problem hiding this comment.
Looks good, except for one more MediaWiki quirk and a potential issue in OP_RIGHT.
murchandamus
left a comment
There was a problem hiding this comment.
Noticed a few more minor things when scanning the changes from the last version I reviewed.
|
Note: I noticed that we used the marker ARITH on some costs. This is not present in the varops BIP: I'm consulting with @jmoik now to see if this is a simple omission, or requires deeper change :( |
fa2c6b6 to
4256c69
Compare
|
My apologies, @rustyrussell. I was intending to experiment on my own branch whether there is an easy way to prevent line breaks in the Input Stack column, but I pushed the commit to your branch instead of my repository. I’ve reverted the change. |
There was a problem hiding this comment.
Thanks for the line breaking. Got a couple more format nits for you. Please feel free to ignore.
Also, let’s refer to the Grand Script Restoration BIPs as BIP 440 and BIP 441. I assume you’ll want to make it BIP440: Varops, and BIP441: Restoration, but please feel free to do it the other way around, if I misunderstood.
Could you please rename the files, set the BIP number and Assigned date in the Preamble headers, and add table entries to the table in the README.mediawiki?
|
OK, I shall also rebase to squash the bazillion fixes, if that's OK? I will leave the final change (which actually was a change in how OP_MUL costs are calculated) as a separate commit though. |
4256c69 to
e322221
Compare
|
I smooshed all the fixes, here's the diff from the last commit I pushed which you reviewed: $ git diff 4256c69b5ade17e36e0cb30c07a33cf47125188a
diff --git a/bip-unknown-script-restoration.mediawiki b/bip-unknown-script-restoration.mediawiki
index 9e01eae6..56691843 100644
--- a/bip-unknown-script-restoration.mediawiki
+++ b/bip-unknown-script-restoration.mediawiki
@@ -624,7 +624,8 @@ Work in progress:
==Changelog==
-- 0.1.0: 2025-09-27: first public posting
+* 0.2.0: 2025-02-21: change costs to match those in varops budget
+* 0.1.0: 2025-09-27: first public posting
==Thanks==
diff --git a/bip-unknown-varops-budget.mediawiki b/bip-unknown-varops-budget.mediawiki
index c74c05be..bfc927b3 100644
--- a/bip-unknown-varops-budget.mediawiki
+++ b/bip-unknown-varops-budget.mediawiki
@@ -111,6 +111,7 @@ Each class then has the following costs.
# 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.
# Copying operations cost 3 units per byte output.
+# Arithmetic operations (which don't pipeline as well due to the overflow between words) cost 6 units per byte output.
# Other operations cost 4 units per byte output.
===Variable Opcode Budget===
@@ -127,6 +128,8 @@ We use the following annotations to indicate the derivation for each opcode:
: Copying bytes: cost = 3 per byte copied.
;LENGTHCONV
: Converting an operand to a length value, including verifying that trailing bytes are zero: cost = 2 per byte examined.
+;ARITH
+: Arithmetic operations which have carry operations: cost = 6 per byte examined.
;SIGCHECK
: Checking a signature is a flat cost: cost = 500,000.
;HASH
@@ -328,8 +331,8 @@ Work in progress:
==Changelog==
-- 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
+* 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
==Thanks==
Sorry, I missed the nbsp; change. But it's horrible, because it makes the text unreadable. Let me experiment with putting a nbsp in the title as a workaround. |
4a87852 to
9341e57
Compare
murchandamus
left a comment
There was a problem hiding this comment.
Thanks for the summary. Squash was a good call, changes look good, except that the Assigned date should be 2026-03-25 (see inline comment).
Sorry, I missed the nbsp; change. But it's horrible, because it makes the text unreadable. Let me experiment with putting a nbsp in the title as a workaround.
Wondering whether we crossed a wire here. I had tried using the non-breakable space HTML code in the commit that I accidentally pushed to your branch, but in <nowiki> it was written out which looked terrible (as you seem to have discovered as well).
Using the non-breakable space UTF-8 character (U+00A0) looked fine in the render and code (unless you have your editor set up to show it?), so that was what I recommended.
Otherwise looks good. Thanks for the quick turn-around, pleasure to work with you. :)
bip-0441.mediawiki
Outdated
| |- | ||
| |OP_CAT | ||
| |126 | ||
| |<nowiki>[A B]</nowiki> |
There was a problem hiding this comment.
I think we crossed a wire here. I had tried and discarded the idea of using an HTML code ( ) in the <nowiki> but that looked terrible. I had then recommended on using a UTF-8 non-breakable space character instead (U+00a0). Like so (space in suggestion is actually a non-breakable space):
| |<nowiki>[A B]</nowiki> | |
| |<nowiki>[A B]</nowiki> |
Preventing a linebreak in the title seems like a good idea, but it seems to be a bit unreliable:
…eaf version (0xc2). Special thanks to Murch for teaching me mediawiki, and so much great formatting and clarity advice. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
…ndary. Julian points out that the implementation does this, which improves accuracy for the case of small B (since the term is multiplied: for normal OP_ADD etc we don't bother, since the difference is very bounded). Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
|
OK, fixed to use literal diff --git a/bip-0440.mediawiki b/bip-0440.mediawiki
index a8d58895..409b5a0f 100644
--- a/bip-0440.mediawiki
+++ b/bip-0440.mediawiki
@@ -6,7 +6,7 @@
Julian Moik <julianmoik@gmail.com>
Status: Draft
Type: Specification
- Assigned: 2026-03-27
+ Assigned: 2026-03-25
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
diff --git a/bip-0441.mediawiki b/bip-0441.mediawiki
index 6caf21b5..f658bcef 100644
--- a/bip-0441.mediawiki
+++ b/bip-0441.mediawiki
@@ -6,7 +6,7 @@
Julian Moik <julianmoik@gmail.com>
Status: Draft
Type: Specification
- Assigned: 2026-03-27
+ Assigned: 2026-03-25
License: BSD-3-Clause
Discussion: https://groups.google.com/g/bitcoindev/c/GisTcPb8Jco/m/8znWcWwKAQAJ
Version: 0.2.1
@@ -181,7 +181,7 @@ Fifteen opcodes that were removed in v0.3.1 are re-enabled in 0xC2 Tapscript.
If there are fewer than the required number of stack elements, these opcodes
fail validation. These are popped off the stack in right-to-left order,
-i.e. <nowiki>[A B]</nowiki> means pop B off the stack, then pop A off the
+i.e. <nowiki>[A B]</nowiki> means pop B off the stack, then pop A off the
stack.
See [[bip-0440.mediawiki|BIP440]] for the meaning of the
@@ -192,7 +192,7 @@ annotations in the varops cost field.
{|
! Mnemonic
! Opcode
-! Input Stack
+! Input Stack
! Description
! Definition
! Varops Cost
@@ -200,7 +200,7 @@ annotations in the varops cost field.
|-
|OP_CAT
|126
-|<nowiki>[A B]</nowiki>
+|<nowiki>[A B]</nowiki>
|Append B to A
|
# Pop operands off the stack.
@@ -211,7 +211,7 @@ annotations in the varops cost field.
|-
|OP_SUBSTR
|127
-|<nowiki>[A BEGIN LEN]</nowiki>
+|<nowiki>[A BEGIN LEN]</nowiki>
|Extract bytes BEGIN through BEGIN+LEN of A
|
# Pop operands off the stack.
@@ -223,7 +223,7 @@ annotations in the varops cost field.
|-
|OP_LEFT
|128
-|<nowiki>[A OFFSET]</nowiki>
+|<nowiki>[A OFFSET]</nowiki>
|Extract the left OFFSET bytes of A
|
# Pop operands off the stack.
@@ -234,7 +234,7 @@ annotations in the varops cost field.
|-
|OP_RIGHT
|129
-|<nowiki>[A OFFSET]</nowiki>
+|<nowiki>[A OFFSET]</nowiki>
|Extract the right bytes of A, from OFFSET onwards
|
# Pop operands off the stack.
@@ -259,7 +259,7 @@ OP_RIGHT must copy the bytes, which depends on the OFFSET value.
{|
! Mnemonic
! Opcode
-! Input Stack
+! Input Stack
! Description
! Definition
! Varops Cost
@@ -278,7 +278,7 @@ OP_RIGHT must copy the bytes, which depends on the OFFSET value.
|-
|OP_AND
|132
-|<nowiki>[A B]</nowiki>
+|<nowiki>[A B]</nowiki>
|Binary AND of A and B
|
# Pop operands off the stack.
@@ -290,7 +290,7 @@ OP_RIGHT must copy the bytes, which depends on the OFFSET value.
|-
|OP_OR
|133
-|<nowiki>[A B]</nowiki>
+|<nowiki>[A B]</nowiki>
|Binary OR of A and B
|
# Pop operands off the stack.
@@ -302,7 +302,7 @@ OP_RIGHT must copy the bytes, which depends on the OFFSET value.
|-
|OP_XOR
|134
-|<nowiki>[A B]</nowiki>
+|<nowiki>[A B]</nowiki>
|Binary exclusive-OR of A and B
|
# Pop operands off the stack.
@@ -331,7 +331,7 @@ OP_DOWNSHIFT (née OP_RSHIFT).
{|
! Mnemonic
! Opcode
-! Input Stack
+! Input Stack
! Description
! Definition
! Varops Cost
@@ -339,7 +339,7 @@ OP_DOWNSHIFT (née OP_RSHIFT).
|-
|OP_UPSHIFT
|152
-|<nowiki>[A BITS]</nowiki>
+|<nowiki>[A BITS]</nowiki>
|Move bits of A right by BITS (numerically increase)
|
# Pop operands off the stack.
@@ -352,7 +352,7 @@ OP_DOWNSHIFT (née OP_RSHIFT).
|-
|OP_DOWNSHIFT
|153
-|<nowiki>[A BITS]</nowiki>
+|<nowiki>[A BITS]</nowiki>
|Move bits of A left by BITS (numerically decrease)
|
# Pop operands off the stack.
@@ -385,7 +385,7 @@ routine as OP_DOWNSHIFT.
{|
! Mnemonic
! Opcode
-! Input Stack
+! Input Stack
! Description
! Definition
! Varops Cost
@@ -418,7 +418,7 @@ routine as OP_DOWNSHIFT.
|-
|OP_MUL
|149
-|<nowiki>[A B]</nowiki>
+|<nowiki>[A B]</nowiki>
|Multiply A by B
|
# Pop operands off the stack.
@@ -432,7 +432,7 @@ routine as OP_DOWNSHIFT.
|-
|OP_DIV
|150
-|<nowiki>[A B]</nowiki>
+|<nowiki>[A B]</nowiki>
|Divide A by (non-zero) B
|
# Pop operands off the stack.
@@ -446,7 +446,7 @@ routine as OP_DOWNSHIFT.
|-
|OP_MOD
|151
-|<nowiki>[A B]</nowiki>
+|<nowiki>[A B]</nowiki>
|Replace A with remainder when A divided by (non-zero) B
|
# Pop operands off the stack.
@@ -476,7 +476,7 @@ The opcodes OP_ADD, OP_SUB, OP_1ADD and OP_1SUB are redefined in 0xC2 Tapscript
{|
! Mnemonic
! Opcode
-! Input Stack
+! Input Stack
! Description
! Definition
! Varops Cost
@@ -484,7 +484,7 @@ The opcodes OP_ADD, OP_SUB, OP_1ADD and OP_1SUB are redefined in 0xC2 Tapscript
|-
|OP_ADD
|147
-|<nowiki>[A B]</nowiki>
+|<nowiki>[A B]</nowiki>
|Add A and B
|
# Pop operands off the stack.
@@ -509,7 +509,7 @@ The opcodes OP_ADD, OP_SUB, OP_1ADD and OP_1SUB are redefined in 0xC2 Tapscript
|-
|OP_SUB
|148
-|<nowiki>[A B]</nowiki>
+|<nowiki>[A B]</nowiki>
|Subtract B from A where B is <= A
|
# Pop operands off the stack. |
9341e57 to
78e7562
Compare
murchandamus
left a comment
There was a problem hiding this comment.
LGTM. I’m gonna leave it open for a few more days to see if more review substantiates. I’ll be afk for a week, will then revisit.
What’s the next step from your perspective? Is there still have planned work, are you waiting for any expected reviewers, or is it ready for publication from your side?
That seems wise: we're not suddenly in a hurry!
I am not expecting more reviewers, but of course I'm hoping that once it's merged we can get some more eyes on it. More feedback is always welcome! |

The full revision history is available in a separate branch (https://github.com/rustyrussell/bips/tree/guilt/varops): this is a clean one to submit for merge.