| use case | apo | ctv | txhash | tluv | intro | vault | catt | matt | tplk |
|---|---|---|---|---|---|---|---|---|---|
| Lightning Symmetry | yes | csfs* | csfs* | ? | yes | no | yes | yes | yes |
| Vaults | yes* | yes* | tap* | yes | tap* | yes | yes | yes | tap* |
| Payment Pools | yes | yes | tap* | yes | tap* | ~ctv | yes | yes | tap* |
| Ark | no | yes | yes | no | yes | ~ctv | yes | yes | yes |
| Fraud Proofs | no | no | no | no | no | no | yes | yes | no |
| Statechains | yes | csfs* | csfs* | ? | yes | no | yes | yes | yes |
| Spacechains | yes | yes | yes | ? | ? | ~ctv | ? | ? | yes |
| Congestion Control | no | yes | yes | no | yes | ~ctv | yes | yes | yes |
- yes*: CTV/APO enable better vaults than are currently possible, but not nearly as good as OP_VAULT ones.
- tap*: yes if combined with something that allows turning a script into a Taproot, plus often
also
OP_CAT - csfs*: yes if combined with
OP_CHECKSIGFROMSTACK - ~ctv: yes but only because the
OP_VAULTproposal also includesOP_CTV
BIP-0119 OP_CHECKTEMPLATEVERIFY has a multitude of benefits for the Bitcoin ecosystem. Are
there other paths to these improvements? In short, yes. This page has a survey
of the other methods for enabling OP_CHECKTEMPLATEVERIFY like functionality and why
such techniques are not suitable substitutes.
OP_CHECKOUTPUTVERIFY
MES16 presents an extension to Bitcoin’s script language enabling covenants, a primitive that allows transactions to restrict howthe value they transfer is used in the future.
OP_COV allows a user to specify a pattern and and output index. The pattern
is then evaluated against the output at that index to see if the output is a
valid representative of the set described by the pattern.
This can be used to emulate something similar to OP_CHECKTEMPLATEVERIFY by
specifying two covenants for outputs 0 and 1 to specify the expanding of a
payment tree.
However, there are a few drawbacks:
OP_COVdoes not have a mechanism to restrict the number of inputs to a single input, meaning the half-spend problem exists- A user needs to specify 2 patterns, as opposed to 1 hash with
OP_CHECKTEMPLATEVERIFY OP_COVis not designed to ensure a stable TXID for the transactions (e.g., locktimes could be malleated) which makesOP_COVbased congestion control unsuitable for lightning channel like contracts or CPFP payments.OP_COVcovenant patterns are not “computationally enumerable”. That is, it is not generally possible to enumerate all possible spends of anOP_COVcovenant. Whereas withOP_CHECKTEMPLATEVERIFY, the limitations ensure that a spending party (by constructing the key) knows all possible executions.
OP_PUSHTXDATA
A Draft BIP by
Johnson Lau proposes OP_PUSHTXDATA.
OP_PUSHTXDATA is a (almost) superset of OP_CHECKTEMPLATEVERIFY in the sense
that it is possible to encode an OP_CHECKTEMPLATEVERIFY into an OP_PUSHTXDATA.
To do so, one simply uses OP_PUSHTXDATA to check that the nVersion,
nLocktime, vouts, sequences, and vins match the expected values.
However, there are a few drawbacks:
- As specified,
OP_PUSHTXDATAdoes not allow the user to get the scriptSig of an input on the stack. This means that without amendment,OP_PUSHTXDATAcannot guarantee TXID stability and is unsuitable for constructing lightning channel like contracts from non-segwit outputs as the stack can be malleated (segwit guarantees scriptsigs are null). - The scripts for
OP_PUSHTXDATAto emulateOP_CHECKTEMPLATEVERIFYare rather long in comparison as they require committing to many fields. For example:
1 OP_PUSHTXDATA 1 OP_EQUALVERIFY
2 OP_PUSHTXDATA 2 OP_EQUALVERIFY
5 OP_PUSHTXDATA 2 OP_EQUALVERIFY
6 OP_PUSHTXDATA 0 OP_EQUALVERIFY
0 11 OP_PUSHTXDATA 0 OP_EQUALVERIFY
0 15 OP_PUSHTXDATA <value vout 0> OP_EQUALVERIFY
<scriptPubkey vout 0> OP_EQUALVERIFY
1 15 OP_PUSHTXDATA <value vout 1> OP_EQUALVERIFY
<scriptPubkey vout 1> OP_EQUALVERIFY
v.s.
<Template Hash> OP_CHECKTEMPLATEVERIFY
OP_PUSHTXDATA could ameliorate this by adding an data type to push the Bag
Hash from OP_CHECKTEMPLATEVERIFY.
- As a superset of functionality,
OP_PUSHTXDATAenables a lot of new use cases that we may or may not want to support.OP_CHECKTEMPLATEVERIFYis, by comparison, conservative in what it enables. OP_CHECKTEMPLATEVERIFYis anOP_NOPupgrade, which maintains compatibility with old scripts, whereasOP_PUSHTXDATArequires new execution semantics.OP_PUSHTXDATAcould be made to work with soft-fork friendly VERIFY semantics, but it would be unwieldy.
OP_CAT + OP_CHECKSIGFROMSTACKVERIFY
By enabling OP_CHECKSIGFROMSTACKVERIFY and OP_CAT it would be
possible to
enable covenants. Russel O’Connor
proposes
to do this instead of OP_CHECKTEMPLATEVERIFY or ANYPREVOUT.
Essentially what OP_CHECKSIGFROMSTACKVERIFY and OP_CAT lets us do is
emulate and OpCode via a script gadget which results in the signature message
being on the stack, i.e., like OP_PUSHTXDATA, but all the data gets pushed
as one serialized blob. It’s then possible to check that this value matches a
pre-supposed template (bits like the prevouts can be passed in through the
witness data).
However, there are a few drawbacks:
- This form of covenants is possible, but highly complex to understand and implement without higher-order scripting primitives.
- Further, with extensions like
OP_EC_KEY_TWEAK, it would be possible to enable recursive covenants. That means this strategy might limit future extensions to Bitcoin with unintended “constructive interference” capabilities. - If the functionality provided is roughly equivalent to
OP_PUSHTXDATA, it would be easier to just to implementOP_PUSHTXDATA - Validation is more expensive to use the
OP_CHECKSIGFROMSTACKgadget compared toOP_CHECKTEMPLATEVERIFYorOP_PUSHTXDATA. - Desire to disable PubKey recovery for signatures would disable the recursive
use of this type of covenant, which would make the technique not able to
be used for
OP_CHECKTEMPLATEVERIFYtype use.
OP_CHECKTXOUTSCRIPTHASHVERIFY
OP_CHECKTXOUTSCRIPTHASHVERIFY, proposed on the mailing
list
is similar to OP_CHECKTEMPLATEVERIFY, but only a single output script is committed
to and not the amount of Bitcoin to be paid to that output. The stated design
goal is theft-resistant vaults.
As specified, OP_CHECKTXOUTSCRIPTHASHVERIFY is not even sufficient for its
own purported use case:
- Inability to limit the amount of fee paid, ensuring the amount of value forwarded
- Inability to limit the number of outputs created
And is insufficient for OP_CHECKTEMPLATEVERIFY semantics for a myriad of reasons
more.
SIGHASH_NOINPUT / ANYPREVOUT
Method 1
With SIGHASH_NOINPUT, it should be theoretically possible for a bare script
(non-segwit) to be specified as follows to emulate OP_CHECKTEMPLATEVERIFY:
scriptSig: <random sig || SIGHASH_NOINPUT>
scriptPubkey: <pkR> OP_CODESEPARATOR OP_CHECKSIGVERIFY
It would then be possible to compute the pkR as being the recovered pubkey
from the transaction without signing the inputs, effectively committing to the
information in the same manner as OP_CHECKTEMPLATEVERIFY.
In a segwit type transaction, this is not possible (without additional modifications) because the scriptPubkey always commits to the entire pubkey, preventing pubkey recovery techniques.
SIGHASH_NOINPUT is furthermore insufficient to emulate OP_CHECKTEMPLATEVERIFY
as the TXID can be malleated by modifying the scriptSig(s) in the transaction,
which makes it unsuitable for use in Lightning Channel construction or CPFP
transactions.
Method 2
Using SIGHASH_ANYPREVOUTANYSCRIPT, it would be possible to have a segwit script:
scriptPubkey: <sig || SIGHASH_ANYPREVOUTANYSCRIPT> <pk> CHECKSIG
This way neither the pk nor the txid are a part of the signature hash.
This method is close to how OP_CHECKTEMPLATEVERIFY should work. If the key
is a well known specific one, and deterministic nonces are used for the
signature, then it also preserves some of the ability to prune interior nodes
data for storage as they can be recomputed.
However, this method has drawbacks in terms of verification time as the signatures must either be verified or recomputed, and without sophisticated pruning layers, use more network and storage bandwidth.
This method also fundamentally does not have the extensibility that
OP_CHECKTEMPLATEVERIFY permits with new template version hash programs that
could be made available in future soft-forks.
Furthermore, SIGHASH_ANYPREVOUTANYSCRIPT has the potential for enabling
certain types of recursive covenants.
Lastly, SIGHASH_ANYPREVOUTANYSCRIPT can be used with SIGHASH flags other
than SIGHASH_ALL signing the whole transaction. This can lead to surprising
behaviors, such as with SIGHASH_SINGLE (which would only enforce a covenant on
one of the coins in an output, not all).
Acknowledgements
Thanks to Olaolu Osuntokun and Bob McElrath whose talks helped to inform this
survey, and to Jonas Nick who made me aware of Method 2 for
SIGHASH_ANYPREVOUTANYSCRIPT.