Skip to content

Commit 7a0a70f

Browse files
jkczyzclaude
andcommitted
Emit SpliceFailed event when funded channels shut down with active splice negotiations
Adds SpliceFailed event emission immediately after ChannelClosed events when a FundedChannel is shut down while having an active splice negotiation. This ensures users are notified when splice operations are terminated due to channel closure. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent aaf09d6 commit 7a0a70f

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

lightning/src/ln/channel.rs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1188,6 +1188,9 @@ pub(crate) struct ShutdownResult {
11881188
pub(crate) unbroadcasted_funding_tx: Option<Transaction>,
11891189
pub(crate) channel_funding_txo: Option<OutPoint>,
11901190
pub(crate) last_local_balance_msat: u64,
1191+
/// If a splice was in progress when the channel was shut down, this contains
1192+
/// the splice funding information for emitting a SpliceFailed event.
1193+
pub(crate) splice_funding_failed: Option<SpliceFundingFailed>,
11911194
}
11921195

11931196
/// Tracks the transaction number, along with current and next commitment points.
@@ -2675,6 +2678,15 @@ pub(crate) struct SpliceInstructions {
26752678
locktime: u32,
26762679
}
26772680

2681+
impl SpliceInstructions {
2682+
fn into_contributed_inputs_and_outputs(self) -> (Vec<bitcoin::OutPoint>, Vec<TxOut>) {
2683+
(
2684+
self.our_funding_inputs.into_iter().map(|input| input.utxo.outpoint).collect(),
2685+
self.our_funding_outputs,
2686+
)
2687+
}
2688+
}
2689+
26782690
impl_writeable_tlv_based!(SpliceInstructions, {
26792691
(1, adjusted_funding_contribution, required),
26802692
(3, our_funding_inputs, required_vec),
@@ -6029,6 +6041,7 @@ where
60296041
is_manual_broadcast: self.is_manual_broadcast,
60306042
channel_funding_txo: funding.get_funding_txo(),
60316043
last_local_balance_msat: funding.value_to_self_msat,
6044+
splice_funding_failed: None,
60326045
}
60336046
}
60346047

@@ -6798,7 +6811,42 @@ where
67986811
}
67996812

68006813
pub fn force_shutdown(&mut self, closure_reason: ClosureReason) -> ShutdownResult {
6801-
self.context.force_shutdown(&self.funding, closure_reason)
6814+
let splice_funding_failed = self
6815+
.pending_splice
6816+
.as_mut()
6817+
.and_then(|pending_splice| pending_splice.funding_negotiation.take())
6818+
.filter(|funding_negotiation| funding_negotiation.is_initiator())
6819+
.map(|_funding_negotiation| {
6820+
// FIXME: Populte after #4120 is merged
6821+
SpliceFundingFailed {
6822+
funding_txo: todo!(),
6823+
channel_type: todo!(),
6824+
contributed_inputs: todo!(),
6825+
contributed_outputs: todo!(),
6826+
}
6827+
})
6828+
.or_else(|| {
6829+
self.quiescent_action.take().and_then(|quiescent_action| match quiescent_action {
6830+
QuiescentAction::Splice(instructions) => {
6831+
let (inputs, outputs) = instructions.into_contributed_inputs_and_outputs();
6832+
Some(SpliceFundingFailed {
6833+
funding_txo: None,
6834+
channel_type: None,
6835+
contributed_inputs: inputs,
6836+
contributed_outputs: outputs,
6837+
})
6838+
},
6839+
#[cfg(any(test, fuzzing))]
6840+
_ => {
6841+
self.quiescent_action = Some(quiescent_action);
6842+
None
6843+
},
6844+
})
6845+
});
6846+
6847+
let mut shutdown_result = self.context.force_shutdown(&self.funding, closure_reason);
6848+
shutdown_result.splice_funding_failed = splice_funding_failed;
6849+
shutdown_result
68026850
}
68036851

68046852
fn interactive_tx_constructor_mut(&mut self) -> Option<&mut InteractiveTxConstructor> {
@@ -10233,6 +10281,7 @@ where
1023310281
is_manual_broadcast: self.context.is_manual_broadcast,
1023410282
channel_funding_txo: self.funding.get_funding_txo(),
1023510283
last_local_balance_msat: self.funding.value_to_self_msat,
10284+
splice_funding_failed: None,
1023610285
}
1023710286
}
1023810287

lightning/src/ln/channelmanager.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4509,6 +4509,19 @@ where
45094509
last_local_balance_msat: Some(shutdown_res.last_local_balance_msat),
45104510
}, None));
45114511

4512+
// Emit SpliceFailed event immediately after ChannelClosed if there was an active splice negotiation
4513+
if let Some(splice_funding_failed) = shutdown_res.splice_funding_failed.take() {
4514+
pending_events.push_back((events::Event::SpliceFailed {
4515+
channel_id: shutdown_res.channel_id,
4516+
counterparty_node_id: shutdown_res.counterparty_node_id,
4517+
user_channel_id: shutdown_res.user_channel_id,
4518+
funding_txo: splice_funding_failed.funding_txo,
4519+
channel_type: splice_funding_failed.channel_type,
4520+
contributed_inputs: splice_funding_failed.contributed_inputs,
4521+
contributed_outputs: splice_funding_failed.contributed_outputs,
4522+
}, None));
4523+
}
4524+
45124525
if let Some(transaction) = shutdown_res.unbroadcasted_funding_tx {
45134526
let funding_info = if shutdown_res.is_manual_broadcast {
45144527
FundingInfo::OutPoint {

0 commit comments

Comments
 (0)