Set the correct floor for the reserves in inbound V2 channels
What changed, and why it matters
This commit fixes a swap in how reserve amounts are calculated for a new type of Lightning channel (V2). Each side's reserve has a minimum floor based on the other side's 'dust limit' (the smallest transaction output they consider meaningful). The code had the two dust limits reversed: the local reserve floor was using the remote dust limit and vice versa. That could let one side set a reserve floor lower than intended, potentially creating a channel state where tiny, uneconomic outputs are created or where balance protections are weaker than the protocol expects.
Review whether any V2 channels were opened with reversed reserve floors; if so, assess whether reserve values fell below the counterparty's dust limit and consider monitoring or renegotiation. Apply the patch promptly.
Security signals we found
Reserve floor mismatch in dual-funded / V2 channel negotiation
Potential creation of sub-dust-limit outputs treated as non-existent by counterparty
Protocol-invariant violation in channel parameter negotiation
Small, targeted fix in a single critical function
Evidence from the diff
In PendingV2Channel::new(), the arguments to get_v2_channel_reserve_satoshis() for counterparty-selected and holder-selected reserves were exchanged. The correct rule is: counterparty_selected_channel_reserve_satoshis should use MIN_CHAN_DUST_LIMIT_SATOSHIS (the holder’s dust floor), and holder_selected_channel_reserve_satoshis should use msg.common_fields.dust_limit_satoshis (the counterparty’s dust limit). The patch swaps them. A wrong floor could allow a reserve below the counterparty’s dust limit, producing outputs the counterparty treats as dust and may not enforce, which can affect channel safety and fee/penalty economics.
Changed components
lightning/src/ln/channel.rsPendingV2Channel::new()V2 (dual-funded / interactive) channel openingInspect captured patch +2 / −2
diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs
index 8b05d98..c2b7e06 100644
--- a/lightning/src/ln/channel.rs
+++ b/lightning/src/ln/channel.rs
@@ -14623,9 +14623,9 @@ impl<SP: SignerProvider> PendingV2Channel<SP> {
let channel_value_satoshis =
our_funding_contribution_sats.saturating_add(msg.common_fields.funding_satoshis);
let counterparty_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
- channel_value_satoshis, msg.common_fields.dust_limit_satoshis);
- let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
channel_value_satoshis, MIN_CHAN_DUST_LIMIT_SATOSHIS);
+ let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
+ channel_value_satoshis, msg.common_fields.dust_limit_satoshis);
let channel_type = channel_type_from_open_channel(&msg.common_fields, our_supported_features)?;
Why this scored 59/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.