Skip to content

Commit d8f266a

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 2ae2f0d commit d8f266a

File tree

1 file changed

+69
-15
lines changed

1 file changed

+69
-15
lines changed

lightning/src/ln/channel.rs

+69-15
Original file line numberDiff line numberDiff line change
@@ -1515,7 +1515,8 @@ impl<SP: Deref> Channel<SP> where
15151515
};
15161516
let mut funded_channel = FundedChannel {
15171517
funding: chan.funding,
1518-
pending_funding: BTreeMap::new(),
1518+
pending_funding: vec![],
1519+
commitment_signed_batch: vec![],
15191520
context: chan.context,
15201521
interactive_tx_signing_session: chan.interactive_tx_signing_session,
15211522
holder_commitment_point,
@@ -4823,7 +4824,8 @@ pub(super) struct DualFundingChannelContext {
48234824
// Counterparty designates channel data owned by the another channel participant entity.
48244825
pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
48254826
pub funding: FundingScope,
4826-
pending_funding: BTreeMap<Txid, FundingScope>,
4827+
pending_funding: Vec<FundingScope>,
4828+
commitment_signed_batch: Vec<msgs::CommitmentSigned>,
48274829
pub context: ChannelContext<SP>,
48284830
pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
48294831
holder_commitment_point: HolderCommitmentPoint,
@@ -5653,7 +5655,53 @@ impl<SP: Deref> FundedChannel<SP> where
56535655
return Err(ChannelError::close("Peer sent commitment_signed after we'd started exchanging closing_signeds".to_owned()));
56545656
}
56555657

5656-
let commitment_tx_info = self.context.validate_commitment_signed(&self.funding, &self.holder_commitment_point, msg, logger)?;
5658+
if msg.batch.is_none() && !self.pending_funding.is_empty() {
5659+
return Err(ChannelError::close("Peer sent commitment_signed without a batch when there's a pending splice".to_owned()));
5660+
}
5661+
5662+
let mut updates = match &msg.batch {
5663+
// No pending splice
5664+
None => {
5665+
debug_assert!(self.pending_funding.is_empty());
5666+
self.context
5667+
.validate_commitment_signed(&self.funding, &self.holder_commitment_point, msg, logger)
5668+
.map(|LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs, nondust_htlc_sources }|
5669+
vec![ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
5670+
commitment_tx, htlc_outputs, claimed_htlcs: vec![], nondust_htlc_sources,
5671+
}]
5672+
)?
5673+
},
5674+
// May or may not have a pending splice
5675+
Some(batch) => {
5676+
self.commitment_signed_batch.push(msg.clone());
5677+
if self.commitment_signed_batch.len() < batch.batch_size as usize {
5678+
return Ok(None);
5679+
}
5680+
5681+
let commitment_signed_batch: BTreeMap<_, _> = self.commitment_signed_batch
5682+
.drain(..)
5683+
.map(|msg| (msg.batch.as_ref().expect("commitment_signed should have a batch").funding_txid, msg))
5684+
.collect();
5685+
5686+
core::iter::once(&self.funding)
5687+
.chain(self.pending_funding.iter())
5688+
.map(|funding| {
5689+
let funding_txid = funding.get_funding_txo().unwrap().txid;
5690+
let msg = commitment_signed_batch
5691+
.get(&funding_txid)
5692+
.ok_or_else(|| ChannelError::close(format!("Peer did not send a commitment_signed for pending splice transaction: {}", funding_txid)))?;
5693+
self.context
5694+
.validate_commitment_signed(funding, &self.holder_commitment_point, msg, logger)
5695+
.map(|LatestHolderCommitmentTXInfo { commitment_tx, htlc_outputs, nondust_htlc_sources }|
5696+
ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
5697+
commitment_tx, htlc_outputs, claimed_htlcs: vec![], nondust_htlc_sources,
5698+
}
5699+
)
5700+
}
5701+
)
5702+
.collect::<Result<Vec<_>, ChannelError>>()?
5703+
},
5704+
};
56575705

56585706
if self.holder_commitment_point.advance(&self.context.holder_signer, &self.context.secp_ctx, logger).is_err() {
56595707
// We only fail to advance our commitment point/number if we're currently
@@ -5708,19 +5756,22 @@ impl<SP: Deref> FundedChannel<SP> where
57085756
}
57095757
}
57105758

5711-
let LatestHolderCommitmentTXInfo {
5712-
commitment_tx, htlc_outputs, nondust_htlc_sources,
5713-
} = commitment_tx_info;
5759+
for mut update in updates.iter_mut() {
5760+
if let ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
5761+
claimed_htlcs: ref mut update_claimed_htlcs, ..
5762+
} = &mut update {
5763+
debug_assert!(update_claimed_htlcs.is_empty());
5764+
*update_claimed_htlcs = claimed_htlcs.clone();
5765+
} else {
5766+
debug_assert!(false);
5767+
}
5768+
}
5769+
57145770
self.context.latest_monitor_update_id += 1;
57155771
let mut monitor_update = ChannelMonitorUpdate {
57165772
update_id: self.context.latest_monitor_update_id,
57175773
counterparty_node_id: Some(self.context.counterparty_node_id),
5718-
updates: vec![ChannelMonitorUpdateStep::LatestHolderCommitmentTXInfo {
5719-
commitment_tx,
5720-
htlc_outputs,
5721-
claimed_htlcs,
5722-
nondust_htlc_sources,
5723-
}],
5774+
updates,
57245775
channel_id: Some(self.context.channel_id()),
57255776
};
57265777

@@ -9282,7 +9333,8 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
92829333

92839334
let mut channel = FundedChannel {
92849335
funding: self.funding,
9285-
pending_funding: BTreeMap::new(),
9336+
pending_funding: vec![],
9337+
commitment_signed_batch: vec![],
92869338
context: self.context,
92879339
interactive_tx_signing_session: None,
92889340
is_v2_established: false,
@@ -9550,7 +9602,8 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
95509602
// `ChannelMonitor`.
95519603
let mut channel = FundedChannel {
95529604
funding: self.funding,
9553-
pending_funding: BTreeMap::new(),
9605+
pending_funding: vec![],
9606+
commitment_signed_batch: vec![],
95549607
context: self.context,
95559608
interactive_tx_signing_session: None,
95569609
is_v2_established: false,
@@ -10791,7 +10844,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1079110844
channel_transaction_parameters: channel_parameters,
1079210845
funding_transaction,
1079310846
},
10794-
pending_funding: BTreeMap::new(),
10847+
pending_funding: vec![],
10848+
commitment_signed_batch: vec![],
1079510849
context: ChannelContext {
1079610850
user_id,
1079710851

0 commit comments

Comments
 (0)