Skip to content

Commit a2741a0

Browse files
committed
Account for dust in closing channel fee
Before we were ignoring dust when creating the closing channel fee. Now if an output would be dust, we will recalculate the fee with the missing output. This should fix some force closes that happen with lnd nodes.
1 parent f068df0 commit a2741a0

File tree

1 file changed

+30
-18
lines changed

1 file changed

+30
-18
lines changed

lightning/src/ln/channel.rs

Lines changed: 30 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4396,6 +4396,22 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
43964396
}
43974397
}
43984398

4399+
fn calculate_proposed_fee_limits(&self, proposed_feerate: u32, normal_feerate: u32, proposed_max_feerate: u32, a_scriptpubkey: Option<&Script>, b_scriptpubkey: Option<&Script>) -> (u64, u64) {
4400+
let tx_weight = self.get_closing_transaction_weight(a_scriptpubkey, b_scriptpubkey);
4401+
let proposed_total_fee_satoshis = proposed_feerate as u64 * tx_weight / 1000;
4402+
let proposed_max_total_fee_satoshis = if self.is_outbound() {
4403+
// We always add force_close_avoidance_max_fee_satoshis to our normal
4404+
// feerate-calculated fee, but allow the max to be overridden if we're using a
4405+
// target feerate-calculated fee.
4406+
cmp::max(normal_feerate as u64 * tx_weight / 1000 + self.config.options.force_close_avoidance_max_fee_satoshis,
4407+
proposed_max_feerate as u64 * tx_weight / 1000)
4408+
} else {
4409+
self.channel_value_satoshis - (self.value_to_self_msat + 999) / 1000
4410+
};
4411+
4412+
(proposed_total_fee_satoshis, proposed_max_total_fee_satoshis)
4413+
}
4414+
43994415
/// Calculates and returns our minimum and maximum closing transaction fee amounts, in whole
44004416
/// satoshis. The amounts remain consistent unless a peer disconnects/reconnects or we restart,
44014417
/// at which point they will be recalculated.
@@ -4424,24 +4440,20 @@ impl<Signer: WriteableEcdsaChannelSigner> Channel<Signer> {
44244440
proposed_max_feerate = cmp::max(proposed_max_feerate, min_feerate);
44254441
}
44264442

4427-
// Note that technically we could end up with a lower minimum fee if one sides' balance is
4428-
// below our dust limit, causing the output to disappear. We don't bother handling this
4429-
// case, however, as this should only happen if a channel is closed before any (material)
4430-
// payments have been made on it. This may cause slight fee overpayment and/or failure to
4431-
// come to consensus with our counterparty on appropriate fees, however it should be a
4432-
// relatively rare case. We can revisit this later, though note that in order to determine
4433-
// if the funders' output is dust we have to know the absolute fee we're going to use.
4434-
let tx_weight = self.get_closing_transaction_weight(Some(&self.get_closing_scriptpubkey()), Some(self.counterparty_shutdown_scriptpubkey.as_ref().unwrap()));
4435-
let proposed_total_fee_satoshis = proposed_feerate as u64 * tx_weight / 1000;
4436-
let proposed_max_total_fee_satoshis = if self.is_outbound() {
4437-
// We always add force_close_avoidance_max_fee_satoshis to our normal
4438-
// feerate-calculated fee, but allow the max to be overridden if we're using a
4439-
// target feerate-calculated fee.
4440-
cmp::max(normal_feerate as u64 * tx_weight / 1000 + self.config.options.force_close_avoidance_max_fee_satoshis,
4441-
proposed_max_feerate as u64 * tx_weight / 1000)
4442-
} else {
4443-
self.channel_value_satoshis - (self.value_to_self_msat + 999) / 1000
4444-
};
4443+
let (mut proposed_total_fee_satoshis, mut proposed_max_total_fee_satoshis) =
4444+
self.calculate_proposed_fee_limits(proposed_feerate, normal_feerate, proposed_max_feerate, Some(&self.get_closing_scriptpubkey()), Some(self.counterparty_shutdown_scriptpubkey.as_ref().unwrap()));
4445+
4446+
let (closing_tx, _) = self.build_closing_transaction(proposed_total_fee_satoshis, false);
4447+
4448+
// if one of the outputs is dust, we need to recalculate the fee limits to account for the
4449+
// dust output being removed
4450+
if closing_tx.to_holder_value_sat() == 0 {
4451+
(proposed_total_fee_satoshis, proposed_max_total_fee_satoshis) =
4452+
self.calculate_proposed_fee_limits(proposed_feerate, normal_feerate, proposed_max_feerate, Some(&self.get_closing_scriptpubkey()), None);
4453+
} else if closing_tx.to_counterparty_value_sat() == 0 {
4454+
(proposed_total_fee_satoshis, proposed_max_total_fee_satoshis) =
4455+
self.calculate_proposed_fee_limits(proposed_feerate, normal_feerate, proposed_max_feerate, None, Some(self.counterparty_shutdown_scriptpubkey.as_ref().unwrap()));
4456+
}
44454457

44464458
self.closing_fee_limits = Some((proposed_total_fee_satoshis, proposed_max_total_fee_satoshis));
44474459
self.closing_fee_limits.clone().unwrap()

0 commit comments

Comments
 (0)