@@ -4145,7 +4145,7 @@ where
41454145 {
41464146 let remote_commit_tx_fee_msat = if funding.is_outbound() { 0 } else {
41474147 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
41494149 };
41504150 if remote_balance_before_fee_msat.saturating_sub(msg.amount_msat) < remote_commit_tx_fee_msat {
41514151 return Err(ChannelError::close("Remote HTLC add would not leave enough to pay for fees".to_owned()));
@@ -4158,7 +4158,7 @@ where
41584158 if funding.is_outbound() {
41594159 // Check that they won't violate our local required channel reserve by adding this HTLC.
41604160 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 );
41624162 if local_balance_before_fee_msat < funding.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 + local_commit_tx_fee_msat {
41634163 return Err(ChannelError::close("Cannot accept HTLC that would put our balance under counterparty-announced channel reserve value".to_owned()));
41644164 }
@@ -4372,7 +4372,7 @@ where
43724372 //
43734373 // A `None` `HTLCCandidate` is used as in this case because we're already accounting for
43744374 // 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 );
43764376 if !funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
43774377 remote_fee_cost_incl_stuck_buffer_msat *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
43784378 }
@@ -4865,10 +4865,8 @@ where
48654865 // dependency.
48664866 // This complicates the computation around dust-values, up to the one-htlc-value.
48674867
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);
48724870 if !funding.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
48734871 max_reserved_commit_tx_fee_msat *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
48744872 min_reserved_commit_tx_fee_msat *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
@@ -4891,8 +4889,7 @@ where
48914889 } else {
48924890 // If the channel is inbound (i.e. counterparty pays the fee), we need to make sure
48934891 // 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);
48964893
48974894 let holder_selected_chan_reserve_msat = funding.holder_selected_channel_reserve_satoshis * 1000;
48984895 if remote_balance_before_fee_msat < max_reserved_commit_tx_fee_msat + holder_selected_chan_reserve_msat {
@@ -4975,18 +4972,22 @@ where
49754972 /// Dust HTLCs are excluded.
49764973 #[rustfmt::skip]
49774974 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 ,
49794976 ) -> u64 {
4977+ debug_assert!(htlc.is_some() || addl_nondust_htlc != 0, "At least one of the options must be set");
4978+
49804979 let context = self;
49814980 assert!(funding.is_outbound());
49824981 let mut htlcs: Vec<HTLCAmountDirection> = Vec::new();
49834982
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+ }
49904991 }
49914992 }
49924993
@@ -5017,13 +5018,13 @@ where
50175018 }
50185019
50195020 #[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;
50215022 #[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;
50235024 #[cfg(any(test, fuzzing))]
5024- {
5025+ if let Some(htlc) = htlc {
50255026 let mut fee = commit_tx_fee_msat;
5026- if fee_spike_buffer_htlc.is_some() {
5027+ if addl_nondust_htlc != 0 {
50275028 fee = SpecTxBuilder {}.commit_tx_fee_sat(context.holder_dust_limit_satoshis, context.feerate_per_kw, &htlcs, 0, funding.get_channel_type()) * 1000;
50285029 }
50295030 let total_pending_htlcs = context.pending_inbound_htlcs.len() + context.pending_outbound_htlcs.len()
@@ -5058,9 +5059,9 @@ where
50585059 /// Dust HTLCs are excluded.
50595060 #[rustfmt::skip]
50605061 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 ,
50625063 ) -> 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");
50645065
50655066 let context = self;
50665067 assert!(!funding.is_outbound());
@@ -5097,13 +5098,13 @@ where
50975098 }
50985099
50995100 #[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;
51015102 #[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;
51035104 #[cfg(any(test, fuzzing))]
51045105 if let Some(htlc) = &htlc {
51055106 let mut fee = commit_tx_fee_msat;
5106- if fee_spike_buffer_htlc.is_some() {
5107+ if addl_nondust_htlc != 0 {
51075108 fee = SpecTxBuilder {}.commit_tx_fee_sat(context.counterparty_dust_limit_satoshis, context.feerate_per_kw, &htlcs, 0, funding.get_channel_type()) * 1000;
51085109 }
51095110 let total_pending_htlcs = context.pending_inbound_htlcs.len() + context.pending_outbound_htlcs.len();
@@ -13450,7 +13451,7 @@ mod tests {
1345013451 // Make sure when Node A calculates their local commitment transaction, none of the HTLCs pass
1345113452 // the dust limit check.
1345213453 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 );
1345413455 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;
1345513456 assert_eq!(local_commit_tx_fee, local_commit_fee_0_htlcs);
1345613457
@@ -13459,7 +13460,7 @@ mod tests {
1345913460 node_a_chan.funding.channel_transaction_parameters.is_outbound_from_holder = false;
1346013461 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;
1346113462 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 );
1346313464 assert_eq!(remote_commit_tx_fee, remote_commit_fee_3_htlcs);
1346413465 }
1346513466
@@ -13489,27 +13490,27 @@ mod tests {
1348913490 // counted as dust when it shouldn't be.
1349013491 let htlc_amt_above_timeout = ((253 * htlc_timeout_tx_weight(chan.funding.get_channel_type()) / 1000) + chan.context.holder_dust_limit_satoshis + 1) * 1000;
1349113492 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 );
1349313494 assert_eq!(commitment_tx_fee, commitment_tx_fee_1_htlc);
1349413495
1349513496 // If swapped: this HTLC would be counted as non-dust when it shouldn't be.
1349613497 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;
1349713498 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 );
1349913500 assert_eq!(commitment_tx_fee, commitment_tx_fee_0_htlcs);
1350013501
1350113502 chan.funding.channel_transaction_parameters.is_outbound_from_holder = false;
1350213503
1350313504 // If swapped: this HTLC would be counted as non-dust when it shouldn't be.
1350413505 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;
1350513506 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 );
1350713508 assert_eq!(commitment_tx_fee, commitment_tx_fee_0_htlcs);
1350813509
1350913510 // If swapped: this HTLC would be counted as dust when it shouldn't be.
1351013511 let htlc_amt_below_success = ((253 * htlc_success_tx_weight(chan.funding.get_channel_type()) / 1000) + chan.context.counterparty_dust_limit_satoshis - 1) * 1000;
1351113512 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 );
1351313514 assert_eq!(commitment_tx_fee, commitment_tx_fee_1_htlc);
1351413515 }
1351513516
0 commit comments