@@ -1984,6 +1984,10 @@ pub(super) struct FundingScope {
1984
1984
next_local_commitment_tx_fee_info_cached: Mutex<Option<CommitmentTxInfoCached>>,
1985
1985
#[cfg(any(test, fuzzing))]
1986
1986
next_remote_commitment_tx_fee_info_cached: Mutex<Option<CommitmentTxInfoCached>>,
1987
+ #[cfg(any(test, fuzzing))]
1988
+ next_local_fee: Mutex<PredictedNextFee>,
1989
+ #[cfg(any(test, fuzzing))]
1990
+ next_remote_fee: Mutex<PredictedNextFee>,
1987
1991
1988
1992
pub(super) channel_transaction_parameters: ChannelTransactionParameters,
1989
1993
@@ -2060,6 +2064,10 @@ impl Readable for FundingScope {
2060
2064
next_local_commitment_tx_fee_info_cached: Mutex::new(None),
2061
2065
#[cfg(any(test, fuzzing))]
2062
2066
next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
2067
+ #[cfg(any(test, fuzzing))]
2068
+ next_local_fee: Mutex::new(PredictedNextFee::default()),
2069
+ #[cfg(any(test, fuzzing))]
2070
+ next_remote_fee: Mutex::new(PredictedNextFee::default()),
2063
2071
})
2064
2072
}
2065
2073
}
@@ -3206,6 +3214,10 @@ where
3206
3214
next_local_commitment_tx_fee_info_cached: Mutex::new(None),
3207
3215
#[cfg(any(test, fuzzing))]
3208
3216
next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
3217
+ #[cfg(any(test, fuzzing))]
3218
+ next_local_fee: Mutex::new(PredictedNextFee::default()),
3219
+ #[cfg(any(test, fuzzing))]
3220
+ next_remote_fee: Mutex::new(PredictedNextFee::default()),
3209
3221
3210
3222
channel_transaction_parameters: ChannelTransactionParameters {
3211
3223
holder_pubkeys: pubkeys,
@@ -3449,6 +3461,10 @@ where
3449
3461
next_local_commitment_tx_fee_info_cached: Mutex::new(None),
3450
3462
#[cfg(any(test, fuzzing))]
3451
3463
next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
3464
+ #[cfg(any(test, fuzzing))]
3465
+ next_local_fee: Mutex::new(PredictedNextFee::default()),
3466
+ #[cfg(any(test, fuzzing))]
3467
+ next_remote_fee: Mutex::new(PredictedNextFee::default()),
3452
3468
3453
3469
channel_transaction_parameters: ChannelTransactionParameters {
3454
3470
holder_pubkeys: pubkeys,
@@ -4329,6 +4345,25 @@ where
4329
4345
}
4330
4346
}
4331
4347
4348
+ #[cfg(any(test, fuzzing))]
4349
+ {
4350
+ let mut local_predicted_htlcs = next_local_commitment_stats.next_commitment_htlcs;
4351
+ local_predicted_htlcs.sort_unstable();
4352
+ *funding.next_local_fee.lock().unwrap() = PredictedNextFee {
4353
+ predicted_feerate: self.feerate_per_kw,
4354
+ predicted_htlcs: local_predicted_htlcs,
4355
+ predicted_fee_sat: next_local_commitment_stats.commit_tx_fee_sat,
4356
+ };
4357
+
4358
+ let mut remote_predicted_htlcs = next_remote_commitment_stats.next_commitment_htlcs;
4359
+ remote_predicted_htlcs.sort_unstable();
4360
+ *funding.next_remote_fee.lock().unwrap() = PredictedNextFee {
4361
+ predicted_feerate: self.feerate_per_kw,
4362
+ predicted_htlcs: remote_predicted_htlcs,
4363
+ predicted_fee_sat: next_remote_commitment_stats.commit_tx_fee_sat,
4364
+ };
4365
+ }
4366
+
4332
4367
Ok(())
4333
4368
}
4334
4369
@@ -4357,6 +4392,25 @@ where
4357
4392
msg.feerate_per_kw, next_remote_commitment_stats.dust_exposure_msat)));
4358
4393
}
4359
4394
4395
+ #[cfg(any(test, fuzzing))]
4396
+ {
4397
+ let mut local_predicted_htlcs = next_local_commitment_stats.next_commitment_htlcs;
4398
+ local_predicted_htlcs.sort_unstable();
4399
+ *funding.next_local_fee.lock().unwrap() = PredictedNextFee {
4400
+ predicted_feerate: msg.feerate_per_kw,
4401
+ predicted_htlcs: local_predicted_htlcs,
4402
+ predicted_fee_sat: next_local_commitment_stats.commit_tx_fee_sat,
4403
+ };
4404
+
4405
+ let mut remote_predicted_htlcs = next_remote_commitment_stats.next_commitment_htlcs;
4406
+ remote_predicted_htlcs.sort_unstable();
4407
+ *funding.next_remote_fee.lock().unwrap() = PredictedNextFee {
4408
+ predicted_feerate: msg.feerate_per_kw,
4409
+ predicted_htlcs: remote_predicted_htlcs,
4410
+ predicted_fee_sat: next_remote_commitment_stats.commit_tx_fee_sat,
4411
+ };
4412
+ }
4413
+
4360
4414
Ok(())
4361
4415
}
4362
4416
@@ -4416,6 +4470,12 @@ where
4416
4470
}
4417
4471
}
4418
4472
}
4473
+ let PredictedNextFee { predicted_feerate, predicted_htlcs, predicted_fee_sat } = funding.next_local_fee.lock().unwrap().clone();
4474
+ let mut actual_nondust_htlcs: Vec<_> = commitment_data.tx.nondust_htlcs().iter().map(|&HTLCOutputInCommitment { offered, amount_msat, .. } | HTLCAmountDirection { outbound: offered, amount_msat }).collect();
4475
+ actual_nondust_htlcs.sort_unstable();
4476
+ if predicted_feerate == commitment_data.tx.feerate_per_kw() && predicted_htlcs == actual_nondust_htlcs {
4477
+ assert_eq!(predicted_fee_sat, commitment_data.stats.commit_tx_fee_sat);
4478
+ }
4419
4479
}
4420
4480
4421
4481
if msg.htlc_signatures.len() != commitment_data.tx.nondust_htlcs().len() {
@@ -4487,6 +4547,27 @@ where
4487
4547
return false;
4488
4548
}
4489
4549
4550
+ #[cfg(any(test, fuzzing))]
4551
+ {
4552
+ let next_local_commitment_stats = self.get_next_local_commitment_stats(funding, None, true, 0, feerate_per_kw, dust_exposure_limiting_feerate);
4553
+ let mut local_predicted_htlcs = next_local_commitment_stats.next_commitment_htlcs;
4554
+ local_predicted_htlcs.sort_unstable();
4555
+ *funding.next_local_fee.lock().unwrap() = PredictedNextFee {
4556
+ predicted_feerate: feerate_per_kw,
4557
+ predicted_htlcs: local_predicted_htlcs,
4558
+ predicted_fee_sat: next_local_commitment_stats.commit_tx_fee_sat,
4559
+ };
4560
+
4561
+ let next_remote_commitment_stats = self.get_next_remote_commitment_stats(funding, None, true, 0, feerate_per_kw, dust_exposure_limiting_feerate);
4562
+ let mut remote_predicted_htlcs = next_remote_commitment_stats.next_commitment_htlcs;
4563
+ remote_predicted_htlcs.sort_unstable();
4564
+ *funding.next_remote_fee.lock().unwrap() = PredictedNextFee {
4565
+ predicted_feerate: feerate_per_kw,
4566
+ predicted_htlcs: remote_predicted_htlcs,
4567
+ predicted_fee_sat: next_remote_commitment_stats.commit_tx_fee_sat,
4568
+ };
4569
+ }
4570
+
4490
4571
return true;
4491
4572
}
4492
4573
@@ -4539,6 +4620,35 @@ where
4539
4620
}
4540
4621
}
4541
4622
4623
+ #[cfg(any(test, fuzzing))]
4624
+ {
4625
+ let next_local_commitment_stats = if fee_spike_buffer_htlc == 1 {
4626
+ self.get_next_local_commitment_stats(funding, None, false, 0, self.feerate_per_kw, dust_exposure_limiting_feerate)
4627
+ } else {
4628
+ next_local_commitment_stats
4629
+ };
4630
+ let mut local_predicted_htlcs = next_local_commitment_stats.next_commitment_htlcs;
4631
+ local_predicted_htlcs.sort_unstable();
4632
+ *funding.next_local_fee.lock().unwrap() = PredictedNextFee {
4633
+ predicted_feerate: self.feerate_per_kw,
4634
+ predicted_htlcs: local_predicted_htlcs,
4635
+ predicted_fee_sat: next_local_commitment_stats.commit_tx_fee_sat,
4636
+ };
4637
+
4638
+ let next_remote_commitment_stats = if fee_spike_buffer_htlc == 1 {
4639
+ self.get_next_remote_commitment_stats(funding, None, false, 0, self.feerate_per_kw, dust_exposure_limiting_feerate)
4640
+ } else {
4641
+ next_remote_commitment_stats
4642
+ };
4643
+ let mut remote_predicted_htlcs = next_remote_commitment_stats.next_commitment_htlcs;
4644
+ remote_predicted_htlcs.sort_unstable();
4645
+ *funding.next_remote_fee.lock().unwrap() = PredictedNextFee {
4646
+ predicted_feerate: self.feerate_per_kw,
4647
+ predicted_htlcs: remote_predicted_htlcs,
4648
+ predicted_fee_sat: next_remote_commitment_stats.commit_tx_fee_sat,
4649
+ };
4650
+ }
4651
+
4542
4652
Ok(())
4543
4653
}
4544
4654
@@ -6028,6 +6138,14 @@ struct CommitmentTxInfoCached {
6028
6138
feerate: u32,
6029
6139
}
6030
6140
6141
+ #[cfg(any(test, fuzzing))]
6142
+ #[derive(Clone, Default)]
6143
+ struct PredictedNextFee {
6144
+ predicted_feerate: u32,
6145
+ predicted_htlcs: Vec<HTLCAmountDirection>,
6146
+ predicted_fee_sat: u64,
6147
+ }
6148
+
6031
6149
/// Contents of a wire message that fails an HTLC backwards. Useful for [`FundedChannel::fail_htlc`] to
6032
6150
/// fail with either [`msgs::UpdateFailMalformedHTLC`] or [`msgs::UpdateFailHTLC`] as needed.
6033
6151
trait FailHTLCContents {
@@ -10992,6 +11110,12 @@ where
10992
11110
}
10993
11111
}
10994
11112
}
11113
+ let PredictedNextFee { predicted_feerate, predicted_htlcs, predicted_fee_sat } = funding.next_remote_fee.lock().unwrap().clone();
11114
+ let mut actual_nondust_htlcs: Vec<_> = counterparty_commitment_tx.nondust_htlcs().iter().map(|&HTLCOutputInCommitment { offered, amount_msat, .. }| HTLCAmountDirection { outbound: !offered, amount_msat }).collect();
11115
+ actual_nondust_htlcs.sort_unstable();
11116
+ if predicted_feerate == counterparty_commitment_tx.feerate_per_kw() && predicted_htlcs == actual_nondust_htlcs {
11117
+ assert_eq!(predicted_fee_sat, commitment_data.stats.commit_tx_fee_sat);
11118
+ }
10995
11119
}
10996
11120
10997
11121
(commitment_data.htlcs_included, counterparty_commitment_tx)
@@ -13617,6 +13741,10 @@ where
13617
13741
next_local_commitment_tx_fee_info_cached: Mutex::new(None),
13618
13742
#[cfg(any(test, fuzzing))]
13619
13743
next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
13744
+ #[cfg(any(test, fuzzing))]
13745
+ next_local_fee: Mutex::new(PredictedNextFee::default()),
13746
+ #[cfg(any(test, fuzzing))]
13747
+ next_remote_fee: Mutex::new(PredictedNextFee::default()),
13620
13748
13621
13749
channel_transaction_parameters: channel_parameters,
13622
13750
funding_transaction,
0 commit comments