From ca94c537224c69b14de7ee483aca101f248f5beb Mon Sep 17 00:00:00 2001 From: Antoine Riard Date: Sun, 22 Aug 2021 18:16:23 -0400 Subject: [PATCH 1/4] Bound exposure to trimmed in-flight HTLCs --- 02-peer-protocol.md | 50 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/02-peer-protocol.md b/02-peer-protocol.md index f61bd3cca..7b51646c4 100644 --- a/02-peer-protocol.md +++ b/02-peer-protocol.md @@ -797,6 +797,56 @@ A fulfilling node: transaction, AND is past this fulfillment deadline: - MUST fail the channel. +### Bounding exposure to trimmed in-flight HTLCs: `max_dust_htlc_exposure_msat` + +When an HTLC in a channel is below the "trimmed" threshold in [BOLT3 #3](03-transactions.md), +the HTLC is not claimable on-chain, instead being turned into additional miner +fees if either party unilaterally closes the channel. Because the threshold is +per-HTLC, the total exposure to such HTLCs may be substantial if there are many +dust HTLCs present when the channel is force-closed. + +This can be exploited in griefing attacks or even in miner-extractable-value attacks, +if the malicious entity avails [mining capabilities](https://lists.linuxfoundation.org/pipermail/lightning-dev/2020-May/002714.html). + +The total exposure is given by the following back-of-the-envelope computation: + + counterparty's `max_accepted_htlcs` * (`HTLC-success-kiloweight` * opener's `feerate_per_kw` + counterparty's `dust_limit_satoshis`) + + holder's `max_accepted_htlcs` * (`HTLC-timeout-kiloweight` * opener's `feerate_per_kw` + counterparty's `dust_limit_satoshis`) + + +To mitigate this scenario, a `max_dust_htlc_exposure_msat` can be applied at +HTLC sending, forwarding and receiving. + +A node: + - upon an incoming HTLC: + - if the HTLC's `amount_msat` is inferior to the counterparty's `dust_limit_satoshis` plus the HTLC-timeout fee at the `feerate_per_kw`: + - if the `amount_msat` plus the dust balance on counterparty transaction is superior to `max_dust_htlc_exposure_msat`: + - SHOULD fail this HTLC once it's committed + - SHOULD NOT reveal a preimage for this HTLC + - if the HTLC's `amount_msat` is inferior to the holder's `dust_limit_satoshis` plus the HTLC-success fee at the `feerate_per_kw`: + - if the `amount_msat` plus the dust balance on holder transaction is superior to `max_dust_htlc_exposure_msat`: + - SHOULD fail this HTLC once it's committed + - SHOULD NOT reveal a preimage for this HTLC + - upon an outgoing HTLC: + - if the HTLC's `amount_msat` is inferior the counterparty's `dust_limit_satoshis` plus the HTLC-success fee at the `feerate_per_kw`: + - if the `amount_msat` plus the dust balance on counterparty transaction is superior to `max_dust_htlc_exposure_msat`: + - SHOULD NOT send this HTLC + - SHOULD fail this HTLC if it's forwarded + - if the HTLC's `amount_msat` is inferior to the holder's `dust_limit_satoshis` plus the HTLC-timeout fee at the `feerate_per_kw`: + - if the `amount_msat` plus the dust balance on holder transaction is superior to `max_dust_htlc_exposure_msat`: + - SHOULD NOT send this HTLC + - SHOULD fail this HTLC if it's forwarded + +For pre-`option_anchors_zero_fee_htlc` channels, the second-stage HTLC transaction +fee is function of the negotiated `feerate_per_kw`. To avoid a node being +significantly more exposed to trimmed balance in case of feerate increases when +several HTLCs are pending which are near the dust limit, it is recommended to +calculate that `feerate_per_kw` with some buffer. + +The `max_dust_htlc_exposure_msat` is an upper bound on the trimmed balance from +dust exposure. The exact value is left as a matter of node policy, as what qualifies +as a notable loss is devolved to the operator subjectivity. + ### Adding an HTLC: `update_add_htlc` Either node can send `update_add_htlc` to offer an HTLC to the other, From 261a2a00b80089df0a7c2df630969725d72fc28b Mon Sep 17 00:00:00 2001 From: Antoine Riard Date: Sun, 22 Aug 2021 18:40:57 -0400 Subject: [PATCH 2/4] Reject update_fee beyond max_dust_htlc_exposure_msat --- 02-peer-protocol.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/02-peer-protocol.md b/02-peer-protocol.md index 7b51646c4..ca96f506c 100644 --- a/02-peer-protocol.md +++ b/02-peer-protocol.md @@ -1168,6 +1168,15 @@ The node _responsible_ for paying the Bitcoin fee: The node _not responsible_ for paying the Bitcoin fee: - MUST NOT send `update_fee`. +A sending node: + - if the `update_fee` is above the `feerate_per_kw`: + - if the dust balance on counterparty transaction at the current `feerate_per_kw` is superior to `max_dust_htlc_exposure_msat`: + - MAY NOT send `update_fee` + - MAY fail the channel + - if the dust balance on holder transaction at the current `feerate_per_kw` is superior to `max_dust_htlc_exposure_msat`: + - MAY NOT send `update_fee` + - MAY fail the channel + A receiving node: - if the `update_fee` is too low for timely processing, OR is unreasonably large: - SHOULD fail the channel. @@ -1177,6 +1186,18 @@ A receiving node: current commitment transaction: - SHOULD fail the channel, - but MAY delay this check until the `update_fee` is committed. + - if the `update_fee` is above the `feerate_per_kw`: + - if the dust balance on counterparty transaction at the current `feerate_per_kw` is superior to `max_dust_htlc_exposure_msat`: + - MAY fail the channel + - if the dust balance on holder transaction at the current `feerate_per_kw` is superior to `max_dust_htlc_exposure_msat`: + - MAY fail the channel + +There is a risk of triggering a third-party channel closure in case of +high-fee spikes by forwarding many trimmed HTLCs on this channel and waiting +for an automatic `update_fee` provoking an unilateral close. For this reason, +closing the channel in case of `update_fee` overflowing the +`max_dust_htlc_exposure_msat` is deferred to the node operator, where it could +be evaluated in function of the channel trust. #### Rationale From 5fb0b5ce66e5c6a20ea7a01db942dcc7f24ee1c8 Mon Sep 17 00:00:00 2001 From: t-bast Date: Mon, 10 Oct 2022 18:26:20 +0200 Subject: [PATCH 3/4] Updates to dust exposure spec This commit contains updates to the dust exposure threshold spec to better match the terminology of the spec: - use local/remote instead of holder/counterparty - use greater/smaller instead of superior/inferior - rephrased some sentences that were unclear --- 02-peer-protocol.md | 74 +++++++++++++++++++++------------------------ 1 file changed, 34 insertions(+), 40 deletions(-) diff --git a/02-peer-protocol.md b/02-peer-protocol.md index ca96f506c..45ab4a74c 100644 --- a/02-peer-protocol.md +++ b/02-peer-protocol.md @@ -800,52 +800,48 @@ A fulfilling node: ### Bounding exposure to trimmed in-flight HTLCs: `max_dust_htlc_exposure_msat` When an HTLC in a channel is below the "trimmed" threshold in [BOLT3 #3](03-transactions.md), -the HTLC is not claimable on-chain, instead being turned into additional miner +the HTLC cannot be claimed on-chain, instead being turned into additional miner fees if either party unilaterally closes the channel. Because the threshold is per-HTLC, the total exposure to such HTLCs may be substantial if there are many -dust HTLCs present when the channel is force-closed. +dust HTLCs committed when the channel is force-closed. This can be exploited in griefing attacks or even in miner-extractable-value attacks, -if the malicious entity avails [mining capabilities](https://lists.linuxfoundation.org/pipermail/lightning-dev/2020-May/002714.html). +if the malicious entity wins [mining capabilities](https://lists.linuxfoundation.org/pipermail/lightning-dev/2020-May/002714.html). The total exposure is given by the following back-of-the-envelope computation: - counterparty's `max_accepted_htlcs` * (`HTLC-success-kiloweight` * opener's `feerate_per_kw` + counterparty's `dust_limit_satoshis`) - + holder's `max_accepted_htlcs` * (`HTLC-timeout-kiloweight` * opener's `feerate_per_kw` + counterparty's `dust_limit_satoshis`) + remote `max_accepted_htlcs` * (`HTLC-success-kiloweight` * `feerate_per_kw` + remote `dust_limit_satoshis`) + + local `max_accepted_htlcs` * (`HTLC-timeout-kiloweight` * `feerate_per_kw` + remote `dust_limit_satoshis`) - -To mitigate this scenario, a `max_dust_htlc_exposure_msat` can be applied at -HTLC sending, forwarding and receiving. +To mitigate this scenario, a `max_dust_htlc_exposure_msat` threshold can be +applied when sending, forwarding and receiving HTLCs. A node: - - upon an incoming HTLC: - - if the HTLC's `amount_msat` is inferior to the counterparty's `dust_limit_satoshis` plus the HTLC-timeout fee at the `feerate_per_kw`: - - if the `amount_msat` plus the dust balance on counterparty transaction is superior to `max_dust_htlc_exposure_msat`: + - when receiving an HTLC: + - if the HTLC's `amount_msat` is smaller than the remote `dust_limit_satoshis` plus the HTLC-timeout fee at `feerate_per_kw`: + - if the `amount_msat` plus the dust balance of the remote transaction is greater than `max_dust_htlc_exposure_msat`: - SHOULD fail this HTLC once it's committed - SHOULD NOT reveal a preimage for this HTLC - - if the HTLC's `amount_msat` is inferior to the holder's `dust_limit_satoshis` plus the HTLC-success fee at the `feerate_per_kw`: - - if the `amount_msat` plus the dust balance on holder transaction is superior to `max_dust_htlc_exposure_msat`: + - if the HTLC's `amount_msat` is smaller than the local `dust_limit_satoshis` plus the HTLC-success fee at `feerate_per_kw`: + - if the `amount_msat` plus the dust balance of the local transaction is greater than `max_dust_htlc_exposure_msat`: - SHOULD fail this HTLC once it's committed - SHOULD NOT reveal a preimage for this HTLC - - upon an outgoing HTLC: - - if the HTLC's `amount_msat` is inferior the counterparty's `dust_limit_satoshis` plus the HTLC-success fee at the `feerate_per_kw`: - - if the `amount_msat` plus the dust balance on counterparty transaction is superior to `max_dust_htlc_exposure_msat`: + - when offering an HTLC: + - if the HTLC's `amount_msat` is smaller than the remote `dust_limit_satoshis` plus the HTLC-success fee at `feerate_per_kw`: + - if the `amount_msat` plus the dust balance of the remote transaction is greater than `max_dust_htlc_exposure_msat`: - SHOULD NOT send this HTLC - - SHOULD fail this HTLC if it's forwarded + - SHOULD fail the corresponding incoming HTLC (if any) - if the HTLC's `amount_msat` is inferior to the holder's `dust_limit_satoshis` plus the HTLC-timeout fee at the `feerate_per_kw`: - - if the `amount_msat` plus the dust balance on holder transaction is superior to `max_dust_htlc_exposure_msat`: + - if the `amount_msat` plus the dust balance of the local transaction is greater than `max_dust_htlc_exposure_msat`: - SHOULD NOT send this HTLC - - SHOULD fail this HTLC if it's forwarded - -For pre-`option_anchors_zero_fee_htlc` channels, the second-stage HTLC transaction -fee is function of the negotiated `feerate_per_kw`. To avoid a node being -significantly more exposed to trimmed balance in case of feerate increases when -several HTLCs are pending which are near the dust limit, it is recommended to -calculate that `feerate_per_kw` with some buffer. + - SHOULD fail the corresponding incoming HTLC (if any) The `max_dust_htlc_exposure_msat` is an upper bound on the trimmed balance from -dust exposure. The exact value is left as a matter of node policy, as what qualifies -as a notable loss is devolved to the operator subjectivity. +dust exposure. The exact value used is a matter of node policy. + +For channels that don't use `option_anchors_zero_fee_htlc_tx`, an increase of +the `feerate_per_kw` may trim multiple htlcs from commitment transactions, +which could create a large increase in dust exposure. ### Adding an HTLC: `update_add_htlc` @@ -1169,11 +1165,11 @@ The node _not responsible_ for paying the Bitcoin fee: - MUST NOT send `update_fee`. A sending node: - - if the `update_fee` is above the `feerate_per_kw`: - - if the dust balance on counterparty transaction at the current `feerate_per_kw` is superior to `max_dust_htlc_exposure_msat`: + - if the `update_fee` increases `feerate_per_kw`: + - if the dust balance of the remote transaction at the updated `feerate_per_kw` is greater than `max_dust_htlc_exposure_msat`: - MAY NOT send `update_fee` - MAY fail the channel - - if the dust balance on holder transaction at the current `feerate_per_kw` is superior to `max_dust_htlc_exposure_msat`: + - if the dust balance of the local transaction at the updated `feerate_per_kw` is greater than `max_dust_htlc_exposure_msat`: - MAY NOT send `update_fee` - MAY fail the channel @@ -1186,19 +1182,12 @@ A receiving node: current commitment transaction: - SHOULD fail the channel, - but MAY delay this check until the `update_fee` is committed. - - if the `update_fee` is above the `feerate_per_kw`: - - if the dust balance on counterparty transaction at the current `feerate_per_kw` is superior to `max_dust_htlc_exposure_msat`: + - if the `update_fee` increases `feerate_per_kw`: + - if the dust balance of the remote transaction at the updated `feerate_per_kw` is greater then `max_dust_htlc_exposure_msat`: - MAY fail the channel - - if the dust balance on holder transaction at the current `feerate_per_kw` is superior to `max_dust_htlc_exposure_msat`: + - if the dust balance of the local transaction at the updated `feerate_per_kw` is greater than `max_dust_htlc_exposure_msat`: - MAY fail the channel -There is a risk of triggering a third-party channel closure in case of -high-fee spikes by forwarding many trimmed HTLCs on this channel and waiting -for an automatic `update_fee` provoking an unilateral close. For this reason, -closing the channel in case of `update_fee` overflowing the -`max_dust_htlc_exposure_msat` is deferred to the node operator, where it could -be evaluated in function of the channel trust. - #### Rationale Bitcoin fees are required for unilateral closes to be effective. @@ -1221,6 +1210,11 @@ it's simplest to only allow it to set fee levels; however, as the same fee rate applies to HTLC transactions, the receiving node must also care about the reasonableness of the fee. +If on-chain fees increase while commitments contain many HTLCs that will +be trimmed at the updated feerate, this could overflow the configured +`max_dust_htlc_exposure_msat`. Whether to close the channel preemptively +or not is left as a matter of node policy. + ## Message Retransmission Because communication transports are unreliable, and may need to be From 77053564e66f83d47813d82de39fa3eef1824b1a Mon Sep 17 00:00:00 2001 From: Antoine Riard Date: Thu, 8 Dec 2022 21:48:19 -0500 Subject: [PATCH 4/4] Add context for option_anchors_zero_fee_htlc_tx --- 02-peer-protocol.md | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/02-peer-protocol.md b/02-peer-protocol.md index 45ab4a74c..4d057e682 100644 --- a/02-peer-protocol.md +++ b/02-peer-protocol.md @@ -1165,13 +1165,14 @@ The node _not responsible_ for paying the Bitcoin fee: - MUST NOT send `update_fee`. A sending node: - - if the `update_fee` increases `feerate_per_kw`: - - if the dust balance of the remote transaction at the updated `feerate_per_kw` is greater than `max_dust_htlc_exposure_msat`: - - MAY NOT send `update_fee` - - MAY fail the channel - - if the dust balance of the local transaction at the updated `feerate_per_kw` is greater than `max_dust_htlc_exposure_msat`: - - MAY NOT send `update_fee` - - MAY fail the channel + - if `option_anchors_zero_fee_htlc_tx` was not negotiated: + - if the `update_fee` increases `feerate_per_kw`: + - if the dust balance of the remote transaction at the updated `feerate_per_kw` is greater than `max_dust_htlc_exposure_msat`: + - MAY NOT send `update_fee` + - MAY fail the channel + - if the dust balance of the local transaction at the updated `feerate_per_kw` is greater than `max_dust_htlc_exposure_msat`: + - MAY NOT send `update_fee` + - MAY fail the channel A receiving node: - if the `update_fee` is too low for timely processing, OR is unreasonably large: @@ -1182,11 +1183,12 @@ A receiving node: current commitment transaction: - SHOULD fail the channel, - but MAY delay this check until the `update_fee` is committed. - - if the `update_fee` increases `feerate_per_kw`: - - if the dust balance of the remote transaction at the updated `feerate_per_kw` is greater then `max_dust_htlc_exposure_msat`: - - MAY fail the channel - - if the dust balance of the local transaction at the updated `feerate_per_kw` is greater than `max_dust_htlc_exposure_msat`: - - MAY fail the channel + - if `option_anchors_zero_fee_htlc_tx` was not negotiated: + - if the `update_fee` increases `feerate_per_kw`: + - if the dust balance of the remote transaction at the updated `feerate_per_kw` is greater then `max_dust_htlc_exposure_msat`: + - MAY fail the channel + - if the dust balance of the local transaction at the updated `feerate_per_kw` is greater than `max_dust_htlc_exposure_msat`: + - MAY fail the channel #### Rationale