Skip to content

Commit a4684b7

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

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
@@ -12864,27 +12864,27 @@ where
1286412864
#[rustfmt::skip]
1286512865
pub fn stfu<L: Deref>(
1286612866
&mut self, msg: &msgs::Stfu, logger: &L
12867-
) -> Result<Option<StfuResponse>, ChannelError> where L::Target: Logger {
12867+
) -> Result<Option<StfuResponse>, (ChannelError, Option<SpliceFundingFailed>)> where L::Target: Logger {
1286812868
if self.context.channel_state.is_quiescent() {
12869-
return Err(ChannelError::Warn("Channel is already quiescent".to_owned()));
12869+
return Err((ChannelError::Warn("Channel is already quiescent".to_owned()), None));
1287012870
}
1287112871
if self.context.channel_state.is_remote_stfu_sent() {
12872-
return Err(ChannelError::Warn(
12872+
return Err((ChannelError::Warn(
1287312873
"Peer sent `stfu` when they already sent it and we've yet to become quiescent".to_owned()
12874-
));
12874+
), None));
1287512875
}
1287612876

1287712877
if !self.context.is_live() {
12878-
return Err(ChannelError::Warn(
12878+
return Err((ChannelError::Warn(
1287912879
"Peer sent `stfu` when we were not in a live state".to_owned()
12880-
));
12880+
), None));
1288112881
}
1288212882

1288312883
if !self.context.channel_state.is_local_stfu_sent() {
1288412884
if !msg.initiator {
12885-
return Err(ChannelError::WarnAndDisconnect(
12885+
return Err((ChannelError::WarnAndDisconnect(
1288612886
"Peer sent unexpected `stfu` without signaling as initiator".to_owned()
12887-
));
12887+
), None));
1288812888
}
1288912889

1289012890
// We don't check `is_waiting_on_peer_pending_channel_update` prior to setting the flag
@@ -12898,7 +12898,7 @@ where
1289812898
return self
1289912899
.send_stfu(logger)
1290012900
.map(|stfu| Some(StfuResponse::Stfu(stfu)))
12901-
.map_err(|e| ChannelError::Ignore(e.to_owned()));
12901+
.map_err(|e| (ChannelError::Ignore(e.to_owned()), None));
1290212902
}
1290312903

1290412904
// We already sent `stfu` and are now processing theirs. It may be in response to ours, or
@@ -12917,9 +12917,9 @@ where
1291712917
// have a monitor update pending if we've processed a message from the counterparty, but
1291812918
// we don't consider this when becoming quiescent since the states are not mutually
1291912919
// exclusive.
12920-
return Err(ChannelError::WarnAndDisconnect(
12920+
return Err((ChannelError::WarnAndDisconnect(
1292112921
"Received counterparty stfu while having pending counterparty updates".to_owned()
12922-
));
12922+
), None));
1292312923
}
1292412924

1292512925
self.context.channel_state.clear_local_stfu_sent();
@@ -12935,14 +12935,25 @@ where
1293512935
match self.quiescent_action.take() {
1293612936
None => {
1293712937
debug_assert!(false);
12938-
return Err(ChannelError::WarnAndDisconnect(
12938+
return Err((ChannelError::WarnAndDisconnect(
1293912939
"Internal Error: Didn't have anything to do after reaching quiescence".to_owned()
12940-
));
12940+
), None));
1294112941
},
1294212942
Some(QuiescentAction::Splice(_instructions)) => {
1294312943
return self.send_splice_init(_instructions)
1294412944
.map(|splice_init| Some(StfuResponse::SpliceInit(splice_init)))
12945-
.map_err(|e| ChannelError::WarnAndDisconnect(e.to_owned()));
12945+
.map_err(|e| {
12946+
let splice_failed = SpliceFundingFailed {
12947+
channel_id: self.context.channel_id,
12948+
counterparty_node_id: self.context.counterparty_node_id,
12949+
user_channel_id: self.context.user_id,
12950+
funding_txo: None,
12951+
channel_type: None,
12952+
contributed_inputs: Vec::new(),
12953+
contributed_outputs: Vec::new(),
12954+
};
12955+
(ChannelError::WarnAndDisconnect(e.to_owned()), Some(splice_failed))
12956+
});
1294612957
},
1294712958
#[cfg(any(test, fuzzing))]
1294812959
Some(QuiescentAction::DoNothing) => {

lightning/src/ln/channelmanager.rs

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

1124711247
let res = chan.stfu(&msg, &&logger);
11248-
let resp = try_channel_entry!(self, peer_state, res, chan_entry);
11248+
let resp = match res {
11249+
Ok(resp) => resp,
11250+
Err((e, splice_funding_failed)) => {
11251+
// Emit SpliceFailed event if there was an active splice negotiation
11252+
if let Some(splice_failed) = splice_funding_failed {
11253+
let pending_events = &mut self.pending_events.lock().unwrap();
11254+
pending_events.push_back((events::Event::SpliceFailed {
11255+
channel_id: splice_failed.channel_id,
11256+
counterparty_node_id: splice_failed.counterparty_node_id,
11257+
user_channel_id: splice_failed.user_channel_id,
11258+
funding_txo: splice_failed.funding_txo,
11259+
channel_type: splice_failed.channel_type,
11260+
contributed_inputs: splice_failed.contributed_inputs,
11261+
contributed_outputs: splice_failed.contributed_outputs,
11262+
}, None));
11263+
}
11264+
try_channel_entry!(self, peer_state, Err(e), chan_entry)
11265+
},
11266+
};
1124911267
match resp {
1125011268
None => Ok(false),
1125111269
Some(StfuResponse::Stfu(msg)) => {

0 commit comments

Comments
 (0)