@@ -877,15 +877,20 @@ struct HTLCStats {
877
877
on_holder_tx_outbound_holding_cell_htlcs_count: u32, // dust HTLCs *non*-included
878
878
}
879
879
880
- /// An enum gathering stats on commitment transaction, either local or remote.
881
- struct CommitmentStats<'a> {
880
+ /// A struct gathering data on a commitment, either local or remote.
881
+ struct CommitmentData<'a> {
882
+ stats: CommitmentStats,
883
+ htlcs_included: Vec<(HTLCOutputInCommitment, Option<&'a HTLCSource>)>, // the list of HTLCs (dust HTLCs *included*) which were not ignored when building the transaction
884
+ outbound_htlc_preimages: Vec<PaymentPreimage>, // preimages for successful offered HTLCs since last commitment
885
+ inbound_htlc_preimages: Vec<PaymentPreimage>, // preimages for successful received HTLCs since last commitment
886
+ }
887
+
888
+ /// A struct gathering stats on a commitment transaction, either local or remote.
889
+ struct CommitmentStats {
882
890
tx: CommitmentTransaction, // the transaction info
883
891
total_fee_sat: u64, // the total fee included in the transaction
884
- htlcs_included: Vec<(HTLCOutputInCommitment, Option<&'a HTLCSource>)>, // the list of HTLCs (dust HTLCs *included*) which were not ignored when building the transaction
885
892
local_balance_before_fee_msat: u64, // local balance before fees *not* considering dust limits
886
893
remote_balance_before_fee_msat: u64, // remote balance before fees *not* considering dust limits
887
- outbound_htlc_preimages: Vec<PaymentPreimage>, // preimages for successful offered HTLCs since last commitment
888
- inbound_htlc_preimages: Vec<PaymentPreimage>, // preimages for successful received HTLCs since last commitment
889
894
}
890
895
891
896
/// Used when calculating whether we or the remote can afford an additional HTLC.
@@ -2043,7 +2048,10 @@ trait InitialRemoteCommitmentReceiver<SP: Deref> where SP::Target: SignerProvide
2043
2048
) -> Result<CommitmentTransaction, ChannelError> where L::Target: Logger {
2044
2049
let funding_script = self.funding().get_funding_redeemscript();
2045
2050
2046
- 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;
2051
+ let commitment_data = self.context().build_commitment_transaction(self.funding(),
2052
+ holder_commitment_point.transaction_number(), &holder_commitment_point.current_point(),
2053
+ true, false, logger);
2054
+ let initial_commitment_tx = commitment_data.stats.tx;
2047
2055
let trusted_tx = initial_commitment_tx.trust();
2048
2056
let initial_commitment_bitcoin_tx = trusted_tx.built_transaction();
2049
2057
let sighash = initial_commitment_bitcoin_tx.get_sighash_all(&funding_script, self.funding().get_value_satoshis());
@@ -2080,7 +2088,10 @@ trait InitialRemoteCommitmentReceiver<SP: Deref> where SP::Target: SignerProvide
2080
2088
}
2081
2089
};
2082
2090
let context = self.context();
2083
- 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;
2091
+ let commitment_data = context.build_commitment_transaction(self.funding(),
2092
+ context.cur_counterparty_commitment_transaction_number,
2093
+ &context.counterparty_cur_commitment_point.unwrap(), false, false, logger);
2094
+ let counterparty_initial_commitment_tx = commitment_data.stats.tx;
2084
2095
let counterparty_trusted_tx = counterparty_initial_commitment_tx.trust();
2085
2096
let counterparty_initial_bitcoin_tx = counterparty_trusted_tx.built_transaction();
2086
2097
@@ -3477,9 +3488,11 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3477
3488
{
3478
3489
let funding_script = funding.get_funding_redeemscript();
3479
3490
3480
- let commitment_stats = self.build_commitment_transaction(funding, holder_commitment_point.transaction_number(), &holder_commitment_point.current_point(), true, false, logger);
3491
+ let commitment_data = self.build_commitment_transaction(funding,
3492
+ holder_commitment_point.transaction_number(), &holder_commitment_point.current_point(),
3493
+ true, false, logger);
3481
3494
let commitment_txid = {
3482
- let trusted_tx = commitment_stats .tx.trust();
3495
+ let trusted_tx = commitment_data.stats .tx.trust();
3483
3496
let bitcoin_tx = trusted_tx.built_transaction();
3484
3497
let sighash = bitcoin_tx.get_sighash_all(&funding_script, funding.get_value_satoshis());
3485
3498
@@ -3492,7 +3505,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3492
3505
}
3493
3506
bitcoin_tx.txid
3494
3507
};
3495
- let mut htlcs_cloned: Vec<_> = commitment_stats .htlcs_included.iter().map(|htlc| (htlc.0.clone(), htlc.1.map(|h| h.clone()))).collect();
3508
+ let mut htlcs_cloned: Vec<_> = commitment_data .htlcs_included.iter().map(|htlc| (htlc.0.clone(), htlc.1.map(|h| h.clone()))).collect();
3496
3509
3497
3510
// If our counterparty updated the channel fee in this commitment transaction, check that
3498
3511
// they can actually afford the new fee now.
@@ -3502,7 +3515,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3502
3515
if update_fee {
3503
3516
debug_assert!(!funding.is_outbound());
3504
3517
let counterparty_reserve_we_require_msat = funding.holder_selected_channel_reserve_satoshis * 1000;
3505
- if commitment_stats. remote_balance_before_fee_msat < commitment_stats .total_fee_sat * 1000 + counterparty_reserve_we_require_msat {
3518
+ if commitment_data.stats. remote_balance_before_fee_msat < commitment_data.stats .total_fee_sat * 1000 + counterparty_reserve_we_require_msat {
3506
3519
return Err(ChannelError::close("Funding remote cannot afford proposed new fee".to_owned()));
3507
3520
}
3508
3521
}
@@ -3518,14 +3531,14 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3518
3531
&& info.next_holder_htlc_id == self.next_holder_htlc_id
3519
3532
&& info.next_counterparty_htlc_id == self.next_counterparty_htlc_id
3520
3533
&& info.feerate == self.feerate_per_kw {
3521
- assert_eq!(commitment_stats .total_fee_sat, info.fee / 1000);
3534
+ assert_eq!(commitment_data.stats .total_fee_sat, info.fee / 1000);
3522
3535
}
3523
3536
}
3524
3537
}
3525
3538
}
3526
3539
3527
- if msg.htlc_signatures.len() != commitment_stats .tx.htlcs().len() {
3528
- 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())));
3540
+ if msg.htlc_signatures.len() != commitment_data.stats .tx.htlcs().len() {
3541
+ 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())));
3529
3542
}
3530
3543
3531
3544
// Up to LDK 0.0.115, HTLC information was required to be duplicated in the
@@ -3545,10 +3558,10 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3545
3558
3546
3559
let mut nondust_htlc_sources = Vec::with_capacity(htlcs_cloned.len());
3547
3560
let mut htlcs_and_sigs = Vec::with_capacity(htlcs_cloned.len());
3548
- let holder_keys = commitment_stats .tx.trust().keys();
3561
+ let holder_keys = commitment_data.stats .tx.trust().keys();
3549
3562
for (idx, (htlc, mut source_opt)) in htlcs_cloned.drain(..).enumerate() {
3550
3563
if let Some(_) = htlc.transaction_output_index {
3551
- let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, commitment_stats .tx.feerate_per_kw(),
3564
+ let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, commitment_data.stats .tx.feerate_per_kw(),
3552
3565
funding.get_counterparty_selected_contest_delay().unwrap(), &htlc, &self.channel_type,
3553
3566
&holder_keys.broadcaster_delayed_payment_key, &holder_keys.revocation_key);
3554
3567
@@ -3576,14 +3589,14 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3576
3589
}
3577
3590
3578
3591
let holder_commitment_tx = HolderCommitmentTransaction::new(
3579
- commitment_stats .tx,
3592
+ commitment_data.stats .tx,
3580
3593
msg.signature,
3581
3594
msg.htlc_signatures.clone(),
3582
3595
&funding.get_holder_pubkeys().funding_pubkey,
3583
3596
funding.counterparty_funding_pubkey()
3584
3597
);
3585
3598
3586
- self.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, commitment_stats .outbound_htlc_preimages)
3599
+ self.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, commitment_data .outbound_htlc_preimages)
3587
3600
.map_err(|_| ChannelError::close("Failed to validate our commitment".to_owned()))?;
3588
3601
3589
3602
Ok(LatestHolderCommitmentTXInfo {
@@ -3607,7 +3620,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3607
3620
/// generated by the peer which proposed adding the HTLCs, and thus we need to understand both
3608
3621
/// which peer generated this transaction and "to whom" this transaction flows.
3609
3622
#[inline]
3610
- 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
3623
+ fn build_commitment_transaction<L: Deref>(&self, funding: &FundingScope, commitment_number: u64, per_commitment_point: &PublicKey, local: bool, generated_by_local: bool, logger: &L) -> CommitmentData
3611
3624
where L::Target: Logger
3612
3625
{
3613
3626
let mut included_dust_htlcs: Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)> = Vec::new();
@@ -3823,12 +3836,16 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3823
3836
htlcs_included.sort_unstable_by_key(|h| h.0.transaction_output_index.unwrap());
3824
3837
htlcs_included.append(&mut included_dust_htlcs);
3825
3838
3826
- CommitmentStats {
3839
+ let stats = CommitmentStats {
3827
3840
tx,
3828
3841
total_fee_sat,
3829
- htlcs_included,
3830
3842
local_balance_before_fee_msat: value_to_self_msat,
3831
3843
remote_balance_before_fee_msat: value_to_remote_msat,
3844
+ };
3845
+
3846
+ CommitmentData {
3847
+ stats,
3848
+ htlcs_included,
3832
3849
inbound_htlc_preimages,
3833
3850
outbound_htlc_preimages,
3834
3851
}
@@ -4616,8 +4633,10 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
4616
4633
SP::Target: SignerProvider,
4617
4634
L::Target: Logger
4618
4635
{
4619
- let counterparty_initial_commitment_tx = self.build_commitment_transaction(
4620
- funding, self.cur_counterparty_commitment_transaction_number, &self.counterparty_cur_commitment_point.unwrap(), false, false, logger).tx;
4636
+ let commitment_data = self.build_commitment_transaction(funding,
4637
+ self.cur_counterparty_commitment_transaction_number,
4638
+ &self.counterparty_cur_commitment_point.unwrap(), false, false, logger);
4639
+ let counterparty_initial_commitment_tx = commitment_data.stats.tx;
4621
4640
match self.holder_signer {
4622
4641
// TODO (taproot|arik): move match into calling method for Taproot
4623
4642
ChannelSignerType::Ecdsa(ref ecdsa) => {
@@ -6330,9 +6349,11 @@ impl<SP: Deref> FundedChannel<SP> where
6330
6349
// Before proposing a feerate update, check that we can actually afford the new fee.
6331
6350
let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator);
6332
6351
let htlc_stats = self.context.get_pending_htlc_stats(Some(feerate_per_kw), dust_exposure_limiting_feerate);
6333
- 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);
6334
- 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;
6335
- let holder_balance_msat = commitment_stats.local_balance_before_fee_msat - htlc_stats.outbound_holding_cell_msat;
6352
+ let commitment_data = self.context.build_commitment_transaction(&self.funding,
6353
+ self.holder_commitment_point.transaction_number(),
6354
+ &self.holder_commitment_point.current_point(), true, true, logger);
6355
+ 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;
6356
+ let holder_balance_msat = commitment_data.stats.local_balance_before_fee_msat - htlc_stats.outbound_holding_cell_msat;
6336
6357
if holder_balance_msat < buffer_fee_msat + self.funding.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 {
6337
6358
//TODO: auto-close after a number of failures?
6338
6359
log_debug!(logger, "Cannot afford to send new feerate at {}", feerate_per_kw);
@@ -6643,7 +6664,10 @@ impl<SP: Deref> FundedChannel<SP> where
6643
6664
self.holder_commitment_point.try_resolve_pending(&self.context.holder_signer, &self.context.secp_ctx, logger);
6644
6665
}
6645
6666
let funding_signed = if self.context.signer_pending_funding && !self.funding.is_outbound() {
6646
- 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;
6667
+ let commitment_data = self.context.build_commitment_transaction(&self.funding,
6668
+ self.context.cur_counterparty_commitment_transaction_number + 1,
6669
+ &self.context.counterparty_cur_commitment_point.unwrap(), false, false, logger);
6670
+ let counterparty_initial_commitment_tx = commitment_data.stats.tx;
6647
6671
self.context.get_funding_signed_msg(&self.funding.channel_transaction_parameters, logger, counterparty_initial_commitment_tx)
6648
6672
} else { None };
6649
6673
// Provide a `channel_ready` message if we need to, but only if we're _not_ still pending
@@ -8716,8 +8740,10 @@ impl<SP: Deref> FundedChannel<SP> where
8716
8740
-> (Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>, CommitmentTransaction)
8717
8741
where L::Target: Logger
8718
8742
{
8719
- 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);
8720
- let counterparty_commitment_tx = commitment_stats.tx;
8743
+ let commitment_data = self.context.build_commitment_transaction(&self.funding,
8744
+ self.context.cur_counterparty_commitment_transaction_number,
8745
+ &self.context.counterparty_cur_commitment_point.unwrap(), false, true, logger);
8746
+ let counterparty_commitment_tx = commitment_data.stats.tx;
8721
8747
8722
8748
#[cfg(any(test, fuzzing))]
8723
8749
{
@@ -8737,7 +8763,7 @@ impl<SP: Deref> FundedChannel<SP> where
8737
8763
}
8738
8764
}
8739
8765
8740
- (commitment_stats .htlcs_included, counterparty_commitment_tx)
8766
+ (commitment_data .htlcs_included, counterparty_commitment_tx)
8741
8767
}
8742
8768
8743
8769
/// Only fails in case of signer rejection. Used for channel_reestablish commitment_signed
@@ -8747,8 +8773,10 @@ impl<SP: Deref> FundedChannel<SP> where
8747
8773
#[cfg(any(test, fuzzing))]
8748
8774
self.build_commitment_no_state_update(logger);
8749
8775
8750
- 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);
8751
- let counterparty_commitment_txid = commitment_stats.tx.trust().txid();
8776
+ let commitment_data = self.context.build_commitment_transaction(&self.funding,
8777
+ self.context.cur_counterparty_commitment_transaction_number,
8778
+ &self.context.counterparty_cur_commitment_point.unwrap(), false, true, logger);
8779
+ let counterparty_commitment_tx = commitment_data.stats.tx;
8752
8780
8753
8781
match &self.context.holder_signer {
8754
8782
ChannelSignerType::Ecdsa(ecdsa) => {
@@ -8757,24 +8785,25 @@ impl<SP: Deref> FundedChannel<SP> where
8757
8785
{
8758
8786
let res = ecdsa.sign_counterparty_commitment(
8759
8787
&self.funding.channel_transaction_parameters,
8760
- &commitment_stats.tx ,
8761
- commitment_stats .inbound_htlc_preimages,
8762
- commitment_stats .outbound_htlc_preimages,
8788
+ &counterparty_commitment_tx ,
8789
+ commitment_data .inbound_htlc_preimages,
8790
+ commitment_data .outbound_htlc_preimages,
8763
8791
&self.context.secp_ctx,
8764
8792
).map_err(|_| ChannelError::Ignore("Failed to get signatures for new commitment_signed".to_owned()))?;
8765
8793
signature = res.0;
8766
8794
htlc_signatures = res.1;
8767
8795
8796
+ let trusted_tx = counterparty_commitment_tx.trust();
8768
8797
log_trace!(logger, "Signed remote commitment tx {} (txid {}) with redeemscript {} -> {} in channel {}",
8769
- encode::serialize_hex(&commitment_stats.tx.trust() .built_transaction().transaction),
8770
- &counterparty_commitment_txid , encode::serialize_hex(&self.funding.get_funding_redeemscript()),
8798
+ encode::serialize_hex(&trusted_tx .built_transaction().transaction),
8799
+ &trusted_tx.txid() , encode::serialize_hex(&self.funding.get_funding_redeemscript()),
8771
8800
log_bytes!(signature.serialize_compact()[..]), &self.context.channel_id());
8772
8801
8773
- let counterparty_keys = commitment_stats.tx.trust() .keys();
8774
- debug_assert_eq!(htlc_signatures.len(), commitment_stats.tx .htlcs().len());
8775
- for (ref htlc_sig, ref htlc) in htlc_signatures.iter().zip(commitment_stats.tx .htlcs()) {
8802
+ let counterparty_keys = trusted_tx .keys();
8803
+ debug_assert_eq!(htlc_signatures.len(), trusted_tx .htlcs().len());
8804
+ for (ref htlc_sig, ref htlc) in htlc_signatures.iter().zip(trusted_tx .htlcs()) {
8776
8805
log_trace!(logger, "Signed remote HTLC tx {} with redeemscript {} with pubkey {} -> {} in channel {}",
8777
- encode::serialize_hex(&chan_utils::build_htlc_transaction(&counterparty_commitment_txid, commitment_stats.tx .feerate_per_kw(), self.funding.get_holder_selected_contest_delay(), htlc, &self.context.channel_type, &counterparty_keys.broadcaster_delayed_payment_key, &counterparty_keys.revocation_key)),
8806
+ encode::serialize_hex(&chan_utils::build_htlc_transaction(&trusted_tx.txid(), trusted_tx .feerate_per_kw(), self.funding.get_holder_selected_contest_delay(), htlc, &self.context.channel_type, &counterparty_keys.broadcaster_delayed_payment_key, &counterparty_keys.revocation_key)),
8778
8807
encode::serialize_hex(&chan_utils::get_htlc_redeemscript(&htlc, &self.context.channel_type, &counterparty_keys)),
8779
8808
log_bytes!(counterparty_keys.broadcaster_htlc_key.to_public_key().serialize()),
8780
8809
log_bytes!(htlc_sig.serialize_compact()[..]), &self.context.channel_id());
@@ -9228,7 +9257,10 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
9228
9257
9229
9258
/// Only allowed after [`FundingScope::channel_transaction_parameters`] is set.
9230
9259
fn get_funding_created_msg<L: Deref>(&mut self, logger: &L) -> Option<msgs::FundingCreated> where L::Target: Logger {
9231
- 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;
9260
+ let commitment_data = self.context.build_commitment_transaction(&self.funding,
9261
+ self.context.cur_counterparty_commitment_transaction_number,
9262
+ &self.context.counterparty_cur_commitment_point.unwrap(), false, false, logger);
9263
+ let counterparty_initial_commitment_tx = commitment_data.stats.tx;
9232
9264
let signature = match &self.context.holder_signer {
9233
9265
// TODO (taproot|arik): move match into calling method for Taproot
9234
9266
ChannelSignerType::Ecdsa(ecdsa) => {
@@ -11879,8 +11911,9 @@ mod tests {
11879
11911
( $counterparty_sig_hex: expr, $sig_hex: expr, $tx_hex: expr, $opt_anchors: expr, {
11880
11912
$( { $htlc_idx: expr, $counterparty_htlc_sig_hex: expr, $htlc_sig_hex: expr, $htlc_tx_hex: expr } ), *
11881
11913
} ) => { {
11882
- let commitment_stats = chan.context.build_commitment_transaction(&chan.funding, 0xffffffffffff - 42, &per_commitment_point, true, false, &logger);
11883
- let commitment_tx = commitment_stats.tx;
11914
+ let commitment_data = chan.context.build_commitment_transaction(&chan.funding,
11915
+ 0xffffffffffff - 42, &per_commitment_point, true, false, &logger);
11916
+ let commitment_tx = commitment_data.stats.tx;
11884
11917
let trusted_tx = commitment_tx.trust();
11885
11918
let unsigned_tx = trusted_tx.built_transaction();
11886
11919
let redeemscript = chan.funding.get_funding_redeemscript();
0 commit comments