AJ,
Interesting stuff! Just a couple thoughts on these proposed opcodes, at
least one we discussed elsewhere:
1) OP_FORWARD_SELF is a JET of OP_FLU in the revaulting common case. Maybe
obvious but I missed this initially and thought it was useful to be pointed
out.
2) Using these extended primitives, you can do rate-limiting of the two
step unvaulting, or just a single step vault by committing to the partial
values. For the single stage case it's something like:
$recovery = Same As Before
$withdrawal = OP_CSV OP_DROP OP_CHECKSIG OP_DUP
OP_LESSTHANOREQUAL OP_VERIFY OP_FORWARD_PARTIAL OP_FORWARD_TARGET
OP_FORWARD_SELF
$withdrawal is spent by:
<0<=v<=V>
where "V" is the max allowed withdrawal value, and "deposit-delay" the
required gap in withdrawals
Due to the OP_LEQ, you are bound to ~21 BTC in value for this operation,
but for larger vaults it's pretty trivial to add larder fixed denominations
to "peel out" value until you get to your final ~21 BTC.
This rate-limiting(in either the two-stage or one-stage scheme) can limit
the risk of theft during a watchtower outage to a constant value per utxo
per time period of watchtower failure. As we've seen in the past with LN
infrastructure, software risks are often correlated, so it's a good idea to
build in belt and suspenders where we can or at least have them available
when possible.
Cheers,
Greg
On Tue, Mar 7, 2023 at 7:45 AM Anthony Towns wrote:
> On Mon, Mar 06, 2023 at 10:25:38AM -0500, James O'Beirne via bitcoin-dev
> wrote:
> > What Greg is proposing above is to in essence TLUV-ify this proposal.
>
> FWIW, the way I'm thinking about this is that the "OP_VAULT" concept is
> introducing two things:
>
> a) the concept of "forwarding" the input amount to specified
> outputs in a way that elegantly allows merging/splitting
>
> b) various restrictions on the form of the output scripts
>
> These concepts go together well, because restricting an output script is
> only an interesting thing to do if you're moving value from this input
> into it. And then it's just a matter of figuring out a nice way to pick
> opcodes that combine those two concepts in interesting ways.
>
> This is different from TLUV, in that TLUV only did part (b), and
> assumed you'd do part (a) manually somehow, eg via "OP_IN_OUT_AMOUNT"
> and arithmetic opcodes. The advantage of this new approach over that
> one is that it makes it really easy to get the logic right (I often
> forgot to include the IN_OUT_AMOUNT checks at all, for instance), and
> also makes spending multiple inputs to a single output really simple,
> something that would otherwise require kind-of gnarly logic.
>
> I think there are perhaps four opcodes that are interesting in this class:
>
>idx sPK OP_FORWARD_TARGET
> -- sends the value to a particular output (given by idx), and
> requires that output have a particular scriptPubKey (given
> by sPK).
>
>idx [...] n script OP_FORWARD_LEAF_UPDATE
> -- sends the value to a particular output (given by idx), and
> requires that output to have almost the same scriptPubKey as this
> input, _except_ that the current leaf is replaced by "script",
> with that script prefixed by "n" pushes (of values given by [...])
>
>idx OP_FORWARD_SELF
> -- sends the value to a particular output (given by idx), and
> requires that output to have the same scriptPubKey as this input
>
>amt OP_FORWARD_PARTIAL
> -- modifies the next OP_FORWARD_* opcode to only affect "amt",
> rather than the entire balance. opcodes after that affect the
> remaining balance, after "amt" has been subtracted. if "amt" is
> 0, the next OP_FORWARD_* becomes a no-op.
>
> Then each time you see OP_FORWARD_TARGET or OP_FORWARD_LEAF_UPDATE, you
> accumulate the value that's expected to be forwarded to the output by
> each input, and verify that the amount for that output is greater-or-equal
> to the accumulated value.
>
> > ## Required opcodes
> > - OP_VAULT: spent to trigger withdrawal
> > - OP_VAULT_RECOVER: spent to recover
>
> Naming here is OP_VAULT ~= OP_FORWARD_LEAF_UPDATE; OP_VAULT_RECOVER ~=
> OP_FORWARD_TARGET.
>
> > For each vault, vaulted coins are spent to an output with the taproot
> > structure
> >
> > taproot(internal_key, {$recovery_leaf, $trigger_leaf, ...})
> >
> > where
> >
> > $trigger_leaf =
> >