@@ -876,15 +876,20 @@ struct HTLCStats {
876
876
on_holder_tx_outbound_holding_cell_htlcs_count: u32, // dust HTLCs *non*-included
877
877
}
878
878
879
- /// An enum gathering stats on commitment transaction, either local or remote.
880
- struct CommitmentStats<'a> {
879
+ /// A struct gathering data on a commitment, either local or remote.
880
+ struct CommitmentData<'a> {
881
+ stats: CommitmentStats,
882
+ htlcs_included: Vec<(HTLCOutputInCommitment, Option<&'a HTLCSource>)>, // the list of HTLCs (dust HTLCs *included*) which were not ignored when building the transaction
883
+ outbound_htlc_preimages: Vec<PaymentPreimage>, // preimages for successful offered HTLCs since last commitment
884
+ inbound_htlc_preimages: Vec<PaymentPreimage>, // preimages for successful received HTLCs since last commitment
885
+ }
886
+
887
+ /// A struct gathering stats on commitment transaction, either local or remote.
888
+ struct CommitmentStats {
881
889
tx: CommitmentTransaction, // the transaction info
882
890
total_fee_sat: u64, // the total fee included in the transaction
883
- htlcs_included: Vec<(HTLCOutputInCommitment, Option<&'a HTLCSource>)>, // the list of HTLCs (dust HTLCs *included*) which were not ignored when building the transaction
884
891
local_balance_msat: u64, // local balance before fees *not* considering dust limits
885
892
remote_balance_msat: u64, // remote balance before fees *not* considering dust limits
886
- outbound_htlc_preimages: Vec<PaymentPreimage>, // preimages for successful offered HTLCs since last commitment
887
- inbound_htlc_preimages: Vec<PaymentPreimage>, // preimages for successful received HTLCs since last commitment
888
893
}
889
894
890
895
/// Used when calculating whether we or the remote can afford an additional HTLC.
@@ -2034,7 +2039,10 @@ trait InitialRemoteCommitmentReceiver<SP: Deref> where SP::Target: SignerProvide
2034
2039
) -> Result<CommitmentTransaction, ChannelError> where L::Target: Logger {
2035
2040
let funding_script = self.funding().get_funding_redeemscript();
2036
2041
2037
- let initial_commitment_tx = self.context().build_commitment_transaction(self.funding(), holder_commitment_point.transaction_number(), &holder_commitment_point.current_point(), true, false, logger).tx;
2042
+ let commitment_data = self.context().build_commitment_transaction(self.funding(),
2043
+ holder_commitment_point.transaction_number(), &holder_commitment_point.current_point(),
2044
+ true, false, logger);
2045
+ let initial_commitment_tx = commitment_data.stats.tx;
2038
2046
let trusted_tx = initial_commitment_tx.trust();
2039
2047
let initial_commitment_bitcoin_tx = trusted_tx.built_transaction();
2040
2048
let sighash = initial_commitment_bitcoin_tx.get_sighash_all(&funding_script, self.funding().get_value_satoshis());
@@ -2071,7 +2079,10 @@ trait InitialRemoteCommitmentReceiver<SP: Deref> where SP::Target: SignerProvide
2071
2079
}
2072
2080
};
2073
2081
let context = self.context();
2074
- let counterparty_initial_commitment_tx = context.build_commitment_transaction(self.funding(), context.cur_counterparty_commitment_transaction_number, &context.counterparty_cur_commitment_point.unwrap(), false, false, logger).tx;
2082
+ let commitment_data = context.build_commitment_transaction(self.funding(),
2083
+ context.cur_counterparty_commitment_transaction_number,
2084
+ &context.counterparty_cur_commitment_point.unwrap(), false, false, logger);
2085
+ let counterparty_initial_commitment_tx = commitment_data.stats.tx;
2075
2086
let counterparty_trusted_tx = counterparty_initial_commitment_tx.trust();
2076
2087
let counterparty_initial_bitcoin_tx = counterparty_trusted_tx.built_transaction();
2077
2088
@@ -3455,9 +3466,11 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3455
3466
{
3456
3467
let funding_script = funding.get_funding_redeemscript();
3457
3468
3458
- let commitment_stats = self.build_commitment_transaction(funding, holder_commitment_point.transaction_number(), &holder_commitment_point.current_point(), true, false, logger);
3469
+ let commitment_data = self.build_commitment_transaction(funding,
3470
+ holder_commitment_point.transaction_number(), &holder_commitment_point.current_point(),
3471
+ true, false, logger);
3459
3472
let commitment_txid = {
3460
- let trusted_tx = commitment_stats .tx.trust();
3473
+ let trusted_tx = commitment_data.stats .tx.trust();
3461
3474
let bitcoin_tx = trusted_tx.built_transaction();
3462
3475
let sighash = bitcoin_tx.get_sighash_all(&funding_script, funding.get_value_satoshis());
3463
3476
@@ -3470,7 +3483,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3470
3483
}
3471
3484
bitcoin_tx.txid
3472
3485
};
3473
- let mut htlcs_cloned: Vec<_> = commitment_stats .htlcs_included.iter().map(|htlc| (htlc.0.clone(), htlc.1.map(|h| h.clone()))).collect();
3486
+ let mut htlcs_cloned: Vec<_> = commitment_data .htlcs_included.iter().map(|htlc| (htlc.0.clone(), htlc.1.map(|h| h.clone()))).collect();
3474
3487
3475
3488
// If our counterparty updated the channel fee in this commitment transaction, check that
3476
3489
// they can actually afford the new fee now.
@@ -3480,7 +3493,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3480
3493
if update_fee {
3481
3494
debug_assert!(!funding.is_outbound());
3482
3495
let counterparty_reserve_we_require_msat = funding.holder_selected_channel_reserve_satoshis * 1000;
3483
- if commitment_stats. remote_balance_msat < commitment_stats .total_fee_sat * 1000 + counterparty_reserve_we_require_msat {
3496
+ if commitment_data.stats. remote_balance_msat < commitment_data.stats .total_fee_sat * 1000 + counterparty_reserve_we_require_msat {
3484
3497
return Err(ChannelError::close("Funding remote cannot afford proposed new fee".to_owned()));
3485
3498
}
3486
3499
}
@@ -3496,14 +3509,14 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3496
3509
&& info.next_holder_htlc_id == self.next_holder_htlc_id
3497
3510
&& info.next_counterparty_htlc_id == self.next_counterparty_htlc_id
3498
3511
&& info.feerate == self.feerate_per_kw {
3499
- assert_eq!(commitment_stats .total_fee_sat, info.fee / 1000);
3512
+ assert_eq!(commitment_data.stats .total_fee_sat, info.fee / 1000);
3500
3513
}
3501
3514
}
3502
3515
}
3503
3516
}
3504
3517
3505
- if msg.htlc_signatures.len() != commitment_stats .tx.htlcs().len() {
3506
- return Err(ChannelError::close(format!("Got wrong number of HTLC signatures ({}) from remote. It must be {}", msg.htlc_signatures.len(), commitment_stats .tx.htlcs().len())));
3518
+ if msg.htlc_signatures.len() != commitment_data.stats .tx.htlcs().len() {
3519
+ return Err(ChannelError::close(format!("Got wrong number of HTLC signatures ({}) from remote. It must be {}", msg.htlc_signatures.len(), commitment_data.stats .tx.htlcs().len())));
3507
3520
}
3508
3521
3509
3522
// Up to LDK 0.0.115, HTLC information was required to be duplicated in the
@@ -3523,10 +3536,10 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3523
3536
3524
3537
let mut nondust_htlc_sources = Vec::with_capacity(htlcs_cloned.len());
3525
3538
let mut htlcs_and_sigs = Vec::with_capacity(htlcs_cloned.len());
3526
- let holder_keys = commitment_stats .tx.trust().keys();
3539
+ let holder_keys = commitment_data.stats .tx.trust().keys();
3527
3540
for (idx, (htlc, mut source_opt)) in htlcs_cloned.drain(..).enumerate() {
3528
3541
if let Some(_) = htlc.transaction_output_index {
3529
- let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, commitment_stats .tx.feerate_per_kw(),
3542
+ let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, commitment_data.stats .tx.feerate_per_kw(),
3530
3543
funding.get_counterparty_selected_contest_delay().unwrap(), &htlc, &self.channel_type,
3531
3544
&holder_keys.broadcaster_delayed_payment_key, &holder_keys.revocation_key);
3532
3545
@@ -3554,14 +3567,14 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3554
3567
}
3555
3568
3556
3569
let holder_commitment_tx = HolderCommitmentTransaction::new(
3557
- commitment_stats .tx,
3570
+ commitment_data.stats .tx,
3558
3571
msg.signature,
3559
3572
msg.htlc_signatures.clone(),
3560
3573
&funding.get_holder_pubkeys().funding_pubkey,
3561
3574
funding.counterparty_funding_pubkey()
3562
3575
);
3563
3576
3564
- self.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, commitment_stats .outbound_htlc_preimages)
3577
+ self.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, commitment_data .outbound_htlc_preimages)
3565
3578
.map_err(|_| ChannelError::close("Failed to validate our commitment".to_owned()))?;
3566
3579
3567
3580
Ok(LatestHolderCommitmentTXInfo {
@@ -3585,7 +3598,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3585
3598
/// generated by the peer which proposed adding the HTLCs, and thus we need to understand both
3586
3599
/// which peer generated this transaction and "to whom" this transaction flows.
3587
3600
#[inline]
3588
- fn build_commitment_transaction<L: Deref>(&self, funding: &FundingScope, commitment_number: u64, per_commitment_point: &PublicKey, local: bool, generated_by_local: bool, logger: &L) -> CommitmentStats
3601
+ fn build_commitment_transaction<L: Deref>(&self, funding: &FundingScope, commitment_number: u64, per_commitment_point: &PublicKey, local: bool, generated_by_local: bool, logger: &L)
3602
+ -> CommitmentData
3589
3603
where L::Target: Logger
3590
3604
{
3591
3605
let num_htlcs = self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len();
@@ -3808,12 +3822,16 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3808
3822
}
3809
3823
});
3810
3824
3811
- CommitmentStats {
3825
+ let stats = CommitmentStats {
3812
3826
tx,
3813
3827
total_fee_sat,
3814
- htlcs_included: htlcs_in_tx,
3815
3828
local_balance_msat: value_to_self_msat,
3816
3829
remote_balance_msat: value_to_remote_msat,
3830
+ };
3831
+
3832
+ CommitmentData {
3833
+ stats,
3834
+ htlcs_included: htlcs_in_tx,
3817
3835
inbound_htlc_preimages,
3818
3836
outbound_htlc_preimages,
3819
3837
}
@@ -4602,8 +4620,10 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
4602
4620
SP::Target: SignerProvider,
4603
4621
L::Target: Logger
4604
4622
{
4605
- let counterparty_initial_commitment_tx = self.build_commitment_transaction(
4606
- funding, self.cur_counterparty_commitment_transaction_number, &self.counterparty_cur_commitment_point.unwrap(), false, false, logger).tx;
4623
+ let commitment_data = self.build_commitment_transaction(funding,
4624
+ self.cur_counterparty_commitment_transaction_number,
4625
+ &self.counterparty_cur_commitment_point.unwrap(), false, false, logger);
4626
+ let counterparty_initial_commitment_tx = commitment_data.stats.tx;
4607
4627
match self.holder_signer {
4608
4628
// TODO (taproot|arik): move match into calling method for Taproot
4609
4629
ChannelSignerType::Ecdsa(ref ecdsa) => {
@@ -6270,9 +6290,11 @@ impl<SP: Deref> FundedChannel<SP> where
6270
6290
// Before proposing a feerate update, check that we can actually afford the new fee.
6271
6291
let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator);
6272
6292
let htlc_stats = self.context.get_pending_htlc_stats(Some(feerate_per_kw), dust_exposure_limiting_feerate);
6273
- let commitment_stats = self.context.build_commitment_transaction(&self.funding, self.holder_commitment_point.transaction_number(), &self.holder_commitment_point.current_point(), true, true, logger);
6274
- let buffer_fee_msat = commit_tx_fee_sat(feerate_per_kw, commitment_stats.tx.htlcs().len() + htlc_stats.on_holder_tx_outbound_holding_cell_htlcs_count as usize + CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize, self.context.get_channel_type()) * 1000;
6275
- let holder_balance_msat = commitment_stats.local_balance_msat - htlc_stats.outbound_holding_cell_msat;
6293
+ let commitment_data = self.context.build_commitment_transaction(&self.funding,
6294
+ self.holder_commitment_point.transaction_number(),
6295
+ &self.holder_commitment_point.current_point(), true, true, logger);
6296
+ let buffer_fee_msat = commit_tx_fee_sat(feerate_per_kw, commitment_data.stats.tx.htlcs().len() + htlc_stats.on_holder_tx_outbound_holding_cell_htlcs_count as usize + CONCURRENT_INBOUND_HTLC_FEE_BUFFER as usize, self.context.get_channel_type()) * 1000;
6297
+ let holder_balance_msat = commitment_data.stats.local_balance_msat - htlc_stats.outbound_holding_cell_msat;
6276
6298
if holder_balance_msat < buffer_fee_msat + self.funding.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 {
6277
6299
//TODO: auto-close after a number of failures?
6278
6300
log_debug!(logger, "Cannot afford to send new feerate at {}", feerate_per_kw);
@@ -6583,7 +6605,10 @@ impl<SP: Deref> FundedChannel<SP> where
6583
6605
self.holder_commitment_point.try_resolve_pending(&self.context.holder_signer, &self.context.secp_ctx, logger);
6584
6606
}
6585
6607
let funding_signed = if self.context.signer_pending_funding && !self.funding.is_outbound() {
6586
- let counterparty_initial_commitment_tx = self.context.build_commitment_transaction(&self.funding, self.context.cur_counterparty_commitment_transaction_number + 1, &self.context.counterparty_cur_commitment_point.unwrap(), false, false, logger).tx;
6608
+ let commitment_data = self.context.build_commitment_transaction(&self.funding,
6609
+ self.context.cur_counterparty_commitment_transaction_number + 1,
6610
+ &self.context.counterparty_cur_commitment_point.unwrap(), false, false, logger);
6611
+ let counterparty_initial_commitment_tx = commitment_data.stats.tx;
6587
6612
self.context.get_funding_signed_msg(&self.funding.channel_transaction_parameters, logger, counterparty_initial_commitment_tx)
6588
6613
} else { None };
6589
6614
// Provide a `channel_ready` message if we need to, but only if we're _not_ still pending
@@ -8523,8 +8548,10 @@ impl<SP: Deref> FundedChannel<SP> where
8523
8548
-> (Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>, CommitmentTransaction)
8524
8549
where L::Target: Logger
8525
8550
{
8526
- let commitment_stats = self.context.build_commitment_transaction(&self.funding, self.context.cur_counterparty_commitment_transaction_number, &self.context.counterparty_cur_commitment_point.unwrap(), false, true, logger);
8527
- let counterparty_commitment_tx = commitment_stats.tx;
8551
+ let commitment_data = self.context.build_commitment_transaction(&self.funding,
8552
+ self.context.cur_counterparty_commitment_transaction_number,
8553
+ &self.context.counterparty_cur_commitment_point.unwrap(), false, true, logger);
8554
+ let counterparty_commitment_tx = commitment_data.stats.tx;
8528
8555
8529
8556
#[cfg(any(test, fuzzing))]
8530
8557
{
@@ -8544,7 +8571,7 @@ impl<SP: Deref> FundedChannel<SP> where
8544
8571
}
8545
8572
}
8546
8573
8547
- (commitment_stats .htlcs_included, counterparty_commitment_tx)
8574
+ (commitment_data .htlcs_included, counterparty_commitment_tx)
8548
8575
}
8549
8576
8550
8577
/// Only fails in case of signer rejection. Used for channel_reestablish commitment_signed
@@ -8554,7 +8581,10 @@ impl<SP: Deref> FundedChannel<SP> where
8554
8581
#[cfg(any(test, fuzzing))]
8555
8582
self.build_commitment_no_state_update(logger);
8556
8583
8557
- let commitment_stats = self.context.build_commitment_transaction(&self.funding, self.context.cur_counterparty_commitment_transaction_number, &self.context.counterparty_cur_commitment_point.unwrap(), false, true, logger);
8584
+ let commitment_data = self.context.build_commitment_transaction(&self.funding,
8585
+ self.context.cur_counterparty_commitment_transaction_number,
8586
+ &self.context.counterparty_cur_commitment_point.unwrap(), false, true, logger);
8587
+ let commitment_stats = commitment_data.stats;
8558
8588
let counterparty_commitment_txid = commitment_stats.tx.trust().txid();
8559
8589
8560
8590
match &self.context.holder_signer {
@@ -8565,8 +8595,8 @@ impl<SP: Deref> FundedChannel<SP> where
8565
8595
let res = ecdsa.sign_counterparty_commitment(
8566
8596
&self.funding.channel_transaction_parameters,
8567
8597
&commitment_stats.tx,
8568
- commitment_stats .inbound_htlc_preimages,
8569
- commitment_stats .outbound_htlc_preimages,
8598
+ commitment_data .inbound_htlc_preimages,
8599
+ commitment_data .outbound_htlc_preimages,
8570
8600
&self.context.secp_ctx,
8571
8601
).map_err(|_| ChannelError::Ignore("Failed to get signatures for new commitment_signed".to_owned()))?;
8572
8602
signature = res.0;
@@ -9035,7 +9065,10 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
9035
9065
9036
9066
/// Only allowed after [`FundingScope::channel_transaction_parameters`] is set.
9037
9067
fn get_funding_created_msg<L: Deref>(&mut self, logger: &L) -> Option<msgs::FundingCreated> where L::Target: Logger {
9038
- let counterparty_initial_commitment_tx = self.context.build_commitment_transaction(&self.funding, self.context.cur_counterparty_commitment_transaction_number, &self.context.counterparty_cur_commitment_point.unwrap(), false, false, logger).tx;
9068
+ let commitment_data = self.context.build_commitment_transaction(&self.funding,
9069
+ self.context.cur_counterparty_commitment_transaction_number,
9070
+ &self.context.counterparty_cur_commitment_point.unwrap(), false, false, logger);
9071
+ let counterparty_initial_commitment_tx = commitment_data.stats.tx;
9039
9072
let signature = match &self.context.holder_signer {
9040
9073
// TODO (taproot|arik): move match into calling method for Taproot
9041
9074
ChannelSignerType::Ecdsa(ecdsa) => {
@@ -11648,8 +11681,9 @@ mod tests {
11648
11681
( $counterparty_sig_hex: expr, $sig_hex: expr, $tx_hex: expr, $opt_anchors: expr, {
11649
11682
$( { $htlc_idx: expr, $counterparty_htlc_sig_hex: expr, $htlc_sig_hex: expr, $htlc_tx_hex: expr } ), *
11650
11683
} ) => { {
11651
- let commitment_stats = chan.context.build_commitment_transaction(&chan.funding, 0xffffffffffff - 42, &per_commitment_point, true, false, &logger);
11652
- let commitment_tx = commitment_stats.tx;
11684
+ let commitment_data = chan.context.build_commitment_transaction(&chan.funding,
11685
+ 0xffffffffffff - 42, &per_commitment_point, true, false, &logger);
11686
+ let commitment_tx = commitment_data.stats.tx;
11653
11687
let trusted_tx = commitment_tx.trust();
11654
11688
let unsigned_tx = trusted_tx.built_transaction();
11655
11689
let redeemscript = chan.funding.get_funding_redeemscript();
0 commit comments