OP_CHECKTEMPLATEVERIFY

Samuel

New member
I'm surprised there isn't already a discussion here about op_ctv. This is BIP 119: https://github.com/bitcoin/bips/blob/0042dec548f8c819df7ea48fdeec78af21974384/bip-0119.mediawiki

I'd like to specifically talk about the requirement of specifying an exact number of inputs that are required to spend the output. I understand the necessity of specifying exact inputs, but I don't understand the use case for specifying a number of inputs without specifying the exact inputs to spend. In addition, the BIP recognizes that committing to the sequences hash makes committing to a number of inputs "strictly redundant", but says doing so makes it easier to construct StandardTemplateHashes from the script.

Can anyone expand on what is said in the "Rationale: Committing to the number of inputs" section in the BIP?

The use case I'm concerned with is creating a timelocked cold wallet where arbitrary funds can be spent, but within some time-period the transaction can be reversed (for example, by a different higher priority key or by a multisig wallet with more keys than were used by the transaction being reversed). Requiring that op_ctv specify a specific number of inputs makes that use-case not generally possible or at best not efficient, since the wallet can contain many inputs, and in order to spend, you'd have to either have to spend each input one at a time, or you would have to have a large script that specifies optional op_ctv spends for every possible number of inputs you expect the wallet to have, which is obviously a bit of a pain and can go wrong if the wallet ends up having more inputs than you built the script for.

Why not make specifying the number of inputs an optional thing so that some people can use it when its necessary and some can omit it when its not?
 

Oleg

Member
How do you imagine preventing an attacker from spending all your coins at once and sending most of their value to fee? E.g. you have three 1 BTC outputs which require that the output be a 1 BTC payment to address bc1apple. A transaction which spends all three at once to a single 1 BTC bc1apple would comply, and yet turning 2 BTC to fees is probably not what you intended to permit.

In my opinion that BIP is essentially focused on a single use case but it kinda pretends to be more generic. The single use case absolutely requires no malleability, and that ends up creating a lot of limitations. But even without that, additional flexibility is difficult to get right. I think it would be worth the time to do it right. The protocol's author disagrees and instead believes he'll be able to ram it down the network's throat really quickly if he keeps it narrowed to his use case.

I hope the network does not deploy that proposal.
 

Akim

Member
How do you imagine preventing an attacker from spending all your coins at once and sending most of their value to fee? E.g. you have three 1 BTC outputs which require that the output be a 1 BTC payment to address bc1apple. A transaction which spends all three at once to a single 1 BTC bc1apple would comply, and yet turning 2 BTC to fees is probably not what you intended to permit.

In my opinion that BIP is essentially focused on a single use case but it kinda pretends to be more generic. The single use case absolutely requires no malleability, and that ends up creating a lot of limitations. But even without that, additional flexibility is difficult to get right. I think it would be worth the time to do it right. The protocol's author disagrees and instead believes he'll be able to ram it down the network's throat really quickly if he keeps it narrowed to his use case.

I hope the network does not deploy that proposal.
Using SIGHASH_ANYPREVOUT and <sig> <G> CHECKSIG as the output script (i.e. the tx that spends it is already defined by the signature in the output) would be a more generic (albeit less space efficient) way of doing such a covenant, and ANYPREVOUT incidentally also makes malleability a non-issue. Users would have to make sure never to have more than one UTXO with the exact same covenant to prevent the bc1apple issue you described... seems like a bit of a footgun.
 

Pavel

Member
A transaction which spends all three at once to a single 1 BTC bc1apple would comply, and yet turning 2 BTC to fees is probably not what you intended to permit.

Well that's a pretty good point I haven't thought of. Perhaps the answer is to allow putting a cap on the fee in the covenant (and rely on cpfp in cases where that fee doesn't end up being sufficient)? But the use case I'm interested in does not involve limiting the amount of coin that can be sent in a transaction (in fact that seems like somewhat of a useless covenant, since whoever has access can simply send multiple transactions to grab most of the balance (leaving whatever remainder doesn't divide equally).

> The single use case absolutely requires no malleability, and that ends up creating a lot of limitations

I agree, and the limitations built into this opcode are what I'm concerned about as well.

> I think it would be worth the time to do it right.

I agree. I do think that the ability to put limitations on how utxos can be spent is incredibly important. The main use case I'm interested in is "bitcoin vaults" that could make it possible to create wallets that are substantially more secure from theft and at the same time substantially more secure. Doing this in a user-friendly way requires allowing users to spend any amount contained within a wallet, but with limitations (for example, that all funds must be sent to a particular address that has a number of spend-paths with different timelocks).

I would agree that op_ctv as it stands is not general enough and has some loose ends and redundant options.
 

King

Member
I'd like to specifically talk about the requirement of specifying an exact number of inputs that are required to spend the output. I understand the necessity of specifying exact inputs, but I don't understand the use case for specifying a number of inputs without specifying the exact inputs to spend
The reason that we want to specify the number of inputs but not the exact inputs is because if we were to specify the exact inputs it creates a hash cycle. This then prevents the opcode from actually being used. I recommend reviewing the RPCs branch -- I'm currently in the process of doing a lot of refactoring, so this is a temporary branch -- https://github.com/JeremyRubin/bitcoin/commits/checktemplateverify-v2-rpcs-rb, which shows how templates are constructed with a bottom-up pass and then a top-down pass.
the BIP recognizes that committing to the sequences hash makes committing to a number of inputs "strictly redundant", but says doing so makes it easier to construct StandardTemplateHashes from the script.
With respect to constructing via script, the reason that separately committing the number of inputs from the sequences makes it possible to write a script that allows the spender to pass in *any* sequences they like, while still be restricted to a specific number of inputs, with the addition of OP_CAT (or similar). E.g.:

<data before sequences hash, including n_inputs set to 7> OP_SWAP OP_CAT <data after sequences hash> OP_CAT OP_SHA256 OP_CTV


It's nice to be able to constrain the passed in hash to be any set of 7 sequences.
Can anyone expand on what is said in the "Rationale: Committing to the number of inputs" section in the BIP?
I think the above answers your question? But more specifically, the half spend problem crops up if I created 2 CTV outputs with the same script (with no # inputs restriction) they could be spent in the same transaction, creating half the outputs as if spent separately. Restricting the number of inputs to 1 prevents any sort of half-spend issue. The other protection from this is the commitment to the currently executing input index, which means identical basic CTV scripts cannot be spent in the same transaction.
The use case I'm concerned with is creating a timelocked cold wallet where arbitrary funds can be spent, but within some time-period the transaction can be reversed (for example, by a different higher priority key or by a multisig wallet with more keys than were used by the transaction being reversed). Requiring that op_ctv specify a specific number of inputs makes that use-case not generally possible or at best not efficient, since the wallet can contain many inputs, and in order to spend, you'd have to either have to spend each input one at a time, or you would have to have a large script that specifies optional op_ctv spends for every possible number of inputs you expect the wallet to have, which is obviously a bit of a pain and can go wrong if the wallet ends up having more inputs than you built the script for.
So I think that your vault use case is too general. If you refine it a little, you'll see that CTV works pretty well. You can see code for this in the repo above. Essentially you spend into a single output that can be either withdrawn 1 step at a time or sent back to cold storage. I don't have code for it at writing, but you can also set up a larger script (maybe using taproot) which allows for bigger withdrawals after bigger timeouts, but I think that simple is better as a first pass.

It's also possible to set up these kind of cold vaults which by default leave the coins at rest, but it's a bit more difficult to reason about so I've focused on the simple ones first.
Why not make specifying the number of inputs an optional thing so that some people can use it when its necessary and some can omit it when its not?
It keeps the BIP and implementation simple and can be added later with OP_CAT or a new template type. Most of the multi-input use cases can be done pretty easily with Taproot. I view OP_CTV as a first, and major, step towards multi-transaction programmability, and as we see the successes of that we can expand to more general mechanisms if the tooling that emerges around OP_CTV is insufficient for a desired use case. But I personally think that CTV is flexible enough to support most of the really compelling use cases in straightforward ways.
 

Anatoly

Member
How do you imagine preventing an attacker from spending all your coins at once and sending most of their value to fee? E.g. you have three 1 BTC outputs which require that the output be a 1 BTC payment to address bc1apple. A transaction which spends all three at once to a single 1 BTC bc1apple would comply, and yet turning 2 BTC to fees is probably not what you intended to permit.

In my opinion that BIP is essentially focused on a single use case but it kinda pretends to be more generic. The single use case absolutely requires no malleability, and that ends up creating a lot of limitations. But even without that, additional flexibility is difficult to get right. I think it would be worth the time to do it right. The protocol's author disagrees and instead believes he'll be able to ram it down the network's throat really quickly if he keeps it narrowed to his use case.

I hope the network does not deploy that proposal.
I think where we can agree is that additional flexibility is:

1) Worth pursuing.
2) Difficult to get right.

For the benefit of other's tuning in, we've chatted about OP_CTV at some length on IRC, the logs for which are here: http://gnusha.org/bitcoin-wizards/2019-11-28.log

I'll pull some quotes from that conversation for context so that I can respond to these concerns here, and then respond to the closing point of Greg's post, that he hopes the network doesn't adopt CTV.


One of Greg's core objections to CTV is that it's encoding for just a specific use case, one that will be made redundant or not very popular. What I want to make clear is that there is a difference between how Greg is using "use-case" and a general parlance for use-case. Here, I interpret use-case to be a use-pattern. This use-pattern can be used in different contexts (much like an HTLC is core to both atomic swaps and lightning).
 

Arkadi

Member
a workshop that many will attend next weekend (invite still stands Greg!)
The Bitcoin protocol shouldn't be specified by invitation private meetings.

Typical consensus rule changes usually take a couple years to mature. By trying to fast track things you are doing exactly what hearn did with bloom filters. I hope Bitcoin has matured to the point that when someone overloads proposal bandwidth the response is just "no" rather than letting it happen.

Bitcoin development right now barely has the bandwidth to be even minimally responsive to basic bread and butter stuff.
 

Nathaniel

Member
The Bitcoin protocol shouldn't be specified by invitation private meetings.

Typical consensus rule changes usually take a couple years to mature. By trying to fast track things you are doing exactly what hearn did with bloom filters. I hope Bitcoin has matured to the point that when someone overloads proposal bandwidth the response is just "no" rather than letting it happen.

Bitcoin development right now barely has the bandwidth to be even minimally responsive to basic bread and butter stuff.
I'm confused by this response. There are no private meetings, I've cast a very wide net for this workshop with an open invite on the mailing list, twitter, on https://utxos.org/workshops/, in addition to reaching out personally to many devs to make sure they were aware of the opportunity. Around 35 people from all different parts of the community have expressed excitement to join (edit: and more, including those who have requested materials for remote participation). How does this differ from Taproot, which also held workshops? I actually didn't know about the workshops until after they happened, I never received a notice that they were occurring, otherwise I would have attended.

Further, I have actually been working on covenants related research for three years now, in public venues. This is a culmination and maturation of that work, and I expect the community and network to embrace this innovation as it gets more review and consensus among developers.
 
Top