SIGHASH_GROUP vs Ephemeral anchors

SIGHASH_GROUP vs Ephemeral anchors
2023-01-12  2:06 ` Antoine Riard
  
From: Anthony Towns @ 2023-01-11  8:00 UTC (permalink / raw)
  To: Bitcoin Protocol Discussion

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



 permalink raw reply	[|nested]
2023-01-11  8:00 [bitcoin-dev] SIGHASH_GROUP vs Ephemeral anchors Anthony Towns

  
From: Antoine Riard @ 2023-01-12  2:06 UTC ( / )
  To: Anthony Towns, Bitcoin Protocol Discussion



Hi AJ,

> 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.

To precise more one of the use-case for SIGHASH_GROUP, you can have one LSP
with hundreds of Lightning channels opened with as much (mobile)
counterparties, of which the majority are probably offline most of their
times to aggregate the LN commitment transaction in a single bundle with
one pair of input/output. Aggregation should be non-interactive,
fee-savings from a L2 viewpoint would be all the saved anchor outputs,
blockspace-savings from a full-node viewpoint would be those same anchor
outputs.

> 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}

I think here a SIGHASH_GROUP-like would be: {i1, i2, i3, i4 i.f, o1, o2,
o3, o.f}. Where `i.f` is the input for feeding external value in the
bundle, `o.f` the output for output fees.

Compared to anchors, I believe you're saving 1-input/2-outputs of fees for
a construction expressing the same semantics ?

> However, it's likely the only benefit to using SIGHASH_ALL there is to
reduce
> malleability risk, and ephemeral anchors probably already achieve that.

If my understanding is correct with ephemeral anchors, we allow third-party
malleability (i.e a entity not owning any key in the funding channel
output) of the chain of transactions. If nversion=3 is robust against
"classic" pinnings at the commitment
transaction-level by a counterparty (scenario 2b in [0] iirc), it should
hold against external parties. However, it might introduce issues, where a
common CPFP is conflicted on one of its input, e.g in the example above
eph1 is replaced by  malicious better fee/feerate eph1', cancelling {i4,
o2, o3} fee-bumping.

[0]
https://lists.linuxfoundation.org/pipermail/lightning-dev/2020-June/002758.html

> 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

See point above, as providing fees for multiple input/output groups *might*
be unsafe, so I think this is a limited downside anyway.

> (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)

From my memory, I think this is correct -- Though now you're introducing
the issue where one might be able to downgrade the fee content of your
miner mempool in a period of emptiness. However, I believe if we move to a
higher fee rate only, it might make
the cost of the replacement issue above.

> 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.

Yes I think the only clear benefit of SIGHASH_GROUP over ephemeral anchors
is the fee/blockspace savings for some types of LN deployments. Comes at
far higher engineering resources as it's a consensus change rather than
relay policy only. However, in the future, if it is combined with other
changes like malleability of the output amounts, it could unlock use-cases
like "dynamic value reallocation" from unknown initial sending.

Best,
Antoine

Le mer. 11 janv. 2023 à 03:00, Anthony Towns via bitcoin-dev <
bitcoin-dev@lists•linuxfoundation.org> a écrit :

> 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
>
> _______________________________________________
> bitcoin-dev mailing list
> bitcoin-dev@lists•linuxfoundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/bitcoin-dev
>