@@ -2062,6 +2062,10 @@ pub(super) struct FundingScope {
2062
2062
next_local_commitment_tx_fee_info_cached: Mutex<Option<CommitmentTxInfoCached>>,
2063
2063
#[cfg(any(test, fuzzing))]
2064
2064
next_remote_commitment_tx_fee_info_cached: Mutex<Option<CommitmentTxInfoCached>>,
2065
+ #[cfg(any(test, fuzzing))]
2066
+ next_local_fee: Mutex<PredictedNextFee>,
2067
+ #[cfg(any(test, fuzzing))]
2068
+ next_remote_fee: Mutex<PredictedNextFee>,
2065
2069
2066
2070
pub(super) channel_transaction_parameters: ChannelTransactionParameters,
2067
2071
@@ -2138,6 +2142,10 @@ impl Readable for FundingScope {
2138
2142
next_local_commitment_tx_fee_info_cached: Mutex::new(None),
2139
2143
#[cfg(any(test, fuzzing))]
2140
2144
next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
2145
+ #[cfg(any(test, fuzzing))]
2146
+ next_local_fee: Mutex::new(PredictedNextFee::default()),
2147
+ #[cfg(any(test, fuzzing))]
2148
+ next_remote_fee: Mutex::new(PredictedNextFee::default()),
2141
2149
})
2142
2150
}
2143
2151
}
@@ -2314,6 +2322,10 @@ impl FundingScope {
2314
2322
next_local_commitment_tx_fee_info_cached: Mutex::new(None),
2315
2323
#[cfg(any(test, fuzzing))]
2316
2324
next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
2325
+ #[cfg(any(test, fuzzing))]
2326
+ next_local_fee: Mutex::new(PredictedNextFee::default()),
2327
+ #[cfg(any(test, fuzzing))]
2328
+ next_remote_fee: Mutex::new(PredictedNextFee::default()),
2317
2329
funding_tx_confirmation_height: 0,
2318
2330
funding_tx_confirmed_in: None,
2319
2331
minimum_depth_override: None,
@@ -3197,6 +3209,10 @@ where
3197
3209
next_local_commitment_tx_fee_info_cached: Mutex::new(None),
3198
3210
#[cfg(any(test, fuzzing))]
3199
3211
next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
3212
+ #[cfg(any(test, fuzzing))]
3213
+ next_local_fee: Mutex::new(PredictedNextFee::default()),
3214
+ #[cfg(any(test, fuzzing))]
3215
+ next_remote_fee: Mutex::new(PredictedNextFee::default()),
3200
3216
3201
3217
channel_transaction_parameters: ChannelTransactionParameters {
3202
3218
holder_pubkeys: pubkeys,
@@ -3437,6 +3453,10 @@ where
3437
3453
next_local_commitment_tx_fee_info_cached: Mutex::new(None),
3438
3454
#[cfg(any(test, fuzzing))]
3439
3455
next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
3456
+ #[cfg(any(test, fuzzing))]
3457
+ next_local_fee: Mutex::new(PredictedNextFee::default()),
3458
+ #[cfg(any(test, fuzzing))]
3459
+ next_remote_fee: Mutex::new(PredictedNextFee::default()),
3440
3460
3441
3461
channel_transaction_parameters: ChannelTransactionParameters {
3442
3462
holder_pubkeys: pubkeys,
@@ -4216,7 +4236,8 @@ where
4216
4236
include_counterparty_unknown_htlcs,
4217
4237
);
4218
4238
let next_value_to_self_msat = self.get_next_commitment_value_to_self_msat(true, funding);
4219
- SpecTxBuilder {}.get_next_commitment_stats(
4239
+
4240
+ let ret = SpecTxBuilder {}.get_next_commitment_stats(
4220
4241
true,
4221
4242
funding.is_outbound(),
4222
4243
funding.get_value_satoshis(),
@@ -4227,7 +4248,38 @@ where
4227
4248
dust_exposure_limiting_feerate,
4228
4249
self.holder_dust_limit_satoshis,
4229
4250
funding.get_channel_type(),
4230
- )
4251
+ );
4252
+
4253
+ #[cfg(any(test, fuzzing))]
4254
+ {
4255
+ if addl_nondust_htlc_count == 0 {
4256
+ *funding.next_local_fee.lock().unwrap() = PredictedNextFee {
4257
+ predicted_feerate: feerate_per_kw,
4258
+ predicted_nondust_htlc_count: ret.nondust_htlc_count,
4259
+ predicted_fee_sat: ret.commit_tx_fee_sat,
4260
+ };
4261
+ } else {
4262
+ let predicted_stats = SpecTxBuilder {}.get_next_commitment_stats(
4263
+ true,
4264
+ funding.is_outbound(),
4265
+ funding.get_value_satoshis(),
4266
+ next_value_to_self_msat,
4267
+ &next_commitment_htlcs,
4268
+ 0,
4269
+ feerate_per_kw,
4270
+ dust_exposure_limiting_feerate,
4271
+ self.holder_dust_limit_satoshis,
4272
+ funding.get_channel_type(),
4273
+ );
4274
+ *funding.next_local_fee.lock().unwrap() = PredictedNextFee {
4275
+ predicted_feerate: feerate_per_kw,
4276
+ predicted_nondust_htlc_count: predicted_stats.nondust_htlc_count,
4277
+ predicted_fee_sat: predicted_stats.commit_tx_fee_sat,
4278
+ };
4279
+ }
4280
+ }
4281
+
4282
+ ret
4231
4283
}
4232
4284
4233
4285
fn get_next_remote_commitment_stats(
@@ -4241,7 +4293,8 @@ where
4241
4293
include_counterparty_unknown_htlcs,
4242
4294
);
4243
4295
let next_value_to_self_msat = self.get_next_commitment_value_to_self_msat(false, funding);
4244
- SpecTxBuilder {}.get_next_commitment_stats(
4296
+
4297
+ let ret = SpecTxBuilder {}.get_next_commitment_stats(
4245
4298
false,
4246
4299
funding.is_outbound(),
4247
4300
funding.get_value_satoshis(),
@@ -4252,7 +4305,38 @@ where
4252
4305
dust_exposure_limiting_feerate,
4253
4306
self.counterparty_dust_limit_satoshis,
4254
4307
funding.get_channel_type(),
4255
- )
4308
+ );
4309
+
4310
+ #[cfg(any(test, fuzzing))]
4311
+ {
4312
+ if addl_nondust_htlc_count == 0 {
4313
+ *funding.next_remote_fee.lock().unwrap() = PredictedNextFee {
4314
+ predicted_feerate: feerate_per_kw,
4315
+ predicted_nondust_htlc_count: ret.nondust_htlc_count,
4316
+ predicted_fee_sat: ret.commit_tx_fee_sat,
4317
+ };
4318
+ } else {
4319
+ let predicted_stats = SpecTxBuilder {}.get_next_commitment_stats(
4320
+ false,
4321
+ funding.is_outbound(),
4322
+ funding.get_value_satoshis(),
4323
+ next_value_to_self_msat,
4324
+ &next_commitment_htlcs,
4325
+ 0,
4326
+ feerate_per_kw,
4327
+ dust_exposure_limiting_feerate,
4328
+ self.counterparty_dust_limit_satoshis,
4329
+ funding.get_channel_type(),
4330
+ );
4331
+ *funding.next_remote_fee.lock().unwrap() = PredictedNextFee {
4332
+ predicted_feerate: feerate_per_kw,
4333
+ predicted_nondust_htlc_count: predicted_stats.nondust_htlc_count,
4334
+ predicted_fee_sat: predicted_stats.commit_tx_fee_sat,
4335
+ };
4336
+ }
4337
+ }
4338
+
4339
+ ret
4256
4340
}
4257
4341
4258
4342
#[rustfmt::skip]
@@ -4410,6 +4494,10 @@ where
4410
4494
}
4411
4495
}
4412
4496
}
4497
+ let PredictedNextFee { predicted_feerate, predicted_nondust_htlc_count, predicted_fee_sat } = *funding.next_local_fee.lock().unwrap();
4498
+ if predicted_feerate == commitment_data.tx.feerate_per_kw() && predicted_nondust_htlc_count == commitment_data.tx.nondust_htlcs().len() {
4499
+ assert_eq!(predicted_fee_sat, commitment_data.stats.commit_tx_fee_sat);
4500
+ }
4413
4501
}
4414
4502
4415
4503
if msg.htlc_signatures.len() != commitment_data.tx.nondust_htlcs().len() {
@@ -6216,6 +6304,14 @@ struct CommitmentTxInfoCached {
6216
6304
feerate: u32,
6217
6305
}
6218
6306
6307
+ #[cfg(any(test, fuzzing))]
6308
+ #[derive(Clone, Copy, Default)]
6309
+ struct PredictedNextFee {
6310
+ predicted_feerate: u32,
6311
+ predicted_nondust_htlc_count: usize,
6312
+ predicted_fee_sat: u64,
6313
+ }
6314
+
6219
6315
/// Contents of a wire message that fails an HTLC backwards. Useful for [`FundedChannel::fail_htlc`] to
6220
6316
/// fail with either [`msgs::UpdateFailMalformedHTLC`] or [`msgs::UpdateFailHTLC`] as needed.
6221
6317
trait FailHTLCContents {
@@ -11386,6 +11482,10 @@ where
11386
11482
}
11387
11483
}
11388
11484
}
11485
+ let PredictedNextFee { predicted_feerate, predicted_nondust_htlc_count, predicted_fee_sat } = *funding.next_remote_fee.lock().unwrap();
11486
+ if predicted_feerate == counterparty_commitment_tx.feerate_per_kw() && predicted_nondust_htlc_count == counterparty_commitment_tx.nondust_htlcs().len() {
11487
+ assert_eq!(predicted_fee_sat, commitment_data.stats.commit_tx_fee_sat);
11488
+ }
11389
11489
}
11390
11490
11391
11491
(commitment_data.htlcs_included, counterparty_commitment_tx)
@@ -14032,6 +14132,10 @@ where
14032
14132
next_local_commitment_tx_fee_info_cached: Mutex::new(None),
14033
14133
#[cfg(any(test, fuzzing))]
14034
14134
next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
14135
+ #[cfg(any(test, fuzzing))]
14136
+ next_local_fee: Mutex::new(PredictedNextFee::default()),
14137
+ #[cfg(any(test, fuzzing))]
14138
+ next_remote_fee: Mutex::new(PredictedNextFee::default()),
14035
14139
14036
14140
channel_transaction_parameters: channel_parameters,
14037
14141
funding_transaction,
@@ -16092,7 +16196,7 @@ mod tests {
16092
16196
fn get_pre_and_post(
16093
16197
pre_channel_value: u64, our_funding_contribution: i64, their_funding_contribution: i64,
16094
16198
) -> (u64, u64) {
16095
- use crate::ln::channel::FundingScope;
16199
+ use crate::ln::channel::{ FundingScope, PredictedNextFee} ;
16096
16200
16097
16201
let funding = FundingScope {
16098
16202
value_to_self_msat: 0,
@@ -16109,6 +16213,11 @@ mod tests {
16109
16213
#[cfg(any(test, fuzzing))]
16110
16214
next_remote_commitment_tx_fee_info_cached: Mutex::new(None),
16111
16215
16216
+ #[cfg(any(test, fuzzing))]
16217
+ next_local_fee: Mutex::new(PredictedNextFee::default()),
16218
+ #[cfg(any(test, fuzzing))]
16219
+ next_remote_fee: Mutex::new(PredictedNextFee::default()),
16220
+
16112
16221
channel_transaction_parameters: ChannelTransactionParameters::test_dummy(
16113
16222
pre_channel_value,
16114
16223
),
0 commit comments