public inbox for bitcoindev@googlegroups.com
 help / color / mirror / Atom feed
From: Anthony Towns <aj@erisian•com.au>
To: Bitcoin Protocol Discussion <bitcoin-dev@lists•linuxfoundation.org>
Subject: [bitcoin-dev] SIGHASH_GROUP vs Ephemeral anchors
Date: Wed, 11 Jan 2023 18:00:14 +1000	[thread overview]
Message-ID: <Y75sjuTjsJNT6M7I@erisian.com.au> (raw)

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



             reply	other threads:[~2023-01-11  8:00 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-01-11  8:00 Anthony Towns [this message]
2023-01-12  2:06 ` Antoine Riard

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=Y75sjuTjsJNT6M7I@erisian.com.au \
    --to=aj@erisian$(echo .)com.au \
    --cc=bitcoin-dev@lists$(echo .)linuxfoundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox