@@ -1600,6 +1600,15 @@ pub(super) struct FundingScope {
16001600 #[cfg(debug_assertions)]
16011601 /// Max to_local and to_remote outputs in a remote-generated commitment transaction
16021602 counterparty_max_commitment_tx_output: Mutex<(u64, u64)>,
1603+
1604+ // We save these values so we can make sure `next_local_commit_tx_fee_msat` and
1605+ // `next_remote_commit_tx_fee_msat` properly predict what the next commitment transaction fee will
1606+ // be, by comparing the cached values to the fee of the transaction generated by
1607+ // `build_commitment_transaction`.
1608+ #[cfg(any(test, fuzzing))]
1609+ next_local_commitment_tx_fee_info_cached: Mutex<Option<CommitmentTxInfoCached>>,
1610+ #[cfg(any(test, fuzzing))]
1611+ next_remote_commitment_tx_fee_info_cached: Mutex<Option<CommitmentTxInfoCached>>,
16031612}
16041613
16051614impl FundingScope {
@@ -1844,15 +1853,6 @@ pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
18441853 /// This can be used to rebroadcast the channel_announcement message later.
18451854 announcement_sigs: Option<(Signature, Signature)>,
18461855
1847- // We save these values so we can make sure `next_local_commit_tx_fee_msat` and
1848- // `next_remote_commit_tx_fee_msat` properly predict what the next commitment transaction fee will
1849- // be, by comparing the cached values to the fee of the tranaction generated by
1850- // `build_commitment_transaction`.
1851- #[cfg(any(test, fuzzing))]
1852- next_local_commitment_tx_fee_info_cached: Mutex<Option<CommitmentTxInfoCached>>,
1853- #[cfg(any(test, fuzzing))]
1854- next_remote_commitment_tx_fee_info_cached: Mutex<Option<CommitmentTxInfoCached>>,
1855-
18561856 /// lnd has a long-standing bug where, upon reconnection, if the channel is not yet confirmed
18571857 /// they will not send a channel_reestablish until the channel locks in. Then, they will send a
18581858 /// channel_ready *before* sending the channel_reestablish (which is clearly a violation of
@@ -2491,6 +2491,11 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
24912491 holder_max_commitment_tx_output: Mutex::new((value_to_self_msat, (channel_value_satoshis * 1000 - msg_push_msat).saturating_sub(value_to_self_msat))),
24922492 #[cfg(debug_assertions)]
24932493 counterparty_max_commitment_tx_output: Mutex::new((value_to_self_msat, (channel_value_satoshis * 1000 - msg_push_msat).saturating_sub(value_to_self_msat))),
2494+
2495+ #[cfg(any(test, fuzzing))]
2496+ next_local_commitment_tx_fee_info_cached: Mutex::new(None),
2497+ #[cfg(any(test, fuzzing))]
2498+ next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
24942499 };
24952500 let channel_context = ChannelContext {
24962501 user_id,
@@ -2599,11 +2604,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
25992604
26002605 announcement_sigs: None,
26012606
2602- #[cfg(any(test, fuzzing))]
2603- next_local_commitment_tx_fee_info_cached: Mutex::new(None),
2604- #[cfg(any(test, fuzzing))]
2605- next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
2606-
26072607 workaround_lnd_bug_4006: None,
26082608 sent_message_awaiting_response: None,
26092609
@@ -2726,6 +2726,11 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
27262726 holder_max_commitment_tx_output: Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)),
27272727 #[cfg(debug_assertions)]
27282728 counterparty_max_commitment_tx_output: Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)),
2729+
2730+ #[cfg(any(test, fuzzing))]
2731+ next_local_commitment_tx_fee_info_cached: Mutex::new(None),
2732+ #[cfg(any(test, fuzzing))]
2733+ next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
27292734 };
27302735 let channel_context = Self {
27312736 user_id,
@@ -2831,11 +2836,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
28312836
28322837 announcement_sigs: None,
28332838
2834- #[cfg(any(test, fuzzing))]
2835- next_local_commitment_tx_fee_info_cached: Mutex::new(None),
2836- #[cfg(any(test, fuzzing))]
2837- next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
2838-
28392839 workaround_lnd_bug_4006: None,
28402840 sent_message_awaiting_response: None,
28412841
@@ -3889,9 +3889,17 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
38893889 }
38903890
38913891 let htlc_above_dust = HTLCCandidate::new(real_dust_limit_timeout_sat * 1000, HTLCInitiator::LocalOffered);
3892- let mut max_reserved_commit_tx_fee_msat = context.next_local_commit_tx_fee_msat(htlc_above_dust, Some(()));
3892+ let mut max_reserved_commit_tx_fee_msat = context.next_local_commit_tx_fee_msat(
3893+ #[cfg(any(test, fuzzing))]
3894+ &funding,
3895+ htlc_above_dust, Some(()),
3896+ );
38933897 let htlc_dust = HTLCCandidate::new(real_dust_limit_timeout_sat * 1000 - 1, HTLCInitiator::LocalOffered);
3894- let mut min_reserved_commit_tx_fee_msat = context.next_local_commit_tx_fee_msat(htlc_dust, Some(()));
3898+ let mut min_reserved_commit_tx_fee_msat = context.next_local_commit_tx_fee_msat(
3899+ #[cfg(any(test, fuzzing))]
3900+ &funding,
3901+ htlc_dust, Some(()),
3902+ );
38953903 if !context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
38963904 max_reserved_commit_tx_fee_msat *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
38973905 min_reserved_commit_tx_fee_msat *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
@@ -3920,7 +3928,11 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
39203928 }
39213929
39223930 let htlc_above_dust = HTLCCandidate::new(real_dust_limit_success_sat * 1000, HTLCInitiator::LocalOffered);
3923- let max_reserved_commit_tx_fee_msat = context.next_remote_commit_tx_fee_msat(Some(htlc_above_dust), None);
3931+ let max_reserved_commit_tx_fee_msat = context.next_remote_commit_tx_fee_msat(
3932+ #[cfg(any(test, fuzzing))]
3933+ &funding,
3934+ Some(htlc_above_dust), None,
3935+ );
39243936
39253937 let holder_selected_chan_reserve_msat = funding.holder_selected_channel_reserve_satoshis * 1000;
39263938 let remote_balance_msat = (funding.channel_value_satoshis * 1000 - funding.value_to_self_msat)
@@ -4017,7 +4029,12 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
40174029 /// second allows for creating a buffer to ensure a further HTLC can always be accepted/added.
40184030 ///
40194031 /// Dust HTLCs are excluded.
4020- fn next_local_commit_tx_fee_msat(&self, htlc: HTLCCandidate, fee_spike_buffer_htlc: Option<()>) -> u64 {
4032+ fn next_local_commit_tx_fee_msat(
4033+ &self,
4034+ #[cfg(any(test, fuzzing))]
4035+ funding: &FundingScope,
4036+ htlc: HTLCCandidate, fee_spike_buffer_htlc: Option<()>,
4037+ ) -> u64 {
40214038 let context = &self;
40224039 assert!(context.is_outbound());
40234040
@@ -4106,7 +4123,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
41064123 },
41074124 feerate: context.feerate_per_kw,
41084125 };
4109- *context .next_local_commitment_tx_fee_info_cached.lock().unwrap() = Some(commitment_tx_info);
4126+ *funding .next_local_commitment_tx_fee_info_cached.lock().unwrap() = Some(commitment_tx_info);
41104127 }
41114128 res
41124129 }
@@ -4121,7 +4138,12 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
41214138 /// second allows for creating a buffer to ensure a further HTLC can always be accepted/added.
41224139 ///
41234140 /// Dust HTLCs are excluded.
4124- fn next_remote_commit_tx_fee_msat(&self, htlc: Option<HTLCCandidate>, fee_spike_buffer_htlc: Option<()>) -> u64 {
4141+ fn next_remote_commit_tx_fee_msat(
4142+ &self,
4143+ #[cfg(any(test, fuzzing))]
4144+ funding: &FundingScope,
4145+ htlc: Option<HTLCCandidate>, fee_spike_buffer_htlc: Option<()>,
4146+ ) -> u64 {
41254147 debug_assert!(htlc.is_some() || fee_spike_buffer_htlc.is_some(), "At least one of the options must be set");
41264148
41274149 let context = &self;
@@ -4200,7 +4222,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
42004222 },
42014223 feerate: context.feerate_per_kw,
42024224 };
4203- *context .next_remote_commitment_tx_fee_info_cached.lock().unwrap() = Some(commitment_tx_info);
4225+ *funding .next_remote_commitment_tx_fee_info_cached.lock().unwrap() = Some(commitment_tx_info);
42044226 }
42054227 res
42064228 }
@@ -5233,7 +5255,11 @@ impl<SP: Deref> FundedChannel<SP> where
52335255 {
52345256 let remote_commit_tx_fee_msat = if self.context.is_outbound() { 0 } else {
52355257 let htlc_candidate = HTLCCandidate::new(msg.amount_msat, HTLCInitiator::RemoteOffered);
5236- self.context.next_remote_commit_tx_fee_msat(Some(htlc_candidate), None) // Don't include the extra fee spike buffer HTLC in calculations
5258+ self.context.next_remote_commit_tx_fee_msat(
5259+ #[cfg(any(test, fuzzing))]
5260+ &self.funding,
5261+ Some(htlc_candidate), None, // Don't include the extra fee spike buffer HTLC in calculations
5262+ )
52375263 };
52385264 let anchor_outputs_value_msat = if !self.context.is_outbound() && self.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
52395265 ANCHOR_OUTPUT_VALUE_SATOSHI * 2 * 1000
@@ -5256,7 +5282,11 @@ impl<SP: Deref> FundedChannel<SP> where
52565282 if self.context.is_outbound() {
52575283 // Check that they won't violate our local required channel reserve by adding this HTLC.
52585284 let htlc_candidate = HTLCCandidate::new(msg.amount_msat, HTLCInitiator::RemoteOffered);
5259- let local_commit_tx_fee_msat = self.context.next_local_commit_tx_fee_msat(htlc_candidate, None);
5285+ let local_commit_tx_fee_msat = self.context.next_local_commit_tx_fee_msat(
5286+ #[cfg(any(test, fuzzing))]
5287+ &self.funding,
5288+ htlc_candidate, None,
5289+ );
52605290 if self.funding.value_to_self_msat < self.funding.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 + local_commit_tx_fee_msat + anchor_outputs_value_msat {
52615291 return Err(ChannelError::close("Cannot accept HTLC that would put our balance under counterparty-announced channel reserve value".to_owned()));
52625292 }
@@ -5434,8 +5464,8 @@ impl<SP: Deref> FundedChannel<SP> where
54345464 #[cfg(any(test, fuzzing))]
54355465 {
54365466 if self.context.is_outbound() {
5437- let projected_commit_tx_info = self.context .next_local_commitment_tx_fee_info_cached.lock().unwrap().take();
5438- *self.context .next_remote_commitment_tx_fee_info_cached.lock().unwrap() = None;
5467+ let projected_commit_tx_info = self.funding .next_local_commitment_tx_fee_info_cached.lock().unwrap().take();
5468+ *self.funding .next_remote_commitment_tx_fee_info_cached.lock().unwrap() = None;
54395469 if let Some(info) = projected_commit_tx_info {
54405470 let total_pending_htlcs = self.context.pending_inbound_htlcs.len() + self.context.pending_outbound_htlcs.len()
54415471 + self.context.holding_cell_htlc_updates.len();
@@ -5804,8 +5834,8 @@ impl<SP: Deref> FundedChannel<SP> where
58045834
58055835 #[cfg(any(test, fuzzing))]
58065836 {
5807- *self.context .next_local_commitment_tx_fee_info_cached.lock().unwrap() = None;
5808- *self.context .next_remote_commitment_tx_fee_info_cached.lock().unwrap() = None;
5837+ *self.funding .next_local_commitment_tx_fee_info_cached.lock().unwrap() = None;
5838+ *self.funding .next_remote_commitment_tx_fee_info_cached.lock().unwrap() = None;
58095839 }
58105840
58115841 match &self.context.holder_signer {
@@ -7445,7 +7475,11 @@ impl<SP: Deref> FundedChannel<SP> where
74457475 //
74467476 // A `None` `HTLCCandidate` is used as in this case because we're already accounting for
74477477 // the incoming HTLC as it has been fully committed by both sides.
7448- let mut remote_fee_cost_incl_stuck_buffer_msat = self.context.next_remote_commit_tx_fee_msat(None, Some(()));
7478+ let mut remote_fee_cost_incl_stuck_buffer_msat = self.context.next_remote_commit_tx_fee_msat(
7479+ #[cfg(any(test, fuzzing))]
7480+ &self.funding,
7481+ None, Some(()),
7482+ );
74497483 if !self.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
74507484 remote_fee_cost_incl_stuck_buffer_msat *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
74517485 }
@@ -8387,8 +8421,8 @@ impl<SP: Deref> FundedChannel<SP> where
83878421 #[cfg(any(test, fuzzing))]
83888422 {
83898423 if !self.context.is_outbound() {
8390- let projected_commit_tx_info = self.context .next_remote_commitment_tx_fee_info_cached.lock().unwrap().take();
8391- *self.context .next_local_commitment_tx_fee_info_cached.lock().unwrap() = None;
8424+ let projected_commit_tx_info = self.funding .next_remote_commitment_tx_fee_info_cached.lock().unwrap().take();
8425+ *self.funding .next_local_commitment_tx_fee_info_cached.lock().unwrap() = None;
83928426 if let Some(info) = projected_commit_tx_info {
83938427 let total_pending_htlcs = self.context.pending_inbound_htlcs.len() + self.context.pending_outbound_htlcs.len();
83948428 if info.total_pending_htlcs == total_pending_htlcs
@@ -10413,6 +10447,11 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
1041310447 holder_max_commitment_tx_output: Mutex::new((0, 0)),
1041410448 #[cfg(debug_assertions)]
1041510449 counterparty_max_commitment_tx_output: Mutex::new((0, 0)),
10450+
10451+ #[cfg(any(test, fuzzing))]
10452+ next_local_commitment_tx_fee_info_cached: Mutex::new(None),
10453+ #[cfg(any(test, fuzzing))]
10454+ next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
1041610455 },
1041710456 context: ChannelContext {
1041810457 user_id,
@@ -10508,11 +10547,6 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
1050810547
1050910548 announcement_sigs,
1051010549
10511- #[cfg(any(test, fuzzing))]
10512- next_local_commitment_tx_fee_info_cached: Mutex::new(None),
10513- #[cfg(any(test, fuzzing))]
10514- next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
10515-
1051610550 workaround_lnd_bug_4006: None,
1051710551 sent_message_awaiting_response: None,
1051810552
@@ -10782,7 +10816,7 @@ mod tests {
1078210816 // Make sure when Node A calculates their local commitment transaction, none of the HTLCs pass
1078310817 // the dust limit check.
1078410818 let htlc_candidate = HTLCCandidate::new(htlc_amount_msat, HTLCInitiator::LocalOffered);
10785- let local_commit_tx_fee = node_a_chan.context.next_local_commit_tx_fee_msat(htlc_candidate, None);
10819+ let local_commit_tx_fee = node_a_chan.context.next_local_commit_tx_fee_msat(&node_a_chan.funding, htlc_candidate, None);
1078610820 let local_commit_fee_0_htlcs = commit_tx_fee_sat(node_a_chan.context.feerate_per_kw, 0, node_a_chan.context.get_channel_type()) * 1000;
1078710821 assert_eq!(local_commit_tx_fee, local_commit_fee_0_htlcs);
1078810822
@@ -10791,7 +10825,7 @@ mod tests {
1079110825 node_a_chan.context.channel_transaction_parameters.is_outbound_from_holder = false;
1079210826 let remote_commit_fee_3_htlcs = commit_tx_fee_sat(node_a_chan.context.feerate_per_kw, 3, node_a_chan.context.get_channel_type()) * 1000;
1079310827 let htlc_candidate = HTLCCandidate::new(htlc_amount_msat, HTLCInitiator::LocalOffered);
10794- let remote_commit_tx_fee = node_a_chan.context.next_remote_commit_tx_fee_msat(Some(htlc_candidate), None);
10828+ let remote_commit_tx_fee = node_a_chan.context.next_remote_commit_tx_fee_msat(&node_a_chan.funding, Some(htlc_candidate), None);
1079510829 assert_eq!(remote_commit_tx_fee, remote_commit_fee_3_htlcs);
1079610830 }
1079710831
@@ -10819,27 +10853,27 @@ mod tests {
1081910853 // counted as dust when it shouldn't be.
1082010854 let htlc_amt_above_timeout = ((253 * htlc_timeout_tx_weight(chan.context.get_channel_type()) / 1000) + chan.context.holder_dust_limit_satoshis + 1) * 1000;
1082110855 let htlc_candidate = HTLCCandidate::new(htlc_amt_above_timeout, HTLCInitiator::LocalOffered);
10822- let commitment_tx_fee = chan.context.next_local_commit_tx_fee_msat(htlc_candidate, None);
10856+ let commitment_tx_fee = chan.context.next_local_commit_tx_fee_msat(&chan.funding, htlc_candidate, None);
1082310857 assert_eq!(commitment_tx_fee, commitment_tx_fee_1_htlc);
1082410858
1082510859 // If swapped: this HTLC would be counted as non-dust when it shouldn't be.
1082610860 let dust_htlc_amt_below_success = ((253 * htlc_success_tx_weight(chan.context.get_channel_type()) / 1000) + chan.context.holder_dust_limit_satoshis - 1) * 1000;
1082710861 let htlc_candidate = HTLCCandidate::new(dust_htlc_amt_below_success, HTLCInitiator::RemoteOffered);
10828- let commitment_tx_fee = chan.context.next_local_commit_tx_fee_msat(htlc_candidate, None);
10862+ let commitment_tx_fee = chan.context.next_local_commit_tx_fee_msat(&chan.funding, htlc_candidate, None);
1082910863 assert_eq!(commitment_tx_fee, commitment_tx_fee_0_htlcs);
1083010864
1083110865 chan.context.channel_transaction_parameters.is_outbound_from_holder = false;
1083210866
1083310867 // If swapped: this HTLC would be counted as non-dust when it shouldn't be.
1083410868 let dust_htlc_amt_above_timeout = ((253 * htlc_timeout_tx_weight(chan.context.get_channel_type()) / 1000) + chan.context.counterparty_dust_limit_satoshis + 1) * 1000;
1083510869 let htlc_candidate = HTLCCandidate::new(dust_htlc_amt_above_timeout, HTLCInitiator::LocalOffered);
10836- let commitment_tx_fee = chan.context.next_remote_commit_tx_fee_msat(Some(htlc_candidate), None);
10870+ let commitment_tx_fee = chan.context.next_remote_commit_tx_fee_msat(&chan.funding, Some(htlc_candidate), None);
1083710871 assert_eq!(commitment_tx_fee, commitment_tx_fee_0_htlcs);
1083810872
1083910873 // If swapped: this HTLC would be counted as dust when it shouldn't be.
1084010874 let htlc_amt_below_success = ((253 * htlc_success_tx_weight(chan.context.get_channel_type()) / 1000) + chan.context.counterparty_dust_limit_satoshis - 1) * 1000;
1084110875 let htlc_candidate = HTLCCandidate::new(htlc_amt_below_success, HTLCInitiator::RemoteOffered);
10842- let commitment_tx_fee = chan.context.next_remote_commit_tx_fee_msat(Some(htlc_candidate), None);
10876+ let commitment_tx_fee = chan.context.next_remote_commit_tx_fee_msat(&chan.funding, Some(htlc_candidate), None);
1084310877 assert_eq!(commitment_tx_fee, commitment_tx_fee_1_htlc);
1084410878 }
1084510879
0 commit comments