Return-Path: Received: from smtp3.osuosl.org (smtp3.osuosl.org [140.211.166.136]) by lists.linuxfoundation.org (Postfix) with ESMTP id 00BA8C002D for ; Wed, 11 Jan 2023 06:52:38 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp3.osuosl.org (Postfix) with ESMTP id BC8C660A89 for ; Wed, 11 Jan 2023 06:52:38 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org BC8C660A89 X-Virus-Scanned: amavisd-new at osuosl.org X-Spam-Flag: NO X-Spam-Score: -1.901 X-Spam-Level: X-Spam-Status: No, score=-1.901 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001, UNPARSEABLE_RELAY=0.001] autolearn=ham autolearn_force=no Received: from smtp3.osuosl.org ([127.0.0.1]) by localhost (smtp3.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id sE-egB1DTJpg for ; Wed, 11 Jan 2023 06:52:37 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.8.0 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp3.osuosl.org 48A3660A77 Received: from azure.erisian.com.au (azure.erisian.com.au [172.104.61.193]) by smtp3.osuosl.org (Postfix) with ESMTPS id 48A3660A77 for ; Wed, 11 Jan 2023 06:52:37 +0000 (UTC) Received: from aj@azure.erisian.com.au (helo=sapphire.erisian.com.au) by azure.erisian.com.au with esmtpsa (Exim 4.92 #3 (Debian)) id 1pFUyO-00011v-Uv; Wed, 11 Jan 2023 16:52:34 +1000 Received: by sapphire.erisian.com.au (sSMTP sendmail emulation); Wed, 11 Jan 2023 16:52:28 +1000 Date: Wed, 11 Jan 2023 16:52:28 +1000 From: Anthony Towns To: James O'Beirne Message-ID: References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: Cc: Bitcoin Protocol Discussion Subject: Re: [bitcoin-dev] OP_VAULT: a new vault proposal X-BeenThere: bitcoin-dev@lists.linuxfoundation.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: Bitcoin Protocol Discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 11 Jan 2023 06:52:39 -0000 On Tue, Jan 10, 2023 at 03:22:54PM -0500, James O'Beirne wrote: > > I don't think that makes sense? With a general scheme, you'd only be > > bloating the witness data (perhaps including the witness script) not > > the scriptPubKey? > Sorry, sloppy language on my part. To be charitable, I'm talking about > the "figurative sPK," which of course these days lives in the witness > for script-path-ish spends. Maybe the witness discount means that > "complicated" scripts aren't as big a deal, depending on the actual > difference in raw script size. Sure. I think there's three aspects that matter for the witness script: 1) it shouldn't be long/costly to do things that are common and easy: if you can express "OP_VAULT" in ~70 bytes, you shouldn't have to spend 1000 bytes to do so; if it can be cheap to validate, you shouldn't have to pay 100x markup in fees to use it. With the exception of things that build up from basics (like CAT/CHECKSIGFROMSTACK approaches), I think this is mostly fine though. 2) once someone figures out a design, it should be easy to reuse; but I think that's not a big deal: you just write up a spec for your script, and people use that in their different wallet software, much like the specialised scripts for lightning HTLCs 3) primitives should be designed to be easy to safely build on and scripts should be as easy as possible to analyse once written; ie, we want things more like miniscript than "The story of Mel, a Real Programmer" With some caveats (like that using the cold wallet xpub to scan the blockchain before you've frozen all your funds is dangerous), OP_VAULT seems really good on all those fronts, of course. > > I think it might be better to use a pay-to-contract construction for > > the recovery path, rather than an empty witness. > So I guess the one advantage that what you're proposing has over just > using a recovery-path key signature is that it's all derivable from your > cold privkey; you don't have to worry about accidentally losing the > recovery-path key. > Of course you're still vulnerable to spurious sweeps if the > sha256(secret) value gets found out, which presumably you'd want in an > accessible cache to avoid touching the cold secret every time you want > to sweep. Sure, "sha256(secret)" itself needs to be semi-secret -- it allows anyone who knows it to freeze your funds, even if it doesn't allow anyone to steal them. You could presumably do all the usual things to protect that secret: split it up with secret sharing; put it in a hardware wallet; keep it offline; etc. > 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? ] "if ] is 32 bytes, treat it as it's currently used. If it's ] 33 bytes, use the first byte as a parameter for how to interpret it." To ] start with, an extra prefix byte of 0x00 could mean "require a witness ] satisfying the scriptPubKey that hashes to the remaining 32 bytes" in the ] same way we do the unvault signing. I don't think 33 bytes would be enough? There isn't really a way to commit to the recovery destination within the script? So I think you'd need "<32 byte recovery-path-hash>" Aside from that, my opinion's one/all of: a) sounds fine b) maybe you could just always have it include a scriptPubKey? for the times when you just want "reveal the cold wallet preimage" just have the scriptPubKey be the single byte "OP_TRUE"; for the times when you it to be "reveal random preimage" you'd have it be the 22 byte "HASH160 EQUAL"? c) delegation to a script is a great idea, that's come up multiple times (OP_EVAL, BIP117, graftroot) -- it's probably better to have it available as a generic feature, than bolted on to particular features > > I think a generic OP_UNVAULT can be used to simulate OP_CTV: replace > > " OP_CTV" with "<000..0> 0 OP_UNVAULT". > Yup, that's an inefficient way of emulating CTV. Sure; I think it's only interesting in establishing how powerful the construct is in the abstract. It's not an exact match for CTV since it hashes some things differently. I don't really think it's necessarily that inefficient fwiw; "0 SHA256 0 UNVAULT" is only 3 more bytes than " CTV", could give you an unspendable recovery path, provided UNVAULT wants either a BIP341 tagged hash (which is what the implementation does, by the looks), or a HASH256 for the recovery path. (Again, this assumes UNVAULT is available in script, and isn't just a special scriptPubKey type) > > I think there's maybe a cleverer way of batching / generalising > > checking that input/output amounts match. > > [...] > > * set C = the sum of each output that has a vault tag with > > #recovery=X > This would also need to take into account that the s are > compatible, but your point is well taken. Sure, I guess output/UNVAULT delay >= input/VAULT delay would be sufficient for that. I guess having all that stuff exposed in the scriptPubKey would be slightly annoying for griefing -- you set your wallet delay to be 1008 blocks, and someone sends to your vault with a 1007 block delay, or a 6 block delay: does your wallet notice the tx? if it does, what do you do with those funds? Maybe that would be a(nother) good reason to hide the OP_VAULT side of things in taproot (or p2wsh): then you just have a (shorter) taproot sPK that encodes both things, and people normally don't even have enough information to correctly tweak your sPK to have a different delay. > I can see what you're saying about having more generic "group amounts by > compatible vault params, and then compare to similarly grouped outputs," I mostly wrote that up because that's what I imagined your batching doing before I'd finished reading... A big disadvantage of that approach compared to yours is that you have to analyse a potentially arbitrarily large transaction as a whole while validating each input -- this input uses recovery key XXX which output's match; this input uses recovery key YYY; oh, this one uses XXX again; etc. With your approach, you only have to look at particular outputs. An advantage of that extra complexity is that you could combine operations from multiple different vaults into a single transaction, potentially along with fees or a coinjoin or whatever else. Maybe that would be interesting if this were something you could code in script via some generic opcodes; but here it would be extra complexity in consensus code, and it doesn't seem like a good match for OP_VAULT's design parameters. Cheers, aj