Return-Path: Received: from smtp1.osuosl.org (smtp1.osuosl.org [IPv6:2605:bc80:3010::138]) by lists.linuxfoundation.org (Postfix) with ESMTP id 44FB5C000B for ; Fri, 28 Jan 2022 01:34:47 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp1.osuosl.org (Postfix) with ESMTP id 29CCD84C3F for ; Fri, 28 Jan 2022 01:34:47 +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 P7KtHKJvK1gC for ; Fri, 28 Jan 2022 01:34:46 +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 DB29884C34 for ; Fri, 28 Jan 2022 01:34:45 +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 1nDG9w-0004nA-Gq; Fri, 28 Jan 2022 11:34:42 +1000 Received: by sapphire.erisian.com.au (sSMTP sendmail emulation); Fri, 28 Jan 2022 11:34:36 +1000 Date: Fri, 28 Jan 2022 11:34:36 +1000 From: Anthony Towns To: Russell O'Connor , Bitcoin Protocol Discussion Message-ID: <20220128013436.GA2939@erisian.com.au> References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.10.1 (2018-07-13) X-Spam-Score-int: -18 X-Spam-Bar: - Subject: Re: [bitcoin-dev] TXHASH + CHECKSIGFROMSTACKVERIFY in lieu of CTV and ANYPREVOUT 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: Fri, 28 Jan 2022 01:34:47 -0000 On Wed, Jan 26, 2022 at 12:20:10PM -0500, Russell O'Connor via bitcoin-dev wrote: > Recapping the relationship between CTV and ANYPREVOUT:: > While this is a pretty neat feature, > something that ANYPREVOUT cannot mimic, the main application for it is > listed as using congestion control to fund lightning channels, fixing their > TXIDs in advance of them being placed on chain. However, if ANYPREVOUT > were used to mimic CTV, then likely it would be eltoo channels that would > be funded, and it isn't necessary to know the TXIDs of eltoo channels in > advance in order to use them. Even if they weren't eltoo channels, they could be updated lightning penalty channels signed with APO signatures so that the txid wasn't crucial. So I don't think this would require all the work to update to eltoo just to have this feature, if APO were available without CTV per se. > An Alternative Proposal:: > ... > For similar reasons, TXHASH is not amenable to extending the set of txflags > at a later date. > I believe the difficulties with upgrading TXHASH can be mitigated by > designing a robust set of TXHASH flags from the start. For example having > bits to control whether [...] I don't think that's really feasible -- eg, what you propose don't cover SIGHASH_GROUP: https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-July/019243.html > That all said, even if other txhash flag modes are needed in the future, > adding TXHASH2 always remains an option. I think baking this in from day 0 might be better: make TXHASH be a multibyte opcode, so that when you decode "0xBB" on the stack, you also decode a serialize.h:VarInt as the version number. Version 0 (0xBB00) gives hashes corresponding to bip342, version 1 (0xBB01) gives hashes corresponding to bip118 (anyprevout), anything else remains as OP_SUCCESS behaviour, and you retain a pretty compact encoding even if we somehow eventually end up needing hundreds or thousands of different TXHASH versions. Because the version here is part of the opcode rather than pulled from the stack, I think this preserves any benefits related to composition or analysis, but is otherwise still pretty general. I'm imagining that the idea would be to be consistent between CHECKSIG key versions and TXHASH versions. So I think just designing it this way means TXHASH *would* be "amenable to extending the set of txflags at a later date." > ' CHECKSIGVERIFY can be simulated by ' TXHASH CHECKSIGFROMSTACKVERIFY'. I don't think that's quite right. BIP 118 anyprevout is done by taking the pubkey "P", marking it as "APO-capable" (by prefixing it with 0x01), and then getting a sighash and sig from the witness. Doing the same with TXHASH/CSFSV would just be replacing " CHECKSIGVERIFY" with "TXHASH

CSFSV" with the witness providing both the signature and txhash flag, just as separate elements rather than concatenated. (The "APO-capable" part is implicit in the "TXHASH" opcode) > In addition to the CTV and ANYPREVOUT applications, with > CHECKSIGFROMSTACKVERIFY we can verify signatures on arbitrary messages > signed by oracles for oracle applications. This is where we see the > benefit of decomposing operations into primitive pieces. By giving users > the ability to program their own use cases from components, we get more > applications out of fewer op codes! While I see the appeal of this from a language design perspective; I'm not sure it's really the goal we want. When I look at bitcoin's existing script, I see a lot of basic opcodes to do simple arithmetic and manipulate the stack in various ways, but the opcodes that are actually useful are more "do everything at once" things like check(multi)sig or sha256. It seems like what's most useful on the blockchain is a higher level language, rather than more of blockchain assembly language made up of small generic pieces. I guess "program their own use cases from components" seems to be coming pretty close to "write your own crypto algorithms" here... I'm not really sure what the dividing line there is, or even which side TXHASH would be on. I'm not even totally convinced that the "high level language" should be describing what consensus provides rather than some layer on top that people compile (a la miniscript). Just trying to put into words why I'm not 100% comfortable with the principle per se. One thing I've thought about is an opcode like "POP_SIGDATA" which would populate a new "register" called "sigdata", which would then be added to the message being signed. That's a generalisation of tapscript's behaviour for "codeseparator" essentially. That is, x POP_SIGDATA p CHECKSIG would be roughly the same as TXHASH x CAT SHA256SUM p CHECKSIGFROMSTACK I think "POP_SIGDATA" makes for an interesting counterpart to "PUSH_ANNEXITEM" -- we implicitly commit to all the annex items in signatures, so PUSH_ANNEXITEM would give a way to use signed data that's given verbatim in the witness in further calculations; but POP_SIGDATA would do the opposite, allowing you to require data that's the result of calculations and not explicitly spelled out in the witness be signed. You could implement CHECKSIGFROMSTACK using that, ie: sig x p CHECKSIGFROMSTACK is the same as: sig' x POP_SIGDATA p CHECKSIG provided sig' applies a new "SIGHASH_NO_TX_DATA_AT_ALL" sighash flag to "sig" that just does what it says. You could likewise implement CTV as an extension to CHECKSIG -- define a new pubkey type that's just the constant "0x0000" and have the "signature" be valid if it's an exact match for the corresponding message hash. You could bump the key to "0x0001" to introduce new hashes; and include a "sighash" with the "signature" as well perhaps. (Apart from reusing an existing opcode instead of introducing a new one, and costing some additional witnss bytes, I don't think that makes much difference eithr way) I think the key tradeoff between "x POP_SIGDATA p CHECKSIG" and "CHECKSIGFROMSTACK" isn't so much that one approach is a couple of bytes more or less or one claims two opcodes vs just one for the other, but whether it's common to want to commit to some extra random data alongside the tx itself, and in the cases where that's desirable, if we can have a standard way of constructing that and assume everyone will use it; or if it's important that wallets can design their own way of committing to the extra data more manually, because it's impotant to support different approaches in different circumstances. If we had CTV, POP_SIGDATA, and SIGHASH_NO_TX_DATA_AT_ALL but no OP_CAT, are there any practical use cases that wouldn't be covered that having TXHASH/CAT/CHECKSIGFROMSTACK instead would allow? Or where those would be significantly more convenient/efficient? (Assume "y x POP_SIGDATA POP_SIGDATA p CHECKSIGVERIFY q CHECKSIG" commits to a vector [x,y] via p but does not commit to either via q so that there's some "CAT"-like behaviour available) I think a difference between "TXHASH EQUALVERIFY" and "CTV" is that because the idea for TXHASH is to be compatible with CHECKSIGFROMSTACK, then the messages it hashes should be distinct from anything else you might ever sign. But for CTV that doesn't matter, because there's no signature to be reused; so as a result, how the message is hashed can be simpler, and that in turn may make it easier to do the "subtractive covenants" and similar. I guess I don't find that super important -- if you're manually constructing covenants in script by putting together various bits of data about a tx, then I guess I think you've already lost the game, and having to have your script be a little more complicated in order to to tagged hashes and the like is no big deal. Concretely: - I think TXHASH needs to be designed to be upgradable; but I think that's solvable - I think it makes sense for TXHASH and CHECKSIG to be synchronised; so any message digest you can hash via txhash should be signable via CHECKSIG and vice-versa. Given that, I don't think this approach replaces APO, just adds to it. - I think I'd prefer having a single set of message digests shared between TXHASH and CHECKSIG, than having one set of message digests for CHECKSIG and a different set for CTV. But that's a design choice for CTV rather than an advantage of TXHASH over CTV. - I think defining some OP_NOPx in terms of TXHASH so that it can be made available without p2sh/segwit/tapscript wrapping would work fine, if that optimisation is worthwhile - Even if we favoured CTV over TXHASH for consensus implementation, I think "TXHASH" seems like a good primitive to use when talking about script language design... Cheers, aj