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