Skip to content

Commit 4530a38

Browse files
author
Antoine Riard
committed
-f fix dust htlcs out of fee
1 parent 6d5a222 commit 4530a38

File tree

3 files changed

+37
-41
lines changed

3 files changed

+37
-41
lines changed

fuzz/src/chanmon_consistency.rs

+6-11
Original file line numberDiff line numberDiff line change
@@ -1131,17 +1131,12 @@ pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out) {
11311131
break;
11321132
}
11331133

1134-
// Finally, make sure that at least one end of each channel can make a substantial payment.
1135-
if out.may_fail.load(atomic::Ordering::Acquire) {
1136-
return;
1137-
} else {
1138-
assert!(
1139-
send_payment(&nodes[0], &nodes[1], chan_a, 10_000_000, &mut payment_id) ||
1140-
send_payment(&nodes[1], &nodes[0], chan_a, 10_000_000, &mut payment_id));
1141-
assert!(
1142-
send_payment(&nodes[1], &nodes[2], chan_b, 10_000_000, &mut payment_id) ||
1143-
send_payment(&nodes[2], &nodes[1], chan_b, 10_000_000, &mut payment_id));
1144-
}
1134+
assert!(
1135+
send_payment(&nodes[0], &nodes[1], chan_a, 10_000_000, &mut payment_id) ||
1136+
send_payment(&nodes[1], &nodes[0], chan_a, 10_000_000, &mut payment_id));
1137+
assert!(
1138+
send_payment(&nodes[1], &nodes[2], chan_b, 10_000_000, &mut payment_id) ||
1139+
send_payment(&nodes[2], &nodes[1], chan_b, 10_000_000, &mut payment_id));
11451140

11461141
last_htlc_clear_fee_a = fee_est_a.ret_val.load(atomic::Ordering::Acquire);
11471142
last_htlc_clear_fee_b = fee_est_b.ret_val.load(atomic::Ordering::Acquire);

lightning/src/ln/channel.rs

+30-29
Original file line numberDiff line numberDiff line change
@@ -1040,7 +1040,7 @@ impl<Signer: Sign> Channel<Signer> {
10401040
/// Note that below-dust HTLCs are included in the fourth return value, but not the third, and
10411041
/// sources are provided only for outbound HTLCs in the fourth return value.
10421042
#[inline]
1043-
fn build_commitment_transaction<L: Deref>(&self, commitment_number: u64, keys: &TxCreationKeys, local: bool, generated_by_local: bool, logger: &L) -> (CommitmentTransaction, u32, usize, Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>) where L::Target: Logger {
1043+
fn build_commitment_transaction<L: Deref>(&self, commitment_number: u64, keys: &TxCreationKeys, local: bool, generated_by_local: bool, htlc_buffer: usize, next_feerate_per_kw: Option<u32>, logger: &L) -> (CommitmentTransaction, u32, usize, Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>, i64, i64) where L::Target: Logger {
10441044
let mut included_dust_htlcs: Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)> = Vec::new();
10451045
let num_htlcs = self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len();
10461046
let mut included_non_dust_htlcs: Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)> = Vec::with_capacity(num_htlcs);
@@ -1062,6 +1062,9 @@ impl<Signer: Sign> Channel<Signer> {
10621062
feerate_per_kw = feerate;
10631063
}
10641064
}
1065+
if let Some(feerate) = next_feerate_per_kw {
1066+
feerate_per_kw = feerate;
1067+
}
10651068

10661069
log_trace!(logger, "Building commitment transaction number {} (really {} xor {}) for channel {} for {}, generated by {} with fee {}...",
10671070
commitment_number, (INITIAL_COMMITMENT_NUMBER - commitment_number),
@@ -1183,7 +1186,7 @@ impl<Signer: Sign> Channel<Signer> {
11831186
broadcaster_max_commitment_tx_output.1 = cmp::max(broadcaster_max_commitment_tx_output.1, value_to_remote_msat as u64);
11841187
}
11851188

1186-
let total_fee_sat = Channel::<Signer>::commit_tx_fee_sat(feerate_per_kw, included_non_dust_htlcs.len());
1189+
let total_fee_sat = Channel::<Signer>::commit_tx_fee_sat(feerate_per_kw, included_non_dust_htlcs.len() + htlc_buffer);
11871190
let (value_to_self, value_to_remote) = if self.is_outbound() {
11881191
(value_to_self_msat / 1000 - total_fee_sat as i64, value_to_remote_msat / 1000)
11891192
} else {
@@ -1231,7 +1234,7 @@ impl<Signer: Sign> Channel<Signer> {
12311234
htlcs_included.sort_unstable_by_key(|h| h.0.transaction_output_index.unwrap());
12321235
htlcs_included.append(&mut included_dust_htlcs);
12331236

1234-
(tx, feerate_per_kw, num_nondust_htlcs, htlcs_included)
1237+
(tx, feerate_per_kw, num_nondust_htlcs, htlcs_included, if local { value_to_self } else { value_to_remote }, if local { value_to_remote } else { value_to_self })
12351238
}
12361239

12371240
#[inline]
@@ -1685,7 +1688,7 @@ impl<Signer: Sign> Channel<Signer> {
16851688
let funding_script = self.get_funding_redeemscript();
16861689

16871690
let keys = self.build_holder_transaction_keys(self.cur_holder_commitment_transaction_number)?;
1688-
let initial_commitment_tx = self.build_commitment_transaction(self.cur_holder_commitment_transaction_number, &keys, true, false, logger).0;
1691+
let initial_commitment_tx = self.build_commitment_transaction(self.cur_holder_commitment_transaction_number, &keys, true, false, 0, None, logger).0;
16891692
{
16901693
let trusted_tx = initial_commitment_tx.trust();
16911694
let initial_commitment_bitcoin_tx = trusted_tx.built_transaction();
@@ -1699,7 +1702,7 @@ impl<Signer: Sign> Channel<Signer> {
16991702
}
17001703

17011704
let counterparty_keys = self.build_remote_transaction_keys()?;
1702-
let counterparty_initial_commitment_tx = self.build_commitment_transaction(self.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).0;
1705+
let counterparty_initial_commitment_tx = self.build_commitment_transaction(self.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, 0, None, logger).0;
17031706

17041707
let counterparty_trusted_tx = counterparty_initial_commitment_tx.trust();
17051708
let counterparty_initial_bitcoin_tx = counterparty_trusted_tx.built_transaction();
@@ -1810,15 +1813,15 @@ impl<Signer: Sign> Channel<Signer> {
18101813
let funding_script = self.get_funding_redeemscript();
18111814

18121815
let counterparty_keys = self.build_remote_transaction_keys()?;
1813-
let counterparty_initial_commitment_tx = self.build_commitment_transaction(self.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).0;
1816+
let counterparty_initial_commitment_tx = self.build_commitment_transaction(self.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, 0, None, logger).0;
18141817
let counterparty_trusted_tx = counterparty_initial_commitment_tx.trust();
18151818
let counterparty_initial_bitcoin_tx = counterparty_trusted_tx.built_transaction();
18161819

18171820
log_trace!(logger, "Initial counterparty tx for channel {} is: txid {} tx {}",
18181821
log_bytes!(self.channel_id()), counterparty_initial_bitcoin_tx.txid, encode::serialize_hex(&counterparty_initial_bitcoin_tx.transaction));
18191822

18201823
let holder_signer = self.build_holder_transaction_keys(self.cur_holder_commitment_transaction_number)?;
1821-
let initial_commitment_tx = self.build_commitment_transaction(self.cur_holder_commitment_transaction_number, &holder_signer, true, false, logger).0;
1824+
let initial_commitment_tx = self.build_commitment_transaction(self.cur_holder_commitment_transaction_number, &holder_signer, true, false, 0, None, logger).0;
18221825
{
18231826
let trusted_tx = initial_commitment_tx.trust();
18241827
let initial_commitment_bitcoin_tx = trusted_tx.built_transaction();
@@ -2407,8 +2410,8 @@ impl<Signer: Sign> Channel<Signer> {
24072410

24082411
let keys = self.build_holder_transaction_keys(self.cur_holder_commitment_transaction_number).map_err(|e| (None, e))?;
24092412

2410-
let (num_htlcs, mut htlcs_cloned, commitment_tx, commitment_txid, feerate_per_kw) = {
2411-
let commitment_tx = self.build_commitment_transaction(self.cur_holder_commitment_transaction_number, &keys, true, false, logger);
2413+
let (num_htlcs, mut htlcs_cloned, commitment_tx, commitment_txid, feerate_per_kw, _, counterparty_balance) = {
2414+
let commitment_tx = self.build_commitment_transaction(self.cur_holder_commitment_transaction_number, &keys, true, false, 0, None, logger);
24122415
let commitment_txid = {
24132416
let trusted_tx = commitment_tx.0.trust();
24142417
let bitcoin_tx = trusted_tx.built_transaction();
@@ -2424,7 +2427,7 @@ impl<Signer: Sign> Channel<Signer> {
24242427
bitcoin_tx.txid
24252428
};
24262429
let htlcs_cloned: Vec<_> = commitment_tx.3.iter().map(|htlc| (htlc.0.clone(), htlc.1.map(|h| h.clone()))).collect();
2427-
(commitment_tx.2, htlcs_cloned, commitment_tx.0, commitment_txid, commitment_tx.1)
2430+
(commitment_tx.2, htlcs_cloned, commitment_tx.0, commitment_txid, commitment_tx.1, commitment_tx.4, commitment_tx.5)
24282431
};
24292432

24302433
// If our counterparty updated the channel fee in this commitment transaction, check that
@@ -2436,7 +2439,7 @@ impl<Signer: Sign> Channel<Signer> {
24362439
let total_fee_sat = Channel::<Signer>::commit_tx_fee_sat(feerate_per_kw, num_htlcs);
24372440
if update_fee {
24382441
let counterparty_reserve_we_require = Channel::<Signer>::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis);
2439-
if self.channel_value_satoshis - self.value_to_self_msat / 1000 < total_fee_sat + counterparty_reserve_we_require {
2442+
if (counterparty_balance as u64) < counterparty_reserve_we_require {
24402443
return Err((None, ChannelError::Close("Funding remote cannot afford proposed new fee".to_owned())));
24412444
}
24422445
}
@@ -2621,7 +2624,7 @@ impl<Signer: Sign> Channel<Signer> {
26212624
// to rebalance channels.
26222625
match &htlc_update {
26232626
&HTLCUpdateAwaitingACK::AddHTLC {amount_msat, cltv_expiry, ref payment_hash, ref source, ref onion_routing_packet, ..} => {
2624-
match self.send_htlc(amount_msat, *payment_hash, cltv_expiry, source.clone(), onion_routing_packet.clone()) {
2627+
match self.send_htlc(amount_msat, *payment_hash, cltv_expiry, source.clone(), onion_routing_packet.clone(), logger) {
26252628
Ok(update_add_msg_option) => update_add_htlcs.push(update_add_msg_option.unwrap()),
26262629
Err(e) => {
26272630
match e {
@@ -2983,9 +2986,10 @@ impl<Signer: Sign> Channel<Signer> {
29832986
// size 2. However, if the number of concurrent update_add_htlc is higher, this still
29842987
// leads to a channel force-close. Ultimately, this is an issue coming from the
29852988
// design of LN state machines, allowing asynchronous updates.
2986-
let total_fee_sat = Channel::<Signer>::commit_tx_fee_sat(feerate_per_kw, (inbound_stats.pending_htlcs + /* HTLC feerate buffer */ 2 + outbound_stats.pending_htlcs) as usize);
2987-
let holder_balance_after_fee_sub = (self.value_to_self_msat / 1000).checked_sub(total_fee_sat).map(|a| a.checked_sub(outbound_stats.pending_htlcs_value_msat / 1000)).unwrap_or(None).unwrap_or(u64::min_value());
2988-
if holder_balance_after_fee_sub < self.counterparty_selected_channel_reserve_satoshis.unwrap() {
2989+
let keys = if let Ok(keys) = self.build_holder_transaction_keys(self.cur_holder_commitment_transaction_number) { keys } else { return None; };
2990+
let commitment_tx = self.build_commitment_transaction(self.cur_holder_commitment_transaction_number, &keys, true, true, 2, Some(feerate_per_kw), logger);
2991+
println!("holder balance {} vs counterparty reserve {}", commitment_tx.4 as u64, self.counterparty_selected_channel_reserve_satoshis.unwrap());
2992+
if (commitment_tx.4 as u64) < self.counterparty_selected_channel_reserve_satoshis.unwrap() {
29892993
//TODO: auto-close after a number of failures?
29902994
log_debug!(logger, "Cannot afford to send new feerate at {}", feerate_per_kw);
29912995
return None;
@@ -4309,7 +4313,7 @@ impl<Signer: Sign> Channel<Signer> {
43094313
/// If an Err is returned, it is a ChannelError::Close (for get_outbound_funding_created)
43104314
fn get_outbound_funding_created_signature<L: Deref>(&mut self, logger: &L) -> Result<Signature, ChannelError> where L::Target: Logger {
43114315
let counterparty_keys = self.build_remote_transaction_keys()?;
4312-
let counterparty_initial_commitment_tx = self.build_commitment_transaction(self.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, logger).0;
4316+
let counterparty_initial_commitment_tx = self.build_commitment_transaction(self.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, false, 0, None, logger).0;
43134317
Ok(self.holder_signer.sign_counterparty_commitment(&counterparty_initial_commitment_tx, &self.secp_ctx)
43144318
.map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed".to_owned()))?.0)
43154319
}
@@ -4528,7 +4532,7 @@ impl<Signer: Sign> Channel<Signer> {
45284532
/// You MUST call send_commitment prior to calling any other methods on this Channel!
45294533
///
45304534
/// If an Err is returned, it's a ChannelError::Ignore!
4531-
pub fn send_htlc(&mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32, source: HTLCSource, onion_routing_packet: msgs::OnionPacket) -> Result<Option<msgs::UpdateAddHTLC>, ChannelError> {
4535+
pub fn send_htlc<L: Deref>(&mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32, source: HTLCSource, onion_routing_packet: msgs::OnionPacket, logger: &L) -> Result<Option<msgs::UpdateAddHTLC>, ChannelError> where L::Target: Logger {
45324536
if (self.channel_state & (ChannelState::ChannelFunded as u32 | BOTH_SIDES_SHUTDOWN_MASK)) != (ChannelState::ChannelFunded as u32) {
45334537
return Err(ChannelError::Ignore("Cannot send HTLC until channel is fully established and we haven't started shutting down".to_owned()));
45344538
}
@@ -4567,11 +4571,11 @@ impl<Signer: Sign> Channel<Signer> {
45674571

45684572
if !self.is_outbound() {
45694573
// Check that we won't violate the remote channel reserve by adding this HTLC.
4570-
let counterparty_balance_msat = self.channel_value_satoshis * 1000 - self.value_to_self_msat;
4571-
let holder_selected_chan_reserve_msat = Channel::<Signer>::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis) * 1000;
4572-
let htlc_candidate = HTLCCandidate::new(amount_msat, HTLCInitiator::LocalOffered);
4573-
let counterparty_commit_tx_fee_msat = self.next_remote_commit_tx_fee_msat(htlc_candidate, None);
4574-
if counterparty_balance_msat < holder_selected_chan_reserve_msat + counterparty_commit_tx_fee_msat {
4574+
let keys = self.build_holder_transaction_keys(self.cur_holder_commitment_transaction_number)?;
4575+
let htlc_buffer = if amount_msat / 1000 > (self.feerate_per_kw as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000) + self.counterparty_dust_limit_satoshis { 1 } else { 0 };
4576+
let commitment_tx = self.build_commitment_transaction(self.cur_holder_commitment_transaction_number, &keys, true, true, htlc_buffer, None, logger);
4577+
let holder_selected_chan_reserve = Channel::<Signer>::get_holder_selected_channel_reserve_satoshis(self.channel_value_satoshis);
4578+
if (commitment_tx.5 as u64) < holder_selected_chan_reserve {
45754579
return Err(ChannelError::Ignore("Cannot send value that would put counterparty balance under holder-announced channel reserve value".to_owned()));
45764580
}
45774581
}
@@ -4745,7 +4749,7 @@ impl<Signer: Sign> Channel<Signer> {
47454749
/// when we shouldn't change HTLC/channel state.
47464750
fn send_commitment_no_state_update<L: Deref>(&self, logger: &L) -> Result<(msgs::CommitmentSigned, (Txid, Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>)), ChannelError> where L::Target: Logger {
47474751
let counterparty_keys = self.build_remote_transaction_keys()?;
4748-
let counterparty_commitment_tx = self.build_commitment_transaction(self.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, true, logger);
4752+
let counterparty_commitment_tx = self.build_commitment_transaction(self.cur_counterparty_commitment_transaction_number, &counterparty_keys, false, true, 0, None, logger);
47494753
let feerate_per_kw = counterparty_commitment_tx.1;
47504754
let counterparty_commitment_txid = counterparty_commitment_tx.0.trust().txid();
47514755
let (signature, htlc_signatures);
@@ -4771,10 +4775,7 @@ impl<Signer: Sign> Channel<Signer> {
47714775
// Log if we can't afford next remote commitment tx fee at pending outbound feerate update.
47724776
if let Some(pending_feerate) = self.pending_update_fee {
47734777
assert_eq!(pending_feerate.1, FeeUpdateState::Outbound);
4774-
let next_total_fee_sat = Channel::<Signer>::commit_tx_fee_sat(pending_feerate.0, self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len());
4775-
let outbound_stats = self.get_outbound_pending_htlc_stats(Some(pending_feerate.0));
4776-
let holder_balance_after_fee_sub_sats = (self.value_to_self_msat / 1000).checked_sub(next_total_fee_sat).map(|a| a.checked_sub(outbound_stats.pending_htlcs_value_msat / 1000)).unwrap_or(None).unwrap_or(u64::min_value());
4777-
if holder_balance_after_fee_sub_sats < self.counterparty_selected_channel_reserve_satoshis.unwrap() {
4778+
if (counterparty_commitment_tx.5 as u64) < self.counterparty_selected_channel_reserve_satoshis.unwrap() {
47784779
log_debug!(logger, "Outbound update_fee HTLC buffer overflow - counterparty should force-close this channel");
47794780
}
47804781
}
@@ -4817,7 +4818,7 @@ impl<Signer: Sign> Channel<Signer> {
48174818
/// Shorthand for calling send_htlc() followed by send_commitment(), see docs on those for
48184819
/// more info.
48194820
pub fn send_htlc_and_commit<L: Deref>(&mut self, amount_msat: u64, payment_hash: PaymentHash, cltv_expiry: u32, source: HTLCSource, onion_routing_packet: msgs::OnionPacket, logger: &L) -> Result<Option<(msgs::UpdateAddHTLC, msgs::CommitmentSigned, ChannelMonitorUpdate)>, ChannelError> where L::Target: Logger {
4820-
match self.send_htlc(amount_msat, payment_hash, cltv_expiry, source, onion_routing_packet)? {
4821+
match self.send_htlc(amount_msat, payment_hash, cltv_expiry, source, onion_routing_packet, logger)? {
48214822
Some(update_add_htlc) => {
48224823
let (commitment_signed, monitor_update) = self.send_commitment_no_status_check(logger)?;
48234824
Ok(Some((update_add_htlc, commitment_signed, monitor_update)))
@@ -6011,7 +6012,7 @@ mod tests {
60116012
$( { $htlc_idx: expr, $counterparty_htlc_sig_hex: expr, $htlc_sig_hex: expr, $htlc_tx_hex: expr } ), *
60126013
} ) => { {
60136014
let (commitment_tx, htlcs): (_, Vec<HTLCOutputInCommitment>) = {
6014-
let mut res = chan.build_commitment_transaction(0xffffffffffff - 42, &keys, true, false, &logger);
6015+
let mut res = chan.build_commitment_transaction(0xffffffffffff - 42, &keys, true, false, 0, None, &logger);
60156016

60166017
let htlcs = res.3.drain(..)
60176018
.filter_map(|(htlc, _)| if htlc.transaction_output_index.is_some() { Some(htlc) } else { None })

lightning/src/ln/channelmanager.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2509,7 +2509,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
25092509
htlc_id: prev_htlc_id,
25102510
incoming_packet_shared_secret: incoming_shared_secret,
25112511
});
2512-
match chan.get_mut().send_htlc(amt_to_forward, payment_hash, outgoing_cltv_value, htlc_source.clone(), onion_packet) {
2512+
match chan.get_mut().send_htlc(amt_to_forward, payment_hash, outgoing_cltv_value, htlc_source.clone(), onion_packet, &self.logger) {
25132513
Err(e) => {
25142514
if let ChannelError::Ignore(msg) = e {
25152515
log_trace!(self.logger, "Failed to forward HTLC with payment_hash {}: {}", log_bytes!(payment_hash.0), msg);

0 commit comments

Comments
 (0)