@@ -1579,6 +1579,15 @@ pub(super) struct FundingScope {
15791579 #[cfg(debug_assertions)]
15801580 /// Max to_local and to_remote outputs in a remote-generated commitment transaction
15811581 counterparty_max_commitment_tx_output: Mutex<(u64, u64)>,
1582+
1583+ // We save these values so we can make sure `next_local_commit_tx_fee_msat` and
1584+ // `next_remote_commit_tx_fee_msat` properly predict what the next commitment transaction fee will
1585+ // be, by comparing the cached values to the fee of the transaction generated by
1586+ // `build_commitment_transaction`.
1587+ #[cfg(any(test, fuzzing))]
1588+ next_local_commitment_tx_fee_info_cached: Mutex<Option<CommitmentTxInfoCached>>,
1589+ #[cfg(any(test, fuzzing))]
1590+ next_remote_commitment_tx_fee_info_cached: Mutex<Option<CommitmentTxInfoCached>>,
15821591}
15831592
15841593impl FundingScope {
@@ -1823,15 +1832,6 @@ pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
18231832 /// This can be used to rebroadcast the channel_announcement message later.
18241833 announcement_sigs: Option<(Signature, Signature)>,
18251834
1826- // We save these values so we can make sure `next_local_commit_tx_fee_msat` and
1827- // `next_remote_commit_tx_fee_msat` properly predict what the next commitment transaction fee will
1828- // be, by comparing the cached values to the fee of the tranaction generated by
1829- // `build_commitment_transaction`.
1830- #[cfg(any(test, fuzzing))]
1831- next_local_commitment_tx_fee_info_cached: Mutex<Option<CommitmentTxInfoCached>>,
1832- #[cfg(any(test, fuzzing))]
1833- next_remote_commitment_tx_fee_info_cached: Mutex<Option<CommitmentTxInfoCached>>,
1834-
18351835 /// lnd has a long-standing bug where, upon reconnection, if the channel is not yet confirmed
18361836 /// they will not send a channel_reestablish until the channel locks in. Then, they will send a
18371837 /// channel_ready *before* sending the channel_reestablish (which is clearly a violation of
@@ -2470,6 +2470,11 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
24702470 holder_max_commitment_tx_output: Mutex::new((value_to_self_msat, (channel_value_satoshis * 1000 - msg_push_msat).saturating_sub(value_to_self_msat))),
24712471 #[cfg(debug_assertions)]
24722472 counterparty_max_commitment_tx_output: Mutex::new((value_to_self_msat, (channel_value_satoshis * 1000 - msg_push_msat).saturating_sub(value_to_self_msat))),
2473+
2474+ #[cfg(any(test, fuzzing))]
2475+ next_local_commitment_tx_fee_info_cached: Mutex::new(None),
2476+ #[cfg(any(test, fuzzing))]
2477+ next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
24732478 };
24742479 let channel_context = ChannelContext {
24752480 user_id,
@@ -2578,11 +2583,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
25782583
25792584 announcement_sigs: None,
25802585
2581- #[cfg(any(test, fuzzing))]
2582- next_local_commitment_tx_fee_info_cached: Mutex::new(None),
2583- #[cfg(any(test, fuzzing))]
2584- next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
2585-
25862586 workaround_lnd_bug_4006: None,
25872587 sent_message_awaiting_response: None,
25882588
@@ -2705,6 +2705,11 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
27052705 holder_max_commitment_tx_output: Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)),
27062706 #[cfg(debug_assertions)]
27072707 counterparty_max_commitment_tx_output: Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)),
2708+
2709+ #[cfg(any(test, fuzzing))]
2710+ next_local_commitment_tx_fee_info_cached: Mutex::new(None),
2711+ #[cfg(any(test, fuzzing))]
2712+ next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
27082713 };
27092714 let channel_context = Self {
27102715 user_id,
@@ -2810,11 +2815,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
28102815
28112816 announcement_sigs: None,
28122817
2813- #[cfg(any(test, fuzzing))]
2814- next_local_commitment_tx_fee_info_cached: Mutex::new(None),
2815- #[cfg(any(test, fuzzing))]
2816- next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
2817-
28182818 workaround_lnd_bug_4006: None,
28192819 sent_message_awaiting_response: None,
28202820
@@ -3868,9 +3868,17 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
38683868 }
38693869
38703870 let htlc_above_dust = HTLCCandidate::new(real_dust_limit_timeout_sat * 1000, HTLCInitiator::LocalOffered);
3871- let mut max_reserved_commit_tx_fee_msat = context.next_local_commit_tx_fee_msat(htlc_above_dust, Some(()));
3871+ let mut max_reserved_commit_tx_fee_msat = context.next_local_commit_tx_fee_msat(
3872+ #[cfg(any(test, fuzzing))]
3873+ &funding,
3874+ htlc_above_dust, Some(()),
3875+ );
38723876 let htlc_dust = HTLCCandidate::new(real_dust_limit_timeout_sat * 1000 - 1, HTLCInitiator::LocalOffered);
3873- let mut min_reserved_commit_tx_fee_msat = context.next_local_commit_tx_fee_msat(htlc_dust, Some(()));
3877+ let mut min_reserved_commit_tx_fee_msat = context.next_local_commit_tx_fee_msat(
3878+ #[cfg(any(test, fuzzing))]
3879+ &funding,
3880+ htlc_dust, Some(()),
3881+ );
38743882 if !context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
38753883 max_reserved_commit_tx_fee_msat *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
38763884 min_reserved_commit_tx_fee_msat *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
@@ -3899,7 +3907,11 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
38993907 }
39003908
39013909 let htlc_above_dust = HTLCCandidate::new(real_dust_limit_success_sat * 1000, HTLCInitiator::LocalOffered);
3902- let max_reserved_commit_tx_fee_msat = context.next_remote_commit_tx_fee_msat(Some(htlc_above_dust), None);
3910+ let max_reserved_commit_tx_fee_msat = context.next_remote_commit_tx_fee_msat(
3911+ #[cfg(any(test, fuzzing))]
3912+ &funding,
3913+ Some(htlc_above_dust), None,
3914+ );
39033915
39043916 let holder_selected_chan_reserve_msat = funding.holder_selected_channel_reserve_satoshis * 1000;
39053917 let remote_balance_msat = (funding.channel_value_satoshis * 1000 - funding.value_to_self_msat)
@@ -3996,7 +4008,12 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
39964008 /// second allows for creating a buffer to ensure a further HTLC can always be accepted/added.
39974009 ///
39984010 /// Dust HTLCs are excluded.
3999- fn next_local_commit_tx_fee_msat(&self, htlc: HTLCCandidate, fee_spike_buffer_htlc: Option<()>) -> u64 {
4011+ fn next_local_commit_tx_fee_msat(
4012+ &self,
4013+ #[cfg(any(test, fuzzing))]
4014+ funding: &FundingScope,
4015+ htlc: HTLCCandidate, fee_spike_buffer_htlc: Option<()>,
4016+ ) -> u64 {
40004017 let context = &self;
40014018 assert!(context.is_outbound());
40024019
@@ -4085,7 +4102,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
40854102 },
40864103 feerate: context.feerate_per_kw,
40874104 };
4088- *context .next_local_commitment_tx_fee_info_cached.lock().unwrap() = Some(commitment_tx_info);
4105+ *funding .next_local_commitment_tx_fee_info_cached.lock().unwrap() = Some(commitment_tx_info);
40894106 }
40904107 res
40914108 }
@@ -4100,7 +4117,12 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
41004117 /// second allows for creating a buffer to ensure a further HTLC can always be accepted/added.
41014118 ///
41024119 /// Dust HTLCs are excluded.
4103- fn next_remote_commit_tx_fee_msat(&self, htlc: Option<HTLCCandidate>, fee_spike_buffer_htlc: Option<()>) -> u64 {
4120+ fn next_remote_commit_tx_fee_msat(
4121+ &self,
4122+ #[cfg(any(test, fuzzing))]
4123+ funding: &FundingScope,
4124+ htlc: Option<HTLCCandidate>, fee_spike_buffer_htlc: Option<()>,
4125+ ) -> u64 {
41044126 debug_assert!(htlc.is_some() || fee_spike_buffer_htlc.is_some(), "At least one of the options must be set");
41054127
41064128 let context = &self;
@@ -4179,7 +4201,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
41794201 },
41804202 feerate: context.feerate_per_kw,
41814203 };
4182- *context .next_remote_commitment_tx_fee_info_cached.lock().unwrap() = Some(commitment_tx_info);
4204+ *funding .next_remote_commitment_tx_fee_info_cached.lock().unwrap() = Some(commitment_tx_info);
41834205 }
41844206 res
41854207 }
@@ -5199,7 +5221,11 @@ impl<SP: Deref> FundedChannel<SP> where
51995221 {
52005222 let remote_commit_tx_fee_msat = if self.context.is_outbound() { 0 } else {
52015223 let htlc_candidate = HTLCCandidate::new(msg.amount_msat, HTLCInitiator::RemoteOffered);
5202- self.context.next_remote_commit_tx_fee_msat(Some(htlc_candidate), None) // Don't include the extra fee spike buffer HTLC in calculations
5224+ self.context.next_remote_commit_tx_fee_msat(
5225+ #[cfg(any(test, fuzzing))]
5226+ &self.funding,
5227+ Some(htlc_candidate), None, // Don't include the extra fee spike buffer HTLC in calculations
5228+ )
52035229 };
52045230 let anchor_outputs_value_msat = if !self.context.is_outbound() && self.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
52055231 ANCHOR_OUTPUT_VALUE_SATOSHI * 2 * 1000
@@ -5222,7 +5248,11 @@ impl<SP: Deref> FundedChannel<SP> where
52225248 if self.context.is_outbound() {
52235249 // Check that they won't violate our local required channel reserve by adding this HTLC.
52245250 let htlc_candidate = HTLCCandidate::new(msg.amount_msat, HTLCInitiator::RemoteOffered);
5225- let local_commit_tx_fee_msat = self.context.next_local_commit_tx_fee_msat(htlc_candidate, None);
5251+ let local_commit_tx_fee_msat = self.context.next_local_commit_tx_fee_msat(
5252+ #[cfg(any(test, fuzzing))]
5253+ &self.funding,
5254+ htlc_candidate, None,
5255+ );
52265256 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 {
52275257 return Err(ChannelError::close("Cannot accept HTLC that would put our balance under counterparty-announced channel reserve value".to_owned()));
52285258 }
@@ -5400,8 +5430,8 @@ impl<SP: Deref> FundedChannel<SP> where
54005430 #[cfg(any(test, fuzzing))]
54015431 {
54025432 if self.context.is_outbound() {
5403- let projected_commit_tx_info = self.context .next_local_commitment_tx_fee_info_cached.lock().unwrap().take();
5404- *self.context .next_remote_commitment_tx_fee_info_cached.lock().unwrap() = None;
5433+ let projected_commit_tx_info = self.funding .next_local_commitment_tx_fee_info_cached.lock().unwrap().take();
5434+ *self.funding .next_remote_commitment_tx_fee_info_cached.lock().unwrap() = None;
54055435 if let Some(info) = projected_commit_tx_info {
54065436 let total_pending_htlcs = self.context.pending_inbound_htlcs.len() + self.context.pending_outbound_htlcs.len()
54075437 + self.context.holding_cell_htlc_updates.len();
@@ -5770,8 +5800,8 @@ impl<SP: Deref> FundedChannel<SP> where
57705800
57715801 #[cfg(any(test, fuzzing))]
57725802 {
5773- *self.context .next_local_commitment_tx_fee_info_cached.lock().unwrap() = None;
5774- *self.context .next_remote_commitment_tx_fee_info_cached.lock().unwrap() = None;
5803+ *self.funding .next_local_commitment_tx_fee_info_cached.lock().unwrap() = None;
5804+ *self.funding .next_remote_commitment_tx_fee_info_cached.lock().unwrap() = None;
57755805 }
57765806
57775807 match &self.context.holder_signer {
@@ -7411,7 +7441,11 @@ impl<SP: Deref> FundedChannel<SP> where
74117441 //
74127442 // A `None` `HTLCCandidate` is used as in this case because we're already accounting for
74137443 // the incoming HTLC as it has been fully committed by both sides.
7414- let mut remote_fee_cost_incl_stuck_buffer_msat = self.context.next_remote_commit_tx_fee_msat(None, Some(()));
7444+ let mut remote_fee_cost_incl_stuck_buffer_msat = self.context.next_remote_commit_tx_fee_msat(
7445+ #[cfg(any(test, fuzzing))]
7446+ &self.funding,
7447+ None, Some(()),
7448+ );
74157449 if !self.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
74167450 remote_fee_cost_incl_stuck_buffer_msat *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
74177451 }
@@ -8353,8 +8387,8 @@ impl<SP: Deref> FundedChannel<SP> where
83538387 #[cfg(any(test, fuzzing))]
83548388 {
83558389 if !self.context.is_outbound() {
8356- let projected_commit_tx_info = self.context .next_remote_commitment_tx_fee_info_cached.lock().unwrap().take();
8357- *self.context .next_local_commitment_tx_fee_info_cached.lock().unwrap() = None;
8390+ let projected_commit_tx_info = self.funding .next_remote_commitment_tx_fee_info_cached.lock().unwrap().take();
8391+ *self.funding .next_local_commitment_tx_fee_info_cached.lock().unwrap() = None;
83588392 if let Some(info) = projected_commit_tx_info {
83598393 let total_pending_htlcs = self.context.pending_inbound_htlcs.len() + self.context.pending_outbound_htlcs.len();
83608394 if info.total_pending_htlcs == total_pending_htlcs
@@ -10375,6 +10409,11 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
1037510409 holder_max_commitment_tx_output: Mutex::new((0, 0)),
1037610410 #[cfg(debug_assertions)]
1037710411 counterparty_max_commitment_tx_output: Mutex::new((0, 0)),
10412+
10413+ #[cfg(any(test, fuzzing))]
10414+ next_local_commitment_tx_fee_info_cached: Mutex::new(None),
10415+ #[cfg(any(test, fuzzing))]
10416+ next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
1037810417 },
1037910418 context: ChannelContext {
1038010419 user_id,
@@ -10470,11 +10509,6 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
1047010509
1047110510 announcement_sigs,
1047210511
10473- #[cfg(any(test, fuzzing))]
10474- next_local_commitment_tx_fee_info_cached: Mutex::new(None),
10475- #[cfg(any(test, fuzzing))]
10476- next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
10477-
1047810512 workaround_lnd_bug_4006: None,
1047910513 sent_message_awaiting_response: None,
1048010514
@@ -10744,7 +10778,7 @@ mod tests {
1074410778 // Make sure when Node A calculates their local commitment transaction, none of the HTLCs pass
1074510779 // the dust limit check.
1074610780 let htlc_candidate = HTLCCandidate::new(htlc_amount_msat, HTLCInitiator::LocalOffered);
10747- let local_commit_tx_fee = node_a_chan.context.next_local_commit_tx_fee_msat(htlc_candidate, None);
10781+ let local_commit_tx_fee = node_a_chan.context.next_local_commit_tx_fee_msat(&node_a_chan.funding, htlc_candidate, None);
1074810782 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;
1074910783 assert_eq!(local_commit_tx_fee, local_commit_fee_0_htlcs);
1075010784
@@ -10753,7 +10787,7 @@ mod tests {
1075310787 node_a_chan.context.channel_transaction_parameters.is_outbound_from_holder = false;
1075410788 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;
1075510789 let htlc_candidate = HTLCCandidate::new(htlc_amount_msat, HTLCInitiator::LocalOffered);
10756- let remote_commit_tx_fee = node_a_chan.context.next_remote_commit_tx_fee_msat(Some(htlc_candidate), None);
10790+ let remote_commit_tx_fee = node_a_chan.context.next_remote_commit_tx_fee_msat(&node_a_chan.funding, Some(htlc_candidate), None);
1075710791 assert_eq!(remote_commit_tx_fee, remote_commit_fee_3_htlcs);
1075810792 }
1075910793
@@ -10781,27 +10815,27 @@ mod tests {
1078110815 // counted as dust when it shouldn't be.
1078210816 let htlc_amt_above_timeout = ((253 * htlc_timeout_tx_weight(chan.context.get_channel_type()) / 1000) + chan.context.holder_dust_limit_satoshis + 1) * 1000;
1078310817 let htlc_candidate = HTLCCandidate::new(htlc_amt_above_timeout, HTLCInitiator::LocalOffered);
10784- let commitment_tx_fee = chan.context.next_local_commit_tx_fee_msat(htlc_candidate, None);
10818+ let commitment_tx_fee = chan.context.next_local_commit_tx_fee_msat(&chan.funding, htlc_candidate, None);
1078510819 assert_eq!(commitment_tx_fee, commitment_tx_fee_1_htlc);
1078610820
1078710821 // If swapped: this HTLC would be counted as non-dust when it shouldn't be.
1078810822 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;
1078910823 let htlc_candidate = HTLCCandidate::new(dust_htlc_amt_below_success, HTLCInitiator::RemoteOffered);
10790- let commitment_tx_fee = chan.context.next_local_commit_tx_fee_msat(htlc_candidate, None);
10824+ let commitment_tx_fee = chan.context.next_local_commit_tx_fee_msat(&chan.funding, htlc_candidate, None);
1079110825 assert_eq!(commitment_tx_fee, commitment_tx_fee_0_htlcs);
1079210826
1079310827 chan.context.channel_transaction_parameters.is_outbound_from_holder = false;
1079410828
1079510829 // If swapped: this HTLC would be counted as non-dust when it shouldn't be.
1079610830 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;
1079710831 let htlc_candidate = HTLCCandidate::new(dust_htlc_amt_above_timeout, HTLCInitiator::LocalOffered);
10798- let commitment_tx_fee = chan.context.next_remote_commit_tx_fee_msat(Some(htlc_candidate), None);
10832+ let commitment_tx_fee = chan.context.next_remote_commit_tx_fee_msat(&chan.funding, Some(htlc_candidate), None);
1079910833 assert_eq!(commitment_tx_fee, commitment_tx_fee_0_htlcs);
1080010834
1080110835 // If swapped: this HTLC would be counted as dust when it shouldn't be.
1080210836 let htlc_amt_below_success = ((253 * htlc_success_tx_weight(chan.context.get_channel_type()) / 1000) + chan.context.counterparty_dust_limit_satoshis - 1) * 1000;
1080310837 let htlc_candidate = HTLCCandidate::new(htlc_amt_below_success, HTLCInitiator::RemoteOffered);
10804- let commitment_tx_fee = chan.context.next_remote_commit_tx_fee_msat(Some(htlc_candidate), None);
10838+ let commitment_tx_fee = chan.context.next_remote_commit_tx_fee_msat(&chan.funding, Some(htlc_candidate), None);
1080510839 assert_eq!(commitment_tx_fee, commitment_tx_fee_1_htlc);
1080610840 }
1080710841
0 commit comments