Return-Path: Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 43D3EC000D for ; Sat, 11 Sep 2021 03:26:54 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 2120C84B78 for ; Sat, 11 Sep 2021 03:26:54 +0000 (UTC) X-Virus-Scanned: amavisd-new at osuosl.org X-Spam-Flag: NO X-Spam-Score: -1.499 X-Spam-Level: X-Spam-Status: No, score=-1.499 tagged_above=-999 required=5 tests=[BAYES_00=-1.9, KHOP_HELO_FCRDNS=0.398, SPF_HELO_NONE=0.001, SPF_NONE=0.001, UNPARSEABLE_RELAY=0.001] autolearn=no autolearn_force=no Received: from smtp1.osuosl.org ([127.0.0.1]) by localhost (smtp1.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id Wxypx42rlTYX for ; Sat, 11 Sep 2021 03:26:53 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.8.0 Received: from azure.erisian.com.au (cerulean.erisian.com.au [139.162.42.226]) by smtp1.osuosl.org (Postfix) with ESMTPS id 3C3A484B77 for ; Sat, 11 Sep 2021 03:26:53 +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 1mOtfE-0001GC-Hs; Sat, 11 Sep 2021 13:26:50 +1000 Received: by sapphire.erisian.com.au (sSMTP sendmail emulation); Sat, 11 Sep 2021 13:26:44 +1000 Date: Sat, 11 Sep 2021 13:26:44 +1000 From: Anthony Towns To: Antoine Riard Message-ID: <20210911032644.GB23578@erisian.com.au> References: <20210909064138.GA22496@erisian.com.au> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) X-Spam-Score-int: -18 X-Spam-Bar: - Cc: Bitcoin Protocol Discussion Subject: Re: [bitcoin-dev] TAPLEAF_UPDATE_VERIFY covenant opcode 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: Sat, 11 Sep 2021 03:26:54 -0000 On Fri, Sep 10, 2021 at 12:12:24AM -0400, Antoine Riard wrote: > "Talk is cheap. Show me the code" :p >     case OP_MERKLESUB: I'm not entirely clear on what your opcode there is trying to do. I think it's taking

MERKLESUB and checking that output N has the same scripts as the current input except with the current script removed, and with its internal pubkey as the current input's internal pubkey plus P. >         txTo->vout[out_pos].scriptPubKey.IsWitnessProgram(witnessversion, > witnessprogram); >         //! The committed to output must be a witness v1 program at least That would mean anyone who could do a valid spend of the tx could violate the covenant by spending to an unencumbered witness v2 output and (by collaborating with a miner) steal the funds. I don't think there's a reasonable way to have existing covenants be forward compatible with future destination addresses (beyond something like CTV that strictly hardcodes them). > One could also imagine a list of output positions to force the taproot update > on multiple outputs ("OP_MULTIMERKLESUB"). Having the output position parameter might be an interesting way to merge/split a vault/pool, but it's not clear to me how much sense it makes sense to optimise for that, rather than just doing that via the key path. For pools, you want the key path to be common anyway (for privacy and efficiency), so it shouldn't be a problem; but even for vaults, you want the cold wallet accessible enough to be useful for the case where theft is attempted, and maybe that's also accessible enough for the ocassional merge/split to keep your utxo count/sizes reasonable. > For the merkle branches extension, I was thinking of introducing a separate > OP_MERKLEADD, maybe to *add* a point to the internal pubkey group signer. If > you're only interested in leaf pruning, using OP_MERKLESUB only should save you > one byte of empty vector ? Saving a byte of witness data at the cost of specifying additional opcodes seems like optimising the wrong thing to me. > One solution I was thinking about was introducing a new tapscript version > (`TAPROOT_INTERNAL_TAPSCRIPT`) signaling that VerifyTaprootCommitment must > compute the TapTweak with a new TapTweak=(internal_pubkey || merkle_root || > parity_bit). A malicious participant wouldn't be able to interfere with the > updated internal key as it would break its own spending taproot commitment > verification ? I don't think that works, because different scripts in the same merkle tree can have different script versions, which would here indicate different parities for the same internal pub key. > > That's useless without some way of verifying that the new utxo retains > > the bitcoin that was in the old utxo, so also include a new opcode > > IN_OUT_AMOUNT that pushes two items onto the stack: the amount from this > > input's utxo, and the amount in the corresponding output, and then expect > > anyone using TLUV to use maths operators to verify that funds are being > > appropriately retained in the updated scriptPubKey. > Credit to you for the SIGHASH_GROUP design, here the code, with > SIGHASH_ANYPUBKEY/ANYAMOUNT extensions. > > I think it's achieving the same effect as IN_OUT_AMOUNT, at least for CoinPool > use-case. The IN_OUT_AMOUNT opcode lets you do maths on the values, so you can specify "hot wallets can withdraw up to X" rather than "hot wallets must withdraw exactly X". I don't think there's a way of doing that with SIGHASH_GROUP, even with a modifier like ANYPUBKEY? > (I think I could come with some use-case from lex mercatoria where if you play > out a hardship provision you want to tweak all the other provisions by a CSV > delay while conserving the rest of their policy) If you want to tweak all the scripts, I think you should be using the key path. One way you could do somthing like that without changing the scripts though, is have the timelock on most of the scripts be something like "[3 months] CSV", and have a "delay" script that doesn't require a CSV, does require a signature from someone able to authorise the delay, and requires the output to have the same scriptPubKey and amount. Then you can use that path to delay resolution by 3 months however often, even if you can't coordinate a key path spend. > > And second, it doesn't provide a way for utxos to "interact", which is > > something that is interesting for automated market makers [5], but perhaps > > only interesting for chains aiming to support multiple asset types, > > and not bitcoin directly. On the other hand, perhaps combining it with > > CTV might be enough to solve that, particularly if the hash passed to > > CTV is constructed via script/CAT/etc. > That's where SIGHASH_GROUP might be more interesting as you could generate > transaction "puzzles". > IIUC, the problem is how to have a set of ratios between x/f(x). Normal way to do it is specify a formula, eg outBTC * outUSDT >= inBTC * inUSDT that's a constant product market maker without a profit margin. There's lots of research in the ethereum world about doing these things, and bitmatrix is trying to do it on liquid. It's not clear to me if there's anywhere in bitcoin per se that it would make sense. Then your relative balances of each token imply a price, and traders will rebalance anytime that price is out of whack with the rest of the market. You can tweak the formula so that you make a profit, which also ends up meaning the fund pool becomes more liquid overtime. But that means that you want to cope with 100 BTC and 5M USDT at $50k, but also 200 BTC and 10M USDT at $50k, and many values in between. So I don't think: > The maker generates a Taproot tree where each leaf is committing to a different > "strike price". really works that well. One irritating thing I realised while reading Jeremy's mail is that CAT "TapBranch" SHA256 DUP CAT SWAP CAT SHA256 doesn't actually work -- the first CAT needs to sort the two branches first, and "LESSTHAN" etc want to compare values numerically rather than lexically. So maybe it would make more sense to introduce an opcode that builds a merkle root from tagged hashes directly, rather than one that lets you compare to 32B strings so that you can do the TapBranch logic manually. Cheers, aj