Hello James, First off, thank you for crafting an interesting idea like this that is aimed at solving a serious problem. I see a lot of excitement about the use cases, and I think it's worth iterating on. Attempting to keep the idealized functionality constant, I'd like to explore a design detour. I'm attempting to decouple the 3 functionalities of `OP_VAULT` and `OP_UNVAULT` into their constituent functions with names I just made up. The goals of this e-mail: 1) Removing variable number of arguments based on values of arguments for the opcodes. To me as a spec reader, I find it very difficult to parse what's precisely happening when. I think the only/last opcode to support this behavior was OP_CHECKMULTISIG(could be wrong), and now I know another reason why OP_CSA construct is nicer going forward with taproot. 2) Remove the recursive evaluation functionality used for authentication, without reducing the efficacy of the targeted solution. Recursive evaluation has a fraught history in Bitcoin script, makes composing functionality with tooling likely more difficult, and has a lot of templated behavior. If we can rely on regular old tapscript to get us where we need to go, I'd prefer that. 3) Increase legibility of the spec. There's a ton going on, breaking things up and naming them based on the method rather than the goal may help here. 4) Not (greatly) increase the expressiveness of the proposal. It's a targeted proposal, and I'd like to respect that. These covenant opcodes are intended to be drop-in replacements for the OP_(UN)VAULT opcodes. To recap, there are three things happen in idealized OP_VAULT scenario: 1) Money comes out, then has to wait (trigger transaction) 2) Money waits long enough, then withdrawals to dynamic set of outputs that are declared at trigger time (withdrawal transaction) 3) Money to single specified output script picked up front, with no wait (recovery) Below is a sketch of a replacement for the two opcodes. Ignore my inconsistency on VERIFY/non-VERIFY behavior, seeing if people agree with this general direction: `OP_TRIGGER_FORWARD`: Takes exactly three arguments: 1) output index to match against (provided at spend time normally) 2) target-outputs-hash: 32 byte hash to be forwarded to output given at (1) (provided at spend time normally) 3) spend-delay: value to be forwarded to output given at (1) Fails script immediately if there aren't enough inputs or they're the wrong format. These last two arguments are "forwarded" to output at index declared in first argument, resulting in: `EXPR_WITHDRAW: OP_CHECKSEQUENCEVERIFY OP_DROP OP_FORWARD_OUTPUTS` As the derived tapscript, embedded in a output scriptpubkey of the form: `tr(NUMS,{...,EXPR_WITHDRAW})`, meaning we literally take the control block from the spending input, swap the inner pubkey for `NUMS`, use `EXPR_WITHDRAW` as the tapleaf, reconstruct the merkle root. If the output scriptpubkey doesnt match, fail. This TLUV-ish script/inner pubkey replacement is meant to allow arbitrary other conditions, which is where the "recovery" path comes in for typical usage. If output at the target output index doesn't match the constructed script, the evaluation fails. `OP_FORWARD_DESTINATION`: Takes exactly two arguments: 1) `dest-vout-idx`: index of output that contains the so-called "recovery" path 2) : the hash of the script destination Fails immediately if the reconstructed output script doesn't match. `OP_FORWARD_OUTPUTS` takes exactly one argument: 1) target-outputs-hash: commits to all outputs' scripts and values Fails immediately if transaction's outputs(including value) hash doesn't match. **Typical usage**: ``` DEPOSITING TO VAULT SCRIPT: EXPR_RECOVERY: OP_FORWARD_DESTINATION EXPR_TRIGGER: OP_TRIGGER_FORWARD tr(KEY, {EXPR_RECOVERY, EXPR_TRIGGER}) ``` ``` EXPR_WITHDRAW: OP_CHECKSEQUENCEVERIFY OP_DROP OP_FORWARD_OUTPUTS ``` ``` TRIGGERING WITHDRAWAL TIMER SCRIPT: tr(NUMS, {EXPR_RECOVERY,EXPR_WITHDRAW}) <--- note EXPR_RECOVERY is forced by the OP_TRIGGER_FORWARD TLUV action ``` Could save 2 WU having OP_FORWARD_OUTPUTS take the directly as an argument, or keep it more general as I did. Would love to know what you and others think about this direction. I apologies for any misunderstandings I have about the current OP_VAULT BIP! Cheers, Greg On Mon, Feb 13, 2023 at 4:09 PM James O'Beirne via bitcoin-dev < bitcoin-dev@lists.linuxfoundation.org> wrote: > Since the last related correspondence on this list [0], a number of > improvements have been made to the OP_VAULT draft [1]: > > * There is no longer a hard dependence on package relay/ephemeral > anchors for fee management. When using "authorized recovery," all > vault-related transactions can be bundled with unrelated inputs and > outputs, facilitating fee management that is self contained to the > transaction. Consequently, the contents of this proposal are in theory > usable today. > > * Specific output locations are no longer hardcoded in any of the > transaction validation algorithms. This means that the proposal is now > compatible with future changes like SIGHASH_GROUP, and > transaction shapes for vault operations are more flexible. > > --- > > I've written a BIP that fully describes the proposal here: > > > https://github.com/jamesob/bips/blob/jamesob-23-02-opvault/bip-vaults.mediawiki > > The corresponding PR is here: > > https://github.com/bitcoin/bips/pull/1421 > > My next steps will be to try for a merge to the inquisition repo. > > Thanks to everyone who has participated so far, but especially to AJ and > Greg for all the advice. > > James > > [0]: > https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2023-January/021318.html > [1]: https://github.com/bitcoin/bitcoin/pull/26857 > _______________________________________________ > bitcoin-dev mailing list > bitcoin-dev@lists.linuxfoundation.org > https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev >