Correct the reserve minimums in `FundingScope::for_splice`
What changed, and why it matters
This commit fixes a swap in the Lightning channel splicing code. When a channel's funding is changed via splicing, each side must keep a minimum reserve balance to prevent the other side from pushing tiny, spammy transactions. The code had accidentally used the counterparty's dust limit when calculating the reserve that protects our own transactions, and used our own fixed minimum dust limit when calculating the reserve that protects the counterparty's transactions. The patch swaps them back so each side's reserve is based on the correct dust limit. A wrong reserve could let a peer set an abnormally low reserve, potentially enabling fee-griefing or dust-spam attacks against the channel.
Review whether any running channels were opened or spliced with code versions containing this swap, and consider whether the incorrect reserve values could have been exploited to force uneconomical outputs. Add or strengthen unit tests that assert the exact reserve values for both holder and counterparty after splice, using distinct dust-limit values to catch future swaps.
Security signals we found
Incorrect reserve calculation in channel funding/splicing logic
Swap of holder and counterparty dust-limit inputs to reserve function
Potential violation of BOLT 2 channel reserve semantics
Risk of peer-influenced reserve being set below dust threshold
Evidence from the diff
In FundingScope::for_splice in lightning/src/ln/channel.rs, the variables counterparty_selected_channel_reserve_satoshis and holder_selected_channel_reserve_satoshis were constructed with swapped dust-limit arguments. The counterparty’s reserve should be computed against context.counterparty_dust_limit_satoshis, while the holder’s reserve should be computed against the local constant MIN_CHAN_DUST_LIMIT_SATOSHIS. The patch restores this mapping. Because channel reserve minimums influence which outputs are considered valid in commitment/splice transactions, using the wrong dust limit could allow a peer to select a reserve below its own dust threshold, violating BOLT 2 intent and potentially making certain outputs uneconomical to claim.
Changed components
lightning/src/ln/channel.rsFundingScope::for_splicesplice-in/splice-out channel reserve computationInspect captured patch +4 / −4
diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs
index 031929e..cc8b0d0 100644
--- a/lightning/src/ln/channel.rs
+++ b/lightning/src/ln/channel.rs
@@ -2298,12 +2298,12 @@ impl FundingScope {
.funding_pubkey = counterparty_funding_pubkey;
// New reserve values are based on the new channel value and are v2-specific
- let counterparty_selected_channel_reserve_satoshis = Some(get_v2_channel_reserve_satoshis(
+ let counterparty_selected_channel_reserve_satoshis =
+ Some(get_v2_channel_reserve_satoshis(post_channel_value, MIN_CHAN_DUST_LIMIT_SATOSHIS));
+ let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
post_channel_value,
context.counterparty_dust_limit_satoshis,
- ));
- let holder_selected_channel_reserve_satoshis =
- get_v2_channel_reserve_satoshis(post_channel_value, MIN_CHAN_DUST_LIMIT_SATOSHIS);
+ );
Self {
channel_transaction_parameters: post_channel_transaction_parameters,
Why this scored 57/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.