Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zero-fee commitments using v3 transactions (feature 40/41) #1228

Draft
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

t-bast
Copy link
Collaborator

@t-bast t-bast commented Feb 14, 2025

We introduce a new channel_type that leverages v3 transactions, pay-to-anchor outputs and ephemeral dust. With this change, commitment transactions don't pay any mining fee, which gets rid of update_fee and all of the related channel reserve issues. It also gets rid of the undesired channel force-closes that happen when the mempool feerate spikes and channel participants disagree on what feerate to use, which has been a major source of wasted on-chain space.

It also offers better protection against pinning attacks (thanks to package relay) and reduces the on-chain footprint compared to anchor output channels. We use a single anchor output whose amount is the sum of all trimmed outputs (and may thus be 0 sat). We remove the 1-block relative delay used by anchor output channels: this allows using our channel outputs (main balance or pending HTLCs) to CPFP a remote commitment transaction (no need to add external inputs).

v3 transactions and pay-to-anchor outputs have been standard since the release of Bitcoin Core v28.0. Ephemeral dust will become standard in the Bitcoin Core v29.0 release.

TODO:

  • add Bolt 3 test vectors for this new commitment format
  • verify v3 transaction limits and the maximum number of allowed HTLCs

We introduce a new `channel_type` that leverages v3 transactions,
pay-to-anchor outputs and ephemeral dust. With this change, commitment
transactions don't pay any mining fee, which gets rid of `update_fee`
and all of the related channel reserve issues. It also gets rid of the
undesired channel force-closes that happen when the mempool feerate
spikes and channel participants disagree on what feerate to use, which
has been a major source of wasted on-chain space.

It also offers better protection against pinning attacks and reduces the
on-chain footprint compared to anchor output channels. We use a single
anchor output whose amount is the sum of all trimmed outputs (and may
thus be `0 sat`). We remove the 1-block relative delay used by anchor
output channels: this allows using our channel outputs (main balance or
pending HTLCs) to CPFP a remote commitment transaction (no need to add
external inputs).

v3 transactions and pay-to-anchor outputs have been standard since the
release of Bitcoin Core v28.0. Ephemeral dust will become standard in
the Bitcoin Core v29.0 release.
05-onchain.md Outdated
Comment on lines 103 to 104
5. _shared ephemeral anchor_: one output paying to the *local* or *remote*
node's funding_pubkey.
Copy link
Contributor

@esneider esneider Feb 15, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The description doesn't seem to match the fact that the shared anchor is using P2A.

Also, the "ephemeral" in the output name isn't used anywhere else. It may make sense to use just "shared anchor" for consistency.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, this isn't consistent with the rest of the spec, I'll clean that up.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 4de2873

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This wasn't fully addressed. It still refers to a keyed anchor instead of P2A.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Damn, thanks 🦅 👁️, done in b0b1fa4

@saubyk
Copy link

saubyk commented Feb 17, 2025

We use a single anchor output whose amount is the sum of all trimmed outputs (and may thus be 0 sat).

Hi @t-bast can you elaborate this a bit?

@saubyk
Copy link

saubyk commented Feb 17, 2025

We use a single anchor output whose amount is the sum of all trimmed outputs (and may thus be 0 sat).

Hi @t-bast can you elaborate this a bit?

Never mind. This delving post has the details, makes for a good supplemental reading:
https://delvingbitcoin.org/t/which-ephemeral-anchor-script-should-lightning-use/1412

* locktime: `0` for HTLC-success, `cltv_expiry` for HTLC-timeout
* txin count: 1
* `txin[0]` outpoint: `txid` of the commitment transaction and `output_index` of the matching HTLC output for the HTLC transaction
* `txin[0]` sequence: `0` (set to `1` for `option_anchors`)
* `txin[0]` sequence: `1` for `option_anchors`, `0xFFFFFFFD` for `zero_fee_commitments`, `0` otherwise
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the difference between using 0 and 0xFFFFFFFD here?
Neither imposes a bip68 timelock, and both explicitly opt-in to bip125 RBF.

I am just trying to understand the motivation for why the old-style txs were using 0 and why the newer style proposed here uses a different value.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about that change at all, this is up for bikeshedding! We were previously using 0 just because we hadn't thought much about it, and 0 is a nice default value. But then we noticed that most wallets by default set nSequence to 0xFFFFFFFD, so we updated our closing transactions to use 0xFFFFFFFD to benefit from a larger anonymity set (in #1205). I figured that since we're changing the transaction format, it would be a good opportunity to be consistent and use 0xFFFFFFFD instead of 0 wherever we can. But HTLC transactions will always be recognized as HTLC transactions because of their unique script: we don't benefit from any anonymity set improvement, so maybe this is unnecessary?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, so there is no interesting technical difference I missed. Thanks.
I understand the potential privacy aspect, but I don't think it's worth the bikeshedding in this case, so feel free to mark this as resolved :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect anyone using TRUC tx will keep this 0 since it's not a meaningful signal, especially post-fullrbf world?

I don't think we have enough data to say exactly.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, it's hard to figure out, I'll ask other implementers how they feel, but we most likely will just keep this to 0 like it is today (when there is no good reason to change, let's keep the existing stuff).

@t-bast
Copy link
Collaborator Author

t-bast commented Feb 19, 2025

Hi @t-bast can you elaborate this a bit?

This will become more obvious when I add the test vectors! It is also already defined in Bolt 3, if the paragraph for this is unclear please put a comment on it with a suggestion on how I could make it clearer.

Copy link
Contributor

@morehouse morehouse left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approach ACK.

Really eager to see this get implemented and used across the network. Also hope we can follow up soon with the changes needed to fix HTLC pinning.

- `max_accepted_htlcs` is greater than 483.
- it considers `feerate_per_kw` too small for timely processing or unreasonably large.
- `channel_type` includes `zero_fee_commitments` and:
- `max_accepted_htlcs` is greater than 283.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

283 is more than 2x what I would expect.

Back-of-the-envelope:

TRUC limit = 40,000 wu
zero-fee commit weight ~= 780 + 172 * num_htlcs

780 + 172 * max_num_htlcs = 40,000
max_num_htlcs = 228
max_accepted_htlcs = 228 / 2 = 114

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're most likely right! I wanted to wait for my prototype implementation to test against bitcoind to make sure the number matches what is supported, I will update once it's verified!

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed this to 114 in 4de2873 while we wait for an official test against bitcoind.

The amounts for each output MUST be rounded down to whole satoshis. If this amount, minus the fees for the HTLC transaction, is less than the `dust_limit_satoshis` set by the owner of the commitment transaction, the output MUST NOT be produced (thus the funds add to fees).
The amounts for each output MUST be rounded down to whole satoshis.
If this amount, minus the fees for the HTLC transaction, is less than the `dust_limit_satoshis` set by the owner of the commitment transaction, the output MUST NOT be produced.
If `zero_fee_commitments` is used, this amount is added to the `shared_anchor`, otherwise it adds to on-chain fees.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
If `zero_fee_commitments` is used, this amount is added to the `shared_anchor`, otherwise it adds to on-chain fees.
In that case, the amount is added to the `shared_anchor` if `zero_fee_commitments` is used, otherwise the amount is added to on-chain fees.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 4de2873

05-onchain.md Outdated
Comment on lines 153 to 156
- MUST spend any `to_local_anchor` or `shared_anchor` output, providing sufficient fees
as incentive to include the commitment transaction in a block. When using `nVersion=2`,
special care must be taken when spending to a third-party, because this re-introduces
the vulnerability that was addressed by adding the CSV delay to the non-anchor outputs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bringing up nVersion=2 here is a bit confusing and may give the reader the idea they can set nVersion=3 for to_local_anchor spends to avoid this issue (which won't relay).

Suggested change
- MUST spend any `to_local_anchor` or `shared_anchor` output, providing sufficient fees
as incentive to include the commitment transaction in a block. When using `nVersion=2`,
special care must be taken when spending to a third-party, because this re-introduces
the vulnerability that was addressed by adding the CSV delay to the non-anchor outputs.
- MUST spend any `to_local_anchor` or `shared_anchor` output, providing sufficient fees
as incentive to include the commitment transaction in a block. For `to_local_anchor`,
special care must be taken when spending to a third-party, because this re-introduces
the pinning vulnerability that was addressed by adding the CSV delay to the non-anchor outputs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 4de2873

05-onchain.md Outdated
@@ -515,7 +517,7 @@ A local node:
using the revocation private key.
- SHOULD extract the payment preimage from the transaction input witness, if
it's not already known.
- if `option_anchors` applies:
- if `SIGHASH_SINGLE|SIGHASH_ANYONECANPAY` is used for HTLC transactions:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- if `SIGHASH_SINGLE|SIGHASH_ANYONECANPAY` is used for HTLC transactions:
- if `SIGHASH_SINGLE|SIGHASH_ANYONECANPAY` is used for HTLC transactions (i.e. `option_anchors` or `zero_fee_commitments` applies):

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 4de2873

05-onchain.md Outdated
Comment on lines 537 to 538
Note: when `SIGHASH_SINGLE|SIGHASH_ANYONECANPAY` is used for HTLC transactions,
the cheating node can pin spends of its HTLC-timeout/HTLC-success outputs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Note: when `SIGHASH_SINGLE|SIGHASH_ANYONECANPAY` is used for HTLC transactions,
the cheating node can pin spends of its HTLC-timeout/HTLC-success outputs.
Note: when `SIGHASH_SINGLE|SIGHASH_ANYONECANPAY` is used for HTLC transactions (i.e. `option_anchors` or `zero_fee_commitments`),
the cheating node can pin spends of its HTLC-timeout/HTLC-success outputs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 4de2873

05-onchain.md Outdated
Comment on lines 593 to 595
If `SIGHASH_ALL` is used for HTLC transactions, then HTLC-timeout and
HTLC-success transactions are complete transactions with (hopefully!)
reasonable fees and must be used directly.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section describes when to use SIGHASH_ALL vs SIGHASH_SINGLE|SIGHASH_ANYONECANPAY. So we shouldn't assume the reader already knows which sighashes to use for each channel type.

Suggested change
If `SIGHASH_ALL` is used for HTLC transactions, then HTLC-timeout and
HTLC-success transactions are complete transactions with (hopefully!)
reasonable fees and must be used directly.
If `option_anchors` and `zero_fee_commitments` do not apply, then HTLC-timeout and
HTLC-success transactions are signed with SIGHASH_ALL and are complete transactions with (hopefully!)
reasonable fees and must be used directly.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 4de2873

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants