Re: [bitcoin-dev] BIP for OP_VAULT

2023-03-06 Thread Greg Sanders via bitcoin-dev
Hi James,

I think everything except the hinted "withdrawal authorization" is spot on.

For withdrawal authorization, I think we'll have to go deeper into the TLUV
direction
as AJ suggested for at least a couple reasons:

1) You need the withdrawal authorization committed at deposit time
2) You need to make sure cheeky opcodes cannot be prepended to the script
at spend time

OP_FORWARD_LEAF_UPDATE(OP_FLU) seems to fit the bill, at the cost of maybe
adding another opcode for "refunds" as he notes.

Cheers,
Greg

On Mon, Mar 6, 2023 at 10:25 AM James O'Beirne 
wrote:

> I'm glad to see that Greg and AJ are forming a habit of hammering
> this proposal into shape. Nice work fellas.
>
> To summarize:
>
> What Greg is proposing above is to in essence TLUV-ify this proposal.
>
> I.e. instead of relying on hashed commitments and recursive script
> execution (e.g.  + later presentation of preimage
> script for execution), OP_VAULT would instead move through its
> withdrawal process by swapping out tapleaf contents according to
> specialized rules. If this is opaque (as it was to me), don't fret -
> I'll describe it below in the "mechanics" section.
>
>
> The benefits of this TLUVification are
>
> - we can avoid any nested/recursive script execution. I know the
>   recursive stuff rankles some greybeards even in spite of it being
>   bounded to a single call. I'm not sure I share the concern but
>   maintaining the status quo seems good.
>
> - the spec is easier to reason about, more or less. The opcodes
>   introduced don't have variadic witness requirements, and each opcode
>   is only consumed in a single way.
>
> - there's less general indirection. Instead of saying "okay, here's the
>   hash of the script I'm going to use to authorize trigger
>   transactions," we're just outright including the trigger auth script
>   in the tapleaf at the birth of the vault as regular 'ol script that is
>   evaluated before execution of the OP_VAULT instruction.
>
>   Similarly, instead of relying on an implicit rule that an OP_VAULT can
>   be claimed by a recovery flow, we're relying on a specific tapleaf that
>   facilitates that recovery with OP_VAULT_RECOVER, described below.
>
> Basically, OP_VAULT would just be implemented in a way that feels
> more native to Taproot primitives.
>
> Greg also introduces different opcodes to facilitate consistent
> witness structure, rather than the variable ones we have now
> since OP_VAULT and OP_UNVAULT can each be spent in two different
> contexts. I've changed those a little here; instead of the three general
> ones Greg gave, we whittled it down to two: OP_VAULT and
> OP_VAULT_RECOVER.
>
>
> So I think that, barring significant implementation complexity - which
> I'll find out about soon and don't expect - this is a good change to the
> proposal. As Greg noted, it doesn't really change anything about the
> usage or expressiveness... other than the fact that, as a bonus, it
> might allow an optional withdrawal authorization script (i.e. trigger
> output => final target), which could be useful if e.g. some kind of
> size-limiting opcode (e.g. OP_TX_MAXSIZE or something) came around in
> the future as a kind of pinning fix.
>
> If that last bit lost you, don't worry - that is speculative, but the
> point is that this rework composes well with other stuff.
>
>
> # CTV use
>
> Another thing that has dawned on us is that we might as well just reuse
> OP_CHECKTEMPLATEVERIFY for withdrawal target spends. Ben Carmen and
> others realized early on that you can synthesize CTV-like behavior by
> spending to a 0-delay OP_UNVAULT output, so something CTVish has always
> implicitly been a part of the proposal. But CTV is better studied and
> basically as simple as the OP_UNVAULT spend semantics, so the thought is
> that we might as well reuse all the existing work (and scrutiny) from
> CTV.
>
> As a concrete example, an issue with the existing proposal is that the
> existing CTVish OP_UNVAULT behavior has txid malleability, since it
> doesn't commit to nVersion or nLockTime or the input sequences. Using
> CTV solves this issue. Otherwise we'd basically reinvent it - "something
> something convergent evolution."
>
> I think this is a satisfying development, because there's clearly demand
> for CTV use in other contexts (DLC efficiency, e.g.), and if it's
> required behavior for practical vaults, I think pulling in the existing
> BIP-119 that's been worked over for years reduces the conceptual
> surface area added by OP_VAULT.
>
>
> # New mechanics of the proposal
>
> So here I'm going to describe my rendering of Greg and AJ's suggestions.
>
>
> ## Required opcodes
>
> - OP_VAULT: spent to trigger withdrawal
> - OP_VAULT_RECOVER: spent to recover
> - OP_CHECKTEMPLATEVERIFY: spent into final withdrawal target
>
>
> Creating an initial deposit
> ---
>
> For each vault, vaulted coins are spent to an output with the taproot
> structure
>
>   taproot(internal_key, 

Re: [bitcoin-dev] BIP for OP_VAULT

2023-03-06 Thread James O'Beirne via bitcoin-dev
I'm glad to see that Greg and AJ are forming a habit of hammering
this proposal into shape. Nice work fellas.

To summarize:

What Greg is proposing above is to in essence TLUV-ify this proposal.

I.e. instead of relying on hashed commitments and recursive script
execution (e.g.  + later presentation of preimage
script for execution), OP_VAULT would instead move through its
withdrawal process by swapping out tapleaf contents according to
specialized rules. If this is opaque (as it was to me), don't fret -
I'll describe it below in the "mechanics" section.


The benefits of this TLUVification are

- we can avoid any nested/recursive script execution. I know the
  recursive stuff rankles some greybeards even in spite of it being
  bounded to a single call. I'm not sure I share the concern but
  maintaining the status quo seems good.

- the spec is easier to reason about, more or less. The opcodes
  introduced don't have variadic witness requirements, and each opcode
  is only consumed in a single way.

- there's less general indirection. Instead of saying "okay, here's the
  hash of the script I'm going to use to authorize trigger
  transactions," we're just outright including the trigger auth script
  in the tapleaf at the birth of the vault as regular 'ol script that is
  evaluated before execution of the OP_VAULT instruction.

  Similarly, instead of relying on an implicit rule that an OP_VAULT can
  be claimed by a recovery flow, we're relying on a specific tapleaf that
  facilitates that recovery with OP_VAULT_RECOVER, described below.

Basically, OP_VAULT would just be implemented in a way that feels
more native to Taproot primitives.

Greg also introduces different opcodes to facilitate consistent
witness structure, rather than the variable ones we have now
since OP_VAULT and OP_UNVAULT can each be spent in two different
contexts. I've changed those a little here; instead of the three general
ones Greg gave, we whittled it down to two: OP_VAULT and
OP_VAULT_RECOVER.


So I think that, barring significant implementation complexity - which
I'll find out about soon and don't expect - this is a good change to the
proposal. As Greg noted, it doesn't really change anything about the
usage or expressiveness... other than the fact that, as a bonus, it
might allow an optional withdrawal authorization script (i.e. trigger
output => final target), which could be useful if e.g. some kind of
size-limiting opcode (e.g. OP_TX_MAXSIZE or something) came around in
the future as a kind of pinning fix.

If that last bit lost you, don't worry - that is speculative, but the
point is that this rework composes well with other stuff.


# CTV use

Another thing that has dawned on us is that we might as well just reuse
OP_CHECKTEMPLATEVERIFY for withdrawal target spends. Ben Carmen and
others realized early on that you can synthesize CTV-like behavior by
spending to a 0-delay OP_UNVAULT output, so something CTVish has always
implicitly been a part of the proposal. But CTV is better studied and
basically as simple as the OP_UNVAULT spend semantics, so the thought is
that we might as well reuse all the existing work (and scrutiny) from
CTV.

As a concrete example, an issue with the existing proposal is that the
existing CTVish OP_UNVAULT behavior has txid malleability, since it
doesn't commit to nVersion or nLockTime or the input sequences. Using
CTV solves this issue. Otherwise we'd basically reinvent it - "something
something convergent evolution."

I think this is a satisfying development, because there's clearly demand
for CTV use in other contexts (DLC efficiency, e.g.), and if it's
required behavior for practical vaults, I think pulling in the existing
BIP-119 that's been worked over for years reduces the conceptual
surface area added by OP_VAULT.


# New mechanics of the proposal

So here I'm going to describe my rendering of Greg and AJ's suggestions.


## Required opcodes

- OP_VAULT: spent to trigger withdrawal
- OP_VAULT_RECOVER: spent to recover
- OP_CHECKTEMPLATEVERIFY: spent into final withdrawal target


Creating an initial deposit
---

For each vault, vaulted coins are spent to an output with the taproot
structure

  taproot(internal_key, {$recovery_leaf, $trigger_leaf, ...})

where

  internal_key =
unchanged from original proposal (some very safe recovery key)

  $recovery_leaf =
[  ]  OP_VAULT_RECOVER

  $trigger_leaf =