Bitcoin Forum
April 18, 2024, 11:22:53 PM *
News: Latest Bitcoin Core release: 26.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1] 2 »  All
  Print  
Author Topic: OP_CHECKTEMPLATEVERIFY  (Read 917 times)
fresheneesz (OP)
Jr. Member
*
Offline Offline

Activity: 33
Merit: 73


View Profile
January 25, 2020, 01:09:05 AM
Last edit: January 25, 2020, 08:36:16 PM by fresheneesz
Merited by d5000 (2), bones261 (2), ABCbits (1)
 #1

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?
1713482573
Hero Member
*
Offline Offline

Posts: 1713482573

View Profile Personal Message (Offline)

Ignore
1713482573
Reply with quote  #2

1713482573
Report to moderator
1713482573
Hero Member
*
Offline Offline

Posts: 1713482573

View Profile Personal Message (Offline)

Ignore
1713482573
Reply with quote  #2

1713482573
Report to moderator
1713482573
Hero Member
*
Offline Offline

Posts: 1713482573

View Profile Personal Message (Offline)

Ignore
1713482573
Reply with quote  #2

1713482573
Report to moderator
Every time a block is mined, a certain amount of BTC (called the subsidy) is created out of thin air and given to the miner. The subsidy halves every four years and will reach 0 in about 130 years.
Advertised sites are not endorsed by the Bitcoin Forum. They may be unsafe, untrustworthy, or illegal in your jurisdiction.
1713482573
Hero Member
*
Offline Offline

Posts: 1713482573

View Profile Personal Message (Offline)

Ignore
1713482573
Reply with quote  #2

1713482573
Report to moderator
1713482573
Hero Member
*
Offline Offline

Posts: 1713482573

View Profile Personal Message (Offline)

Ignore
1713482573
Reply with quote  #2

1713482573
Report to moderator
gmaxwell
Moderator
Legendary
*
expert
Offline Offline

Activity: 4158
Merit: 8382



View Profile WWW
January 25, 2020, 03:48:18 PM
Merited by bones261 (5), Foxpup (4), ABCbits (2), d5000 (1)
 #2

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.
RubenSomsen
Newbie
*
Offline Offline

Activity: 1
Merit: 11


View Profile
January 25, 2020, 05:18:15 PM
Merited by bones261 (4), gmaxwell (2), darosior (2), Foxpup (1), d5000 (1), ABCbits (1)
 #3

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.
fresheneesz (OP)
Jr. Member
*
Offline Offline

Activity: 33
Merit: 73


View Profile
January 25, 2020, 08:56:34 PM
 #4

> 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.
jeremyrubin
Newbie
*
Offline Offline

Activity: 15
Merit: 5


View Profile
January 26, 2020, 05:48:16 PM
 #5

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.

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.

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.

jeremyrubin
Newbie
*
Offline Offline

Activity: 15
Merit: 5


View Profile
January 26, 2020, 09:22:35 PM
Last edit: January 27, 2020, 06:42:54 PM by gmaxwell
 #6

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).

Quote
12:36 < gmaxwell> I don't think opcodes that essentially hard code a specific
 use case are ones that would be easy to get through... they just turn into
 technical debt if the usecase is eclipsed or turns out to not be popular.
 12:37 < jeremyrubin> I don't think it's fair to say CTV is a hard coded specific
 use case
 12:37 < gmaxwell> and a couple lightning specifc things have essentially been
 shot down for that reason in the past.
 12:38 < gmaxwell> jeremyrubin: no, but I don't think it's clear that it doesn't
 either.  Stuff like making it essentialy impossible to add inputs is a really
 extreme restriction. (yes you can allow multiple inputs, but as I pointed out--
 I think it's really hard if not impossible to do that safely due to double
 dipping)
 12:40 < gmaxwell> There is a natural tension between wanting to provide a
 generic mechenism that has the most usecases, providing something that is simple
 to implement and review, and proving something that isn't a heinous footgun that
 is hard/impossible to use safely.
 12:41 < jeremyrubin> The multi-input use cases listed are basically limited to
 wallet vault infrastructure, where you are implementing stuff in a walled
 garden. Easy enough to prevent key reuse which obviates that concern.


Core to this point not just that Greg feels the multi-input case is not really usable, but that the single input use case is not very useful.


This comes up in the context of fees, where Greg shares a specific concern that fees are hard to add.

Quote
11:59 < gmaxwell> jeremyrubin: as far as masking flags go, one concern I have
 had with your opcode is that it's extremely specific for its usecase, e.g.
 binding all outputs and the input count makes it basically impossible to add
 additional fees.  I know there are anti-doubledipping reasons why particular
 applications may want to cover all fields, but it's a pretty extreme
 restriction.

There are multiple ways to handle fees with OP_CTV (it's pretty flexible). Imagine you have a chain of CTV transactions, where an arrow `->` indicates one of the outputs is spent.

A -> B -> C


There are a few different ways to ensure fees.

One obvious way, in use today by certain services, is to just wildly overpay fees. This isn't robust, as fees can't be perfectly predicted, but if you're signing over 1000 BTC into a vault you may as well over-spend a bit on fees. Let's ignore this, and assume we want something that works when we don't want to over-pay. (In general, overpayment isn't a bad idea, especially because for protocols it can often be only overpay in the non-cooperative case, but assume we want mechanisms robust and not overpaid when we are completely non-interactive).


The next most obvious way is to use Child Pays For Parent.

In this case, you create a spend D

A -> B -> C -> D such that D pays high enough fee to cover A B C. This is kind-of obvious to do, but it turns out that there are two specific drawbacks:

1) The MemPool is not that good at handling long-chain CPFP (we're working on improving this though!)
2) It requires spending from C which you might want to *create* the output D spends, but not consume it.


Gas Outputs:
To make this better, another way of adding fees would be to add an output at some point in the chain which exists only to be spent in a CPFP. E.g. A->B->C{0,1}, C.1->E. Now spending C.1 to E covers the fee, and C.0 can stay unspent. This can be applied recursively.


Imagine a protocol with some really long chain DAG. Now, a user can craft a transaction spending all of the Gas Outputs along that path, and pay an appropriate fee. This has a nice atomicity property -- either you've paid for the full execution trace you wanted, or nothing extra at all and you can re-emit your fee bump transaction.

This is particularly nice because you do not disturb the sub-protocols in the DAG (e.g., LN channels).

Gas outputs also work nicely (if more than one is used, and CPFP becomes more rational) for cooperative fee-sharing.

Gas Inputs

 In this case, we can specify a CTV A which has an additional input slot which can be filled with all fees. But what about change addresses? Well, the solution is to separately create that perfectly-sized UTXO in a transaction to be spent with the desired nodes.

The main issue here is that the transaction is now malleable (both by third party and first party). See below (conditionalizing) for ways of dealing with this.

Conditionalizing
It's also possible to write the script IF <H(A)> ELSE <H(B)> ENDIF OP_CTV.

With taproot, this is even better.

We can specify (at least) four different types of conditions:

1) More Gas Inputs
2) More Gas Outputs
3) More Fees (subtracted from outputs) after a longer sequence from original spend

These options can be hidden from miners so that it's not seen that delaying a txn will get them more fees.


Conditioning more Gas Inputs (from 0 to 1) is slightly problematic in that it introduces malleability. Now an arbitrary third party can malleate the transaction by adding fee. One way of dealing with this would be to write the script:

IF <H(A)> CTV ELSE   IF <N of N Multisig> ELSE <1 month lock> CSV <1 key checksig> <H(B)> CTV ENDIF ENDIF

In this case, the logic expresses that at any time, with no modified fee, and no interaction, the original transaction may be broadcast.

At any time, N of N may agree to a new transaction.

If we haven't made progress for a month, then any participant (assuming the 1 key is known to all N) may make progress, potentially malleating the txid but not the outputs. One can imagine writing a script that goes N, N-1, N-2.... 1 in order to balance agreement and non-malleability of the txid (e.g., if the protocol step contains lightning channel outputs).


New Fee OpCode

In general, it might be advisable to introduce an arbitrary CPFP relationship flag or opcode that allows an unrelated transaction to "observe" if another transaction exists in the present block. This would take some engineering to get right, but it can be expressed using the same logic as CPFP today.

This is nice conceptually because we can then abstract from the transactions you are doing (which are the execution) and how you're paying for it. CTV doesn't contain a proposal for this today, but I think this is of independent interest as more protocols are built on Bitcoin struggle to figure out how to pay fees.

New General OpCode

As opposed to conditionality, it's also possible that with the addition of OP_CAT it's much easier to dynamically add a fee input/output.

It's then trivial to write something like (definitely not correct here -- written expediently for the gist):


stack top: <1 or more> X <other sequences> X <change output>
<pre input data> OP_SWAP OP_CAT OP_SWAP
<1 known sequences> OP_SWAP OP_CAT OP_SHA256 OP_SWAP OP_CAT OP_SWAP
<outputs> OP_SWAP OP_CAT OP_SHA256 OP_SWAP OP_CAT
<other data> OP_SWAP OP_CAT OP_SHA256 OP_CTV

This type of operation would allow the witness to pass in some arbitrary new change input and output data, while keeping the original intent intact. However, like above, you have malleability.



The above presents many different ways of paying fees, and I also hope helps underscore that CTV actually is pretty flexible! In practice, applications will probably just pick one mechanism to work with.

The larger question that I have is what sort of fee paying flexibility is being imagined that isn't provided as above? This seems to cover most cases -- short of, the common protocol desire of "I wish I didn't have to think about fees" (although a new fee opcode seems to get close to that). Keep in mind, any new proposal for a different path to covenants also has to answer similar questions about fees, and I don't think something simple can be accomplished as a part of the covenants mechanisms.


A further contention is that this is something that graftroot has an advantage in.

Quote
11:27 < gmaxwell> Is it just me or does the CHECKTEMPLATEVERIFY proposal totally
 miss the insight of graftroot?  -- that a signature is a lot more flexible than
 a hash, and except for storage considerations, basically strictly superior?
 11:28 < gmaxwell> ISTM that proposal would be much better constructed if it
 pushed the output hash (with optional masking) onto the stack... where it could
 then be constrained for equality or validated w/ a signature operator that
 checksigs stuff on the stack.
 11:28 < gmaxwell> then it could be used either in a stateless taproot sort of
 way, or in a more flexible graftroot sort of way.

Quote
12:09 < gmaxwell> jeremyrubin: as far as non-interactive goes, graftrooting
 doesn't necessarily imply interaction. If the signature used doesn't commit to
 the pubkey, then it can be used as a disguised hash.  E.g. I can pick a nums
 signature and compute the pubkey that makes it valid for a particular message.
 A third party that doesn't know the nums seed can't distinguish that from a
 signature.  I would have
 12:09 < gmaxwell> lobbied heavily to never do taproot and only do graftroot,
 except an additional signature is space inefficient.
 12:09 < jeremyrubin> Hmmm
 12:09 < jeremyrubin> Well then isn't there an issue if you do that of not being
 able to bind multiple values?
 12:09 < jeremyrubin> Or are you imaging a graftroot opcode?
 12:10 < jeremyrubin> Because OP_IF <h(t1)> OP_CTV OP_ELSE <h(t2)> OP_CTV
 OP_ENDIF is a pretty desirable script
 12:11 < gmaxwell> If you use a nums signature to treat a signature has a
 hashcheck then you're stuck with a single value. But it has the nice property
 that a third party observer can't tell that you did that.  Only the first and
 second party can.  It has the downside that it's bigger than a hash.
 12:11 < gmaxwell> Of course, in applications where you might revise the outputs
 (e.g. using a decrementing CSV sequence like a payment channel), the ability to
 make revised outputs is probably super useful... it just comes at a cost of
 interaction.


I think this is a reasonable point. It certainly seems to be the case that were there to be a graftroot like thing available, you would use
it to elide a CTV script for compactness reasons (in fact I've previously suggested being able to hide a CTV hash in a taproot leaf for efficiency). However, it doesn't really suit the CTV use case that well because we want to support non-interactive cases with multiple branches.

Unless there is a script level graftroot which supports recursion, in which case it's possible that you can make it work by conditionalizing different keys to different CTV-equivalents. But a recursive graftroot construction would seem to me to be fraught to design.

Further, if you're doing complex programs which require large compilations, the curve operations may make it prohibitive compared to just hashing.

Lastly, Greg's point that a signature is more flexible than a hash is kind-of incorrect. A hash must be strictly more flexible, in a sense, because a signature contains a hash. As shown above in the discussion of fees, you can do some really flexible stuff with CTV.



Another issue Greg brings up is an important one, which is covered in the BIP.
Quote
12:02 < gmaxwell> (and, I think actually if you ever allow 2 inputs, I think it
 immediately opens up a "spend two outputs at once that allow two inputs,
 converting half the funds into fees" attack.   E.g. I create two idencial coins,
 A and A'  which allow two inputs, so they can get a variable fee input, and each
 one requires an output of B with all its value.  But then an attacker makes a
 txn that spends both at
 12:02 < gmaxwell> once, creating only one B output, and sends the rest of the
 funds to fees)

This is addressed in two different ways. The first, is by restricting the number of inputs.

If you're fitting within a common use case of a single input per branch of a CTV tree, you "for free" don't have to worry about most of the malleability issues and can merrily design your protocol.

If you do need more than one, you now have 2 issues:

1) Malleability
2) Key-Reuse

Malleability is in two categories:

1) Third party
2) First Party



The key reuse issue is "solved" by including the index at which a coin should be spent at in the the hash. This means if I spend to two identical basic CTV scripts, they provably cannot be spent in the same transaction. If you specify two different indexes, that's you indicating that you're open to them being spent together, and should take similar precautions to malleability.

If you're worried about third party malleability, and you have more than one input, one option is to include a public key that is known to all participants in addition to the CTV. Now, no third party can create a spend in an unintended way, because first-parties have to "approve" of the CTV for it to go through (signing other outputs).


If you're worried about first party malleability, it requires some tradeoffs (or something like OP_CAT) to make it truly robust (see as presented in the fees section).


These solutions also end up solving, for the most part, the "half-spend" problem Greg mentioned. In typical uses, it shouldn't come up.





The last application point I wanted to cover, was this claim:
Quote
12:16 < gmaxwell> And for things like payment pools, interaction is assumed, so
 real signatures are fine. (I didn't look at your applications yet, so I don't
 know if you've got payment pools there, perhaps under another name)

In general, this is exactly what CTV is here to avoid. We don't want signatures because they are interactive and they preclude non-interactive setups. Non interactive setups are a much more scalable solution because it means that senders can *pay into* complex protocol setups immediately.

E.g., coinbase can redeem users *always* into payment pools, where the participants online can immediately begin transacting (I have thoughts on how payment pools should be architected, the conclusion of those thoughts being that creating a CTV tree of multiparty channels which terminates in 2-of-2 channels, and "novates up the tree" when needed, has the best set of tradeoffs for privacy and efficiency).



--------------------------------------------------------------------------------------------------------------------------------------------


I sincerely hope that the network adopts CTV, and reject the notion that it's worth not deploying in the near term to take time to come up with a more powerful model for smart contracts (perhaps one day we'll know how to do a compact zero knowledge EVM for all I know).

With BIP-119, I've worked diligently to look at a wide variety of use cases and patterns to make sure that CHECKTEMPLATEVERIFY is compatible, even with it's restrictions.

I'm not confident that we'd be able to ever make something much more flexible than CHECKTEMPLATEVERIFY given the propensity for such transaction introspection to trigger superlinear hashing issues.

It's also less clear to me that additional flexibility is required for CheckTemplateVerify to cover the bases sufficiently. Is there a particular application that you have in mind that you believe CheckTemplateVerify to not work well for? I am happy to look into it and see if there's a similar design that works well under CTV.

From my experience designing around it, CheckTemplateVerify is going to be a useful tool in the belt for payment channels, vaults, payment pools, and much more. For some protocols where CheckTemplateVerify seems insufficient or unwieldy to use, what I've seen is that a small set of new opcodes (such as OP_CAT, OP_MBV, OP_CHECKINPUT) were required for the design in addition to a covenant system, but the designs were ultimately compatible with OP_CTV (without  crazy scripts like checksigfromstack covenants).

If you can give a concrete protocol example of where you think OP_CTV falls short I'm happy to walk through how you can build something sufficient with OP_CTV.

In general, I also think that rather than pursuing a "magic bullet" (which could be some snark verifier opcode, potentially), it's nice to add functionality in compose-able chunks so that the network can benefit from new use cases immediately and we can inform our later engineering efforts from real world use cases.

Lastly, I apologize to anyone who feels that I've been trying to ram a change down the network's throat. I've tried to make every effort to form an inclusive review and development process, with numerous presentations, online resources at https://utxos.org, mailing lists posts, reference implementations, a BIP, one on one meetings with companies, and a workshop that many will attend next weekend (invite still stands Greg!), but I understand that individuals expectations of procedure vary. At the end of the day, everyone wants something different from Bitcoin.

While I don't agree with Greg's characterizations of my work -- neither on a technical level nor on a procedural level -- I trust the Bitcoin network & it's participants carefully weigh changes and improvements and decide what's best.
gmaxwell
Moderator
Legendary
*
expert
Offline Offline

Activity: 4158
Merit: 8382



View Profile WWW
January 27, 2020, 03:25:18 AM
Last edit: January 27, 2020, 06:44:05 PM by gmaxwell
 #7

Quote
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.
jeremyrubin
Newbie
*
Offline Offline

Activity: 15
Merit: 5


View Profile
January 27, 2020, 04:25:56 AM
 #8

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.
fresheneesz (OP)
Jr. Member
*
Offline Offline

Activity: 33
Merit: 73


View Profile
January 27, 2020, 06:59:58 AM
 #9

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.

OP_CAT

Am I missing something, or is OP_CAT not really a thing anymore? The info here says its disabled. https://en.bitcoin.it/wiki/Script#Splice

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

Hmm, well that makes it sound like its not actually strictly redundant then. Why would you want to restrict a transaction to a specific number of inputs (other than 1) tho?

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

Is this the same problem Greg brought up in his first post, about "preventing an attacker from .. sending most of [the] value to fee?" Are you saying that if 2 CTV UTXOs that have the same script commit to specific outputs, both UTXOs will be spent for no reason (because the outputs are set in stone)?

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.

What do you mean by "too general". What downside are you implying with that generality? The issue with op_ctv as it is is that it basically requires that outputs be spent one at a time, rather than allowing the wallet owner arbitrary ability to construct a transaction with as many inputs and to as many outputs as they want. This would make the use of a wallet that uses this construct a lot more expensive to use, and a lot less convenient.

It seems like there are a couple primary things you might want to do with an op like this:

1. Require that an output be spent with a specific transaction (ie you can commit to a hash of the whole transaction).
2. Require that an output be to a specific address (perhaps less some fee), or more generally, require that the transaction that spends the input must spend at least X coin to a specified address (or multiple specified addresses), where X is less than or equal to the input value and is specified in the covenant.
3. Require a particular locktime.

I must admit I'm not practiced in bitcoin scripting, but it seems like the types of things we might want a covenant to commit to is somewhat more limited than op_ctv is (less fields able to independently commit to) and at the same time provides more general abilities. I'm curious about your thoughts on what the above three mechanisms would be unable to do well that op_ctv can do better.

cold vaults which by default leave the coins at rest

I'm very curious to hear what you mean by "by default leave the coins at rest".
harding
Jr. Member
*
Offline Offline

Activity: 50
Merit: 46


View Profile WWW
January 27, 2020, 11:32:45 AM
Last edit: January 27, 2020, 03:12:43 PM by harding
Merited by ABCbits (1), RubenSomsen (1)
 #10

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.

If you're referring to https://bitcoinops.org/workshops/#taproot-workshop, please note those were private training sessions for Optech member companies (who all pay an annual fee in part so that we can produce training material for them).  The workshops did not involve any of the primary contributors to taproot (edit: this is incorrect: Pieter Wuille attended the SF workshop and Andrew Poelstra attended the NYC workshop) and did not involve any protocol development.  Indeed, here are some quotes from Bryan Bishop's rough transcript of the New York session https://diyhpl.us/wiki/transcripts/bitcoinops/schnorr-taproot-workshop-2019/notes/ :

Quote
Why Bitcoin Optech?

Why are we doing this? Why is Bitcoin Optech involved? We started Optech 18 months ago because we wanted to help bitcoin companies adopt scaling technologies. At the time that was batching and fee estimation, but we're also looking at what's coming along like Schnorr, Taproot, eltoo maybe. We're also helping to get Schnorr and Taproot reviewed and later implemented by services. So we want to help drive adoption of scaling tech to bitcoin.

Why this workshop?

Schnorr/taproot is still a few months or a year out. We still want to share the current thinking around Schnorr and taproot. Pieter and Andrew have been working very hard on this proposal. They want to share with people in the industry what the current thinking is, around taproot. We want to give you guys a chance to play with the technology, write code, and see what you can do with the technology. We also want you involved in the feedback process. Right now the proposal is going through community feedback right now, and we want you guys to be able to take part of that feedback process since you guys are the ones who will be implementing it out when this gets rolled out.

A few warnings

Schonrr/taproot is a proposal. It will change. In fact, it has changed. In our notebooks, we were using 33 byte public keys. But in the proposal, they have now switched to 32 byte public keys.

There is no roadmap. Nobody is in charge of bitcoin and says when we can make a consensus change. This stuff could be rolled out and implemented, it could be in 6 months or many years, we don't know. It probably won't be 1 month.

Also, all of the code you see today is only for educational purposes, please don't spend real money with our libraries. They are not secure.

I'm sorry if there was any confusion about these workshops somehow being official.
jeremyrubin
Newbie
*
Offline Offline

Activity: 15
Merit: 5


View Profile
January 27, 2020, 05:17:08 PM
 #11

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.

OP_CAT

Am I missing something, or is OP_CAT not really a thing anymore? The info here says its disabled. https://en.bitcoin.it/wiki/Script#Splice

Nope, you're not wrong here. My point was that if those sorts of covenants are desirable to express, we can add great support for that functionality with another often requested opcode (OP_CAT or a similar solution). There are a few variants to OP_CAT to consider, but I don't think there would be much objection if someone went through the effort of re-specifying it as a Tapscript upgrade (OP_SUCCESSX makes it easier to introduce opcodes which manipulate the stack).

Personally, I like that there's a "roadmap" for more powerful covenants enabled by OP_CTV, while we can introduce the fundamentals today.


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

Hmm, well that makes it sound like its not actually strictly redundant then. Why would you want to restrict a transaction to a specific number of inputs (other than 1) tho?

Well it's strictly redundant insofar as the sequences commits to the length which transitively commits to the number of inputs.

I think it's less so that you want a restriction to a specific number of inputs and more that committing the field lets you programmatically select a number of inputs.

You might want to restrict this number in future applications where a script (with a new OP, something like CHECKINPUTVERIFY) checks a property of all the inputs. If you could add or remove an input, then you might break such a script.

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

Is this the same problem Greg brought up in his first post, about "preventing an attacker from .. sending most of [the] value to fee?" Are you saying that if 2 CTV UTXOs that have the same script commit to specific outputs, both UTXOs will be spent for no reason (because the outputs are set in stone)?

This is a class of vulnerability which I believe I originally came up with when writing the BIP. You can review https://github.com/bitcoin/bips/blob/master/bip-0119.mediawiki for "half-spend".

Specifically, this is not an issue with OP_CTV because we designed OP_CTV with this in mind. CTV commits to the input index being spent at, which precludes this sort of issue in the context of key reuse for basic CTV scripts. (We meaning myself and other Bitcoin developers I discussed this issue with).

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.

What do you mean by "too general". What downside are you implying with that generality? The issue with op_ctv as it is is that it basically requires that outputs be spent one at a time, rather than allowing the wallet owner arbitrary ability to construct a transaction with as many inputs and to as many outputs as they want. This would make the use of a wallet that uses this construct a lot more expensive to use, and a lot less convenient.

It seems like there are a couple primary things you might want to do with an op like this:

1. Require that an output be spent with a specific transaction (ie you can commit to a hash of the whole transaction).
2. Require that an output be to a specific address (perhaps less some fee), or more generally, require that the transaction that spends the input must spend at least X coin to a specified address (or multiple specified addresses), where X is less than or equal to the input value and is specified in the covenant.
3. Require a particular locktime.

I must admit I'm not practiced in bitcoin scripting, but it seems like the types of things we might want a covenant to commit to is somewhat more limited than op_ctv is (less fields able to independently commit to) and at the same time provides more general abilities. I'm curious about your thoughts on what the above three mechanisms would be unable to do well that op_ctv can do better.


Well so you've said stuff that translates to me as "I want to be able to arbitrarily spend the coins in whatever manner I want". Tongue in cheek, but bitcoin already has this... it's called P2[w]PKH! When you're using a covenant you're generally trying to encumber the coins with new restrictions. I think CTV strikes an elegant balance between encumbrance and flexibility, but you're right that it's far from being able to run an arbitrary piece of code outside of the transaction checking arbitrary properties.

That said, it is possible to do *some* of these things.

1. There's a kinda clunky way to do this when the other input is non-segwit. However, I think this behavior is best left to a separate op_code so that the "checkinput" functionality can be used standalone from op_ctv.
2. So this is the fundamental thing CTV does. But without OP_CAT (or similar), you can't restrict it to just requiring *some* output be specified
3. This exists presently as locktime is comitted.

Generally, I think the right way to design a contract with CTV is to come up with the end states and preconditions for the end states that you want to encode, and then figure out a transaction structure that meets your goal. I've found this to be successful for OP_CTV. If you instead, design an arbitrary system with whichever features you want, map it onto transactions, and then try to convert that into OP_CTV it may not be possible.

With respect to efficiency, you can always create as many outputs as you want, so I'll interpret your comment to be about how many inputs you are co-spending. You can definitely write safe contracts with CTV that spend many inputs together to create the contract, because the first step is not bound by anything.

But I think if you *generally* analyze the program size it will be more transactions (as nodes in your program graph) but the overall size is not too great. Remember, if I have O(N) inputs in O(1) transactions, it's within constant factors of O(1) inputs in O(N) transactions. But without a specific example (e.g., I have these UTXOS, I want to end up with these other UTXOS if preconditions X are met) it's hard for me to tell you how much less efficient or more efficient the CTV version will be. CTV scripts are also *small* and *cheap* to verify, so each node isn't that expensive to verify anyways.


Here are some pics of a vault contract that I implemented a (power user) GUI for https://imgur.com/a/rhxW4F0

cold vaults which by default leave the coins at rest

I'm very curious to hear what you mean by "by default leave the coins at rest".


Recommend you watch my BPASE 17 talk https://www.youtube.com/watch?v=r7xN7K0OqaA https://cyber.stanford.edu/sites/g/files/sbiybj9936/f/jeremyrubin.pdf

I go over a lot of different covenant mechanisms and designs. Specifically this is the "optically isolated" idea -- it's a security trade-off but sometimes it can be a good design.
BramCohen
Newbie
*
Offline Offline

Activity: 2
Merit: 0


View Profile
January 28, 2020, 08:32:48 PM
 #12

It's very difficult to get from 'here' to 'there' in terms of adding new functionality to Bitcoin. I've gone through the exercise of figuring out how to make a much more powerful on-chain programming environment in the UTXO model for Chia, and it it turns out it can be done and results in something very powerful and compelling but everything is subtly broken in much deeper ways than adding an opcode. For example:

The transaction format is vastly simpler, to make it easier to generate and talk about in the language and to put a minimum amount of information necessary into the transactions themselves.

Transactions as a whole are fuzzier things which are a collection of individual inputs and scriptsigs of those inputs which may have dependencies on each other.

Instead of having a transaction which declares everything which happens and then the scriptpubkey is asked if it's okay, the scriptpubkey is called and returns what should happen and is required.

BLS signature support is added and every transaction has a single aggregated BLS signature

Individual transactions aren't serialized in a block and go through in parallel so they can have circular dependencies

The language used has no side effects whatsoever and is well-suited for talking about itself.

The language supports loops and has a cost (or 'virtual size') function which charges for all operations.


Despite how different that all sounds, it's completely in line with the UTXO model, and in some places it's quite a bit more explicit about what data is available where instead of cobbling together a bunch of things half-assedly. In particular:

Every transactions has no access to external oracles. It's only allowed dependencies are on absolute global timelocks, relative timelocks of its inputs, and its inputs not being spent.

Every transaction is completely monotonic in its validity. The only thing which can make it invalid is a reorg to change the birthdates of its inputs or its inputs getting spent.

The only things which full nodes have to store are a current UTXO set and birthdates for all of them.

To spend a UTXO you need a reveal of its scriptpubkey (it contains the hash) and a scriptsig which causes that program to pass (but usually returns extra conditions as well, including information about new outputs)


The thing we're fudging on is on cost optimization for blocks being a completely one dimensional optimization problem, mostly because once you get even moderately complex transactions their costs go through the roof if there's no way of doing compression across multiple similar scriptpubkeys.


If you make the assumption that Bitcoin would like to get here or at least to something in this neighborhood eventually with its scripting the lessons learned from building actual smart transactions in Chia are a bit discouraging. Although a huge amount of power is unlocked with the whole new system even failing to adopt one small part of it dramatically reduces the power of the whole thing, and each of those small things is a deep breaking change to the underlying semantics of how Bitcoin works. All in the same spirit, but subtly different enough to make porting highly problematic. One could of course do an extension block, but that's a huge leap of faith and Bitcoin development would likely want to wait until there's a much more mature system before even considering that.
fresheneesz (OP)
Jr. Member
*
Offline Offline

Activity: 33
Merit: 73


View Profile
January 29, 2020, 04:16:49 AM
 #13

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 don't understand what you mean by "hash cycle". Could you explain that further? It sounds like you're saying that if you specify the exact inputs, it would create hash cycle. Are you saying its *possible* to create this hash cycle, or a hash cycle will always happen if you specify the exact inputs?

Well it's strictly redundant insofar as the sequences commits to the length which transitively commits to the number of inputs.

So committing to the number of inputs is redundant if and only if you commit to the input sequence. But not if you don't want to commit to that sequence. Right? I'm trying to clarify my understanding here.

Well it's strictly redundant insofar as the sequences commits to the length which transitively commits to the number of inputs.

I think it's less so that you want a restriction to a specific number of inputs and more that committing the field lets you programmatically select a number of inputs.

I don't understand the distinction you're making there. Restricting to "a specific number of inputs" and "programmatically selecting a number of inputs" sound identical to me. Could you give an example use case for this?

This is a class of vulnerability which I believe I originally came up with when writing the BIP. You can review https://github.com/bitcoin/bips/blob/master/bip-0119.mediawiki for "half-spend".

So are you telling me that, no, this isn't the fee issue Greg mentioned, then? I had already read the BIP. It doesn't seem to properly explain what the half-spend problem is, but seems to expect the reader to know what it is already. What is it? An example would help.

Well so you've said stuff that translates to me as "I want to be able to arbitrarily spend the coins in whatever manner I want".

No. What I said translates to "I want to be able to arbitrarily restrict how the coins can be spent in whatever manner I want."

1. There's a kinda clunky way to do this when the other input is non-segwit.

What mechanism is that?

3. This exists presently as locktime is comitted.

The next transaction's locktime cannot be committed to. I assume that's what op_ctv's locktime commitment is as well.

Recommend you watch my BPASE 17 talk

Interesting. I'll need to watch more of the full video to really understand it.
jeremyrubin
Newbie
*
Offline Offline

Activity: 15
Merit: 5


View Profile
January 29, 2020, 08:54:29 PM
 #14

I don't understand what you mean by "hash cycle". Could you explain that further? It sounds like you're saying that if you specify the exact inputs, it would create hash cycle. Are you saying its *possible* to create this hash cycle, or a hash cycle will always happen if you specify the exact inputs?

I'm saying that it always would require you to be able to generate a hash cycle, which is cryptographically impossible.

If I have a scriptPubKey corresponding to input 5 to a transaction, there is a txid for input 5 "ABCDEF...". ABCDEF commits to the scriptPubKey. But the scriptPubKey commits to spending ABCDEF. But ABCDEF = H(... || scriptPubKey || ...) = H(... || ABCDEF || ...).

So ABCDEF is a hash which contains itself (not quite a fixed point, but close). That shouldn't be possible for SHA256!

So committing to the number of inputs is redundant if and only if you commit to the input sequence. But not if you don't want to commit to that sequence. Right? I'm trying to clarify my understanding here.

Presently, without an OP_CAT like thing, you always commit to both. But in the future, you may want to restrict just the number of inputs and not the sequences.


I don't understand the distinction you're making there. Restricting to "a specific number of inputs" and "programmatically selecting a number of inputs" sound identical to me. Could you give an example use case for this?

Ok then they are the same. Semantics.

Example is given above in the discussion of adding fees dynamically.


So are you telling me that, no, this isn't the fee issue Greg mentioned, then? I had already read the BIP. It doesn't seem to properly explain what the half-spend problem is, but seems to expect the reader to know what it is already. What is it? An example would help.
Straight from the BIP:
Quote
If we allow more than one input to be spent in the transaction then it would be possible for two outputs to request payment to the same set of outputs, resulting in half the intended payments being discarded, the "half-spend" problem.


I can't give you a good example of the issue occuring, because CTV is generally not vulnerable to this class of error, the example would probably only confuse you more. But I'll try.

Let's say I create an output R for 1 BTC that is spk <A> OP_CTV. And I create another one P that is 1 BTC to spk <A> OP_CTV.

Let's say hash A covers a transaction that has 2 inputs and one output to address X for 1 BTC.

If you were able to create a transaction that spends P and R to create X, it would be valid, and create 1 output to X for 1 BTC, paying 1 BTC in fees. Spent separately, you would get two payments to X.

HOWEVER because A commits to the input index (e.g., index 0) if those values are actually identical then they can't be co-spent, avoiding the half-spend problem from key reuse.


No. What I said translates to "I want to be able to arbitrarily restrict how the coins can be spent in whatever manner I want."

Then use Ethereum? I'm not kidding; there's no roadmap anywhere for supporting completely arbitrary restrictions in Bitcoin. You need to narrow your request to things that fall within Bitcoin's abstractions and informational barriers, as well as validation computational limits.

What mechanism is that?

Because you commit to the scriptsigs if you're using a P2SH or bare script you can commit to:

1) if non witness, the exact txid via the signatures
2) if witness, the program being spent from

because the hash commits to the scriptSig.

This is a bit weird, but the alternative would be to disallow spending with any scriptSigs in the txn, forcing it to always be segwit spends (or OP_CTVs, things without a scriptSig)

Future work should just add a new covenants mechanism for inspecting the other inputs COutpoint or witness script if we want to have a more robust mechanism for using this (we may).

The next transaction's locktime cannot be committed to. I assume that's what op_ctv's locktime commitment is as well.

What do you mean it can't be committed to? Either use OP_CTV again, recursively, or use an OP_CLTV/OP_CSV?
fresheneesz (OP)
Jr. Member
*
Offline Offline

Activity: 33
Merit: 73


View Profile
January 31, 2020, 06:07:36 AM
 #15

If I have a scriptPubKey corresponding to input 5 to a transaction, there is a txid for input 5 "ABCDEF...". ABCDEF commits to the scriptPubKey. But the scriptPubKey commits to spending ABCDEF. But ABCDEF = H(... || scriptPubKey || ...) = H(... || ABCDEF || ...).

I think I see what you're saying. You're saying the output would depend on the input, but the input would also depend on the output.

You need to narrow your request to things that fall within Bitcoin's abstractions and informational barriers, as well as validation computational limits.

Well, I suppose I misspoke. I detailed the 4 cases I would like supported. Committing to an exact transaction, committing to sending to a particular address, committing to a fee, and committing to a next-locktime.
jeremyrubin
Newbie
*
Offline Offline

Activity: 15
Merit: 5


View Profile
January 31, 2020, 07:14:46 PM
 #16

I think I see what you're saying. You're saying the output would depend on the input, but the input would also depend on the output.

Yep. And because "depend" means contains a cryptographic hash of, we have a hash cycle. If SHA-256 is secure we can't do this.

Well, I suppose I misspoke. I detailed the 4 cases I would like supported. Committing to an exact transaction, committing to sending to a particular address, committing to a fee, and committing to a next-locktime.

You're just communicating in a way that is a bit unclear. I'm doing a lot of work to try to explain the concept to you -- which is my burden -- but you aren't giving me a whole lot of detail to understand exactly what you want. Can you maybe draw some diagrams?

1. You can't commit to an exact transaction ahead of time in any scheme because it has the same hash cycle problem (can't observe your own TXID). You could commit to all the outputs. In CTV we elect not to commit to the other inputs, because then we would have more types of hash cycle issues (e.g., input A commits to B, input B commit to A, hash cycle). We therefore commit to none of the inputs. If you want this functionality, it should come as a separate opcode (and I am fine to prepare & propose it after CTV).
2. If I understand what you're asking: You want to have a coin that you say it can be spent in whatever transaction you want, but it MUST go to this specific address? You can do this with CTV if you are OK not specifying additional outputs, which for most applications of this should be fine. (Once OP_CAT is re-added it's a bit more flexible again).
3. I'm not sure what this means. I've separately discussed wanting to have some "safety" opcodes to check the total transaction value.
4. You can do this already in script without CTV using CLTV. Not sure what you're asking for beyond that.
fresheneesz (OP)
Jr. Member
*
Offline Offline

Activity: 33
Merit: 73


View Profile
February 01, 2020, 11:15:26 PM
 #17

detail to understand exactly what you want

It sounds like you're understanding what I'm trying to discuss, and I'll respond to each numbered point. Thanks for putting in the time to explain all this to me tho! I appreciate it, tho I don't want to put too much burden you since its likely that I won't understand every piece of this perfectly, and I'm fine with that.

What I'm looking for here is just a discussion of how the various use cases would be best supported. I'm not saying one op code should provide the functionality for all of them (tho I'm not saying the opposite either). I'm primarily concerned with how exactly bitcoin vaults will be created, and I'm hoping that op_ctv, another new op_code, or a combination will provide the functionality to create bitcoin vaults that can be used without extra limitations that basic wallets don't have (eg with regard to number of inputs). Also important is the efficiency of the vault (in terms of transaction size in bytes). So my goal with this thread is to understand the limitations of op_ctv as it stands with regard to bitcoin vaults, and what additional op codes might be needed to fully support the kind of bitcoin vault I'm interested in.

I can be a bit more detailed about the type of bitcoin vault I've been thinking of. An example would be a two-key wallet where any coins sent to it can be spent in arbitrary combinations with the following (and only the following) restrictions:

A. If *both* keys sign the transaction, the destination address can spend immediately.
B1. If only *one* of the two keys signs the transaction and *fewer* than 1000 blocks have passed since the transaction was mined, the output can be spent only by signing with both keys and must be spent back to the original input address using a maximum fee of X.
B2. If only *one* of the two keys signs the transaction and *greater* than or equal to 1000 blocks have passed since the transaction was mined, the destination address can spend immediately.

Coins can be spent to any destination, using any number of inputs (from this wallet or not), as long as the above restrictions are followed. Here's another description of a similar wallet setup: https://github.com/fresheneesz/TordlWalletProtocols/blob/master/experimental/singleWalletProtocols/Time-locked%203-Seed%20Cold%20Wallet.md

The above uses another non-existent concept: a time-unlock or time-switch. Currently we have relative and absolute timelocks, but we don't have a way to unlock some behavior after some time. The ability to do that would allow these bitcoin vaults to do the above in a single transaction that becomes finalized after some time (eg 1000 blocks in the above example) without any additional transaction needed. Without that, 2 transactions are needed (one transaction with a timelocked transaction who's script is similar to B1 and B2 above and then another non-timelocked transaction to the destination).

One issue I can see with B2 is that it basically requires that input constraints be composed with output constraints (ie, if you want to pay from a vault like this to a script hash). Is it possible to create a script that has a branch that requires an external script be satisfied (eg a "condition on script hash", or something like that)? Without that ability, it seems that one vault wouldn't be able to send to another vault.

One issue with op_ctv is that an output using it can't practically be used in batched transactions. In the future, I think it might become standard to batch transactions for both privacy and efficiency (as in wasabi wallet). If I'm right that's the case, then op_ctv might be relatively a very expensive op to use.

1. Gotcha, that makes sense. Regardless of the inability to commit to a transaction hash, it should be possible to create a convenant with multiple inputs for which there is only one possible transaction that spends them. Granted, I have no use case for doing specifically that with multiple inputs, so we don't need to discuss that use case. However, it sounds like op_ctv does allow doing this (only allowing one possible transaction) in the case of a single input, correct?

2. Yes, but I would like to specify additional outputs in order to support batched transactions.

3. This point is to address the first question Greg brought up in this thread. This would allow the fee specification in restriction B1 above. Without this, Greg's point was that an attacker (eg who stole one of the two keys in the wallet above) could spend your entire wallet as fee (which obviously isn't something you want to allow).

4. I don't believe I'm asking for anything new here, actually. I'm just including this for completeness. Op_ctv allows committing to the locktime of the next transaction (as opposed to the locktime of the transaction guarded by a script using op_ctv), right? That's all I'm saying here. This is not the same thing as verifying the locktime without the use of covenants.
jeremyrubin
Newbie
*
Offline Offline

Activity: 15
Merit: 5


View Profile
February 05, 2020, 02:52:06 AM
 #18

The above uses another non-existent concept: a time-unlock or time-switch. Currently we have relative and absolute timelocks, but we don't have a way to unlock some behavior after some time. The ability to do that would allow these bitcoin vaults to do the above in a single transaction that becomes finalized after some time (eg 1000 blocks in the above example) without any additional transaction needed. Without that, 2 transactions are needed (one transaction with a timelocked transaction who's script is similar to B1 and B2 above and then another non-timelocked transaction to the destination).

So it seems you have some core misconceptions with how script validation works today.


Code:
OP_IF <key a> op_checksigverify <t1> OP_CSV  OP_ELSE <key b> OP_checksigverify <t2> OP_CSV  OP_ENDIF OP_DROP

does exactly what you're saying (unlocks a behavior after a specific time). You can implement the logic you wanted exactly like this.


I'll try to recommend some resources so you can learn more about Bitcoin script, which I think would enhance your understanding! This is hard stuff, but it's worth fully understanding if you're interested in programming Bitcoin.

https://medium.com/summa-technology/bitcoins-time-locks-27e0c362d7a1
https://bitcoin.stackexchange.com/questions/75232/bitcoin-script-tutorial


Once you've done that, feel free to reach back out and we can carry on the conversation, but I think without that context it will be hard to get on the same page about what CTV is accomplishing...
fresheneesz (OP)
Jr. Member
*
Offline Offline

Activity: 33
Merit: 73


View Profile
February 08, 2020, 11:23:47 PM
Last edit: February 09, 2020, 09:14:17 PM by fresheneesz
 #19

> does exactly what you're saying (unlocks a behavior after a specific time)

I'm sorry, I see that the phrase "time-unlock" might be a bit misleading and I also misspoke when I said "we don't have a way to unlock some behavior after some time". I actually meant that we don't have a way to *lock* some behavior after some time. I meant to describe is a (currently non-existent) opcode that would allow a spend-path to remain unlocked for a period of time (just as a time-lock locks a spend path for a period of time). So after the specified block (or relative number of blocks), the spend path would no longer be useable. This "time-unlock" opcode might be better named something like op_invalidafter, op_validbefore, or op_isbefore.

This opcode would allow ownership of an output to "switch over" from one owner to another at a specified time. Before that switch over time, there could be various ways to "reverse" the transaction by spending the output. Correct me if I'm wrong, but I don't believe this is possible with current bitcoin opcodes.
jeremyrubin
Newbie
*
Offline Offline

Activity: 15
Merit: 5


View Profile
February 10, 2020, 10:19:58 PM
 #20

> does exactly what you're saying (unlocks a behavior after a specific time)

I'm sorry, I see that the phrase "time-unlock" might be a bit misleading and I also misspoke when I said "we don't have a way to unlock some behavior after some time". I actually meant that we don't have a way to *lock* some behavior after some time. I meant to describe is a (currently non-existent) opcode that would allow a spend-path to remain unlocked for a period of time (just as a time-lock locks a spend path for a period of time). So after the specified block (or relative number of blocks), the spend path would no longer be useable. This "time-unlock" opcode might be better named something like op_invalidafter, op_validbefore, or op_isbefore.

This opcode would allow ownership of an output to "switch over" from one owner to another at a specified time. Before that switch over time, there could be various ways to "reverse" the transaction by spending the output. Correct me if I'm wrong, but I don't believe this is possible with current bitcoin opcodes.

The only way to lock a behavior is to spend the funds to a new UTXO. In Bitcoin we don't do this at the script level because we want script authorization to be context-free and monotonic. E.g., if something is true, it should always be true. At the transaction level, you can remove a spending path one by one. This is kinda what CTV is doing fundamentally.
Pages: [1] 2 »  All
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!