Skip to content

Commit 30f2668

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 <[email protected]>
1 parent 6ab0a09 commit 30f2668

File tree

2 files changed

+50
-1
lines changed

2 files changed

+50
-1
lines changed

lightning/src/ln/channel.rs

Lines changed: 37 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.
@@ -6043,6 +6046,7 @@ where
60436046
is_manual_broadcast: self.is_manual_broadcast,
60446047
channel_funding_txo: funding.get_funding_txo(),
60456048
last_local_balance_msat: funding.value_to_self_msat,
6049+
splice_funding_failed: None,
60466050
}
60476051
}
60486052

@@ -6846,7 +6850,38 @@ where
68466850
}
68476851

68486852
pub fn force_shutdown(&mut self, closure_reason: ClosureReason) -> ShutdownResult {
6849-
self.context.force_shutdown(&self.funding, closure_reason)
6853+
// Capture splice funding failed information if we have an active splice negotiation
6854+
let splice_funding_failed = self.pending_splice.as_mut()
6855+
.and_then(|pending_splice| pending_splice.funding_negotiation.take())
6856+
.filter(|funding_negotiation| funding_negotiation.is_initiator())
6857+
.map(|funding_negotiation| {
6858+
// Create SpliceFundingFailed for any active splice negotiation during shutdown
6859+
let (funding_txo, channel_type) = match &funding_negotiation {
6860+
FundingNegotiation::AwaitingAck { .. } => {
6861+
(None, None)
6862+
},
6863+
FundingNegotiation::ConstructingTransaction { funding, .. } => {
6864+
(funding.get_funding_txo().map(|txo| txo.into_bitcoin_outpoint()), Some(funding.get_channel_type().clone()))
6865+
},
6866+
FundingNegotiation::AwaitingSignatures { funding, .. } => {
6867+
(funding.get_funding_txo().map(|txo| txo.into_bitcoin_outpoint()), Some(funding.get_channel_type().clone()))
6868+
},
6869+
};
6870+
6871+
SpliceFundingFailed {
6872+
channel_id: self.context.channel_id,
6873+
counterparty_node_id: self.context.counterparty_node_id,
6874+
user_channel_id: self.context.user_id,
6875+
funding_txo,
6876+
channel_type,
6877+
contributed_inputs: Vec::new(),
6878+
contributed_outputs: Vec::new(),
6879+
}
6880+
});
6881+
6882+
let mut shutdown_result = self.context.force_shutdown(&self.funding, closure_reason);
6883+
shutdown_result.splice_funding_failed = splice_funding_failed;
6884+
shutdown_result
68506885
}
68516886

68526887
fn interactive_tx_constructor_mut(&mut self) -> Option<&mut InteractiveTxConstructor> {
@@ -10284,6 +10319,7 @@ where
1028410319
is_manual_broadcast: self.context.is_manual_broadcast,
1028510320
channel_funding_txo: self.funding.get_funding_txo(),
1028610321
last_local_balance_msat: self.funding.value_to_self_msat,
10322+
splice_funding_failed: None,
1028710323
}
1028810324
}
1028910325

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: splice_funding_failed.channel_id,
4516+
counterparty_node_id: splice_funding_failed.counterparty_node_id,
4517+
user_channel_id: splice_funding_failed.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)