@@ -3452,6 +3452,145 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
34523452 !matches!(self.channel_state, ChannelState::AwaitingChannelReady(flags) if flags.is_set(AwaitingChannelReadyFlags::WAITING_FOR_BATCH))
34533453 }
34543454
3455+ fn commitment_signed_check<L: Deref>(
3456+ &self, funding: &FundingScope, holder_commitment_point: &HolderCommitmentPoint,
3457+ msg: &msgs::CommitmentSigned, logger: &L,
3458+ ) -> Result<LatestHolderCommitmentTXInfo, ChannelError>
3459+ where
3460+ L::Target: Logger,
3461+ {
3462+ if self.channel_state.is_quiescent() {
3463+ return Err(ChannelError::WarnAndDisconnect("Got commitment_signed message while quiescent".to_owned()));
3464+ }
3465+ if !matches!(self.channel_state, ChannelState::ChannelReady(_)) {
3466+ return Err(ChannelError::close("Got commitment signed message when channel was not in an operational state".to_owned()));
3467+ }
3468+ if self.channel_state.is_peer_disconnected() {
3469+ return Err(ChannelError::close("Peer sent commitment_signed when we needed a channel_reestablish".to_owned()));
3470+ }
3471+ if self.channel_state.is_both_sides_shutdown() && self.last_sent_closing_fee.is_some() {
3472+ return Err(ChannelError::close("Peer sent commitment_signed after we'd started exchanging closing_signeds".to_owned()));
3473+ }
3474+
3475+ let funding_script = funding.get_funding_redeemscript();
3476+
3477+ let keys = self.build_holder_transaction_keys(funding, holder_commitment_point.current_point());
3478+
3479+ let commitment_stats = self.build_commitment_transaction(funding, holder_commitment_point.transaction_number(), &keys, true, false, logger);
3480+ let commitment_txid = {
3481+ let trusted_tx = commitment_stats.tx.trust();
3482+ let bitcoin_tx = trusted_tx.built_transaction();
3483+ let sighash = bitcoin_tx.get_sighash_all(&funding_script, funding.get_value_satoshis());
3484+
3485+ log_trace!(logger, "Checking commitment tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} in channel {}",
3486+ log_bytes!(msg.signature.serialize_compact()[..]),
3487+ log_bytes!(funding.counterparty_funding_pubkey().serialize()), encode::serialize_hex(&bitcoin_tx.transaction),
3488+ log_bytes!(sighash[..]), encode::serialize_hex(&funding_script), &self.channel_id());
3489+ if let Err(_) = self.secp_ctx.verify_ecdsa(&sighash, &msg.signature, &funding.counterparty_funding_pubkey()) {
3490+ return Err(ChannelError::close("Invalid commitment tx signature from peer".to_owned()));
3491+ }
3492+ bitcoin_tx.txid
3493+ };
3494+ let mut htlcs_cloned: Vec<_> = commitment_stats.htlcs_included.iter().map(|htlc| (htlc.0.clone(), htlc.1.map(|h| h.clone()))).collect();
3495+
3496+ // If our counterparty updated the channel fee in this commitment transaction, check that
3497+ // they can actually afford the new fee now.
3498+ let update_fee = if let Some((_, update_state)) = self.pending_update_fee {
3499+ update_state == FeeUpdateState::RemoteAnnounced
3500+ } else { false };
3501+ if update_fee {
3502+ debug_assert!(!funding.is_outbound());
3503+ let counterparty_reserve_we_require_msat = funding.holder_selected_channel_reserve_satoshis * 1000;
3504+ if commitment_stats.remote_balance_msat < commitment_stats.total_fee_sat * 1000 + counterparty_reserve_we_require_msat {
3505+ return Err(ChannelError::close("Funding remote cannot afford proposed new fee".to_owned()));
3506+ }
3507+ }
3508+ #[cfg(any(test, fuzzing))]
3509+ {
3510+ if funding.is_outbound() {
3511+ let projected_commit_tx_info = funding.next_local_commitment_tx_fee_info_cached.lock().unwrap().take();
3512+ *funding.next_remote_commitment_tx_fee_info_cached.lock().unwrap() = None;
3513+ if let Some(info) = projected_commit_tx_info {
3514+ let total_pending_htlcs = self.pending_inbound_htlcs.len() + self.pending_outbound_htlcs.len()
3515+ + self.holding_cell_htlc_updates.len();
3516+ if info.total_pending_htlcs == total_pending_htlcs
3517+ && info.next_holder_htlc_id == self.next_holder_htlc_id
3518+ && info.next_counterparty_htlc_id == self.next_counterparty_htlc_id
3519+ && info.feerate == self.feerate_per_kw {
3520+ assert_eq!(commitment_stats.total_fee_sat, info.fee / 1000);
3521+ }
3522+ }
3523+ }
3524+ }
3525+
3526+ if msg.htlc_signatures.len() != commitment_stats.num_nondust_htlcs {
3527+ return Err(ChannelError::close(format!("Got wrong number of HTLC signatures ({}) from remote. It must be {}", msg.htlc_signatures.len(), commitment_stats.num_nondust_htlcs)));
3528+ }
3529+
3530+ // Up to LDK 0.0.115, HTLC information was required to be duplicated in the
3531+ // `htlcs_and_sigs` vec and in the `holder_commitment_tx` itself, both of which were passed
3532+ // in the `ChannelMonitorUpdate`. In 0.0.115, support for having a separate set of
3533+ // outbound-non-dust-HTLCSources in the `ChannelMonitorUpdate` was added, however for
3534+ // backwards compatibility, we never use it in production. To provide test coverage, here,
3535+ // we randomly decide (in test/fuzzing builds) to use the new vec sometimes.
3536+ #[allow(unused_assignments, unused_mut)]
3537+ let mut separate_nondust_htlc_sources = false;
3538+ #[cfg(all(feature = "std", any(test, fuzzing)))] {
3539+ use core::hash::{BuildHasher, Hasher};
3540+ // Get a random value using the only std API to do so - the DefaultHasher
3541+ let rand_val = std::collections::hash_map::RandomState::new().build_hasher().finish();
3542+ separate_nondust_htlc_sources = rand_val % 2 == 0;
3543+ }
3544+
3545+ let mut nondust_htlc_sources = Vec::with_capacity(htlcs_cloned.len());
3546+ let mut htlcs_and_sigs = Vec::with_capacity(htlcs_cloned.len());
3547+ for (idx, (htlc, mut source_opt)) in htlcs_cloned.drain(..).enumerate() {
3548+ if let Some(_) = htlc.transaction_output_index {
3549+ let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, commitment_stats.feerate_per_kw,
3550+ funding.get_counterparty_selected_contest_delay().unwrap(), &htlc, &self.channel_type,
3551+ &keys.broadcaster_delayed_payment_key, &keys.revocation_key);
3552+
3553+ let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &self.channel_type, &keys);
3554+ let htlc_sighashtype = if self.channel_type.supports_anchors_zero_fee_htlc_tx() { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All };
3555+ let htlc_sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).p2wsh_signature_hash(0, &htlc_redeemscript, htlc.to_bitcoin_amount(), htlc_sighashtype).unwrap()[..]);
3556+ log_trace!(logger, "Checking HTLC tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} in channel {}.",
3557+ log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(keys.countersignatory_htlc_key.to_public_key().serialize()),
3558+ encode::serialize_hex(&htlc_tx), log_bytes!(htlc_sighash[..]), encode::serialize_hex(&htlc_redeemscript), &self.channel_id());
3559+ if let Err(_) = self.secp_ctx.verify_ecdsa(&htlc_sighash, &msg.htlc_signatures[idx], &keys.countersignatory_htlc_key.to_public_key()) {
3560+ return Err(ChannelError::close("Invalid HTLC tx signature from peer".to_owned()));
3561+ }
3562+ if !separate_nondust_htlc_sources {
3563+ htlcs_and_sigs.push((htlc, Some(msg.htlc_signatures[idx]), source_opt.take()));
3564+ }
3565+ } else {
3566+ htlcs_and_sigs.push((htlc, None, source_opt.take()));
3567+ }
3568+ if separate_nondust_htlc_sources {
3569+ if let Some(source) = source_opt.take() {
3570+ nondust_htlc_sources.push(source);
3571+ }
3572+ }
3573+ debug_assert!(source_opt.is_none(), "HTLCSource should have been put somewhere");
3574+ }
3575+
3576+ let holder_commitment_tx = HolderCommitmentTransaction::new(
3577+ commitment_stats.tx,
3578+ msg.signature,
3579+ msg.htlc_signatures.clone(),
3580+ &funding.get_holder_pubkeys().funding_pubkey,
3581+ funding.counterparty_funding_pubkey()
3582+ );
3583+
3584+ self.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, commitment_stats.outbound_htlc_preimages)
3585+ .map_err(|_| ChannelError::close("Failed to validate our commitment".to_owned()))?;
3586+
3587+ Ok(LatestHolderCommitmentTXInfo {
3588+ commitment_tx: holder_commitment_tx,
3589+ htlc_outputs: htlcs_and_sigs,
3590+ nondust_htlc_sources,
3591+ })
3592+ }
3593+
34553594 /// Transaction nomenclature is somewhat confusing here as there are many different cases - a
34563595 /// transaction is referred to as "a's transaction" implying that a will be able to broadcast
34573596 /// the transaction. Thus, b will generally be sending a signature over such a transaction to
@@ -5494,145 +5633,10 @@ impl<SP: Deref> FundedChannel<SP> where
54945633 Ok(channel_monitor)
54955634 }
54965635
5497- fn commitment_signed_check<L: Deref>(&self, msg: &msgs::CommitmentSigned, logger: &L) -> Result<LatestHolderCommitmentTXInfo, ChannelError>
5498- where L::Target: Logger
5499- {
5500- if self.context.channel_state.is_quiescent() {
5501- return Err(ChannelError::WarnAndDisconnect("Got commitment_signed message while quiescent".to_owned()));
5502- }
5503- if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) {
5504- return Err(ChannelError::close("Got commitment signed message when channel was not in an operational state".to_owned()));
5505- }
5506- if self.context.channel_state.is_peer_disconnected() {
5507- return Err(ChannelError::close("Peer sent commitment_signed when we needed a channel_reestablish".to_owned()));
5508- }
5509- if self.context.channel_state.is_both_sides_shutdown() && self.context.last_sent_closing_fee.is_some() {
5510- return Err(ChannelError::close("Peer sent commitment_signed after we'd started exchanging closing_signeds".to_owned()));
5511- }
5512-
5513- let funding_script = self.funding.get_funding_redeemscript();
5514-
5515- let keys = self.context.build_holder_transaction_keys(&self.funding, self.holder_commitment_point.current_point());
5516-
5517- let commitment_stats = self.context.build_commitment_transaction(&self.funding, self.holder_commitment_point.transaction_number(), &keys, true, false, logger);
5518- let commitment_txid = {
5519- let trusted_tx = commitment_stats.tx.trust();
5520- let bitcoin_tx = trusted_tx.built_transaction();
5521- let sighash = bitcoin_tx.get_sighash_all(&funding_script, self.funding.get_value_satoshis());
5522-
5523- log_trace!(logger, "Checking commitment tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} in channel {}",
5524- log_bytes!(msg.signature.serialize_compact()[..]),
5525- log_bytes!(self.funding.counterparty_funding_pubkey().serialize()), encode::serialize_hex(&bitcoin_tx.transaction),
5526- log_bytes!(sighash[..]), encode::serialize_hex(&funding_script), &self.context.channel_id());
5527- if let Err(_) = self.context.secp_ctx.verify_ecdsa(&sighash, &msg.signature, &self.funding.counterparty_funding_pubkey()) {
5528- return Err(ChannelError::close("Invalid commitment tx signature from peer".to_owned()));
5529- }
5530- bitcoin_tx.txid
5531- };
5532- let mut htlcs_cloned: Vec<_> = commitment_stats.htlcs_included.iter().map(|htlc| (htlc.0.clone(), htlc.1.map(|h| h.clone()))).collect();
5533-
5534- // If our counterparty updated the channel fee in this commitment transaction, check that
5535- // they can actually afford the new fee now.
5536- let update_fee = if let Some((_, update_state)) = self.context.pending_update_fee {
5537- update_state == FeeUpdateState::RemoteAnnounced
5538- } else { false };
5539- if update_fee {
5540- debug_assert!(!self.funding.is_outbound());
5541- let counterparty_reserve_we_require_msat = self.funding.holder_selected_channel_reserve_satoshis * 1000;
5542- if commitment_stats.remote_balance_msat < commitment_stats.total_fee_sat * 1000 + counterparty_reserve_we_require_msat {
5543- return Err(ChannelError::close("Funding remote cannot afford proposed new fee".to_owned()));
5544- }
5545- }
5546- #[cfg(any(test, fuzzing))]
5547- {
5548- if self.funding.is_outbound() {
5549- let projected_commit_tx_info = self.funding.next_local_commitment_tx_fee_info_cached.lock().unwrap().take();
5550- *self.funding.next_remote_commitment_tx_fee_info_cached.lock().unwrap() = None;
5551- if let Some(info) = projected_commit_tx_info {
5552- let total_pending_htlcs = self.context.pending_inbound_htlcs.len() + self.context.pending_outbound_htlcs.len()
5553- + self.context.holding_cell_htlc_updates.len();
5554- if info.total_pending_htlcs == total_pending_htlcs
5555- && info.next_holder_htlc_id == self.context.next_holder_htlc_id
5556- && info.next_counterparty_htlc_id == self.context.next_counterparty_htlc_id
5557- && info.feerate == self.context.feerate_per_kw {
5558- assert_eq!(commitment_stats.total_fee_sat, info.fee / 1000);
5559- }
5560- }
5561- }
5562- }
5563-
5564- if msg.htlc_signatures.len() != commitment_stats.num_nondust_htlcs {
5565- return Err(ChannelError::close(format!("Got wrong number of HTLC signatures ({}) from remote. It must be {}", msg.htlc_signatures.len(), commitment_stats.num_nondust_htlcs)));
5566- }
5567-
5568- // Up to LDK 0.0.115, HTLC information was required to be duplicated in the
5569- // `htlcs_and_sigs` vec and in the `holder_commitment_tx` itself, both of which were passed
5570- // in the `ChannelMonitorUpdate`. In 0.0.115, support for having a separate set of
5571- // outbound-non-dust-HTLCSources in the `ChannelMonitorUpdate` was added, however for
5572- // backwards compatibility, we never use it in production. To provide test coverage, here,
5573- // we randomly decide (in test/fuzzing builds) to use the new vec sometimes.
5574- #[allow(unused_assignments, unused_mut)]
5575- let mut separate_nondust_htlc_sources = false;
5576- #[cfg(all(feature = "std", any(test, fuzzing)))] {
5577- use core::hash::{BuildHasher, Hasher};
5578- // Get a random value using the only std API to do so - the DefaultHasher
5579- let rand_val = std::collections::hash_map::RandomState::new().build_hasher().finish();
5580- separate_nondust_htlc_sources = rand_val % 2 == 0;
5581- }
5582-
5583- let mut nondust_htlc_sources = Vec::with_capacity(htlcs_cloned.len());
5584- let mut htlcs_and_sigs = Vec::with_capacity(htlcs_cloned.len());
5585- for (idx, (htlc, mut source_opt)) in htlcs_cloned.drain(..).enumerate() {
5586- if let Some(_) = htlc.transaction_output_index {
5587- let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, commitment_stats.feerate_per_kw,
5588- self.funding.get_counterparty_selected_contest_delay().unwrap(), &htlc, &self.context.channel_type,
5589- &keys.broadcaster_delayed_payment_key, &keys.revocation_key);
5590-
5591- let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &self.context.channel_type, &keys);
5592- let htlc_sighashtype = if self.context.channel_type.supports_anchors_zero_fee_htlc_tx() { EcdsaSighashType::SinglePlusAnyoneCanPay } else { EcdsaSighashType::All };
5593- let htlc_sighash = hash_to_message!(&sighash::SighashCache::new(&htlc_tx).p2wsh_signature_hash(0, &htlc_redeemscript, htlc.to_bitcoin_amount(), htlc_sighashtype).unwrap()[..]);
5594- log_trace!(logger, "Checking HTLC tx signature {} by key {} against tx {} (sighash {}) with redeemscript {} in channel {}.",
5595- log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(keys.countersignatory_htlc_key.to_public_key().serialize()),
5596- encode::serialize_hex(&htlc_tx), log_bytes!(htlc_sighash[..]), encode::serialize_hex(&htlc_redeemscript), &self.context.channel_id());
5597- if let Err(_) = self.context.secp_ctx.verify_ecdsa(&htlc_sighash, &msg.htlc_signatures[idx], &keys.countersignatory_htlc_key.to_public_key()) {
5598- return Err(ChannelError::close("Invalid HTLC tx signature from peer".to_owned()));
5599- }
5600- if !separate_nondust_htlc_sources {
5601- htlcs_and_sigs.push((htlc, Some(msg.htlc_signatures[idx]), source_opt.take()));
5602- }
5603- } else {
5604- htlcs_and_sigs.push((htlc, None, source_opt.take()));
5605- }
5606- if separate_nondust_htlc_sources {
5607- if let Some(source) = source_opt.take() {
5608- nondust_htlc_sources.push(source);
5609- }
5610- }
5611- debug_assert!(source_opt.is_none(), "HTLCSource should have been put somewhere");
5612- }
5613-
5614- let holder_commitment_tx = HolderCommitmentTransaction::new(
5615- commitment_stats.tx,
5616- msg.signature,
5617- msg.htlc_signatures.clone(),
5618- &self.funding.get_holder_pubkeys().funding_pubkey,
5619- self.funding.counterparty_funding_pubkey()
5620- );
5621-
5622- self.context.holder_signer.as_ref().validate_holder_commitment(&holder_commitment_tx, commitment_stats.outbound_htlc_preimages)
5623- .map_err(|_| ChannelError::close("Failed to validate our commitment".to_owned()))?;
5624-
5625- Ok(LatestHolderCommitmentTXInfo {
5626- commitment_tx: holder_commitment_tx,
5627- htlc_outputs: htlcs_and_sigs,
5628- nondust_htlc_sources,
5629- })
5630- }
5631-
56325636 pub fn commitment_signed<L: Deref>(&mut self, msg: &msgs::CommitmentSigned, logger: &L) -> Result<Option<ChannelMonitorUpdate>, ChannelError>
56335637 where L::Target: Logger
56345638 {
5635- let commitment_tx_info = self.commitment_signed_check(msg, logger)?;
5639+ let commitment_tx_info = self.context. commitment_signed_check(&self.funding, &self.holder_commitment_point, msg, logger)?;
56365640
56375641 // Update state now that we've passed all the can-fail calls...
56385642 let mut need_commitment = false;
0 commit comments