Subject: Re: [bitcoin-dev] OP_VAULT: a new vault proposal

From: Billy Tetrud <[email-masked]>
Date: Wed, 18 Jan 2023 13:00:29 -0600

I like the proposal of a targeted wallet vault opcode. It keeps things
constrained, limiting objections to those of the form "but if we had X it
would do all this and more so why add this complexity when it will be
obsoleted in the future?"

> An idealized vault
> no existing vault design meets this set of features.

My proposal for efficient wallet vaults
<https://github.com/fresheneesz/bip-efficient-bitcoin-vaults> was designed
to meet all of those criteria, and allows batching as well. It also allows
sending in a single transaction vs the two it would take with OP_VAULT and
several other benefits. However, it uses a general covenant opcode to do
it, along with several other new opcodes specified in that write up.

>  it must first be spent into an OP_UNVAULT output

I don't see in the write up how a node verifies that the destination of a
spend using an OP_VAULT output uses an appropriate OP_UNVAULT script. I see
you mentioned above (but not in the write up) that the script pub key needs
to be bare. But it would be very helpful if you detailed exactly how this
is intended to be done in that document.

It seems that Greg Sanders noticed the same thing. I like his suggestion as
you reworded it above, makes a lot of sense.

> I think the fix is just requiring a single additional witness data item
during OP_VAULT spend (for unvault path), mandating the
<target-outputs-hash> to be included in the witness stack as an input to
OP_VAULT opcode, and transaction introspection then checks to make sure the
witness item and the corresponding output script template matches the
expected.

>  If it becomes necessary to make use of the recovery path, the recovery
scriptPubKey will be revealed, which means that any other vaults with that
recovery path may be swept there by an unauthenticated party.

Another issue is that the recovery path becomes the easiest mechanism of
attack. It would usually be prudent to store this recovery address with
every key to the vault, and potentially in other places as well, so as to
minimize the possibility that the funds are lost or stolen. In such a
situation, this means that an attacker that finds any key can grief the
vault by spending it to its recovery address. My "efficient wallet vault"
design I mentioned above doesn't have this issue, nor the associated
batching DoS attack.

> if the recovery path should be committed with a signature
> This would enable a "sign-to-recover" flow at the option of the user,
specified during vault creation.

This is rather limiting isn't it? Losing the key required to sign loses
your recovery option. Seems brittle. It seems better to me to include a
<recovery-initiation-spk-hash> that operates similarly to
<recovery-spk-hash> - where some arbitrary script must be fulfilled to
allow the recovery path to be spent. For a recovery path, you'd probably
often want one of the keys required to spend from the recovery address,
since without access to one of those keys, you can't spend from the
recovery address anyway (and the spend path is an effective burn). Having
some ability to allow an n-of-m situation for triggering the recovery path
seems desirable.

>  What do you think about the idea of making the recovery-path
authorization behavior variable on a single byte flag preceding the 32 byte
data push, as I mentioned in another post?

A more arbitrary construct here that allows you to use any kind of recovery
script would be much more flexible and preclude the need for any kind of
switching like this. It seems like it would also solve the issue Andrew
Chow mentioned where recovery transactions can only be batched if they all
share the same recovery output, since each output can simply include the
appropriate witness matching its recovery scriptPubkey.

Tho I don't think I quite understand why you mention the constraint
requiring recovery batching to only be done with vault outputs that have
matching recovery destinations. Wouldn't it be reasonably possible to allow
recovery outputs with any recovery address to be batched, and the amount
sums sent to each to be added up and verified?

>  1. script validation rules could require some allowable “range” of
amount discounts
>  seems like a bad design

> 2. script validation rules could require that the unvault/recovery
outputs preserve the full value
> seems like the preferable approach

Both have tradeoffs. I would not call #1 an inherently bad design. I would
point out that for 2, disallowing the spending of vault funds without
access to already-unvaulted bitcoin seems like a very inconvenient design,
since it would require you in the best of cases to create more complex
transactions (or cpfp transaction chains) involving a 2nd wallet that you
involve in the unvaulting process, and in the worst case (if you have no
other bitcoin or other money on hand) you have to go asking a 3rd party for
their bitcoin to use in the unvaulting process. If someday wallet vaults
are the standard wallet construct, people might not even want to have a
non-vault wallet just for use in unvaulting.

#1 is the approach I used to design OP_LIMITFEECONTRIBUTION
<https://github.com/fresheneesz/bip-efficient-bitcoin-vaults/blob/main/lfc/bip-limit-fee-contribution.md>,
which allows for a fee-range specification that depends on recent median
fees included in blocks. This allows rather flexibly limiting fees to a
particular range of "priorities" regardless of fee environment.

For #2, it seems like Jeremy Rubin's Sponsor transactions would be ideal
for facilitation of adding a fee to an unvaulting transaction.

>  In the case of a withdrawal, unvaulted funds can skip the “warm” wallet
step that precomputed vault funds must pass through on their way to
destinations only known at unvault time.

Hmm, it seems inaccurate to say that step is "skipped". While there isn't a
warm wallet step, its replaced with an OP_UNVAULT script step. So its not
skipped as much as modified I think, right?

It looks like the way the OP_UNVAULT is specified prevents any use where
you don't know the full set of outputs, which might happen in cases where
certain sighash flags might be useful (signing some outputs you know, but
allowing outputs that you don't know to be added later). This is another
thing my "efficient wallet vault" design should allow.

On Tue, Jan 17, 2023 at 1:47 AM Anthony Towns via bitcoin-dev <
[email-masked]> wrote:

> On Mon, Jan 16, 2023 at 11:47:09PM +0000, Andrew Chow via bitcoin-dev
> wrote:
> > It seems like this proposal will encourage address reuse for vaults,
>
> (That is listed as an explicit goal: "A single vault scriptPubKey should
> be able to "receive" multiple deposits")
>
> > However the current construction makes it impossible to spend these
> > vaults together. Since OP_VAULT requires the recovery script of the
> > unvault output to match what's provided in the input,
>
> I don't think this part is a big problem -- the recovery path requires
> revealing a secret, but if you separate that secret from the recovery
> path sPK, you could vary the secret. ie:
>
>   unvault1 delay recovery1 VAULT
>   unvault2 delay recovery2 VAULT
>
> where recovery1 = SHA256(SHA256(secret1), rSPK) and recovery2 =
> SHA256(SHA256(secret2), rSPK), and both are spendable when the top stack
> element is secretN and the first output pays at least the sum of all
> the OP_VAULT using inputs to rSPK. So batched recovery could work fine,
> I think.
>
> (If you're using the same "recovery" parameter to each VAULT, then
> you're revealing which txs are in your vault at spend time, rather than
> at receive time, which doesn't seem all that much better to me)
>
> But the problem with this is it prevents you from combining vaults when
> spending normally: so if you've got a bunch of vaults with 1 BTC each,
> and want to spend 10 BTC on a house, you'll need to make 11 separate
> transactions:
>
>   * 10 txs each spending a single vault utxo, satisfying
>       <uN> <delay> <rN> OP_VAULT
>     via the uN path, creating an output of
>       <outhash> <delay> <rN> OP_UNVAULT
>
>   * 1 tx spending all the OP_UNVAULT outputs to a common set of outputs
>     <uN>, with nSequence set to a relative timelock of at least <delay>
>
> Whereas if you use an identical OP_VAULT script for all the utxos in
> your vault, that can look like:
>
>   * 1 tx, spending all the vault utxos, to a single OP_UNVAULT output,
>     with the same <delay> <rN> that all the inputs share.
>
>   * 1 tx spending the OP_UNVAULT output after a delay
>
> But maybe you can get the best of both worlds just by having the unvault
> path for OP_VAULT require you to put the vout number for its corresponding
> OP_UNVAULT output on the stack? Then if you're doing address reuse, you
> use a single vout for multiple inputs; and if you're avoiding address
> reuse, you use multiple outputs, and provide the mapping between inputs
> and outputs explicitly.
>
> Cheers,
> aj
>
> _______________________________________________
> bitcoin-dev mailing list
> [email-masked]
> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>