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 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, 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 <bitcoin-dev@lists.linuxfoundation.org> 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
bitcoin-dev@lists.linuxfoundation.org
https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev