diff --git a/bip-tapscript.mediawiki b/bip-tapscript.mediawiki
index 603990e0..33b64da0 100644
--- a/bip-tapscript.mediawiki
+++ b/bip-tapscript.mediawiki
@@ -61,18 +61,18 @@ Validation of such inputs must be equivalent to performing the following steps i
# If the size of any element in the '''initial stack''' as defined in bip-taproot (i.e., the witness stack after removing both the optional annex and the two last stack elements after that) is bigger than 520 bytes, fail.
# If the tapscript is bigger than 10000 bytes, fail.
# The tapscript is executed according to the rules in the following section, with the initial stack as input.
-## If execution fails for any reason (including the 201 non-push opcode limit), fail.
+## If execution fails for any reason, fail.
## If the execution results in anything but exactly one element on the stack which evaluates to true with CastToBool()
, fail.
# If this step is reached without encountering a failure, validation succeeds.
===Script execution===
The execution rules for tapscript are based on those for P2WSH according to BIP141, including the OP_CHECKLOCKTIMEVERIFY
and OP_CHECKSEQUENCEVERIFY
opcodes defined in BIP65 and BIP112, but with the following modifications:
-* '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG
and OP_CHECKMULTISIGVERIFY
. The disabled opcodes behave in the same way as OP_RETURN
, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch. While being ignored, they are still counted towards the 201 non-push opcodes limit.
+* '''Disabled script opcodes''' The following script opcodes are disabled in tapscript: OP_CHECKMULTISIG
and OP_CHECKMULTISIGVERIFY
. The disabled opcodes behave in the same way as OP_RETURN
, by failing and terminating the script immediately when executed, and being ignored when found in unexecuted branch.
* '''Consensus-enforced MINIMALIF''' The MINIMALIF rules, which are only a standardness rule in P2WSH, are consensus enforced in tapscript. This means that the input argument to the OP_IF
and OP_NOTIF
opcodes must be either exactly 0 (the empty vector) or exactly 1 (the one-byte vector with value 1)['''Why make MINIMALIF consensus?''' This makes it considerably easier to write non-malleable scripts that take branch information from the stack.].
* '''OP_SUCCESSx opcodes''' As listed above, some opcodes are renamed to OP_SUCCESSx
, and make the script unconditionally valid.
* '''Signature opcodes'''. The OP_CHECKSIG
and OP_CHECKSIGVERIFY
are modified to operate on Schnorr public keys and signatures (see bip-schnorr) instead of ECDSA, and a new opcode OP_CHECKSIGADD
is added.
-** The opcode 186 (0xba
) is named as OP_CHECKSIGADD
. [''']OP_CHECKSIGADD
''' This opcode is added to compensate for the loss of OP_CHECKMULTISIG
-like opcodes, which are incompatible with batch verification. OP_CHECKSIGADD
is functionally equivalent to OP_ROT OP_SWAP OP_CHECKSIG OP_ADD
, but is only counted as one opcode towards the 201 non-push opcodes limit. All CScriptNum
-related behaviours of OP_ADD
are also applicable to OP_CHECKSIGADD
.['''Comparison of ]CHECKMULTISIG
and CHECKSIG
''' A CHECKMULTISIG
script m ... n CHECKMULTISIG
with witness 0 ...
can be rewritten as script CHECKSIG ... CHECKSIGADD m NUMEQUAL
with witness ...
. Every witness element w_i
is either a signature corresponding to the public key with the same index or an empty vector. A similar CHECKMULTISIGVERIFY
script can be translated to bip-tapscript by replacing NUMEQUAL
with NUMEQUALVERIFY
. Alternatively, an m-of-n multisig policy can be implemented by splitting the script into several leaves of the Merkle tree, each implementing an m-of-m policy using CHECKSIGVERIFY ... CHECKSIGVERIFY CHECKSIG
. If the setting allows the participants to interactively collaborate while signing, multisig policies can be realized with [https://eprint.iacr.org/2018/068 MuSig] for m-of-m and with [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps threshold signatures] using verifiable secret sharing for m-of-n.
+** The opcode 186 (0xba
) is named as OP_CHECKSIGADD
. [''']OP_CHECKSIGADD
''' This opcode is added to compensate for the loss of OP_CHECKMULTISIG
-like opcodes, which are incompatible with batch verification. OP_CHECKSIGADD
is functionally equivalent to OP_ROT OP_SWAP OP_CHECKSIG OP_ADD
, but only takes 1 byte. All CScriptNum
-related behaviours of OP_ADD
are also applicable to OP_CHECKSIGADD
.['''Comparison of ]CHECKMULTISIG
and CHECKSIG
''' A CHECKMULTISIG
script m ... n CHECKMULTISIG
with witness 0 ...
can be rewritten as script CHECKSIG ... CHECKSIGADD m NUMEQUAL
with witness ...
. Every witness element w_i
is either a signature corresponding to the public key with the same index or an empty vector. A similar CHECKMULTISIGVERIFY
script can be translated to bip-tapscript by replacing NUMEQUAL
with NUMEQUALVERIFY
. Alternatively, an m-of-n multisig policy can be implemented by splitting the script into several leaves of the Merkle tree, each implementing an m-of-m policy using CHECKSIGVERIFY ... CHECKSIGVERIFY CHECKSIG
. If the setting allows the participants to interactively collaborate while signing, multisig policies can be realized with [https://eprint.iacr.org/2018/068 MuSig] for m-of-m and with [http://cacr.uwaterloo.ca/techreports/2001/corr2001-13.ps threshold signatures] using verifiable secret sharing for m-of-n.
===Rules for signature opcodes===
@@ -97,8 +97,6 @@ The following rules apply to OP_CHECKSIG
, OP_CHECKSIGVERIFY
*** For OP_CHECKSIG
, a 1-byte value 0x01
is pushed onto the stack.
*** For OP_CHECKSIGADD
, a CScriptNum
with value of n + 1
is pushed onto the stack.
-These opcodes count toward the 201 non-push opcodes limit.
-
===Transaction digest===
As the message for signature opcodes signature verification, transaction digest has the same definition as in bip-taproot, except the following:
@@ -122,16 +120,14 @@ In summary, the semantics of the BIP143 sighash types remain unchanged, except t
# The digest commits to the executed script through the tapleaf_hash
which includes the leaf version and script instead of scriptCode
. This implies that this commitment is unaffected by OP_CODESEPARATOR
.
# The digest commits to the opcode position of the last executed OP_CODESEPARATOR
.['''Why does the transaction digest commit to the position of the last executed ]OP_CODESEPARATOR
?''' This allows continuing to use OP_CODESEPARATOR
to sign the executed path of the script. Because the codeseparator_position
is the last input to the digest, the SHA256 midstate can be efficiently cached for multiple OP_CODESEPARATOR
s in a single script. In contrast, the BIP143 handling of OP_CODESEPARATOR
is to commit to the executed script only from the last executed OP_CODESEPARATOR
onwards which requires unnecessary rehashing of the script. It should be noted that the one known OP_CODESEPARATOR
use case of saving a second public key push in a script by sharing the first one between two code branches can be most likely expressed even cheaper by moving each branch into a separate taproot leaf.
-===Signature opcodes limitation===
+===Resource limits===
-In addition to the 201 non-push opcodes limit, the use of signature opcodes is subject to further limitations.
-
-* input_witness_weight
is defined as the size of the serialized input witness associated to a particular transaction input. As defined in BIP141, a serialized input witness includes CCompactSize
tags indicating the number of elements and size of each element, and contents of each element. input_witness_weight
is the total size of the said CCompactSize
tags and element contents.
-* sigops_passed
is defined as the total number of successfully executed signature opcodes, which have non-zero signature size and do not fail and terminate the script. For the avoidance of doubt, passing signature opcodes with unknown type public key and non-zero size signature are also counted towards sigops_passed
.
-* If 50 * (sigops_passed - 1)
is greater than input_witness_weight
, the script MUST fail and terminate immediately.
-
-This rule limits worst-case validation costs in tapscript similar to the ''sigops limit'' that only applies to legacy and P2WSH scripts['''The tapscript sigop limit''' The signature opcode limit protects against scripts which are slow to verify due to excessively many signature operations. In tapscript the number of signature opcodes does not count towards the BIP141 or legacy sigop limit. The old sigop limit makes transaction selection in block construction unnecessarily difficult because it is a second constraint in addition to weight. Instead, the number of tapscript signature opcodes is limited by witness weight. Additionally, the limit applies to the transaction input instead of the block and only actually executed signature opcodes are counted. Tapscript execution allows one signature opcode per 50 witness weight units plus one free signature opcode. The tapscript signature opcode limit allows to add new signature opcodes like ]CHECKSIGFROMSTACK
to count towards the limit through a soft fork. Even if in the future new opcodes are introduced which change normal script cost there is need to stuff the witness with meaningless data. In that case the taproot annex can be used to add weight to the witness without increasing the actual witness size.
-['''Parameter choice of the sigop limit''' Regular witnesses are unaffected by the limit as their weight is composed of public key and (]SIGHASH_ALL
) signature pairs with ''33 + 65'' weight units each (which includes a 1 weight unit CCompactSize
tag). This is also the case if public keys are reused in the script because a signature's weight alone is 65 or 66 weight units. However, the limit increases the fees of abnormal scripts with duplicate signatures (and public keys) by requiring additional weight. The weight per sigop factor 50 corresponds to the ratio of BIP141 block limits: 4 mega weight units divided by 80,000 sigops. The "free" signature opcode permitted by the limit exists to account for the weight of the non-witness parts of the transaction input..
+In addition to changing the semantics of a number of opcodes, there are also some changes to the resource limitations:
+* '''Script size limit''' The maximum script size of 10000 bytes does not apply. Their size is only implicitly limited by the limits on transaction and block size.['''Why is a limit on script size no longer needed?''' Since there is no ]scriptCode
directly included in the signature hash (only indirectly through a precomputable tapleaf hash), the CPU time spent on a signature check is no longer proportional to the size of the script being executed.
+* '''Non-push opcodes limit''' The maximum non-push opcodes limit of 201 per script does not apply.['''Why is a limit on the number of opcodes no longer needed?''' An opcode limit only helps to the extent that it can prevent data structures from growing unboundedly during execution (both because of memory usage, and because of time that may grow in proportion to the size of those structures. The size of stack and altstack is already independently limited. Using O(1) logic for ]OP_IF
, OP_NOTIF
, OP_ELSE
, and OP_ENDIF
like suggested [https://bitslog.com/2017/04/17/new-quadratic-delays-in-bitcoin-scripts/ here] and implemented [https://github.com/bitcoin/bitcoin/pull/16902 here] the only other instance can be avoided as well.
+* '''Sigops limit''' The sigops in tapscripts do not count towards the block-wide limit of 80000 (weighted). Instead, there is a per-script sigops ''budget''. The budget equals 50 + the total serialized size in bytes of the transaction input's witness (including the CCompactSize
prefix). Executing a signature opcode (OP_CHECKSIG
, OP_CHECKSIGVERIFY
, or OP_CHECKSIGADD
) with a non-empty signature decrements the budget by 50. If that brings the budget below zero, the script fails immediately. Signature opcodes with unknown public key type and non-empty signature are also counted.['''The tapscript sigop limit''' The signature opcode limit protects against scripts which are slow to verify due to excessively many signature operations. In tapscript the number of signature opcodes does not count towards the BIP141 or legacy sigop limit. The old sigop limit makes transaction selection in block construction unnecessarily difficult because it is a second constraint in addition to weight. Instead, the number of tapscript signature opcodes is limited by witness weight. Additionally, the limit applies to the transaction input instead of the block and only actually executed signature opcodes are counted. Tapscript execution allows one signature opcode per 50 witness weight units plus one free signature opcode.]['''Parameter choice of the sigop limit''' Regular witnesses are unaffected by the limit as their weight is composed of public key and (]SIGHASH_ALL
) signature pairs with ''33 + 65'' weight units each (which includes a 1 weight unit CCompactSize
tag). This is also the case if public keys are reused in the script because a signature's weight alone is 65 or 66 weight units. However, the limit increases the fees of abnormal scripts with duplicate signatures (and public keys) by requiring additional weight. The weight per sigop factor 50 corresponds to the ratio of BIP141 block limits: 4 mega weight units divided by 80,000 sigops. The "free" signature opcode permitted by the limit exists to account for the weight of the non-witness parts of the transaction input.['''Why are only signature opcodes counted toward the budget, and not for example hashing opcodes or other expensive operations?''' It turns out that the CPU cost per witness byte for verification of a script consisting of the maximum density of signature checking opcodes (taking the 50 WU/sigop limit into account) is already very close to that of scripts packed with other opcodes, including hashing opcodes (taking the 520 byte stack element limit into account) and ]OP_ROLL
(taking the 1000 stack element limit into account). That said, the construction is very flexible, and allows adding new signature opcodes like CHECKSIGFROMSTACK
to count towards the limit through a soft fork. Even if in the future new opcodes are introduced which change normal script cost there is no need to stuff the witness with meaningless data. Instead, the taproot annex can be used to add weight to the witness without increasing the actual witness size..
+* '''Stack + altstack element count limit''' The existing limit of 1000 elements in the stack and altstack together after every executed opcode remains. It is extended to also apply to the size of initial stack.
+* '''Stack element size limit''' The existing limit of maximum 520 bytes per stack element remains, both in the initial stack and in push opcodes.
==Rationale==