Skip to content

Commit d2022c4

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 f0503c9 commit d2022c4

File tree

1 file changed

+66
-10
lines changed

1 file changed

+66
-10
lines changed

lightning/src/ln/channel.rs

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

68+
use alloc::collections::BTreeMap;
69+
6870
use crate::io;
6971
use crate::prelude::*;
7072
use core::{cmp,mem,fmt};
@@ -1514,6 +1516,7 @@ impl<SP: Deref> Channel<SP> where
15141516
let mut funded_channel = FundedChannel {
15151517
funding: chan.funding,
15161518
pending_funding: vec![],
1519+
commitment_signed_batch: vec![],
15171520
context: chan.context,
15181521
interactive_tx_signing_session: chan.interactive_tx_signing_session,
15191522
holder_commitment_point,
@@ -4846,6 +4849,7 @@ pub(super) struct DualFundingChannelContext {
48464849
pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
48474850
pub funding: FundingScope,
48484851
pending_funding: Vec<FundingScope>,
4852+
commitment_signed_batch: Vec<msgs::CommitmentSigned>,
48494853
pub context: ChannelContext<SP>,
48504854
pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
48514855
holder_commitment_point: HolderCommitmentPoint,
@@ -5675,7 +5679,53 @@ impl<SP: Deref> FundedChannel<SP> where
56755679
return Err(ChannelError::close("Peer sent commitment_signed after we'd started exchanging closing_signeds".to_owned()));
56765680
}
56775681

5678-
let commitment_tx_info = self.context.validate_commitment_signed(&self.funding, &self.holder_commitment_point, msg, logger)?;
5682+
if msg.batch.is_none() && !self.pending_funding.is_empty() {
5683+
return Err(ChannelError::close("Peer sent commitment_signed without a batch when there's a pending splice".to_owned()));
5684+
}
5685+
5686+
let mut updates = match &msg.batch {
5687+
// No pending splice
5688+
None => {
5689+
debug_assert!(self.pending_funding.is_empty());
5690+
self.context
5691+
.validate_commitment_signed(&self.funding, &self.holder_commitment_point, msg, logger)
5692+
.map(|LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs, nondust_htlc_sources }|
5693+
vec![ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
5694+
commitment_tx, htlc_outputs, claimed_htlcs: vec![], nondust_htlc_sources,
5695+
}]
5696+
)?
5697+
},
5698+
// May or may not have a pending splice
5699+
Some(batch) => {
5700+
self.commitment_signed_batch.push(msg.clone());
5701+
if self.commitment_signed_batch.len() < batch.batch_size as usize {
5702+
return Ok(None);
5703+
}
5704+
5705+
let commitment_signed_batch: BTreeMap<_, _> = self.commitment_signed_batch
5706+
.drain(..)
5707+
.map(|msg| (msg.batch.as_ref().expect("commitment_signed should have a batch").funding_txid, msg))
5708+
.collect();
5709+
5710+
core::iter::once(&self.funding)
5711+
.chain(self.pending_funding.iter())
5712+
.map(|funding| {
5713+
let funding_txid = funding.get_funding_txo().unwrap().txid;
5714+
let msg = commitment_signed_batch
5715+
.get(&funding_txid)
5716+
.ok_or_else(|| ChannelError::close(format!("Peer did not send a commitment_signed for pending splice transaction: {}", funding_txid)))?;
5717+
self.context
5718+
.validate_commitment_signed(funding, &self.holder_commitment_point, msg, logger)
5719+
.map(|LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs, nondust_htlc_sources }|
5720+
ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
5721+
commitment_tx, htlc_outputs, claimed_htlcs: vec![], nondust_htlc_sources,
5722+
}
5723+
)
5724+
}
5725+
)
5726+
.collect::<Result<Vec<_>, ChannelError>>()?
5727+
},
5728+
};
56795729

56805730
if self.holder_commitment_point.advance(&self.context.holder_signer, &self.context.secp_ctx, logger).is_err() {
56815731
// We only fail to advance our commitment point/number if we're currently
@@ -5730,19 +5780,22 @@ impl<SP: Deref> FundedChannel<SP> where
57305780
}
57315781
}
57325782

5733-
let LatestHolderCommitmentTXInfo {
5734-
commitment_tx, htlc_outputs, nondust_htlc_sources,
5735-
} = commitment_tx_info;
5783+
for mut update in updates.iter_mut() {
5784+
if let ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
5785+
claimed_htlcs: ref mut update_claimed_htlcs, ..
5786+
} = &mut update {
5787+
debug_assert!(update_claimed_htlcs.is_empty());
5788+
*update_claimed_htlcs = claimed_htlcs.clone();
5789+
} else {
5790+
debug_assert!(false);
5791+
}
5792+
}
5793+
57365794
self.context.latest_monitor_update_id += 1;
57375795
let mut monitor_update = ChannelMonitorUpdate {
57385796
update_id: self.context.latest_monitor_update_id,
57395797
counterparty_node_id: Some(self.context.counterparty_node_id),
5740-
updates: vec![ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
5741-
commitment_tx,
5742-
htlc_outputs,
5743-
claimed_htlcs,
5744-
nondust_htlc_sources,
5745-
}],
5798+
updates,
57465799
channel_id: Some(self.context.channel_id()),
57475800
};
57485801

@@ -9305,6 +9358,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
93059358
let mut channel = FundedChannel {
93069359
funding: self.funding,
93079360
pending_funding: vec![],
9361+
commitment_signed_batch: vec![],
93089362
context: self.context,
93099363
interactive_tx_signing_session: None,
93109364
is_v2_established: false,
@@ -9573,6 +9627,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
95739627
let mut channel = FundedChannel {
95749628
funding: self.funding,
95759629
pending_funding: vec![],
9630+
commitment_signed_batch: vec![],
95769631
context: self.context,
95779632
interactive_tx_signing_session: None,
95789633
is_v2_established: false,
@@ -10818,6 +10873,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1081810873
funding_transaction,
1081910874
},
1082010875
pending_funding: pending_funding.unwrap(),
10876+
commitment_signed_batch: vec![],
1082110877
context: ChannelContext {
1082210878
user_id,
1082310879

0 commit comments

Comments
 (0)