Shinobi’s Strawman is a weekly series where our Technical Editor Shinobi challenges the Bitcoin community, aiming to stir up conversation around heated technical debates.
Last week I published a short prompt looking to hear some readers thinking on different covenant proposals. The design space of covenants has rapidly evolved in the last two years or so, going from a mere two proposals (CTV and APO) to almost a dozen different proposals for very basic functionality that can offer large optimizations to existing use cases such as cold storage schemes or off-chain protocols like the Lightning network. It’s quite a lot to reason through on the part of the communities in this space trying to assess what proposals they should or should not support. Especially when the reasons for supporting or not supporting any specific proposal could be anything from not wanting or viewing as dangerous things it enables, to efficiency differences between one proposal and another that implement the same functionality.
I think while the developer and more technical user communities are moving closer to consensus on what is or is not desirable, or which proposals enable specific use cases more efficiently, the larger communities of active users are much more uncertain or undecided. Taking that into account I am going to break up the first response here to address in pieces
Rearden, proposer of Template Key, sent this in over Twitter:
BIP119/CTV/OP_CHECKTEMPLATEVERIFY is far and away the most thoroughly explored, well reasoned, ready for activation covenant proposal. It alone enables a category of scaling enhancements to bitcoin (of which Ark is an example). What makes CTV a blindingly obvious addition to bitcoin is that it composes beautifully with other proposed changes, as seen in OP_VAULT. CTV is a building block for bitcoin like OP_CHECKSIG, probably more fundamental than CLTV or CSV.
OP_VAULT also includes 2 covenant opcodes beyond CTV: one that restricts spends to carrying through the same taptree with only the selected leaf modified in a specific way (OP_UNVAULT); and another which restricts spends to a specific output script (address) (OP_VAULT_RECOVER). While these are introduced in the OP_VAULT proposal, they are also designed to be composable and may enable a broader ecosystem of self-custody improvements than OP_VAULT.
OP_VAULT has actually evolved quite a bit since the original proposal. Originally it was a very basic two part proposal, OP_VAULT and OP_UNVAULT. Each would accept three pieces of data as input for validation, with OP_UNVAULT requiring two of those pieces of data be the same as an OP_VAULT input being spent. OP_VAULT, when creating a vault, requires the hash of a recovery key in cold storage, a time lock delay length, and the hash of a key used to sign the transaction spending from the vault. The resulting UTXO locked to OP_UNVAULT that would be created would require having the same time lock value as the OP_VAULT input, the same hash of the recovery key, and then a hash requiring the eventual withdrawal transaction to match that exact hash (this part is essentially CTV baked into the OP_UNVAULT). So this proposal very simply accomplished supporting vaults, but also kind of implemented CTV, just with the requirement that you create an OP_VAULT output, and have to spend from it into an OP_UNVAULT output to be able to use it for CTV purposes. This would always be stoppable by sweeping it to a recovery address before the timelock expired and the “CTV” path was spendable.
The most recent version of OP_VAULT has been changed pretty heavily, and actually in some ways looks wholly different in accomplishing the same thing. Firstly, there is no OP_UNVAULT. That is replaced with a separate OP_VAULT_RECOVER opcode. Secondly, OP_VAULT is now entirely done in tapscript. This means every OP_VAULT restriction on spending from the vault, instead of being its own bare script in a UTXO, is now done as a taptree path. There are a lot of data values it takes as arguments, but the three things it is ultimately enforcing is this: data describing a new script to replace the taptree path being spent with, which is the first output being spent to, and the amount that has to go back into the vault, which is the second output being spent to. The script of the first output, the funds being set up to withdraw from the vault, must be the exact same taptree in its entirety, except for the one leaf being spent (which is replaced). This new leaf uses CTV itself to commit to a time locked transaction restricting where the withdrawal will eventually go. Every other path except the one spent that exists in the vault tree still exists in this output. Including a path using OP_VAULT_RECOVER, which literally just specifies the recovery cold storage path, and which output in the spending transaction has to match that script. It also enforces that the entire input amount has to go to that output. The second output in the transaction under discussion just exactly replicates the taptree being spent from, and requires the defined amount to put back into the vault.
Not only does this refactored version of OP_VAULT take advantage of CTV itself, so that it can be used on its own without unneeded inefficiency, but the use of taproot for OP_VAULT allows for more flexibility in vault construction. Different paths can allow less and less to be re-vaulted, but with longer time locks, for example. Using CTV instead of baking that into OP_UNVAULT in the previous proposal also opens the door to using something other than CTV to fill that role in a vault scheme if it becomes available in future.
I think Rearden is entirely right that both of these proposals have very clear and obvious use cases with little or no downside, and the current state of each proposal has gotten to a point that there is no needless redundancy between them, and both complement each other quite well.
BIP118/APO/SIGHASH_ANYPREVOUT is a very path dependent solution to the problem of reducing the burden of running lightning nodes and watchtowers. It started with the simple idea of letting an input not commit to its prevout point; but you can’t add a new sighash flag without a new key version, so we get a new key version; you can’t skip only this input’s prevout because that could lead to quadratic hashing work in validation, so we get implied ANYONECANPAY; the resulting tx size is large, unless we add a magic key for the taproot internal key; possibly &c. The result is a change that is _sold_ as “just adding a sighash flag” but actually adds a new key version, then reuses most of the existing sighash, and unintentionally adds a brand of inefficient covenant through pre-signed output scripts.
My Template Key draft aims to resolve most of APO’s path dependent choices by taking a step back and looking at what can be done once a new key version is required. Template Key takes a fresh look at signature hashing modes, and abandons the existing ones in favor of a new set with greater flexibility and specifically intended to be usable with either signature opcodes or CTV (most of them any way). I’m 100% positive that I missed some important considerations in the design of Template Key, but I think it’s directionally more correct than APO.
All that said, I would not stand in the way of a community effort to activate APO; it’s not evil, just could be better.
Again, I’m pretty much in agreement with Rearden here. The entire issue of APO creating a new sighash flag with different semantics is it is not something you can do in a backwards compatible way if you just try to apply it to everything, so only a new key version would be able to actually use it. There have been quite a few different tweaks and design changes/realizations over the years, and ultimately all of it has been aimed at the single new use of sighash flags: having a signature that can be reattached to any input versioned right using the same script and holding the same value amount.
If we are going to be extending the sighash flag system, there is more useful things that could be done aside from just APO. I haven’t really digested his Template Key proposal in depth, but one good benefit of having more flexibility in what inputs and outputs a signature does or doesn’t commit to is making it easier to change output amounts later in multiparty protocols to increase fees. Some protocols could do this with more sighash options without everyone having to coordinate to do it.
Ultimately I think APO is definitely a desired functionality, but there is still room in my opinion to look at more efficient and/or more flexible ways to accomplish more than just APO in one go.
Other 2 sats: Similar to you, I initially had a gut negative reaction to covenants, and especially recursive ones; but at the end of the day each _recipient_ of bitcoin chooses their receiving output script (address) and can choose to permanently lock them in some stupid way if they want. This is already possible, covenants just make it possible in new and creative ways that also enable useful/smart things. Even if we _are_ concerned about recursion, the only proposal currently close to ready to activate that enables it is APO. Much has been made about the potential for APO to enable recursion and Spookchains. As I said in my Template Key draft somewhere however, these are an academic curiosity only; as they require trusted setup with deleted keys, and can still only recurse within a fully pre-mapped set of states.
My only concern at this point with recursive covenants isn’t the potential for government blacklists, or censoring control, but enabling things that distort the overall system incentives by introducing too much complex functionality. For the charm that is the third time, I again agree with Rearden. None of the concrete covenant proposals published to date enable enough complexity to convincingly open the door to any serious incentive distortions.
An anon on Telegram sent this:
A few years ago when Jeremy was proposing OP_CTV activation, the majority of the louder voices on Bitcoin Twitter came together to shout idioms of ossification and in general prevent any sort of positive discourse from progressing the activation attempts. As far as I can tell, the majority of negative feelings towards covenants were mainly based on two factors; the fear of restriction on future coin spends by large regulating bodies, and the use of speedy trial. I never really understood the first part, as covenants are opt-in by nature, and any spends out of a covenant remove any forward facing restrictions on transactions. The fear of a government somehow enforcing and requiring everyone to join a covenant and restrict future payments seems unfounded, not to mention this same situation could more or less be replicated in a clever multisignature scheme. As for the speedy trial concerns, I suppose I understand that slightly, but only from a meta-stance, and not in particular to any elements present in OP_CTV itself.
Now that the dust has settled, do you have any sympathy for the fears of the covenant deniers of yesterday? Is there any merit to their social rejection? Why did OP_CTV achieve such a level of technical consensus but fail to achieve the same level of social acceptance?
Confused Covenant Cultist
To a degree of course I do, it’s a very healthy sign for active Bitcoiners to be by default skeptical of proposals or changes that they do not fully understand, either in how they work or what they are for. I think a good part of the reaction when Jeremy was discussing activation went far beyond that, with numerous people actively in bad faith continuing to “voice concerns” after they had been explained and definitively demonstrated to be baseless. A lot of that though, like you said, intertwines with concerns and issues over using Speedy Trial as an activation mechanism again.
To put it bluntly, I just think in a large part it was simply people not liking Jeremy on a personal level, or at least the way that he engaged on the topic of CTV and its activation publicly. It’s sad, and definitely undeserved, but I see the whole incident as a case of people not having a problem with the message (if they understood it), just the messenger.
Until next week, ciao.