Skip to content

Commit d16db06

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 b815cdf commit d16db06

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,
@@ -4916,6 +4919,7 @@ pub(super) struct DualFundingChannelContext {
49164919
pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
49174920
pub funding: FundingScope,
49184921
pending_funding: Vec<FundingScope>,
4922+
commitment_signed_batch: Vec<msgs::CommitmentSigned>,
49194923
pub context: ChannelContext<SP>,
49204924
pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
49214925
holder_commitment_point: HolderCommitmentPoint,
@@ -5739,7 +5743,53 @@ impl<SP: Deref> FundedChannel<SP> where
57395743
return Err(ChannelError::close("Peer sent commitment_signed after we'd started exchanging closing_signeds".to_owned()));
57405744
}
57415745

5742-
let commitment_tx_info = self.context.validate_commitment_signed(&self.funding, &self.holder_commitment_point, msg, logger)?;
5746+
if msg.batch.is_none() && !self.pending_funding.is_empty() {
5747+
return Err(ChannelError::close("Peer sent commitment_signed without a batch when there's a pending splice".to_owned()));
5748+
}
5749+
5750+
let mut updates = match &msg.batch {
5751+
// No pending splice
5752+
None => {
5753+
debug_assert!(self.pending_funding.is_empty());
5754+
self.context
5755+
.validate_commitment_signed(&self.funding, &self.holder_commitment_point, msg, logger)
5756+
.map(|LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs, nondust_htlc_sources }|
5757+
vec![ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
5758+
commitment_tx, htlc_outputs, claimed_htlcs: vec![], nondust_htlc_sources,
5759+
}]
5760+
)?
5761+
},
5762+
// May or may not have a pending splice
5763+
Some(batch) => {
5764+
self.commitment_signed_batch.push(msg.clone());
5765+
if self.commitment_signed_batch.len() < batch.batch_size as usize {
5766+
return Ok(None);
5767+
}
5768+
5769+
let commitment_signed_batch: BTreeMap<_, _> = self.commitment_signed_batch
5770+
.drain(..)
5771+
.map(|msg| (msg.batch.as_ref().expect("commitment_signed should have a batch").funding_txid, msg))
5772+
.collect();
5773+
5774+
core::iter::once(&self.funding)
5775+
.chain(self.pending_funding.iter())
5776+
.map(|funding| {
5777+
let funding_txid = funding.get_funding_txo().unwrap().txid;
5778+
let msg = commitment_signed_batch
5779+
.get(&funding_txid)
5780+
.ok_or_else(|| ChannelError::close(format!("Peer did not send a commitment_signed for pending splice transaction: {}", funding_txid)))?;
5781+
self.context
5782+
.validate_commitment_signed(funding, &self.holder_commitment_point, msg, logger)
5783+
.map(|LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs, nondust_htlc_sources }|
5784+
ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
5785+
commitment_tx, htlc_outputs, claimed_htlcs: vec![], nondust_htlc_sources,
5786+
}
5787+
)
5788+
}
5789+
)
5790+
.collect::<Result<Vec<_>, ChannelError>>()?
5791+
},
5792+
};
57435793

57445794
if self.holder_commitment_point.advance(&self.context.holder_signer, &self.context.secp_ctx, logger).is_err() {
57455795
// We only fail to advance our commitment point/number if we're currently
@@ -5794,18 +5844,21 @@ impl<SP: Deref> FundedChannel<SP> where
57945844
}
57955845
}
57965846

5797-
let LatestHolderCommitmentTXInfo {
5798-
commitment_tx, htlc_outputs, nondust_htlc_sources,
5799-
} = commitment_tx_info;
5847+
for mut update in updates.iter_mut() {
5848+
if let ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
5849+
claimed_htlcs: ref mut update_claimed_htlcs, ..
5850+
} = &mut update {
5851+
debug_assert!(update_claimed_htlcs.is_empty());
5852+
*update_claimed_htlcs = claimed_htlcs.clone();
5853+
} else {
5854+
debug_assert!(false);
5855+
}
5856+
}
5857+
58005858
self.context.latest_monitor_update_id += 1;
58015859
let mut monitor_update = ChannelMonitorUpdate {
58025860
update_id: self.context.latest_monitor_update_id,
5803-
updates: vec![ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
5804-
commitment_tx,
5805-
htlc_outputs,
5806-
claimed_htlcs,
5807-
nondust_htlc_sources,
5808-
}],
5861+
updates,
58095862
channel_id: Some(self.context.channel_id()),
58105863
};
58115864

@@ -9499,6 +9552,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
94999552
let mut channel = FundedChannel {
95009553
funding: self.funding,
95019554
pending_funding: vec![],
9555+
commitment_signed_batch: vec![],
95029556
context: self.context,
95039557
interactive_tx_signing_session: None,
95049558
is_v2_established: false,
@@ -9776,6 +9830,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
97769830
let mut channel = FundedChannel {
97779831
funding: self.funding,
97789832
pending_funding: vec![],
9833+
commitment_signed_batch: vec![],
97799834
context: self.context,
97809835
interactive_tx_signing_session: None,
97819836
is_v2_established: false,
@@ -11042,6 +11097,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1104211097
funding_transaction,
1104311098
},
1104411099
pending_funding: pending_funding.unwrap(),
11100+
commitment_signed_batch: vec![],
1104511101
context: ChannelContext {
1104611102
user_id,
1104711103

0 commit comments

Comments
 (0)