Skip to content

Commit 4a71e21

Browse files
jkczyzclaude
andcommitted
Emit SpliceFailed event when splice initialization fails during quiescence
Users need to be notified when splice operations fail at any stage. Previously, splice failures during the quiescence initialization phase were not reported, leaving users unaware of failed splice attempts. Now emits Event::SpliceFailed when send_splice_init fails during stfu processing of QuiescentAction::Splice, ensuring consistent splice failure reporting across all phases of the splice lifecycle. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 07f87c6 commit 4a71e21

File tree

2 files changed

+44
-15
lines changed

2 files changed

+44
-15
lines changed

lightning/src/ln/channel.rs

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12832,27 +12832,27 @@ where
1283212832
#[rustfmt::skip]
1283312833
pub fn stfu<L: Deref>(
1283412834
&mut self, msg: &msgs::Stfu, logger: &L
12835-
) -> Result<Option<StfuResponse>, ChannelError> where L::Target: Logger {
12835+
) -> Result<Option<StfuResponse>, (ChannelError, Option<SpliceFundingFailed>)> where L::Target: Logger {
1283612836
if self.context.channel_state.is_quiescent() {
12837-
return Err(ChannelError::Warn("Channel is already quiescent".to_owned()));
12837+
return Err((ChannelError::Warn("Channel is already quiescent".to_owned()), None));
1283812838
}
1283912839
if self.context.channel_state.is_remote_stfu_sent() {
12840-
return Err(ChannelError::Warn(
12840+
return Err((ChannelError::Warn(
1284112841
"Peer sent `stfu` when they already sent it and we've yet to become quiescent".to_owned()
12842-
));
12842+
), None));
1284312843
}
1284412844

1284512845
if !self.context.is_live() {
12846-
return Err(ChannelError::Warn(
12846+
return Err((ChannelError::Warn(
1284712847
"Peer sent `stfu` when we were not in a live state".to_owned()
12848-
));
12848+
), None));
1284912849
}
1285012850

1285112851
if !self.context.channel_state.is_local_stfu_sent() {
1285212852
if !msg.initiator {
12853-
return Err(ChannelError::WarnAndDisconnect(
12853+
return Err((ChannelError::WarnAndDisconnect(
1285412854
"Peer sent unexpected `stfu` without signaling as initiator".to_owned()
12855-
));
12855+
), None));
1285612856
}
1285712857

1285812858
// We don't check `is_waiting_on_peer_pending_channel_update` prior to setting the flag
@@ -12866,7 +12866,7 @@ where
1286612866
return self
1286712867
.send_stfu(logger)
1286812868
.map(|stfu| Some(StfuResponse::Stfu(stfu)))
12869-
.map_err(|e| ChannelError::Ignore(e.to_owned()));
12869+
.map_err(|e| (ChannelError::Ignore(e.to_owned()), None));
1287012870
}
1287112871

1287212872
// We already sent `stfu` and are now processing theirs. It may be in response to ours, or
@@ -12885,9 +12885,9 @@ where
1288512885
// have a monitor update pending if we've processed a message from the counterparty, but
1288612886
// we don't consider this when becoming quiescent since the states are not mutually
1288712887
// exclusive.
12888-
return Err(ChannelError::WarnAndDisconnect(
12888+
return Err((ChannelError::WarnAndDisconnect(
1288912889
"Received counterparty stfu while having pending counterparty updates".to_owned()
12890-
));
12890+
), None));
1289112891
}
1289212892

1289312893
self.context.channel_state.clear_local_stfu_sent();
@@ -12903,14 +12903,25 @@ where
1290312903
match self.quiescent_action.take() {
1290412904
None => {
1290512905
debug_assert!(false);
12906-
return Err(ChannelError::WarnAndDisconnect(
12906+
return Err((ChannelError::WarnAndDisconnect(
1290712907
"Internal Error: Didn't have anything to do after reaching quiescence".to_owned()
12908-
));
12908+
), None));
1290912909
},
1291012910
Some(QuiescentAction::Splice(_instructions)) => {
1291112911
return self.send_splice_init(_instructions)
1291212912
.map(|splice_init| Some(StfuResponse::SpliceInit(splice_init)))
12913-
.map_err(|e| ChannelError::WarnAndDisconnect(e.to_owned()));
12913+
.map_err(|e| {
12914+
let splice_failed = SpliceFundingFailed {
12915+
channel_id: self.context.channel_id,
12916+
counterparty_node_id: self.context.counterparty_node_id,
12917+
user_channel_id: self.context.user_id,
12918+
funding_txo: None,
12919+
channel_type: None,
12920+
contributed_inputs: Vec::new(),
12921+
contributed_outputs: Vec::new(),
12922+
};
12923+
(ChannelError::WarnAndDisconnect(e.to_owned()), Some(splice_failed))
12924+
});
1291412925
},
1291512926
#[cfg(any(test, fuzzing))]
1291612927
Some(QuiescentAction::DoNothing) => {

lightning/src/ln/channelmanager.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11033,7 +11033,25 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1103311033
);
1103411034

1103511035
let res = chan.stfu(&msg, &&logger);
11036-
let resp = try_channel_entry!(self, peer_state, res, chan_entry);
11036+
let resp = match res {
11037+
Ok(resp) => resp,
11038+
Err((e, splice_funding_failed)) => {
11039+
// Emit SpliceFailed event if there was an active splice negotiation
11040+
if let Some(splice_failed) = splice_funding_failed {
11041+
let pending_events = &mut self.pending_events.lock().unwrap();
11042+
pending_events.push_back((events::Event::SpliceFailed {
11043+
channel_id: splice_failed.channel_id,
11044+
counterparty_node_id: splice_failed.counterparty_node_id,
11045+
user_channel_id: splice_failed.user_channel_id,
11046+
funding_txo: splice_failed.funding_txo,
11047+
channel_type: splice_failed.channel_type,
11048+
contributed_inputs: splice_failed.contributed_inputs,
11049+
contributed_outputs: splice_failed.contributed_outputs,
11050+
}, None));
11051+
}
11052+
try_channel_entry!(self, peer_state, Err(e), chan_entry)
11053+
},
11054+
};
1103711055
match resp {
1103811056
None => Ok(false),
1103911057
Some(StfuResponse::Stfu(msg)) => {

0 commit comments

Comments
 (0)