@@ -66,6 +66,8 @@ use crate::util::errors::APIError;
66
66
use crate::util::config::{UserConfig, ChannelConfig, LegacyChannelConfig, ChannelHandshakeConfig, ChannelHandshakeLimits, MaxDustHTLCExposure};
67
67
use crate::util::scid_utils::scid_from_parts;
68
68
69
+ use alloc::collections::{btree_map, BTreeMap};
70
+
69
71
use crate::io;
70
72
use crate::prelude::*;
71
73
use core::{cmp,mem,fmt};
@@ -1515,6 +1517,7 @@ impl<SP: Deref> Channel<SP> where
1515
1517
let mut funded_channel = FundedChannel {
1516
1518
funding: chan.funding,
1517
1519
pending_funding: vec![],
1520
+ commitment_signed_batch: BTreeMap::new(),
1518
1521
context: chan.context,
1519
1522
interactive_tx_signing_session: chan.interactive_tx_signing_session,
1520
1523
holder_commitment_point,
@@ -4949,6 +4952,7 @@ pub(super) struct DualFundingChannelContext {
4949
4952
pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
4950
4953
pub funding: FundingScope,
4951
4954
pending_funding: Vec<FundingScope>,
4955
+ commitment_signed_batch: BTreeMap<Txid, msgs::CommitmentSigned>,
4952
4956
pub context: ChannelContext<SP>,
4953
4957
pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
4954
4958
holder_commitment_point: HolderCommitmentPoint,
@@ -5741,6 +5745,11 @@ impl<SP: Deref> FundedChannel<SP> where
5741
5745
ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
5742
5746
)));
5743
5747
}
5748
+
5749
+ if msg.batch.is_some() {
5750
+ return Err(ChannelError::close("Peer sent initial commitment_signed with a batch".to_owned()));
5751
+ }
5752
+
5744
5753
let holder_commitment_point = &mut self.holder_commitment_point.clone();
5745
5754
self.context.assert_no_commitment_advancement(holder_commitment_point.transaction_number(), "initial commitment_signed");
5746
5755
@@ -5781,7 +5790,58 @@ impl<SP: Deref> FundedChannel<SP> where
5781
5790
return Err(ChannelError::close("Peer sent commitment_signed after we'd started exchanging closing_signeds".to_owned()));
5782
5791
}
5783
5792
5784
- let commitment_tx_info = self.context.validate_commitment_signed(&self.funding, &self.holder_commitment_point, msg, logger)?;
5793
+ if msg.batch.is_none() && !self.pending_funding.is_empty() {
5794
+ return Err(ChannelError::close("Peer sent commitment_signed without a batch when there's a pending splice".to_owned()));
5795
+ }
5796
+
5797
+ let mut updates = match &msg.batch {
5798
+ // No pending splice
5799
+ None => {
5800
+ debug_assert!(self.pending_funding.is_empty());
5801
+ debug_assert!(self.commitment_signed_batch.is_empty());
5802
+ self.context
5803
+ .validate_commitment_signed(&self.funding, &self.holder_commitment_point, msg, logger)
5804
+ .map(|LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs, nondust_htlc_sources }|
5805
+ vec![ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
5806
+ commitment_tx, htlc_outputs, claimed_htlcs: vec![], nondust_htlc_sources,
5807
+ }]
5808
+ )?
5809
+ },
5810
+ // May or may not have a pending splice
5811
+ Some(batch) => {
5812
+ match self.commitment_signed_batch.entry(batch.funding_txid) {
5813
+ btree_map::Entry::Vacant(entry) => { entry.insert(msg.clone()); },
5814
+ btree_map::Entry::Occupied(entry) => {
5815
+ return Err(ChannelError::close(format!("Peer sent commitment_signed with duplicate funding_txid {} in a batch", entry.key())));
5816
+ },
5817
+ }
5818
+
5819
+ if self.commitment_signed_batch.len() < batch.batch_size as usize {
5820
+ return Ok(None);
5821
+ }
5822
+
5823
+ // Any commitment_signed not associated with a FundingScope is ignored below if a
5824
+ // pending splice transaction has confirmed since receiving the batch.
5825
+ core::iter::once(&self.funding)
5826
+ .chain(self.pending_funding.iter())
5827
+ .map(|funding| {
5828
+ let funding_txid = funding.get_funding_txo().unwrap().txid;
5829
+ let msg = self.commitment_signed_batch
5830
+ .get(&funding_txid)
5831
+ .ok_or_else(|| ChannelError::close(format!("Peer did not send a commitment_signed for pending splice transaction: {}", funding_txid)))?;
5832
+ self.context
5833
+ .validate_commitment_signed(funding, &self.holder_commitment_point, msg, logger)
5834
+ .map(|LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs, nondust_htlc_sources }|
5835
+ ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
5836
+ commitment_tx, htlc_outputs, claimed_htlcs: vec![], nondust_htlc_sources,
5837
+ }
5838
+ )
5839
+ }
5840
+ )
5841
+ .collect::<Result<Vec<_>, ChannelError>>()?
5842
+ },
5843
+ };
5844
+ self.commitment_signed_batch.clear();
5785
5845
5786
5846
if self.holder_commitment_point.advance(&self.context.holder_signer, &self.context.secp_ctx, logger).is_err() {
5787
5847
// We only fail to advance our commitment point/number if we're currently
@@ -5836,18 +5896,21 @@ impl<SP: Deref> FundedChannel<SP> where
5836
5896
}
5837
5897
}
5838
5898
5839
- let LatestHolderCommitmentTXInfo {
5840
- commitment_tx, htlc_outputs, nondust_htlc_sources,
5841
- } = commitment_tx_info;
5899
+ for mut update in updates.iter_mut() {
5900
+ if let ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
5901
+ claimed_htlcs: ref mut update_claimed_htlcs, ..
5902
+ } = &mut update {
5903
+ debug_assert!(update_claimed_htlcs.is_empty());
5904
+ *update_claimed_htlcs = claimed_htlcs.clone();
5905
+ } else {
5906
+ debug_assert!(false);
5907
+ }
5908
+ }
5909
+
5842
5910
self.context.latest_monitor_update_id += 1;
5843
5911
let mut monitor_update = ChannelMonitorUpdate {
5844
5912
update_id: self.context.latest_monitor_update_id,
5845
- updates: vec![ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
5846
- commitment_tx,
5847
- htlc_outputs,
5848
- claimed_htlcs,
5849
- nondust_htlc_sources,
5850
- }],
5913
+ updates,
5851
5914
channel_id: Some(self.context.channel_id()),
5852
5915
};
5853
5916
@@ -9541,6 +9604,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
9541
9604
let mut channel = FundedChannel {
9542
9605
funding: self.funding,
9543
9606
pending_funding: vec![],
9607
+ commitment_signed_batch: BTreeMap::new(),
9544
9608
context: self.context,
9545
9609
interactive_tx_signing_session: None,
9546
9610
is_v2_established: false,
@@ -9818,6 +9882,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
9818
9882
let mut channel = FundedChannel {
9819
9883
funding: self.funding,
9820
9884
pending_funding: vec![],
9885
+ commitment_signed_batch: BTreeMap::new(),
9821
9886
context: self.context,
9822
9887
interactive_tx_signing_session: None,
9823
9888
is_v2_established: false,
@@ -11084,6 +11149,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
11084
11149
funding_transaction,
11085
11150
},
11086
11151
pending_funding: pending_funding.unwrap(),
11152
+ commitment_signed_batch: BTreeMap::new(),
11087
11153
context: ChannelContext {
11088
11154
user_id,
11089
11155
0 commit comments