Return-Path: Received: from smtp2.osuosl.org (smtp2.osuosl.org [140.211.166.133]) by lists.linuxfoundation.org (Postfix) with ESMTP id 932A9C002D for ; Wed, 11 Jan 2023 08:00:23 +0000 (UTC) Received: from localhost (localhost [127.0.0.1]) by smtp2.osuosl.org (Postfix) with ESMTP id 6EF07404B2 for ; Wed, 11 Jan 2023 08:00:23 +0000 (UTC) DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 6EF07404B2 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 smtp2.osuosl.org ([127.0.0.1]) by localhost (smtp2.osuosl.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id yx4RkxoRih7x for ; Wed, 11 Jan 2023 08:00:22 +0000 (UTC) X-Greylist: from auto-whitelisted by SQLgrey-1.8.0 DKIM-Filter: OpenDKIM Filter v2.11.0 smtp2.osuosl.org 47C4A408C9 Received: from azure.erisian.com.au (azure.erisian.com.au [172.104.61.193]) by smtp2.osuosl.org (Postfix) with ESMTPS id 47C4A408C9 for ; Wed, 11 Jan 2023 08:00:22 +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 1pFW1x-0001Qj-W6 for ; Wed, 11 Jan 2023 18:00:19 +1000 Received: by sapphire.erisian.com.au (sSMTP sendmail emulation); Wed, 11 Jan 2023 18:00:14 +1000 Date: Wed, 11 Jan 2023 18:00:14 +1000 From: Anthony Towns To: Bitcoin Protocol Discussion Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Subject: [bitcoin-dev] SIGHASH_GROUP vs Ephemeral anchors 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 08:00:23 -0000 Hello world, I think it's interesting to compare SIGHASH_GROUP [0] and Ephemeral anchors [1]. [0] https://lists.linuxfoundation.org/pipermail/bitcoin-dev/2021-July/019243.html [1] https://github.com/bitcoin/bitcoin/pull/26403 SIGHASH_GROUP is the idea that you provide a way for the inputs of a transaction to divide the outputs of a transaction into non-overlapping groups. So input 1 can specify "I'm starting a group of 3 outputs", input 2 can specify "I'm using the same group as the previous input", input 3 can specify "I'm starting a group of 2 outputs"; and each input can use the SIGHASH_GROUP flag to specify their signature is signing for the subgroup they've specified, rather than just a single output, or all of them. The idea behind this is that then you can use a signature to link a set of inputs and outputs via a signature in a way that's more general than SIGHASH_ANYONECANPAY (since you can have many inputs attesting to the same subset of outputs), SIGHASH_SINGLE (since you can attest to multiple outputs), and SIGHASH_ALL (since you don't have to attest to all outputs). This means that (eg) you can have a tx closing a lightning channel commit to a dozen outputs that specify where the channel's funds end up, but are also able to add additional inputs to cover fees, and additional outputs to collect the change from those fees. Ephemeral anchors, by contrast, are just a realy policy level rule that a transaction may create a single 0-value output with sPK of OP_TRUE (the "ephemeral anchor"), and that that tx won't be rejected as being dust, provided that the tx that introduces the anchor pays 0 fees (so it is not profitable to mine on its own) and that it's relayed as a package with another tx that spends that anchor. (And there are additional proposed rules beyond those) To some degree, this provides an alternative way of getting the same benefits of SIGHASH_GROUP: if you were constructing a transaction consisting of {i1,i2,i3,i4,f} -> {o1,o2,o3,c} with {i1,i2,i3} committing to {o1} and {i4} committing to {o2,o3} and f providing the fees with c collecting the change, you could instead create three transactions: {i1,i2,i3} -> {o1, eph1} {i4} -> {o2,o3, eph2} {eph1, eph2, f} -> {c} (where eph1/eph2 are ephemeral anchors) and instead of signing with SIGHASH_GROUP, you'd just sign with SIGHASH_ALL. (This is likewise similar to the "sponsored transactions" concept [2], where a transaction may "sponsor" another transaction, meaning it cannot be included in a block unless the transaction it sponsors is also included in the block. Given the "txs-may-only-have-one-sponsor" rule, ephemeral anchors could be considered as "you can design a tx that always has a sponsor, or never has a sponsor") [2] https://bitcoinops.org/en/newsletters/2020/09/23/#transaction-fee-sponsorship Ephemeral anchors aren't a complete replacement for SIGHASH_GROUP -- if i1 had two signatures, one signing with SIGHASH_GROUP, but the other signing with SIGHASH_ALL, then it's difficult to duplicate that behaviour exactly with ephemeral anchors. However, it's likely the only benefit to using SIGHASH_ALL there is to reduce malleability risk, and ephemeral anchors probably already achieve that. Additionally, if the value of i1+i2+i3 was less than o1 or i4 was less than o2+o3, then the introduction of f is too late to compensate for that with ephemeral anchors, but would have been fine with SIGHASH_GROUP. The detailed proposed rules for ephemeral anchors as they stand are, I think: > A transaction with one or more CScript([OP_2]) output MUST: > eph.1) Be 0-fee > eph.2) Have [the ephemeral anchor output] spent in the same memppol relay > package > eph.3) Be nversion==3 > eph.4) Must not have more than one [such output] - https://github.com/bitcoin/bitcoin/pull/26403/commits/431a5e3e0376d8bf55563a0168e79dd73b04a1f8 And implied by "nversion==3": > v3.1) A V3 transaction can be replaced, [...] > v3.2) Any descendant of an unconfirmed V3 transaction must also be V3. > v3.3) A V3 transaction's unconfirmed ancestors must all be V3. > v3.4) A V3 transaction cannot have more than 1 descendant. > v3.5) A V3 transaction that has an unconfirmed V3 ancestor cannot be > larger than 1000 virtual bytes. > v3.4b) A V3 transaction cannot have more than 1 ancestor - https://github.com/bitcoin/bitcoin/blob/0c089a327a70d16f824b1b4dfd029d260cc43f09/doc/policy/version3_transactions.md The v3.4b rule unfortunately prevents ephemeral anchors from being used to provide fees for multiple input/output groups in the way I suggest above. That's intended to prevent attaching large ancestors to a package, allowing the descendent to be high fee / low feerate, thus preventing that descendant from both being replaced (due to requiring a higher absolute fee) and mined (due to having a low fee rate). (I suspect the only way to remove that restriction without reinstating the pinning vector is to allow replacements that have a higher fee rate, even though they have a lower absolute fee) Anyway, in theory, I think ephemeral anchors get most of the potential benefits of SIGHASH_GROUP, particularly if the (v3.4b) rule can be removed or loosened somehow. And it's obviously much less costly to implement: it's relay policy only, rather than a consensus change; and it only operates at the transaction level, so we don't have to start worrying about pinning of inputs vs whole transactions. Cheers, aj