Skip to content

Commit bed20cf

Browse files
authored
Merge pull request #3873 from jkczyz/2025-06-splice-locked-fixes
Follow-ups #3741: Exchange `splice_locked` messages
2 parents 4392a9d + db69ec7 commit bed20cf

File tree

2 files changed

+145
-94
lines changed

2 files changed

+145
-94
lines changed

lightning/src/ln/channel.rs

Lines changed: 99 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1424,7 +1424,7 @@ pub(crate) const COINBASE_MATURITY: u32 = 100;
14241424
/// The number of blocks to wait for a channel_announcement to propagate such that payments using an
14251425
/// older SCID can still be relayed. Once the spend of the previous funding transaction has reached
14261426
/// this number of confirmations, the corresponding SCID will be forgotten.
1427-
const CHANNEL_ANNOUNCEMENT_PROPAGATION_DELAY: u32 = 12;
1427+
const CHANNEL_ANNOUNCEMENT_PROPAGATION_DELAY: u32 = 144;
14281428

14291429
struct PendingChannelMonitorUpdate {
14301430
update: ChannelMonitorUpdate,
@@ -2156,6 +2156,40 @@ struct PendingSplice {
21562156
received_funding_txid: Option<Txid>,
21572157
}
21582158

2159+
#[cfg(splicing)]
2160+
impl PendingSplice {
2161+
fn check_get_splice_locked<SP: Deref>(
2162+
&mut self, context: &ChannelContext<SP>, funding: &FundingScope, height: u32,
2163+
) -> Option<msgs::SpliceLocked>
2164+
where
2165+
SP::Target: SignerProvider,
2166+
{
2167+
if !context.check_funding_meets_minimum_depth(funding, height) {
2168+
return None;
2169+
}
2170+
2171+
let confirmed_funding_txid = match funding.get_funding_txid() {
2172+
Some(funding_txid) => funding_txid,
2173+
None => {
2174+
debug_assert!(false);
2175+
return None;
2176+
},
2177+
};
2178+
2179+
match self.sent_funding_txid {
2180+
Some(sent_funding_txid) if confirmed_funding_txid == sent_funding_txid => None,
2181+
_ => {
2182+
let splice_locked = msgs::SpliceLocked {
2183+
channel_id: context.channel_id(),
2184+
splice_txid: confirmed_funding_txid,
2185+
};
2186+
self.sent_funding_txid = Some(splice_locked.splice_txid);
2187+
Some(splice_locked)
2188+
},
2189+
}
2190+
}
2191+
}
2192+
21592193
/// Wrapper around a [`Transaction`] useful for caching the result of [`Transaction::compute_txid`].
21602194
struct ConfirmedTransaction<'a> {
21612195
tx: &'a Transaction,
@@ -5551,6 +5585,29 @@ where
55515585
self.get_initial_counterparty_commitment_signature(funding, logger)
55525586
}
55535587

5588+
fn check_funding_meets_minimum_depth(&self, funding: &FundingScope, height: u32) -> bool {
5589+
let minimum_depth = self
5590+
.minimum_depth(funding)
5591+
.expect("ChannelContext::minimum_depth should be set for FundedChannel");
5592+
5593+
// Zero-conf channels always meet the minimum depth.
5594+
if minimum_depth == 0 {
5595+
return true;
5596+
}
5597+
5598+
if funding.funding_tx_confirmation_height == 0 {
5599+
return false;
5600+
}
5601+
5602+
let funding_tx_confirmations =
5603+
height as i64 - funding.funding_tx_confirmation_height as i64 + 1;
5604+
if funding_tx_confirmations < minimum_depth as i64 {
5605+
return false;
5606+
}
5607+
5608+
return true;
5609+
}
5610+
55545611
#[rustfmt::skip]
55555612
fn check_for_funding_tx_confirmed<L: Deref>(
55565613
&mut self, funding: &mut FundingScope, block_hash: &BlockHash, height: u32,
@@ -9234,58 +9291,13 @@ where
92349291
}
92359292
}
92369293

9237-
#[cfg(splicing)]
9238-
fn check_get_splice_locked(
9239-
&self, pending_splice: &PendingSplice, funding: &FundingScope, height: u32,
9240-
) -> Option<msgs::SpliceLocked> {
9241-
if !self.check_funding_meets_minimum_depth(funding, height) {
9242-
return None;
9243-
}
9244-
9245-
let confirmed_funding_txid = match funding.get_funding_txid() {
9246-
Some(funding_txid) => funding_txid,
9247-
None => {
9248-
debug_assert!(false);
9249-
return None;
9250-
},
9251-
};
9252-
9253-
match pending_splice.sent_funding_txid {
9254-
Some(sent_funding_txid) if confirmed_funding_txid == sent_funding_txid => None,
9255-
_ => Some(msgs::SpliceLocked {
9256-
channel_id: self.context.channel_id(),
9257-
splice_txid: confirmed_funding_txid,
9258-
}),
9259-
}
9260-
}
9261-
92629294
fn check_funding_meets_minimum_depth(&self, funding: &FundingScope, height: u32) -> bool {
9263-
let minimum_depth = self
9264-
.context
9265-
.minimum_depth(funding)
9266-
.expect("ChannelContext::minimum_depth should be set for FundedChannel");
9267-
9268-
// Zero-conf channels always meet the minimum depth.
9269-
if minimum_depth == 0 {
9270-
return true;
9271-
}
9272-
9273-
if funding.funding_tx_confirmation_height == 0 {
9274-
return false;
9275-
}
9276-
9277-
let funding_tx_confirmations =
9278-
height as i64 - funding.funding_tx_confirmation_height as i64 + 1;
9279-
if funding_tx_confirmations < minimum_depth as i64 {
9280-
return false;
9281-
}
9282-
9283-
return true;
9295+
self.context.check_funding_meets_minimum_depth(funding, height)
92849296
}
92859297

92869298
#[cfg(splicing)]
92879299
fn maybe_promote_splice_funding<L: Deref>(
9288-
&mut self, splice_txid: Txid, confirmed_funding_index: usize, logger: &L,
9300+
&mut self, confirmed_funding_index: usize, logger: &L,
92899301
) -> bool
92909302
where
92919303
L::Target: Logger,
@@ -9294,7 +9306,13 @@ where
92949306
debug_assert!(confirmed_funding_index < self.pending_funding.len());
92959307

92969308
let pending_splice = self.pending_splice.as_mut().unwrap();
9297-
pending_splice.sent_funding_txid = Some(splice_txid);
9309+
let splice_txid = match pending_splice.sent_funding_txid {
9310+
Some(sent_funding_txid) => sent_funding_txid,
9311+
None => {
9312+
debug_assert!(false);
9313+
return false;
9314+
},
9315+
};
92989316

92999317
if pending_splice.sent_funding_txid == pending_splice.received_funding_txid {
93009318
log_info!(
@@ -9305,6 +9323,7 @@ where
93059323
);
93069324

93079325
let funding = self.pending_funding.get_mut(confirmed_funding_index).unwrap();
9326+
debug_assert_eq!(Some(splice_txid), funding.get_funding_txid());
93089327
promote_splice_funding!(self, funding);
93099328

93109329
return true;
@@ -9394,7 +9413,7 @@ where
93949413

93959414
#[cfg(splicing)]
93969415
if let Some(confirmed_funding_index) = confirmed_funding_index {
9397-
let pending_splice = match self.pending_splice.as_ref() {
9416+
let pending_splice = match self.pending_splice.as_mut() {
93989417
Some(pending_splice) => pending_splice,
93999418
None => {
94009419
// TODO: Move pending_funding into pending_splice
@@ -9405,7 +9424,7 @@ where
94059424
};
94069425
let funding = self.pending_funding.get(confirmed_funding_index).unwrap();
94079426

9408-
if let Some(splice_locked) = self.check_get_splice_locked(pending_splice, funding, height) {
9427+
if let Some(splice_locked) = pending_splice.check_get_splice_locked(&self.context, funding, height) {
94099428
for &(idx, tx) in txdata.iter() {
94109429
if idx > index_in_block {
94119430
self.context.check_for_funding_tx_spent(funding, tx, logger)?;
@@ -9419,12 +9438,18 @@ where
94199438
&self.context.channel_id,
94209439
);
94219440

9422-
let announcement_sigs = self
9423-
.maybe_promote_splice_funding(splice_locked.splice_txid, confirmed_funding_index, logger)
9441+
let funding_promoted =
9442+
self.maybe_promote_splice_funding(confirmed_funding_index, logger);
9443+
let funding_txo = funding_promoted.then(|| {
9444+
self.funding
9445+
.get_funding_txo()
9446+
.expect("Splice FundingScope should always have a funding_txo")
9447+
});
9448+
let announcement_sigs = funding_promoted
94249449
.then(|| self.get_announcement_sigs(node_signer, chain_hash, user_config, height, logger))
94259450
.flatten();
94269451

9427-
return Ok((Some(FundingConfirmedMessage::Splice(splice_locked)), announcement_sigs));
9452+
return Ok((Some(FundingConfirmedMessage::Splice(splice_locked, funding_txo)), announcement_sigs));
94289453
}
94299454
}
94309455

@@ -9577,21 +9602,27 @@ where
95779602
}
95789603
}
95799604

9580-
let pending_splice = self.pending_splice.as_ref().unwrap();
9605+
let pending_splice = self.pending_splice.as_mut().unwrap();
95819606
let funding = self.pending_funding.get(confirmed_funding_index).unwrap();
9582-
if let Some(splice_locked) = self.check_get_splice_locked(pending_splice, funding, height) {
9607+
if let Some(splice_locked) = pending_splice.check_get_splice_locked(&self.context, funding, height) {
95839608
log_info!(logger, "Sending a splice_locked to our peer for channel {}", &self.context.channel_id);
95849609

9585-
let announcement_sigs = self
9586-
.maybe_promote_splice_funding(splice_locked.splice_txid, confirmed_funding_index, logger)
9610+
let funding_promoted =
9611+
self.maybe_promote_splice_funding(confirmed_funding_index, logger);
9612+
let funding_txo = funding_promoted.then(|| {
9613+
self.funding
9614+
.get_funding_txo()
9615+
.expect("Splice FundingScope should always have a funding_txo")
9616+
});
9617+
let announcement_sigs = funding_promoted
95879618
.then(|| chain_node_signer
95889619
.and_then(|(chain_hash, node_signer, user_config)|
95899620
self.get_announcement_sigs(node_signer, chain_hash, user_config, height, logger)
95909621
)
95919622
)
95929623
.flatten();
95939624

9594-
return Ok((Some(FundingConfirmedMessage::Splice(splice_locked)), timed_out_htlcs, announcement_sigs));
9625+
return Ok((Some(FundingConfirmedMessage::Splice(splice_locked, funding_txo)), timed_out_htlcs, announcement_sigs));
95959626
}
95969627
}
95979628

@@ -10085,7 +10116,7 @@ where
1008510116
pub fn splice_locked<NS: Deref, L: Deref>(
1008610117
&mut self, msg: &msgs::SpliceLocked, node_signer: &NS, chain_hash: ChainHash,
1008710118
user_config: &UserConfig, best_block: &BestBlock, logger: &L,
10088-
) -> Result<Option<msgs::AnnouncementSignatures>, ChannelError>
10119+
) -> Result<(Option<OutPoint>, Option<msgs::AnnouncementSignatures>), ChannelError>
1008910120
where
1009010121
NS::Target: NodeSigner,
1009110122
L::Target: Logger,
@@ -10118,13 +10149,18 @@ where
1011810149
&self.context.channel_id,
1011910150
);
1012010151
promote_splice_funding!(self, funding);
10121-
return Ok(self.get_announcement_sigs(
10152+
let funding_txo = self
10153+
.funding
10154+
.get_funding_txo()
10155+
.expect("Splice FundingScope should always have a funding_txo");
10156+
let announcement_sigs = self.get_announcement_sigs(
1012210157
node_signer,
1012310158
chain_hash,
1012410159
user_config,
1012510160
best_block.height,
1012610161
logger,
10127-
));
10162+
);
10163+
return Ok((Some(funding_txo), announcement_sigs));
1012810164
}
1012910165

1013010166
let err = "unknown splice funding txid";
@@ -10148,7 +10184,7 @@ where
1014810184
}
1014910185

1015010186
pending_splice.received_funding_txid = Some(msg.splice_txid);
10151-
Ok(None)
10187+
Ok((None, None))
1015210188
}
1015310189

1015410190
// Send stuff to our remote peers:
@@ -10899,11 +10935,6 @@ where
1089910935
}
1090010936
}
1090110937

10902-
#[cfg(splicing)]
10903-
pub fn has_pending_splice(&self) -> bool {
10904-
self.pending_splice.is_some()
10905-
}
10906-
1090710938
pub fn remove_legacy_scids_before_block(&mut self, height: u32) -> alloc::vec::Drain<u64> {
1090810939
let end = self
1090910940
.funding

0 commit comments

Comments
 (0)