@@ -876,15 +876,20 @@ struct HTLCStats {
876876 on_holder_tx_outbound_holding_cell_htlcs_count: u32, // dust HTLCs *non*-included
877877}
878878
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 {
881889 tx: CommitmentTransaction, // the transaction info
882890 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
884891 local_balance_msat: u64, // local balance before fees *not* considering dust limits
885892 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
888893}
889894
890895/// 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
20342039 ) -> Result<CommitmentTransaction, ChannelError> where L::Target: Logger {
20352040 let funding_script = self.funding().get_funding_redeemscript();
20362041
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;
20382046 let trusted_tx = initial_commitment_tx.trust();
20392047 let initial_commitment_bitcoin_tx = trusted_tx.built_transaction();
20402048 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
20712079 }
20722080 };
20732081 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;
20752086 let counterparty_trusted_tx = counterparty_initial_commitment_tx.trust();
20762087 let counterparty_initial_bitcoin_tx = counterparty_trusted_tx.built_transaction();
20772088
@@ -3455,9 +3466,11 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
34553466 {
34563467 let funding_script = funding.get_funding_redeemscript();
34573468
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);
34593472 let commitment_txid = {
3460- let trusted_tx = commitment_stats .tx.trust();
3473+ let trusted_tx = commitment_data.stats .tx.trust();
34613474 let bitcoin_tx = trusted_tx.built_transaction();
34623475 let sighash = bitcoin_tx.get_sighash_all(&funding_script, funding.get_value_satoshis());
34633476
@@ -3470,7 +3483,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
34703483 }
34713484 bitcoin_tx.txid
34723485 };
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();
34743487
34753488 // If our counterparty updated the channel fee in this commitment transaction, check that
34763489 // they can actually afford the new fee now.
@@ -3480,7 +3493,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
34803493 if update_fee {
34813494 debug_assert!(!funding.is_outbound());
34823495 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 {
34843497 return Err(ChannelError::close("Funding remote cannot afford proposed new fee".to_owned()));
34853498 }
34863499 }
@@ -3496,14 +3509,14 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
34963509 && info.next_holder_htlc_id == self.next_holder_htlc_id
34973510 && info.next_counterparty_htlc_id == self.next_counterparty_htlc_id
34983511 && 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);
35003513 }
35013514 }
35023515 }
35033516 }
35043517
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())));
35073520 }
35083521
35093522 // 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 {
35233536
35243537 let mut nondust_htlc_sources = Vec::with_capacity(htlcs_cloned.len());
35253538 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();
35273540 for (idx, (htlc, mut source_opt)) in htlcs_cloned.drain(..).enumerate() {
35283541 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(),
35303543 funding.get_counterparty_selected_contest_delay().unwrap(), &htlc, &self.channel_type,
35313544 &holder_keys.broadcaster_delayed_payment_key, &holder_keys.revocation_key);
35323545
@@ -3554,14 +3567,14 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
35543567 }
35553568
35563569 let holder_commitment_tx = HolderCommitmentTransaction::new(
3557- commitment_stats .tx,
3570+ commitment_data.stats .tx,
35583571 msg.signature,
35593572 msg.htlc_signatures.clone(),
35603573 &funding.get_holder_pubkeys().funding_pubkey,
35613574 funding.counterparty_funding_pubkey()
35623575 );
35633576
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)
35653578 .map_err(|_| ChannelError::close("Failed to validate our commitment".to_owned()))?;
35663579
35673580 Ok(LatestHolderCommitmentTXInfo {
@@ -3585,7 +3598,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
35853598 /// generated by the peer which proposed adding the HTLCs, and thus we need to understand both
35863599 /// which peer generated this transaction and "to whom" this transaction flows.
35873600 #[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
35893603 where L::Target: Logger
35903604 {
35913605 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 {
38083822 }
38093823 });
38103824
3811- CommitmentStats {
3825+ let stats = CommitmentStats {
38123826 tx,
38133827 total_fee_sat,
3814- htlcs_included: htlcs_in_tx,
38153828 local_balance_msat: value_to_self_msat,
38163829 remote_balance_msat: value_to_remote_msat,
3830+ };
3831+
3832+ CommitmentData {
3833+ stats,
3834+ htlcs_included: htlcs_in_tx,
38173835 inbound_htlc_preimages,
38183836 outbound_htlc_preimages,
38193837 }
@@ -4602,8 +4620,10 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
46024620 SP::Target: SignerProvider,
46034621 L::Target: Logger
46044622 {
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;
46074627 match self.holder_signer {
46084628 // TODO (taproot|arik): move match into calling method for Taproot
46094629 ChannelSignerType::Ecdsa(ref ecdsa) => {
@@ -6270,9 +6290,11 @@ impl<SP: Deref> FundedChannel<SP> where
62706290 // Before proposing a feerate update, check that we can actually afford the new fee.
62716291 let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator);
62726292 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;
62766298 if holder_balance_msat < buffer_fee_msat + self.funding.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 {
62776299 //TODO: auto-close after a number of failures?
62786300 log_debug!(logger, "Cannot afford to send new feerate at {}", feerate_per_kw);
@@ -6583,7 +6605,10 @@ impl<SP: Deref> FundedChannel<SP> where
65836605 self.holder_commitment_point.try_resolve_pending(&self.context.holder_signer, &self.context.secp_ctx, logger);
65846606 }
65856607 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;
65876612 self.context.get_funding_signed_msg(&self.funding.channel_transaction_parameters, logger, counterparty_initial_commitment_tx)
65886613 } else { None };
65896614 // 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
85238548 -> (Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>, CommitmentTransaction)
85248549 where L::Target: Logger
85258550 {
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;
85288555
85298556 #[cfg(any(test, fuzzing))]
85308557 {
@@ -8544,7 +8571,7 @@ impl<SP: Deref> FundedChannel<SP> where
85448571 }
85458572 }
85468573
8547- (commitment_stats .htlcs_included, counterparty_commitment_tx)
8574+ (commitment_data .htlcs_included, counterparty_commitment_tx)
85488575 }
85498576
85508577 /// Only fails in case of signer rejection. Used for channel_reestablish commitment_signed
@@ -8554,7 +8581,10 @@ impl<SP: Deref> FundedChannel<SP> where
85548581 #[cfg(any(test, fuzzing))]
85558582 self.build_commitment_no_state_update(logger);
85568583
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;
85588588 let counterparty_commitment_txid = commitment_stats.tx.trust().txid();
85598589
85608590 match &self.context.holder_signer {
@@ -8565,8 +8595,8 @@ impl<SP: Deref> FundedChannel<SP> where
85658595 let res = ecdsa.sign_counterparty_commitment(
85668596 &self.funding.channel_transaction_parameters,
85678597 &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,
85708600 &self.context.secp_ctx,
85718601 ).map_err(|_| ChannelError::Ignore("Failed to get signatures for new commitment_signed".to_owned()))?;
85728602 signature = res.0;
@@ -9035,7 +9065,10 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
90359065
90369066 /// Only allowed after [`FundingScope::channel_transaction_parameters`] is set.
90379067 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;
90399072 let signature = match &self.context.holder_signer {
90409073 // TODO (taproot|arik): move match into calling method for Taproot
90419074 ChannelSignerType::Ecdsa(ecdsa) => {
@@ -11648,8 +11681,9 @@ mod tests {
1164811681 ( $counterparty_sig_hex: expr, $sig_hex: expr, $tx_hex: expr, $opt_anchors: expr, {
1164911682 $( { $htlc_idx: expr, $counterparty_htlc_sig_hex: expr, $htlc_sig_hex: expr, $htlc_tx_hex: expr } ), *
1165011683 } ) => { {
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;
1165311687 let trusted_tx = commitment_tx.trust();
1165411688 let unsigned_tx = trusted_tx.built_transaction();
1165511689 let redeemscript = chan.funding.get_funding_redeemscript();
0 commit comments