@@ -1600,6 +1600,15 @@ pub(super) struct FundingScope {
1600
1600
#[cfg(debug_assertions)]
1601
1601
/// Max to_local and to_remote outputs in a remote-generated commitment transaction
1602
1602
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>>,
1603
1612
}
1604
1613
1605
1614
impl FundingScope {
@@ -1844,15 +1853,6 @@ pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
1844
1853
/// This can be used to rebroadcast the channel_announcement message later.
1845
1854
announcement_sigs: Option<(Signature, Signature)>,
1846
1855
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
-
1856
1856
/// lnd has a long-standing bug where, upon reconnection, if the channel is not yet confirmed
1857
1857
/// they will not send a channel_reestablish until the channel locks in. Then, they will send a
1858
1858
/// 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 {
2491
2491
holder_max_commitment_tx_output: Mutex::new((value_to_self_msat, (channel_value_satoshis * 1000 - msg_push_msat).saturating_sub(value_to_self_msat))),
2492
2492
#[cfg(debug_assertions)]
2493
2493
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),
2494
2499
};
2495
2500
let channel_context = ChannelContext {
2496
2501
user_id,
@@ -2599,11 +2604,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
2599
2604
2600
2605
announcement_sigs: None,
2601
2606
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
-
2607
2607
workaround_lnd_bug_4006: None,
2608
2608
sent_message_awaiting_response: None,
2609
2609
@@ -2726,6 +2726,11 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
2726
2726
holder_max_commitment_tx_output: Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)),
2727
2727
#[cfg(debug_assertions)]
2728
2728
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),
2729
2734
};
2730
2735
let channel_context = Self {
2731
2736
user_id,
@@ -2831,11 +2836,6 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
2831
2836
2832
2837
announcement_sigs: None,
2833
2838
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
-
2839
2839
workaround_lnd_bug_4006: None,
2840
2840
sent_message_awaiting_response: None,
2841
2841
@@ -3889,9 +3889,17 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3889
3889
}
3890
3890
3891
3891
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
+ );
3893
3897
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
+ );
3895
3903
if !context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
3896
3904
max_reserved_commit_tx_fee_msat *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
3897
3905
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 {
3920
3928
}
3921
3929
3922
3930
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
+ );
3924
3936
3925
3937
let holder_selected_chan_reserve_msat = funding.holder_selected_channel_reserve_satoshis * 1000;
3926
3938
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 {
4017
4029
/// second allows for creating a buffer to ensure a further HTLC can always be accepted/added.
4018
4030
///
4019
4031
/// 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 {
4021
4038
let context = &self;
4022
4039
assert!(context.is_outbound());
4023
4040
@@ -4106,7 +4123,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
4106
4123
},
4107
4124
feerate: context.feerate_per_kw,
4108
4125
};
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);
4110
4127
}
4111
4128
res
4112
4129
}
@@ -4121,7 +4138,12 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
4121
4138
/// second allows for creating a buffer to ensure a further HTLC can always be accepted/added.
4122
4139
///
4123
4140
/// 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 {
4125
4147
debug_assert!(htlc.is_some() || fee_spike_buffer_htlc.is_some(), "At least one of the options must be set");
4126
4148
4127
4149
let context = &self;
@@ -4200,7 +4222,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
4200
4222
},
4201
4223
feerate: context.feerate_per_kw,
4202
4224
};
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);
4204
4226
}
4205
4227
res
4206
4228
}
@@ -5233,7 +5255,11 @@ impl<SP: Deref> FundedChannel<SP> where
5233
5255
{
5234
5256
let remote_commit_tx_fee_msat = if self.context.is_outbound() { 0 } else {
5235
5257
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
+ )
5237
5263
};
5238
5264
let anchor_outputs_value_msat = if !self.context.is_outbound() && self.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
5239
5265
ANCHOR_OUTPUT_VALUE_SATOSHI * 2 * 1000
@@ -5256,7 +5282,11 @@ impl<SP: Deref> FundedChannel<SP> where
5256
5282
if self.context.is_outbound() {
5257
5283
// Check that they won't violate our local required channel reserve by adding this HTLC.
5258
5284
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
+ );
5260
5290
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 {
5261
5291
return Err(ChannelError::close("Cannot accept HTLC that would put our balance under counterparty-announced channel reserve value".to_owned()));
5262
5292
}
@@ -5434,8 +5464,8 @@ impl<SP: Deref> FundedChannel<SP> where
5434
5464
#[cfg(any(test, fuzzing))]
5435
5465
{
5436
5466
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;
5439
5469
if let Some(info) = projected_commit_tx_info {
5440
5470
let total_pending_htlcs = self.context.pending_inbound_htlcs.len() + self.context.pending_outbound_htlcs.len()
5441
5471
+ self.context.holding_cell_htlc_updates.len();
@@ -5804,8 +5834,8 @@ impl<SP: Deref> FundedChannel<SP> where
5804
5834
5805
5835
#[cfg(any(test, fuzzing))]
5806
5836
{
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;
5809
5839
}
5810
5840
5811
5841
match &self.context.holder_signer {
@@ -7445,7 +7475,11 @@ impl<SP: Deref> FundedChannel<SP> where
7445
7475
//
7446
7476
// A `None` `HTLCCandidate` is used as in this case because we're already accounting for
7447
7477
// 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
+ );
7449
7483
if !self.context.get_channel_type().supports_anchors_zero_fee_htlc_tx() {
7450
7484
remote_fee_cost_incl_stuck_buffer_msat *= FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
7451
7485
}
@@ -8387,8 +8421,8 @@ impl<SP: Deref> FundedChannel<SP> where
8387
8421
#[cfg(any(test, fuzzing))]
8388
8422
{
8389
8423
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;
8392
8426
if let Some(info) = projected_commit_tx_info {
8393
8427
let total_pending_htlcs = self.context.pending_inbound_htlcs.len() + self.context.pending_outbound_htlcs.len();
8394
8428
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
10413
10447
holder_max_commitment_tx_output: Mutex::new((0, 0)),
10414
10448
#[cfg(debug_assertions)]
10415
10449
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),
10416
10455
},
10417
10456
context: ChannelContext {
10418
10457
user_id,
@@ -10508,11 +10547,6 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
10508
10547
10509
10548
announcement_sigs,
10510
10549
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
-
10516
10550
workaround_lnd_bug_4006: None,
10517
10551
sent_message_awaiting_response: None,
10518
10552
@@ -10782,7 +10816,7 @@ mod tests {
10782
10816
// Make sure when Node A calculates their local commitment transaction, none of the HTLCs pass
10783
10817
// the dust limit check.
10784
10818
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);
10786
10820
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;
10787
10821
assert_eq!(local_commit_tx_fee, local_commit_fee_0_htlcs);
10788
10822
@@ -10791,7 +10825,7 @@ mod tests {
10791
10825
node_a_chan.context.channel_transaction_parameters.is_outbound_from_holder = false;
10792
10826
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;
10793
10827
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);
10795
10829
assert_eq!(remote_commit_tx_fee, remote_commit_fee_3_htlcs);
10796
10830
}
10797
10831
@@ -10819,27 +10853,27 @@ mod tests {
10819
10853
// counted as dust when it shouldn't be.
10820
10854
let htlc_amt_above_timeout = ((253 * htlc_timeout_tx_weight(chan.context.get_channel_type()) / 1000) + chan.context.holder_dust_limit_satoshis + 1) * 1000;
10821
10855
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);
10823
10857
assert_eq!(commitment_tx_fee, commitment_tx_fee_1_htlc);
10824
10858
10825
10859
// If swapped: this HTLC would be counted as non-dust when it shouldn't be.
10826
10860
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;
10827
10861
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);
10829
10863
assert_eq!(commitment_tx_fee, commitment_tx_fee_0_htlcs);
10830
10864
10831
10865
chan.context.channel_transaction_parameters.is_outbound_from_holder = false;
10832
10866
10833
10867
// If swapped: this HTLC would be counted as non-dust when it shouldn't be.
10834
10868
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;
10835
10869
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);
10837
10871
assert_eq!(commitment_tx_fee, commitment_tx_fee_0_htlcs);
10838
10872
10839
10873
// If swapped: this HTLC would be counted as dust when it shouldn't be.
10840
10874
let htlc_amt_below_success = ((253 * htlc_success_tx_weight(chan.context.get_channel_type()) / 1000) + chan.context.counterparty_dust_limit_satoshis - 1) * 1000;
10841
10875
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);
10843
10877
assert_eq!(commitment_tx_fee, commitment_tx_fee_1_htlc);
10844
10878
}
10845
10879
0 commit comments