@@ -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,
@@ -4322,6 +4338,25 @@ where
4322
4338
}
4323
4339
}
4324
4340
4341
+ #[cfg(any(test, fuzzing))]
4342
+ {
4343
+ let mut local_predicted_htlcs = next_local_commitment_stats.next_commitment_htlcs;
4344
+ local_predicted_htlcs.sort_unstable();
4345
+ *funding.next_local_fee.lock().unwrap() = PredictedNextFee {
4346
+ predicted_feerate: self.feerate_per_kw,
4347
+ predicted_htlcs: local_predicted_htlcs,
4348
+ predicted_fee_sat: next_local_commitment_stats.commit_tx_fee_sat,
4349
+ };
4350
+
4351
+ let mut remote_predicted_htlcs = next_remote_commitment_stats.next_commitment_htlcs;
4352
+ remote_predicted_htlcs.sort_unstable();
4353
+ *funding.next_remote_fee.lock().unwrap() = PredictedNextFee {
4354
+ predicted_feerate: self.feerate_per_kw,
4355
+ predicted_htlcs: remote_predicted_htlcs,
4356
+ predicted_fee_sat: next_remote_commitment_stats.commit_tx_fee_sat,
4357
+ };
4358
+ }
4359
+
4325
4360
Ok(())
4326
4361
}
4327
4362
@@ -4352,6 +4387,25 @@ where
4352
4387
msg.feerate_per_kw, next_remote_commitment_stats.dust_exposure_msat)));
4353
4388
}
4354
4389
4390
+ #[cfg(any(test, fuzzing))]
4391
+ {
4392
+ let mut local_predicted_htlcs = next_local_commitment_stats.next_commitment_htlcs;
4393
+ local_predicted_htlcs.sort_unstable();
4394
+ *funding.next_local_fee.lock().unwrap() = PredictedNextFee {
4395
+ predicted_feerate: msg.feerate_per_kw,
4396
+ predicted_htlcs: local_predicted_htlcs,
4397
+ predicted_fee_sat: next_local_commitment_stats.commit_tx_fee_sat,
4398
+ };
4399
+
4400
+ let mut remote_predicted_htlcs = next_remote_commitment_stats.next_commitment_htlcs;
4401
+ remote_predicted_htlcs.sort_unstable();
4402
+ *funding.next_remote_fee.lock().unwrap() = PredictedNextFee {
4403
+ predicted_feerate: msg.feerate_per_kw,
4404
+ predicted_htlcs: remote_predicted_htlcs,
4405
+ predicted_fee_sat: next_remote_commitment_stats.commit_tx_fee_sat,
4406
+ };
4407
+ }
4408
+
4355
4409
Ok(())
4356
4410
}
4357
4411
@@ -4411,6 +4465,12 @@ where
4411
4465
}
4412
4466
}
4413
4467
}
4468
+ let PredictedNextFee { predicted_feerate, predicted_htlcs, predicted_fee_sat } = funding.next_local_fee.lock().unwrap().clone();
4469
+ let mut actual_nondust_htlcs: Vec<_> = commitment_data.tx.nondust_htlcs().iter().map(|&HTLCOutputInCommitment { offered, amount_msat, .. } | HTLCAmountDirection { outbound: offered, amount_msat }).collect();
4470
+ actual_nondust_htlcs.sort_unstable();
4471
+ if predicted_feerate == commitment_data.tx.feerate_per_kw() && predicted_htlcs == actual_nondust_htlcs {
4472
+ assert_eq!(predicted_fee_sat, commitment_data.stats.commit_tx_fee_sat);
4473
+ }
4414
4474
}
4415
4475
4416
4476
if msg.htlc_signatures.len() != commitment_data.tx.nondust_htlcs().len() {
@@ -4484,6 +4544,27 @@ where
4484
4544
return false;
4485
4545
}
4486
4546
4547
+ #[cfg(any(test, fuzzing))]
4548
+ {
4549
+ let next_local_commitment_stats = self.get_next_local_commitment_stats(funding, None, true, 0, feerate_per_kw, dust_exposure_limiting_feerate);
4550
+ let mut local_predicted_htlcs = next_local_commitment_stats.next_commitment_htlcs;
4551
+ local_predicted_htlcs.sort_unstable();
4552
+ *funding.next_local_fee.lock().unwrap() = PredictedNextFee {
4553
+ predicted_feerate: feerate_per_kw,
4554
+ predicted_htlcs: local_predicted_htlcs,
4555
+ predicted_fee_sat: next_local_commitment_stats.commit_tx_fee_sat,
4556
+ };
4557
+
4558
+ let next_remote_commitment_stats = self.get_next_remote_commitment_stats(funding, None, true, 0, feerate_per_kw, dust_exposure_limiting_feerate);
4559
+ let mut remote_predicted_htlcs = next_remote_commitment_stats.next_commitment_htlcs;
4560
+ remote_predicted_htlcs.sort_unstable();
4561
+ *funding.next_remote_fee.lock().unwrap() = PredictedNextFee {
4562
+ predicted_feerate: feerate_per_kw,
4563
+ predicted_htlcs: remote_predicted_htlcs,
4564
+ predicted_fee_sat: next_remote_commitment_stats.commit_tx_fee_sat,
4565
+ };
4566
+ }
4567
+
4487
4568
return true;
4488
4569
}
4489
4570
@@ -4538,6 +4619,35 @@ where
4538
4619
}
4539
4620
}
4540
4621
4622
+ #[cfg(any(test, fuzzing))]
4623
+ {
4624
+ let next_local_commitment_stats = if fee_spike_buffer_htlc == 1 {
4625
+ self.get_next_local_commitment_stats(funding, None, false, 0, self.feerate_per_kw, dust_exposure_limiting_feerate)
4626
+ } else {
4627
+ next_local_commitment_stats
4628
+ };
4629
+ let mut local_predicted_htlcs = next_local_commitment_stats.next_commitment_htlcs;
4630
+ local_predicted_htlcs.sort_unstable();
4631
+ *funding.next_local_fee.lock().unwrap() = PredictedNextFee {
4632
+ predicted_feerate: self.feerate_per_kw,
4633
+ predicted_htlcs: local_predicted_htlcs,
4634
+ predicted_fee_sat: next_local_commitment_stats.commit_tx_fee_sat,
4635
+ };
4636
+
4637
+ let next_remote_commitment_stats = if fee_spike_buffer_htlc == 1 {
4638
+ self.get_next_remote_commitment_stats(funding, None, false, 0, self.feerate_per_kw, dust_exposure_limiting_feerate)
4639
+ } else {
4640
+ next_remote_commitment_stats
4641
+ };
4642
+ let mut remote_predicted_htlcs = next_remote_commitment_stats.next_commitment_htlcs;
4643
+ remote_predicted_htlcs.sort_unstable();
4644
+ *funding.next_remote_fee.lock().unwrap() = PredictedNextFee {
4645
+ predicted_feerate: self.feerate_per_kw,
4646
+ predicted_htlcs: remote_predicted_htlcs,
4647
+ predicted_fee_sat: next_remote_commitment_stats.commit_tx_fee_sat,
4648
+ };
4649
+ }
4650
+
4541
4651
Ok(())
4542
4652
}
4543
4653
@@ -6027,6 +6137,14 @@ struct CommitmentTxInfoCached {
6027
6137
feerate: u32,
6028
6138
}
6029
6139
6140
+ #[cfg(any(test, fuzzing))]
6141
+ #[derive(Clone, Default)]
6142
+ struct PredictedNextFee {
6143
+ predicted_feerate: u32,
6144
+ predicted_htlcs: Vec<HTLCAmountDirection>,
6145
+ predicted_fee_sat: u64,
6146
+ }
6147
+
6030
6148
/// Contents of a wire message that fails an HTLC backwards. Useful for [`FundedChannel::fail_htlc`] to
6031
6149
/// fail with either [`msgs::UpdateFailMalformedHTLC`] or [`msgs::UpdateFailHTLC`] as needed.
6032
6150
trait FailHTLCContents {
@@ -10991,6 +11109,12 @@ where
10991
11109
}
10992
11110
}
10993
11111
}
11112
+ let PredictedNextFee { predicted_feerate, predicted_htlcs, predicted_fee_sat } = funding.next_remote_fee.lock().unwrap().clone();
11113
+ let mut actual_nondust_htlcs: Vec<_> = counterparty_commitment_tx.nondust_htlcs().iter().map(|&HTLCOutputInCommitment { offered, amount_msat, .. }| HTLCAmountDirection { outbound: !offered, amount_msat }).collect();
11114
+ actual_nondust_htlcs.sort_unstable();
11115
+ if predicted_feerate == counterparty_commitment_tx.feerate_per_kw() && predicted_htlcs == actual_nondust_htlcs {
11116
+ assert_eq!(predicted_fee_sat, commitment_data.stats.commit_tx_fee_sat);
11117
+ }
10994
11118
}
10995
11119
10996
11120
(commitment_data.htlcs_included, counterparty_commitment_tx)
@@ -13616,6 +13740,10 @@ where
13616
13740
next_local_commitment_tx_fee_info_cached: Mutex::new(None),
13617
13741
#[cfg(any(test, fuzzing))]
13618
13742
next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
13743
+ #[cfg(any(test, fuzzing))]
13744
+ next_local_fee: Mutex::new(PredictedNextFee::default()),
13745
+ #[cfg(any(test, fuzzing))]
13746
+ next_remote_fee: Mutex::new(PredictedNextFee::default()),
13619
13747
13620
13748
channel_transaction_parameters: channel_parameters,
13621
13749
funding_transaction,
0 commit comments