Skip to content

Commit a6819ac

Browse files
jkczyzclaude
andcommitted
Emit DiscardFunding before SpliceFailed
Reverse the event ordering at all emission sites so that Event::DiscardFunding is emitted before Event::SpliceFailed. If the user retries the splice when handling SpliceFailed, the contributed inputs would still be locked. A subsequent DiscardFunding would then incorrectly unlock inputs that are now committed to the new attempt. Emitting DiscardFunding first avoids this by ensuring inputs are unlocked before any retry occurs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent d09cccc commit a6819ac

3 files changed

Lines changed: 140 additions & 140 deletions

File tree

lightning/src/ln/channelmanager.rs

Lines changed: 97 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -4004,16 +4004,6 @@ impl<
40044004

40054005
if let Some(splice_funding_failed) = splice_funding_failed {
40064006
let mut pending_events = self.pending_events.lock().unwrap();
4007-
pending_events.push_back((
4008-
events::Event::SpliceFailed {
4009-
channel_id: *chan_id,
4010-
counterparty_node_id: *counterparty_node_id,
4011-
user_channel_id: chan.context().get_user_id(),
4012-
contribution: splice_funding_failed.contribution,
4013-
reason: events::NegotiationFailureReason::ChannelClosing,
4014-
},
4015-
None,
4016-
));
40174007
pending_events.push_back((
40184008
events::Event::DiscardFunding {
40194009
channel_id: *chan_id,
@@ -4024,6 +4014,16 @@ impl<
40244014
},
40254015
None,
40264016
));
4017+
pending_events.push_back((
4018+
events::Event::SpliceFailed {
4019+
channel_id: *chan_id,
4020+
counterparty_node_id: *counterparty_node_id,
4021+
user_channel_id: chan.context().get_user_id(),
4022+
contribution: splice_funding_failed.contribution,
4023+
reason: events::NegotiationFailureReason::ChannelClosing,
4024+
},
4025+
None,
4026+
));
40274027
}
40284028

40294029
// We can send the `shutdown` message before updating the `ChannelMonitor`
@@ -4310,16 +4310,6 @@ impl<
43104310
));
43114311

43124312
if let Some(splice_funding_failed) = shutdown_res.splice_funding_failed.take() {
4313-
pending_events.push_back((
4314-
events::Event::SpliceFailed {
4315-
channel_id: shutdown_res.channel_id,
4316-
counterparty_node_id: shutdown_res.counterparty_node_id,
4317-
user_channel_id: shutdown_res.user_channel_id,
4318-
contribution: splice_funding_failed.contribution,
4319-
reason: events::NegotiationFailureReason::ChannelClosing,
4320-
},
4321-
None,
4322-
));
43234313
pending_events.push_back((
43244314
events::Event::DiscardFunding {
43254315
channel_id: shutdown_res.channel_id,
@@ -4330,6 +4320,16 @@ impl<
43304320
},
43314321
None,
43324322
));
4323+
pending_events.push_back((
4324+
events::Event::SpliceFailed {
4325+
channel_id: shutdown_res.channel_id,
4326+
counterparty_node_id: shutdown_res.counterparty_node_id,
4327+
user_channel_id: shutdown_res.user_channel_id,
4328+
contribution: splice_funding_failed.contribution,
4329+
reason: events::NegotiationFailureReason::ChannelClosing,
4330+
},
4331+
None,
4332+
));
43334333
}
43344334

43354335
if let Some(transaction) = shutdown_res.unbroadcasted_funding_tx {
@@ -4816,16 +4816,6 @@ impl<
48164816

48174817
if let Some(splice_funding_failed) = splice_funding_failed {
48184818
let pending_events = &mut self.pending_events.lock().unwrap();
4819-
pending_events.push_back((
4820-
events::Event::SpliceFailed {
4821-
channel_id: *channel_id,
4822-
counterparty_node_id: *counterparty_node_id,
4823-
user_channel_id: chan.context.get_user_id(),
4824-
contribution: splice_funding_failed.contribution,
4825-
reason: events::NegotiationFailureReason::LocallyAbandoned,
4826-
},
4827-
None,
4828-
));
48294819
pending_events.push_back((
48304820
events::Event::DiscardFunding {
48314821
channel_id: *channel_id,
@@ -4836,6 +4826,16 @@ impl<
48364826
},
48374827
None,
48384828
));
4829+
pending_events.push_back((
4830+
events::Event::SpliceFailed {
4831+
channel_id: *channel_id,
4832+
counterparty_node_id: *counterparty_node_id,
4833+
user_channel_id: chan.context.get_user_id(),
4834+
contribution: splice_funding_failed.contribution,
4835+
reason: events::NegotiationFailureReason::LocallyAbandoned,
4836+
},
4837+
None,
4838+
));
48394839
}
48404840

48414841
Ok(())
@@ -6512,16 +6512,6 @@ impl<
65126512
reason,
65136513
) => {
65146514
let pending_events = &mut self.pending_events.lock().unwrap();
6515-
pending_events.push_back((
6516-
events::Event::SpliceFailed {
6517-
channel_id,
6518-
counterparty_node_id,
6519-
user_channel_id,
6520-
reason,
6521-
contribution,
6522-
},
6523-
None,
6524-
));
65256515
if !contributed_inputs.is_empty() || !contributed_outputs.is_empty() {
65266516
pending_events.push_back((
65276517
events::Event::DiscardFunding {
@@ -6534,6 +6524,16 @@ impl<
65346524
None,
65356525
));
65366526
}
6527+
pending_events.push_back((
6528+
events::Event::SpliceFailed {
6529+
channel_id,
6530+
counterparty_node_id,
6531+
user_channel_id,
6532+
reason,
6533+
contribution,
6534+
},
6535+
None,
6536+
));
65376537
},
65386538
}
65396539
}
@@ -11701,16 +11701,6 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1170111701
}) => {
1170211702
if let Some(splice_funding_failed) = splice_funding_failed {
1170311703
let pending_events = &mut self.pending_events.lock().unwrap();
11704-
pending_events.push_back((
11705-
events::Event::SpliceFailed {
11706-
channel_id,
11707-
counterparty_node_id: *counterparty_node_id,
11708-
user_channel_id: channel.context().get_user_id(),
11709-
contribution: splice_funding_failed.contribution.clone(),
11710-
reason: events::NegotiationFailureReason::NegotiationError,
11711-
},
11712-
None,
11713-
));
1171411704
pending_events.push_back((
1171511705
events::Event::DiscardFunding {
1171611706
channel_id,
@@ -11721,6 +11711,16 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1172111711
},
1172211712
None,
1172311713
));
11714+
pending_events.push_back((
11715+
events::Event::SpliceFailed {
11716+
channel_id,
11717+
counterparty_node_id: *counterparty_node_id,
11718+
user_channel_id: channel.context().get_user_id(),
11719+
contribution: splice_funding_failed.contribution.clone(),
11720+
reason: events::NegotiationFailureReason::NegotiationError,
11721+
},
11722+
None,
11723+
));
1172411724
}
1172511725
debug_assert!(!exited_quiescence || matches!(err, ChannelError::Abort(_)));
1172611726

@@ -11860,16 +11860,6 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1186011860
}) => {
1186111861
if let Some(splice_funding_failed) = splice_funding_failed {
1186211862
let pending_events = &mut self.pending_events.lock().unwrap();
11863-
pending_events.push_back((
11864-
events::Event::SpliceFailed {
11865-
channel_id: msg.channel_id,
11866-
counterparty_node_id,
11867-
user_channel_id: chan.context().get_user_id(),
11868-
contribution: splice_funding_failed.contribution.clone(),
11869-
reason: events::NegotiationFailureReason::NegotiationError,
11870-
},
11871-
None,
11872-
));
1187311863
pending_events.push_back((
1187411864
events::Event::DiscardFunding {
1187511865
channel_id: msg.channel_id,
@@ -11880,6 +11870,16 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1188011870
},
1188111871
None,
1188211872
));
11873+
pending_events.push_back((
11874+
events::Event::SpliceFailed {
11875+
channel_id: msg.channel_id,
11876+
counterparty_node_id,
11877+
user_channel_id: chan.context().get_user_id(),
11878+
contribution: splice_funding_failed.contribution.clone(),
11879+
reason: events::NegotiationFailureReason::NegotiationError,
11880+
},
11881+
None,
11882+
));
1188311883
}
1188411884
debug_assert!(!exited_quiescence || matches!(err, ChannelError::Abort(_)));
1188511885

@@ -12030,16 +12030,6 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1203012030

1203112031
if let Some(splice_funding_failed) = splice_failed {
1203212032
let pending_events = &mut self.pending_events.lock().unwrap();
12033-
pending_events.push_back((
12034-
events::Event::SpliceFailed {
12035-
channel_id: msg.channel_id,
12036-
counterparty_node_id: *counterparty_node_id,
12037-
user_channel_id: chan_entry.get().context().get_user_id(),
12038-
contribution: splice_funding_failed.contribution,
12039-
reason: events::NegotiationFailureReason::CounterpartyAborted,
12040-
},
12041-
None,
12042-
));
1204312033
pending_events.push_back((
1204412034
events::Event::DiscardFunding {
1204512035
channel_id: msg.channel_id,
@@ -12050,6 +12040,16 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1205012040
},
1205112041
None,
1205212042
));
12043+
pending_events.push_back((
12044+
events::Event::SpliceFailed {
12045+
channel_id: msg.channel_id,
12046+
counterparty_node_id: *counterparty_node_id,
12047+
user_channel_id: chan_entry.get().context().get_user_id(),
12048+
contribution: splice_funding_failed.contribution,
12049+
reason: events::NegotiationFailureReason::CounterpartyAborted,
12050+
},
12051+
None,
12052+
));
1205312053
}
1205412054

1205512055
let holding_cell_res = if exited_quiescence {
@@ -12178,16 +12178,6 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1217812178

1217912179
if let Some(splice_funding_failed) = splice_funding_failed {
1218012180
let mut pending_events = self.pending_events.lock().unwrap();
12181-
pending_events.push_back((
12182-
events::Event::SpliceFailed {
12183-
channel_id: msg.channel_id,
12184-
counterparty_node_id: *counterparty_node_id,
12185-
user_channel_id: chan.context().get_user_id(),
12186-
contribution: splice_funding_failed.contribution,
12187-
reason: events::NegotiationFailureReason::ChannelClosing,
12188-
},
12189-
None,
12190-
));
1219112181
pending_events.push_back((
1219212182
events::Event::DiscardFunding {
1219312183
channel_id: msg.channel_id,
@@ -12198,6 +12188,16 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1219812188
},
1219912189
None,
1220012190
));
12191+
pending_events.push_back((
12192+
events::Event::SpliceFailed {
12193+
channel_id: msg.channel_id,
12194+
counterparty_node_id: *counterparty_node_id,
12195+
user_channel_id: chan.context().get_user_id(),
12196+
contribution: splice_funding_failed.contribution,
12197+
reason: events::NegotiationFailureReason::ChannelClosing,
12198+
},
12199+
None,
12200+
));
1220112201
}
1220212202

1220312203
if let Some(msg) = shutdown {
@@ -15287,20 +15287,20 @@ impl<
1528715287
chan.peer_disconnected_is_resumable(&&logger);
1528815288

1528915289
if let Some(splice_funding_failed) = splice_funding_failed {
15290-
splice_failed_events.push(events::Event::SpliceFailed {
15291-
channel_id: chan.context().channel_id(),
15292-
counterparty_node_id,
15293-
user_channel_id: chan.context().get_user_id(),
15294-
contribution: splice_funding_failed.contribution,
15295-
reason: events::NegotiationFailureReason::PeerDisconnected,
15296-
});
1529715290
splice_failed_events.push(events::Event::DiscardFunding {
1529815291
channel_id: chan.context().channel_id(),
1529915292
funding_info: FundingInfo::Contribution {
1530015293
inputs: splice_funding_failed.contributed_inputs,
1530115294
outputs: splice_funding_failed.contributed_outputs,
1530215295
},
1530315296
});
15297+
splice_failed_events.push(events::Event::SpliceFailed {
15298+
channel_id: chan.context().channel_id(),
15299+
counterparty_node_id,
15300+
user_channel_id: chan.context().get_user_id(),
15301+
contribution: splice_funding_failed.contribution,
15302+
reason: events::NegotiationFailureReason::PeerDisconnected,
15303+
});
1530415304
}
1530515305

1530615306
if is_resumable {
@@ -17936,16 +17936,6 @@ impl<
1793617936
for peer_state in peer_states.iter() {
1793717937
for chan in peer_state.channel_by_id.values().filter_map(Channel::as_funded) {
1793817938
if let Some(splice_funding_failed) = chan.maybe_splice_funding_failed() {
17939-
events.push_back((
17940-
events::Event::SpliceFailed {
17941-
channel_id: chan.context.channel_id(),
17942-
counterparty_node_id: chan.context.get_counterparty_node_id(),
17943-
user_channel_id: chan.context.get_user_id(),
17944-
reason: events::NegotiationFailureReason::PeerDisconnected,
17945-
contribution: splice_funding_failed.contribution,
17946-
},
17947-
None,
17948-
));
1794917939
events.push_back((
1795017940
events::Event::DiscardFunding {
1795117941
channel_id: chan.context().channel_id(),
@@ -17956,6 +17946,16 @@ impl<
1795617946
},
1795717947
None,
1795817948
));
17949+
events.push_back((
17950+
events::Event::SpliceFailed {
17951+
channel_id: chan.context.channel_id(),
17952+
counterparty_node_id: chan.context.get_counterparty_node_id(),
17953+
user_channel_id: chan.context.get_user_id(),
17954+
reason: events::NegotiationFailureReason::PeerDisconnected,
17955+
contribution: splice_funding_failed.contribution,
17956+
},
17957+
None,
17958+
));
1795917959
}
1796017960
}
1796117961
}

lightning/src/ln/functional_test_utils.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3243,18 +3243,10 @@ pub fn expect_splice_failed_events<'a, 'b, 'c, 'd>(
32433243
let events = node.node.get_and_clear_pending_events();
32443244
assert_eq!(events.len(), 2);
32453245
match &events[0] {
3246-
Event::SpliceFailed { channel_id, reason, contribution, .. } => {
3247-
assert_eq!(*expected_channel_id, *channel_id);
3248-
assert_eq!(*reason, expected_reason);
3249-
assert_eq!(contribution.as_ref(), Some(&funding_contribution));
3250-
},
3251-
_ => panic!("Unexpected event"),
3252-
}
3253-
match &events[1] {
32543246
Event::DiscardFunding { funding_info, .. } => {
32553247
if let FundingInfo::Contribution { inputs, outputs } = &funding_info {
32563248
let (expected_inputs, expected_outputs) =
3257-
funding_contribution.into_contributed_inputs_and_outputs();
3249+
funding_contribution.clone().into_contributed_inputs_and_outputs();
32583250
assert_eq!(*inputs, expected_inputs);
32593251
assert_eq!(*outputs, expected_outputs);
32603252
} else {
@@ -3263,6 +3255,14 @@ pub fn expect_splice_failed_events<'a, 'b, 'c, 'd>(
32633255
},
32643256
_ => panic!("Unexpected event"),
32653257
}
3258+
match &events[1] {
3259+
Event::SpliceFailed { channel_id, reason, contribution, .. } => {
3260+
assert_eq!(*expected_channel_id, *channel_id);
3261+
assert_eq!(*reason, expected_reason);
3262+
assert_eq!(contribution.as_ref(), Some(&funding_contribution));
3263+
},
3264+
_ => panic!("Unexpected event"),
3265+
}
32663266
}
32673267

32683268
#[cfg(any(test, ldk_bench, feature = "_test_utils"))]

0 commit comments

Comments
 (0)