@@ -875,15 +875,20 @@ struct HTLCStats {
875875 on_holder_tx_outbound_holding_cell_htlcs_count: u32, // dust HTLCs *non*-included
876876}
877877
878+ /// An enum gathering data on a commitment, either local or remote.
879+ struct CommitmentData<'a> {
880+ stats: CommitmentStats,
881+ htlcs_included: Vec<(HTLCOutputInCommitment, Option<&'a HTLCSource>)>, // the list of HTLCs (dust HTLCs *included*) which were not ignored when building the transaction
882+ outbound_htlc_preimages: Vec<PaymentPreimage>, // preimages for successful offered HTLCs since last commitment
883+ inbound_htlc_preimages: Vec<PaymentPreimage>, // preimages for successful received HTLCs since last commitment
884+ }
885+
878886/// An enum gathering stats on commitment transaction, either local or remote.
879- struct CommitmentStats<'a> {
887+ struct CommitmentStats {
880888 tx: CommitmentTransaction, // the transaction info
881889 total_fee_sat: u64, // the total fee included in the transaction
882- htlcs_included: Vec<(HTLCOutputInCommitment, Option<&'a HTLCSource>)>, // the list of HTLCs (dust HTLCs *included*) which were not ignored when building the transaction
883890 local_balance_msat: u64, // local balance before fees *not* considering dust limits
884891 remote_balance_msat: u64, // remote balance before fees *not* considering dust limits
885- outbound_htlc_preimages: Vec<PaymentPreimage>, // preimages for successful offered HTLCs since last commitment
886- inbound_htlc_preimages: Vec<PaymentPreimage>, // preimages for successful received HTLCs since last commitment
887892}
888893
889894/// Used when calculating whether we or the remote can afford an additional HTLC.
@@ -1966,7 +1971,8 @@ trait InitialRemoteCommitmentReceiver<SP: Deref> where SP::Target: SignerProvide
19661971 ) -> Result<CommitmentTransaction, ChannelError> where L::Target: Logger {
19671972 let funding_script = self.context().get_funding_redeemscript();
19681973
1969- 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;
1974+ let commitment_data = self.context().build_commitment_transaction(self.funding(), holder_commitment_point.transaction_number(), &holder_commitment_point.current_point(), true, false, logger);
1975+ let initial_commitment_tx = commitment_data.stats.tx;
19701976 let trusted_tx = initial_commitment_tx.trust();
19711977 let initial_commitment_bitcoin_tx = trusted_tx.built_transaction();
19721978 let sighash = initial_commitment_bitcoin_tx.get_sighash_all(&funding_script, self.funding().channel_value_satoshis);
@@ -2003,7 +2009,8 @@ trait InitialRemoteCommitmentReceiver<SP: Deref> where SP::Target: SignerProvide
20032009 }
20042010 };
20052011 let context = self.context();
2006- 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;
2012+ let commitment_data = context.build_commitment_transaction(self.funding(), context.cur_counterparty_commitment_transaction_number, &context.counterparty_cur_commitment_point.unwrap(), false, false, logger);
2013+ let counterparty_initial_commitment_tx = commitment_data.stats.tx;
20072014 let counterparty_trusted_tx = counterparty_initial_commitment_tx.trust();
20082015 let counterparty_initial_bitcoin_tx = counterparty_trusted_tx.built_transaction();
20092016
@@ -3408,7 +3415,8 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
34083415 /// generated by the peer which proposed adding the HTLCs, and thus we need to understand both
34093416 /// which peer generated this transaction and "to whom" this transaction flows.
34103417 #[inline]
3411- 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
3418+ fn build_commitment_transaction<L: Deref>(&self, funding: &FundingScope, commitment_number: u64, per_commitment_point: &PublicKey, local: bool, generated_by_local: bool, logger: &L)
3419+ -> CommitmentData
34123420 where L::Target: Logger
34133421 {
34143422 let num_htlcs = self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len();
@@ -3637,12 +3645,16 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
36373645 }
36383646 });
36393647
3640- CommitmentStats {
3648+ let stats = CommitmentStats {
36413649 tx,
36423650 total_fee_sat,
3643- htlcs_included: htlcs_in_tx,
36443651 local_balance_msat: value_to_self_msat,
36453652 remote_balance_msat: value_to_remote_msat,
3653+ };
3654+
3655+ CommitmentData {
3656+ stats,
3657+ htlcs_included: htlcs_in_tx,
36463658 inbound_htlc_preimages,
36473659 outbound_htlc_preimages,
36483660 }
@@ -4441,8 +4453,9 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
44414453 SP::Target: SignerProvider,
44424454 L::Target: Logger
44434455 {
4444- let counterparty_initial_commitment_tx = self.build_commitment_transaction(
4445- funding, self.cur_counterparty_commitment_transaction_number, &self.counterparty_cur_commitment_point.unwrap(), false, false, logger).tx;
4456+ let commitment_data = self.build_commitment_transaction(
4457+ funding, self.cur_counterparty_commitment_transaction_number, &self.counterparty_cur_commitment_point.unwrap(), false, false, logger);
4458+ let counterparty_initial_commitment_tx = commitment_data.stats.tx;
44464459 match self.holder_signer {
44474460 // TODO (taproot|arik): move match into calling method for Taproot
44484461 ChannelSignerType::Ecdsa(ref ecdsa) => {
@@ -5435,7 +5448,8 @@ impl<SP: Deref> FundedChannel<SP> where
54355448
54365449 let funding_script = self.context.get_funding_redeemscript();
54375450
5438- let commitment_stats = self.context.build_commitment_transaction(&self.funding, self.holder_commitment_point.transaction_number(), &self.holder_commitment_point.current_point(), true, false, logger);
5451+ let commitment_data = self.context.build_commitment_transaction(&self.funding, self.holder_commitment_point.transaction_number(), &self.holder_commitment_point.current_point(), true, false, logger);
5452+ let commitment_stats = commitment_data.stats;
54395453 let commitment_txid = {
54405454 let trusted_tx = commitment_stats.tx.trust();
54415455 let bitcoin_tx = trusted_tx.built_transaction();
@@ -5450,7 +5464,7 @@ impl<SP: Deref> FundedChannel<SP> where
54505464 }
54515465 bitcoin_tx.txid
54525466 };
5453- let mut htlcs_cloned: Vec<_> = commitment_stats .htlcs_included.iter().map(|htlc| (htlc.0.clone(), htlc.1.map(|h| h.clone()))).collect();
5467+ let mut htlcs_cloned: Vec<_> = commitment_data .htlcs_included.iter().map(|htlc| (htlc.0.clone(), htlc.1.map(|h| h.clone()))).collect();
54545468
54555469 // If our counterparty updated the channel fee in this commitment transaction, check that
54565470 // they can actually afford the new fee now.
@@ -5541,7 +5555,7 @@ impl<SP: Deref> FundedChannel<SP> where
55415555 self.context.counterparty_funding_pubkey()
55425556 );
55435557
5544- self.context.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, commitment_stats .outbound_htlc_preimages)
5558+ self.context.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, commitment_data .outbound_htlc_preimages)
55455559 .map_err(|_| ChannelError::close("Failed to validate our commitment".to_owned()))?;
55465560
55475561 // Update state now that we've passed all the can-fail calls...
@@ -6198,9 +6212,9 @@ impl<SP: Deref> FundedChannel<SP> where
61986212 // Before proposing a feerate update, check that we can actually afford the new fee.
61996213 let dust_exposure_limiting_feerate = self.context.get_dust_exposure_limiting_feerate(&fee_estimator);
62006214 let htlc_stats = self.context.get_pending_htlc_stats(Some(feerate_per_kw), dust_exposure_limiting_feerate);
6201- 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);
6202- 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;
6203- let holder_balance_msat = commitment_stats .local_balance_msat - htlc_stats.outbound_holding_cell_msat;
6215+ let commitment_data = self.context.build_commitment_transaction(&self.funding, self.holder_commitment_point.transaction_number(), &self.holder_commitment_point.current_point(), true, true, logger);
6216+ 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;
6217+ let holder_balance_msat = commitment_data.stats .local_balance_msat - htlc_stats.outbound_holding_cell_msat;
62046218 if holder_balance_msat < buffer_fee_msat + self.funding.counterparty_selected_channel_reserve_satoshis.unwrap() * 1000 {
62056219 //TODO: auto-close after a number of failures?
62066220 log_debug!(logger, "Cannot afford to send new feerate at {}", feerate_per_kw);
@@ -6511,7 +6525,8 @@ impl<SP: Deref> FundedChannel<SP> where
65116525 self.holder_commitment_point.try_resolve_pending(&self.context.holder_signer, &self.context.secp_ctx, logger);
65126526 }
65136527 let funding_signed = if self.context.signer_pending_funding && !self.context.is_outbound() {
6514- 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;
6528+ let commitment_data = 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);
6529+ let counterparty_initial_commitment_tx = commitment_data.stats.tx;
65156530 self.context.get_funding_signed_msg(logger, counterparty_initial_commitment_tx)
65166531 } else { None };
65176532 // Provide a `channel_ready` message if we need to, but only if we're _not_ still pending
@@ -8447,8 +8462,8 @@ impl<SP: Deref> FundedChannel<SP> where
84478462 -> (Vec<(HTLCOutputInCommitment, Option<&HTLCSource>)>, CommitmentTransaction)
84488463 where L::Target: Logger
84498464 {
8450- 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);
8451- let counterparty_commitment_tx = commitment_stats .tx;
8465+ let commitment_data = self.context.build_commitment_transaction(&self.funding, self.context.cur_counterparty_commitment_transaction_number, &self.context.counterparty_cur_commitment_point.unwrap(), false, true, logger);
8466+ let counterparty_commitment_tx = commitment_data.stats .tx;
84528467
84538468 #[cfg(any(test, fuzzing))]
84548469 {
@@ -8468,7 +8483,7 @@ impl<SP: Deref> FundedChannel<SP> where
84688483 }
84698484 }
84708485
8471- (commitment_stats .htlcs_included, counterparty_commitment_tx)
8486+ (commitment_data .htlcs_included, counterparty_commitment_tx)
84728487 }
84738488
84748489 /// Only fails in case of signer rejection. Used for channel_reestablish commitment_signed
@@ -8478,23 +8493,25 @@ impl<SP: Deref> FundedChannel<SP> where
84788493 #[cfg(any(test, fuzzing))]
84798494 self.build_commitment_no_state_update(logger);
84808495
8481- 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);
8496+ let commitment_data = self.context.build_commitment_transaction(&self.funding, self.context.cur_counterparty_commitment_transaction_number, &self.context.counterparty_cur_commitment_point.unwrap(), false, true, logger);
8497+ let commitment_stats = commitment_data.stats;
8498+ let htlcs_included = commitment_data.htlcs_included;
84828499 let counterparty_commitment_txid = commitment_stats.tx.trust().txid();
84838500
84848501 match &self.context.holder_signer {
84858502 ChannelSignerType::Ecdsa(ecdsa) => {
84868503 let (signature, htlc_signatures);
84878504
84888505 {
8489- let mut htlcs = Vec::with_capacity(commitment_stats. htlcs_included.len());
8490- for &(ref htlc, _) in commitment_stats. htlcs_included.iter() {
8506+ let mut htlcs = Vec::with_capacity(htlcs_included.len());
8507+ for &(ref htlc, _) in htlcs_included.iter() {
84918508 htlcs.push(htlc);
84928509 }
84938510
84948511 let res = ecdsa.sign_counterparty_commitment(
84958512 &commitment_stats.tx,
8496- commitment_stats .inbound_htlc_preimages,
8497- commitment_stats .outbound_htlc_preimages,
8513+ commitment_data .inbound_htlc_preimages,
8514+ commitment_data .outbound_htlc_preimages,
84988515 &self.context.secp_ctx,
84998516 ).map_err(|_| ChannelError::Ignore("Failed to get signatures for new commitment_signed".to_owned()))?;
85008517 signature = res.0;
@@ -8522,7 +8539,7 @@ impl<SP: Deref> FundedChannel<SP> where
85228539 batch: None,
85238540 #[cfg(taproot)]
85248541 partial_signature_with_nonce: None,
8525- }, (counterparty_commitment_txid, commitment_stats. htlcs_included)))
8542+ }, (counterparty_commitment_txid, htlcs_included)))
85268543 },
85278544 // TODO (taproot|arik)
85288545 #[cfg(taproot)]
@@ -8957,7 +8974,8 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
89578974
89588975 /// Only allowed after [`ChannelContext::channel_transaction_parameters`] is set.
89598976 fn get_funding_created_msg<L: Deref>(&mut self, logger: &L) -> Option<msgs::FundingCreated> where L::Target: Logger {
8960- 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;
8977+ let commitment_data = self.context.build_commitment_transaction(&self.funding, self.context.cur_counterparty_commitment_transaction_number, &self.context.counterparty_cur_commitment_point.unwrap(), false, false, logger);
8978+ let counterparty_initial_commitment_tx = commitment_data.stats.tx;
89618979 let signature = match &self.context.holder_signer {
89628980 // TODO (taproot|arik): move match into calling method for Taproot
89638981 ChannelSignerType::Ecdsa(ecdsa) => {
@@ -11609,12 +11627,12 @@ mod tests {
1160911627 $( { $htlc_idx: expr, $counterparty_htlc_sig_hex: expr, $htlc_sig_hex: expr, $htlc_tx_hex: expr } ), *
1161011628 } ) => { {
1161111629 let (commitment_tx, htlcs): (_, Vec<HTLCOutputInCommitment>) = {
11612- let mut commitment_stats = chan.context.build_commitment_transaction(&chan.funding, 0xffffffffffff - 42, &per_commitment_point, true, false, &logger);
11630+ let mut commitment_data = chan.context.build_commitment_transaction(&chan.funding, 0xffffffffffff - 42, &per_commitment_point, true, false, &logger);
1161311631
11614- let htlcs = commitment_stats .htlcs_included.drain(..)
11632+ let htlcs = commitment_data .htlcs_included.drain(..)
1161511633 .filter_map(|(htlc, _)| if htlc.transaction_output_index.is_some() { Some(htlc) } else { None })
1161611634 .collect();
11617- (commitment_stats .tx, htlcs)
11635+ (commitment_data.stats .tx, htlcs)
1161811636 };
1161911637 let trusted_tx = commitment_tx.trust();
1162011638 let unsigned_tx = trusted_tx.built_transaction();
0 commit comments