Skip to content

Commit ade88ea

Browse files
committed
Batch commitment_signed messages for splicing
A FundedChannel may have more than one pending FundingScope during splicing, one for the splice attempt and one or more for any RBF attempts. The counterparty will send a commitment_signed message for each pending splice transaction and the current funding transaction. Defer handling these commitment_signed messages until the entire batch has arrived. Then validate them individually, also checking if all the pending splice transactions and the current funding transaction have a corresponding commitment_signed in the batch.
1 parent 2297d7c commit ade88ea

File tree

1 file changed

+66
-10
lines changed

1 file changed

+66
-10
lines changed

lightning/src/ln/channel.rs

Lines changed: 66 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ use crate::util::errors::APIError;
6666
use crate::util::config::{UserConfig, ChannelConfig, LegacyChannelConfig, ChannelHandshakeConfig, ChannelHandshakeLimits, MaxDustHTLCExposure};
6767
use crate::util::scid_utils::scid_from_parts;
6868

69+
use alloc::collections::BTreeMap;
70+
6971
use crate::io;
7072
use crate::prelude::*;
7173
use core::{cmp,mem,fmt};
@@ -1515,6 +1517,7 @@ impl<SP: Deref> Channel<SP> where
15151517
let mut funded_channel = FundedChannel {
15161518
funding: chan.funding,
15171519
pending_funding: vec![],
1520+
commitment_signed_batch: vec![],
15181521
context: chan.context,
15191522
interactive_tx_signing_session: chan.interactive_tx_signing_session,
15201523
holder_commitment_point,
@@ -4953,6 +4956,7 @@ pub(super) struct DualFundingChannelContext {
49534956
pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
49544957
pub funding: FundingScope,
49554958
pending_funding: Vec<FundingScope>,
4959+
commitment_signed_batch: Vec<msgs::CommitmentSigned>,
49564960
pub context: ChannelContext<SP>,
49574961
pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
49584962
holder_commitment_point: HolderCommitmentPoint,
@@ -5785,7 +5789,53 @@ impl<SP: Deref> FundedChannel<SP> where
57855789
return Err(ChannelError::close("Peer sent commitment_signed after we'd started exchanging closing_signeds".to_owned()));
57865790
}
57875791

5788-
let commitment_tx_info = self.context.validate_commitment_signed(&self.funding, &self.holder_commitment_point, msg, logger)?;
5792+
if msg.batch.is_none() && !self.pending_funding.is_empty() {
5793+
return Err(ChannelError::close("Peer sent commitment_signed without a batch when there's a pending splice".to_owned()));
5794+
}
5795+
5796+
let mut updates = match &msg.batch {
5797+
// No pending splice
5798+
None => {
5799+
debug_assert!(self.pending_funding.is_empty());
5800+
self.context
5801+
.validate_commitment_signed(&self.funding, &self.holder_commitment_point, msg, logger)
5802+
.map(|LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs, nondust_htlc_sources }|
5803+
vec![ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
5804+
commitment_tx, htlc_outputs, claimed_htlcs: vec![], nondust_htlc_sources,
5805+
}]
5806+
)?
5807+
},
5808+
// May or may not have a pending splice
5809+
Some(batch) => {
5810+
self.commitment_signed_batch.push(msg.clone());
5811+
if self.commitment_signed_batch.len() < batch.batch_size as usize {
5812+
return Ok(None);
5813+
}
5814+
5815+
let commitment_signed_batch: BTreeMap<_, _> = self.commitment_signed_batch
5816+
.drain(..)
5817+
.map(|msg| (msg.batch.as_ref().expect("commitment_signed should have a batch").funding_txid, msg))
5818+
.collect();
5819+
5820+
core::iter::once(&self.funding)
5821+
.chain(self.pending_funding.iter())
5822+
.map(|funding| {
5823+
let funding_txid = funding.get_funding_txo().unwrap().txid;
5824+
let msg = commitment_signed_batch
5825+
.get(&funding_txid)
5826+
.ok_or_else(|| ChannelError::close(format!("Peer did not send a commitment_signed for pending splice transaction: {}", funding_txid)))?;
5827+
self.context
5828+
.validate_commitment_signed(funding, &self.holder_commitment_point, msg, logger)
5829+
.map(|LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs, nondust_htlc_sources }|
5830+
ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
5831+
commitment_tx, htlc_outputs, claimed_htlcs: vec![], nondust_htlc_sources,
5832+
}
5833+
)
5834+
}
5835+
)
5836+
.collect::<Result<Vec<_>, ChannelError>>()?
5837+
},
5838+
};
57895839

57905840
if self.holder_commitment_point.advance(&self.context.holder_signer, &self.context.secp_ctx, logger).is_err() {
57915841
// We only fail to advance our commitment point/number if we're currently
@@ -5840,18 +5890,21 @@ impl<SP: Deref> FundedChannel<SP> where
58405890
}
58415891
}
58425892

5843-
let LatestHolderCommitmentTXInfo {
5844-
commitment_tx, htlc_outputs, nondust_htlc_sources,
5845-
} = commitment_tx_info;
5893+
for mut update in updates.iter_mut() {
5894+
if let ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
5895+
claimed_htlcs: ref mut update_claimed_htlcs, ..
5896+
} = &mut update {
5897+
debug_assert!(update_claimed_htlcs.is_empty());
5898+
*update_claimed_htlcs = claimed_htlcs.clone();
5899+
} else {
5900+
debug_assert!(false);
5901+
}
5902+
}
5903+
58465904
self.context.latest_monitor_update_id += 1;
58475905
let mut monitor_update = ChannelMonitorUpdate {
58485906
update_id: self.context.latest_monitor_update_id,
5849-
updates: vec![ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
5850-
commitment_tx,
5851-
htlc_outputs,
5852-
claimed_htlcs,
5853-
nondust_htlc_sources,
5854-
}],
5907+
updates,
58555908
channel_id: Some(self.context.channel_id()),
58565909
};
58575910

@@ -9545,6 +9598,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
95459598
let mut channel = FundedChannel {
95469599
funding: self.funding,
95479600
pending_funding: vec![],
9601+
commitment_signed_batch: vec![],
95489602
context: self.context,
95499603
interactive_tx_signing_session: None,
95509604
is_v2_established: false,
@@ -9822,6 +9876,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
98229876
let mut channel = FundedChannel {
98239877
funding: self.funding,
98249878
pending_funding: vec![],
9879+
commitment_signed_batch: vec![],
98259880
context: self.context,
98269881
interactive_tx_signing_session: None,
98279882
is_v2_established: false,
@@ -11088,6 +11143,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1108811143
funding_transaction,
1108911144
},
1109011145
pending_funding: pending_funding.unwrap(),
11146+
commitment_signed_batch: vec![],
1109111147
context: ChannelContext {
1109211148
user_id,
1109311149

0 commit comments

Comments
 (0)