@@ -4145,7 +4145,7 @@ where
4145
4145
{
4146
4146
let remote_commit_tx_fee_msat = if funding.is_outbound() { 0 } else {
4147
4147
let htlc_candidate = HTLCCandidate::new(msg.amount_msat, HTLCInitiator::RemoteOffered);
4148
- self.next_remote_commit_tx_fee_msat(funding, Some(htlc_candidate), None ) // Don't include the extra fee spike buffer HTLC in calculations
4148
+ self.next_remote_commit_tx_fee_msat(funding, Some(htlc_candidate), 0 ) // Don't include the extra fee spike buffer HTLC in calculations
4149
4149
};
4150
4150
if remote_balance_before_fee_msat.saturating_sub(msg.amount_msat) < remote_commit_tx_fee_msat {
4151
4151
return Err(ChannelError::close("Remote HTLC add would not leave enough to pay for fees".to_owned()));
@@ -4158,7 +4158,7 @@ where
4158
4158
if funding.is_outbound() {
4159
4159
// Check that they won't violate our local required channel reserve by adding this HTLC.
4160
4160
let htlc_candidate = HTLCCandidate::new(msg.amount_msat, HTLCInitiator::RemoteOffered);
4161
- let local_commit_tx_fee_msat = self.next_local_commit_tx_fee_msat(funding, htlc_candidate, None );
4161
+ let local_commit_tx_fee_msat = self.next_local_commit_tx_fee_msat(funding, Some( htlc_candidate), 0 );
4162
4162
if local_balance_before_fee_msat < funding.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 + local_commit_tx_fee_msat {
4163
4163
return Err(ChannelError::close("Cannot accept HTLC that would put our balance under counterparty-announced channel reserve value".to_owned()));
4164
4164
}
@@ -4372,7 +4372,7 @@ where
4372
4372
//
4373
4373
// A `None` `HTLCCandidate` is used as in this case because we're already accounting for
4374
4374
// the incoming HTLC as it has been fully committed by both sides.
4375
- let mut remote_fee_cost_incl_stuck_buffer_msat = self.next_remote_commit_tx_fee_msat(funding, None, Some(()) );
4375
+ let mut remote_fee_cost_incl_stuck_buffer_msat = self.next_remote_commit_tx_fee_msat(funding, None, 1 );
4376
4376
if !funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
4377
4377
remote_fee_cost_incl_stuck_buffer_msat *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
4378
4378
}
@@ -4865,10 +4865,8 @@ where
4865
4865
// dependency.
4866
4866
// This complicates the computation around dust-values, up to the one-htlc-value.
4867
4867
4868
- let htlc_above_dust = HTLCCandidate::new(real_dust_limit_timeout_sat * 1000, HTLCInitiator::LocalOffered);
4869
- let mut max_reserved_commit_tx_fee_msat = context.next_local_commit_tx_fee_msat(funding, htlc_above_dust, Some(()));
4870
- let htlc_dust = HTLCCandidate::new(real_dust_limit_timeout_sat * 1000 - 1, HTLCInitiator::LocalOffered);
4871
- let mut min_reserved_commit_tx_fee_msat = context.next_local_commit_tx_fee_msat(funding, htlc_dust, Some(()));
4868
+ let mut max_reserved_commit_tx_fee_msat = context.next_local_commit_tx_fee_msat(funding, None, 2);
4869
+ let mut min_reserved_commit_tx_fee_msat = context.next_local_commit_tx_fee_msat(funding, None, 1);
4872
4870
if !funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
4873
4871
max_reserved_commit_tx_fee_msat *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
4874
4872
min_reserved_commit_tx_fee_msat *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
@@ -4891,8 +4889,7 @@ where
4891
4889
} else {
4892
4890
// If the channel is inbound (i.e. counterparty pays the fee), we need to make sure
4893
4891
// sending a new HTLC won't reduce their balance below our reserve threshold.
4894
- let htlc_above_dust = HTLCCandidate::new(real_dust_limit_success_sat * 1000, HTLCInitiator::LocalOffered);
4895
- let max_reserved_commit_tx_fee_msat = context.next_remote_commit_tx_fee_msat(funding, Some(htlc_above_dust), None);
4892
+ let max_reserved_commit_tx_fee_msat = context.next_remote_commit_tx_fee_msat(funding, None, 1);
4896
4893
4897
4894
let holder_selected_chan_reserve_msat = funding.holder_selected_channel_reserve_satoshis * 1000;
4898
4895
if remote_balance_before_fee_msat < max_reserved_commit_tx_fee_msat + holder_selected_chan_reserve_msat {
@@ -4975,18 +4972,22 @@ where
4975
4972
/// Dust HTLCs are excluded.
4976
4973
#[rustfmt::skip]
4977
4974
fn next_local_commit_tx_fee_msat(
4978
- &self, funding: &FundingScope, htlc: HTLCCandidate, fee_spike_buffer_htlc: Option<()> ,
4975
+ &self, funding: &FundingScope, htlc: Option< HTLCCandidate>, addl_nondust_htlc: usize ,
4979
4976
) -> u64 {
4977
+ debug_assert!(htlc.is_some() || addl_nondust_htlc != 0, "At least one of the options must be set");
4978
+
4980
4979
let context = self;
4981
4980
assert!(funding.is_outbound());
4982
4981
let mut htlcs: Vec<HTLCAmountDirection> = Vec::new();
4983
4982
4984
- match htlc.origin {
4985
- HTLCInitiator::LocalOffered => {
4986
- htlcs.push(HTLCAmountDirection { offered: true, amount_msat: htlc.amount_msat });
4987
- },
4988
- HTLCInitiator::RemoteOffered => {
4989
- htlcs.push(HTLCAmountDirection { offered: false, amount_msat: htlc.amount_msat });
4983
+ if let Some(htlc) = &htlc {
4984
+ match htlc.origin {
4985
+ HTLCInitiator::LocalOffered => {
4986
+ htlcs.push(HTLCAmountDirection { offered: true, amount_msat: htlc.amount_msat });
4987
+ },
4988
+ HTLCInitiator::RemoteOffered => {
4989
+ htlcs.push(HTLCAmountDirection { offered: false, amount_msat: htlc.amount_msat });
4990
+ }
4990
4991
}
4991
4992
}
4992
4993
@@ -5017,13 +5018,13 @@ where
5017
5018
}
5018
5019
5019
5020
#[cfg(any(test, fuzzing))]
5020
- let commit_tx_fee_msat = SpecTxBuilder {}.commit_tx_fee_sat(context.holder_dust_limit_satoshis, context.feerate_per_kw, &htlcs, fee_spike_buffer_htlc.map(|_| 1).unwrap_or(0) , funding.get_channel_type()) * 1000;
5021
+ let commit_tx_fee_msat = SpecTxBuilder {}.commit_tx_fee_sat(context.holder_dust_limit_satoshis, context.feerate_per_kw, &htlcs, addl_nondust_htlc , funding.get_channel_type()) * 1000;
5021
5022
#[cfg(not(any(test, fuzzing)))]
5022
- let commit_tx_fee_msat = SpecTxBuilder {}.commit_tx_fee_sat(context.holder_dust_limit_satoshis, context.feerate_per_kw, &htlcs, fee_spike_buffer_htlc.map(|_| 1).unwrap_or(0) , funding.get_channel_type()) * 1000;
5023
+ let commit_tx_fee_msat = SpecTxBuilder {}.commit_tx_fee_sat(context.holder_dust_limit_satoshis, context.feerate_per_kw, &htlcs, addl_nondust_htlc , funding.get_channel_type()) * 1000;
5023
5024
#[cfg(any(test, fuzzing))]
5024
- {
5025
+ if let Some(htlc) = htlc {
5025
5026
let mut fee = commit_tx_fee_msat;
5026
- if fee_spike_buffer_htlc.is_some() {
5027
+ if addl_nondust_htlc != 0 {
5027
5028
fee = SpecTxBuilder {}.commit_tx_fee_sat(context.holder_dust_limit_satoshis, context.feerate_per_kw, &htlcs, 0, funding.get_channel_type()) * 1000;
5028
5029
}
5029
5030
let total_pending_htlcs = context.pending_inbound_htlcs.len() + context.pending_outbound_htlcs.len()
@@ -5058,9 +5059,9 @@ where
5058
5059
/// Dust HTLCs are excluded.
5059
5060
#[rustfmt::skip]
5060
5061
fn next_remote_commit_tx_fee_msat(
5061
- &self, funding: &FundingScope, htlc: Option<HTLCCandidate>, fee_spike_buffer_htlc: Option<()> ,
5062
+ &self, funding: &FundingScope, htlc: Option<HTLCCandidate>, addl_nondust_htlc: usize ,
5062
5063
) -> u64 {
5063
- debug_assert!(htlc.is_some() || fee_spike_buffer_htlc.is_some() , "At least one of the options must be set");
5064
+ debug_assert!(htlc.is_some() || addl_nondust_htlc != 0 , "At least one of the options must be set");
5064
5065
5065
5066
let context = self;
5066
5067
assert!(!funding.is_outbound());
@@ -5097,13 +5098,13 @@ where
5097
5098
}
5098
5099
5099
5100
#[cfg(any(test, fuzzing))]
5100
- let commit_tx_fee_msat = SpecTxBuilder {}.commit_tx_fee_sat(context.counterparty_dust_limit_satoshis, context.feerate_per_kw, &htlcs, fee_spike_buffer_htlc.map(|_| 1).unwrap_or(0) , funding.get_channel_type()) * 1000;
5101
+ let commit_tx_fee_msat = SpecTxBuilder {}.commit_tx_fee_sat(context.counterparty_dust_limit_satoshis, context.feerate_per_kw, &htlcs, addl_nondust_htlc , funding.get_channel_type()) * 1000;
5101
5102
#[cfg(not(any(test, fuzzing)))]
5102
- let commit_tx_fee_msat = SpecTxBuilder {}.commit_tx_fee_sat(context.counterparty_dust_limit_satoshis, context.feerate_per_kw, &htlcs, fee_spike_buffer_htlc.map(|_| 1).unwrap_or(0) , funding.get_channel_type()) * 1000;
5103
+ let commit_tx_fee_msat = SpecTxBuilder {}.commit_tx_fee_sat(context.counterparty_dust_limit_satoshis, context.feerate_per_kw, &htlcs, addl_nondust_htlc , funding.get_channel_type()) * 1000;
5103
5104
#[cfg(any(test, fuzzing))]
5104
5105
if let Some(htlc) = &htlc {
5105
5106
let mut fee = commit_tx_fee_msat;
5106
- if fee_spike_buffer_htlc.is_some() {
5107
+ if addl_nondust_htlc != 0 {
5107
5108
fee = SpecTxBuilder {}.commit_tx_fee_sat(context.counterparty_dust_limit_satoshis, context.feerate_per_kw, &htlcs, 0, funding.get_channel_type()) * 1000;
5108
5109
}
5109
5110
let total_pending_htlcs = context.pending_inbound_htlcs.len() + context.pending_outbound_htlcs.len();
@@ -13450,7 +13451,7 @@ mod tests {
13450
13451
// Make sure when Node A calculates their local commitment transaction, none of the HTLCs pass
13451
13452
// the dust limit check.
13452
13453
let htlc_candidate = HTLCCandidate::new(htlc_amount_msat, HTLCInitiator::LocalOffered);
13453
- let local_commit_tx_fee = node_a_chan.context.next_local_commit_tx_fee_msat(&node_a_chan.funding, htlc_candidate, None );
13454
+ let local_commit_tx_fee = node_a_chan.context.next_local_commit_tx_fee_msat(&node_a_chan.funding, Some( htlc_candidate), 0 );
13454
13455
let local_commit_fee_0_htlcs = commit_tx_fee_sat(node_a_chan.context.feerate_per_kw, 0, node_a_chan.funding.get_channel_type()) * 1000;
13455
13456
assert_eq!(local_commit_tx_fee, local_commit_fee_0_htlcs);
13456
13457
@@ -13459,7 +13460,7 @@ mod tests {
13459
13460
node_a_chan.funding.channel_transaction_parameters.is_outbound_from_holder = false;
13460
13461
let remote_commit_fee_3_htlcs = commit_tx_fee_sat(node_a_chan.context.feerate_per_kw, 3, node_a_chan.funding.get_channel_type()) * 1000;
13461
13462
let htlc_candidate = HTLCCandidate::new(htlc_amount_msat, HTLCInitiator::LocalOffered);
13462
- let remote_commit_tx_fee = node_a_chan.context.next_remote_commit_tx_fee_msat(&node_a_chan.funding, Some(htlc_candidate), None );
13463
+ let remote_commit_tx_fee = node_a_chan.context.next_remote_commit_tx_fee_msat(&node_a_chan.funding, Some(htlc_candidate), 0 );
13463
13464
assert_eq!(remote_commit_tx_fee, remote_commit_fee_3_htlcs);
13464
13465
}
13465
13466
@@ -13489,27 +13490,27 @@ mod tests {
13489
13490
// counted as dust when it shouldn't be.
13490
13491
let htlc_amt_above_timeout = ((253 * htlc_timeout_tx_weight(chan.funding.get_channel_type()) / 1000) + chan.context.holder_dust_limit_satoshis + 1) * 1000;
13491
13492
let htlc_candidate = HTLCCandidate::new(htlc_amt_above_timeout, HTLCInitiator::LocalOffered);
13492
- let commitment_tx_fee = chan.context.next_local_commit_tx_fee_msat(&chan.funding, htlc_candidate, None );
13493
+ let commitment_tx_fee = chan.context.next_local_commit_tx_fee_msat(&chan.funding, Some( htlc_candidate), 0 );
13493
13494
assert_eq!(commitment_tx_fee, commitment_tx_fee_1_htlc);
13494
13495
13495
13496
// If swapped: this HTLC would be counted as non-dust when it shouldn't be.
13496
13497
let dust_htlc_amt_below_success = ((253 * htlc_success_tx_weight(chan.funding.get_channel_type()) / 1000) + chan.context.holder_dust_limit_satoshis - 1) * 1000;
13497
13498
let htlc_candidate = HTLCCandidate::new(dust_htlc_amt_below_success, HTLCInitiator::RemoteOffered);
13498
- let commitment_tx_fee = chan.context.next_local_commit_tx_fee_msat(&chan.funding, htlc_candidate, None );
13499
+ let commitment_tx_fee = chan.context.next_local_commit_tx_fee_msat(&chan.funding, Some( htlc_candidate), 0 );
13499
13500
assert_eq!(commitment_tx_fee, commitment_tx_fee_0_htlcs);
13500
13501
13501
13502
chan.funding.channel_transaction_parameters.is_outbound_from_holder = false;
13502
13503
13503
13504
// If swapped: this HTLC would be counted as non-dust when it shouldn't be.
13504
13505
let dust_htlc_amt_above_timeout = ((253 * htlc_timeout_tx_weight(chan.funding.get_channel_type()) / 1000) + chan.context.counterparty_dust_limit_satoshis + 1) * 1000;
13505
13506
let htlc_candidate = HTLCCandidate::new(dust_htlc_amt_above_timeout, HTLCInitiator::LocalOffered);
13506
- let commitment_tx_fee = chan.context.next_remote_commit_tx_fee_msat(&chan.funding, Some(htlc_candidate), None );
13507
+ let commitment_tx_fee = chan.context.next_remote_commit_tx_fee_msat(&chan.funding, Some(htlc_candidate), 0 );
13507
13508
assert_eq!(commitment_tx_fee, commitment_tx_fee_0_htlcs);
13508
13509
13509
13510
// If swapped: this HTLC would be counted as dust when it shouldn't be.
13510
13511
let htlc_amt_below_success = ((253 * htlc_success_tx_weight(chan.funding.get_channel_type()) / 1000) + chan.context.counterparty_dust_limit_satoshis - 1) * 1000;
13511
13512
let htlc_candidate = HTLCCandidate::new(htlc_amt_below_success, HTLCInitiator::RemoteOffered);
13512
- let commitment_tx_fee = chan.context.next_remote_commit_tx_fee_msat(&chan.funding, Some(htlc_candidate), None );
13513
+ let commitment_tx_fee = chan.context.next_remote_commit_tx_fee_msat(&chan.funding, Some(htlc_candidate), 0 );
13513
13514
assert_eq!(commitment_tx_fee, commitment_tx_fee_1_htlc);
13514
13515
}
13515
13516
0 commit comments