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