Skip to content

Commit 3a10d37

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 77b764d commit 3a10d37

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
@@ -4108,16 +4108,6 @@ impl<
41084108

41094109
if let Some(splice_funding_failed) = splice_funding_failed {
41104110
let mut pending_events = self.pending_events.lock().unwrap();
4111-
pending_events.push_back((
4112-
events::Event::SpliceFailed {
4113-
channel_id: *chan_id,
4114-
counterparty_node_id: *counterparty_node_id,
4115-
user_channel_id: chan.context().get_user_id(),
4116-
contribution: splice_funding_failed.contribution,
4117-
reason: events::NegotiationFailureReason::ChannelClosing,
4118-
},
4119-
None,
4120-
));
41214111
pending_events.push_back((
41224112
events::Event::DiscardFunding {
41234113
channel_id: *chan_id,
@@ -4128,6 +4118,16 @@ impl<
41284118
},
41294119
None,
41304120
));
4121+
pending_events.push_back((
4122+
events::Event::SpliceFailed {
4123+
channel_id: *chan_id,
4124+
counterparty_node_id: *counterparty_node_id,
4125+
user_channel_id: chan.context().get_user_id(),
4126+
contribution: splice_funding_failed.contribution,
4127+
reason: events::NegotiationFailureReason::ChannelClosing,
4128+
},
4129+
None,
4130+
));
41314131
}
41324132

41334133
// We can send the `shutdown` message before updating the `ChannelMonitor`
@@ -4414,16 +4414,6 @@ impl<
44144414
));
44154415

44164416
if let Some(splice_funding_failed) = shutdown_res.splice_funding_failed.take() {
4417-
pending_events.push_back((
4418-
events::Event::SpliceFailed {
4419-
channel_id: shutdown_res.channel_id,
4420-
counterparty_node_id: shutdown_res.counterparty_node_id,
4421-
user_channel_id: shutdown_res.user_channel_id,
4422-
contribution: splice_funding_failed.contribution,
4423-
reason: events::NegotiationFailureReason::ChannelClosing,
4424-
},
4425-
None,
4426-
));
44274417
pending_events.push_back((
44284418
events::Event::DiscardFunding {
44294419
channel_id: shutdown_res.channel_id,
@@ -4434,6 +4424,16 @@ impl<
44344424
},
44354425
None,
44364426
));
4427+
pending_events.push_back((
4428+
events::Event::SpliceFailed {
4429+
channel_id: shutdown_res.channel_id,
4430+
counterparty_node_id: shutdown_res.counterparty_node_id,
4431+
user_channel_id: shutdown_res.user_channel_id,
4432+
contribution: splice_funding_failed.contribution,
4433+
reason: events::NegotiationFailureReason::ChannelClosing,
4434+
},
4435+
None,
4436+
));
44374437
}
44384438

44394439
if let Some(transaction) = shutdown_res.unbroadcasted_funding_tx {
@@ -4920,16 +4920,6 @@ impl<
49204920

49214921
if let Some(splice_funding_failed) = splice_funding_failed {
49224922
let pending_events = &mut self.pending_events.lock().unwrap();
4923-
pending_events.push_back((
4924-
events::Event::SpliceFailed {
4925-
channel_id: *channel_id,
4926-
counterparty_node_id: *counterparty_node_id,
4927-
user_channel_id: chan.context.get_user_id(),
4928-
contribution: splice_funding_failed.contribution,
4929-
reason: events::NegotiationFailureReason::LocallyAbandoned,
4930-
},
4931-
None,
4932-
));
49334923
pending_events.push_back((
49344924
events::Event::DiscardFunding {
49354925
channel_id: *channel_id,
@@ -4940,6 +4930,16 @@ impl<
49404930
},
49414931
None,
49424932
));
4933+
pending_events.push_back((
4934+
events::Event::SpliceFailed {
4935+
channel_id: *channel_id,
4936+
counterparty_node_id: *counterparty_node_id,
4937+
user_channel_id: chan.context.get_user_id(),
4938+
contribution: splice_funding_failed.contribution,
4939+
reason: events::NegotiationFailureReason::LocallyAbandoned,
4940+
},
4941+
None,
4942+
));
49434943
}
49444944

49454945
Ok(())
@@ -6616,16 +6616,6 @@ impl<
66166616
reason,
66176617
) => {
66186618
let pending_events = &mut self.pending_events.lock().unwrap();
6619-
pending_events.push_back((
6620-
events::Event::SpliceFailed {
6621-
channel_id,
6622-
counterparty_node_id,
6623-
user_channel_id,
6624-
reason,
6625-
contribution,
6626-
},
6627-
None,
6628-
));
66296619
if !contributed_inputs.is_empty() || !contributed_outputs.is_empty() {
66306620
pending_events.push_back((
66316621
events::Event::DiscardFunding {
@@ -6638,6 +6628,16 @@ impl<
66386628
None,
66396629
));
66406630
}
6631+
pending_events.push_back((
6632+
events::Event::SpliceFailed {
6633+
channel_id,
6634+
counterparty_node_id,
6635+
user_channel_id,
6636+
reason,
6637+
contribution,
6638+
},
6639+
None,
6640+
));
66416641
},
66426642
}
66436643
}
@@ -11853,16 +11853,6 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1185311853
contributed_inputs, contributed_outputs, contribution, ..
1185411854
}) = splice_funding_failed {
1185511855
let pending_events = &mut self.pending_events.lock().unwrap();
11856-
pending_events.push_back((
11857-
events::Event::SpliceFailed {
11858-
channel_id,
11859-
counterparty_node_id: *counterparty_node_id,
11860-
user_channel_id: channel.context().get_user_id(),
11861-
contribution,
11862-
reason: events::NegotiationFailureReason::NegotiationError,
11863-
},
11864-
None,
11865-
));
1186611856
pending_events.push_back((
1186711857
events::Event::DiscardFunding {
1186811858
channel_id,
@@ -11873,6 +11863,16 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1187311863
},
1187411864
None,
1187511865
));
11866+
pending_events.push_back((
11867+
events::Event::SpliceFailed {
11868+
channel_id,
11869+
counterparty_node_id: *counterparty_node_id,
11870+
user_channel_id: channel.context().get_user_id(),
11871+
contribution,
11872+
reason: events::NegotiationFailureReason::NegotiationError,
11873+
},
11874+
None,
11875+
));
1187611876
}
1187711877
debug_assert!(!exited_quiescence || matches!(err, ChannelError::Abort(_)));
1187811878

@@ -12014,16 +12014,6 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1201412014
contributed_inputs, contributed_outputs, contribution, ..
1201512015
}) = splice_funding_failed {
1201612016
let pending_events = &mut self.pending_events.lock().unwrap();
12017-
pending_events.push_back((
12018-
events::Event::SpliceFailed {
12019-
channel_id: msg.channel_id,
12020-
counterparty_node_id,
12021-
user_channel_id: chan.context().get_user_id(),
12022-
contribution,
12023-
reason: events::NegotiationFailureReason::NegotiationError,
12024-
},
12025-
None,
12026-
));
1202712017
pending_events.push_back((
1202812018
events::Event::DiscardFunding {
1202912019
channel_id: msg.channel_id,
@@ -12034,6 +12024,16 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1203412024
},
1203512025
None,
1203612026
));
12027+
pending_events.push_back((
12028+
events::Event::SpliceFailed {
12029+
channel_id: msg.channel_id,
12030+
counterparty_node_id,
12031+
user_channel_id: chan.context().get_user_id(),
12032+
contribution,
12033+
reason: events::NegotiationFailureReason::NegotiationError,
12034+
},
12035+
None,
12036+
));
1203712037
}
1203812038
debug_assert!(!exited_quiescence || matches!(err, ChannelError::Abort(_)));
1203912039

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

1218512185
if let Some(splice_funding_failed) = splice_failed {
1218612186
let pending_events = &mut self.pending_events.lock().unwrap();
12187-
pending_events.push_back((
12188-
events::Event::SpliceFailed {
12189-
channel_id: msg.channel_id,
12190-
counterparty_node_id: *counterparty_node_id,
12191-
user_channel_id: chan_entry.get().context().get_user_id(),
12192-
contribution: splice_funding_failed.contribution,
12193-
reason: events::NegotiationFailureReason::CounterpartyAborted,
12194-
},
12195-
None,
12196-
));
1219712187
pending_events.push_back((
1219812188
events::Event::DiscardFunding {
1219912189
channel_id: msg.channel_id,
@@ -12204,6 +12194,16 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1220412194
},
1220512195
None,
1220612196
));
12197+
pending_events.push_back((
12198+
events::Event::SpliceFailed {
12199+
channel_id: msg.channel_id,
12200+
counterparty_node_id: *counterparty_node_id,
12201+
user_channel_id: chan_entry.get().context().get_user_id(),
12202+
contribution: splice_funding_failed.contribution,
12203+
reason: events::NegotiationFailureReason::CounterpartyAborted,
12204+
},
12205+
None,
12206+
));
1220712207
}
1220812208

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

1233312333
if let Some(splice_funding_failed) = splice_funding_failed {
1233412334
let mut pending_events = self.pending_events.lock().unwrap();
12335-
pending_events.push_back((
12336-
events::Event::SpliceFailed {
12337-
channel_id: msg.channel_id,
12338-
counterparty_node_id: *counterparty_node_id,
12339-
user_channel_id: chan.context().get_user_id(),
12340-
contribution: splice_funding_failed.contribution,
12341-
reason: events::NegotiationFailureReason::ChannelClosing,
12342-
},
12343-
None,
12344-
));
1234512335
pending_events.push_back((
1234612336
events::Event::DiscardFunding {
1234712337
channel_id: msg.channel_id,
@@ -12352,6 +12342,16 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
1235212342
},
1235312343
None,
1235412344
));
12345+
pending_events.push_back((
12346+
events::Event::SpliceFailed {
12347+
channel_id: msg.channel_id,
12348+
counterparty_node_id: *counterparty_node_id,
12349+
user_channel_id: chan.context().get_user_id(),
12350+
contribution: splice_funding_failed.contribution,
12351+
reason: events::NegotiationFailureReason::ChannelClosing,
12352+
},
12353+
None,
12354+
));
1235512355
}
1235612356

1235712357
if let Some(msg) = shutdown {
@@ -15449,20 +15449,20 @@ impl<
1544915449
chan.peer_disconnected_is_resumable(&&logger);
1545015450

1545115451
if let Some(splice_funding_failed) = splice_funding_failed {
15452-
splice_failed_events.push(events::Event::SpliceFailed {
15453-
channel_id: chan.context().channel_id(),
15454-
counterparty_node_id,
15455-
user_channel_id: chan.context().get_user_id(),
15456-
contribution: splice_funding_failed.contribution,
15457-
reason: events::NegotiationFailureReason::PeerDisconnected,
15458-
});
1545915452
splice_failed_events.push(events::Event::DiscardFunding {
1546015453
channel_id: chan.context().channel_id(),
1546115454
funding_info: FundingInfo::Contribution {
1546215455
inputs: splice_funding_failed.contributed_inputs,
1546315456
outputs: splice_funding_failed.contributed_outputs,
1546415457
},
1546515458
});
15459+
splice_failed_events.push(events::Event::SpliceFailed {
15460+
channel_id: chan.context().channel_id(),
15461+
counterparty_node_id,
15462+
user_channel_id: chan.context().get_user_id(),
15463+
contribution: splice_funding_failed.contribution,
15464+
reason: events::NegotiationFailureReason::PeerDisconnected,
15465+
});
1546615466
}
1546715467

1546815468
if is_resumable {
@@ -18120,16 +18120,6 @@ impl<
1812018120
for peer_state in peer_states.iter() {
1812118121
for chan in peer_state.channel_by_id.values().filter_map(Channel::as_funded) {
1812218122
if let Some(splice_funding_failed) = chan.maybe_splice_funding_failed() {
18123-
events.push_back((
18124-
events::Event::SpliceFailed {
18125-
channel_id: chan.context.channel_id(),
18126-
counterparty_node_id: chan.context.get_counterparty_node_id(),
18127-
user_channel_id: chan.context.get_user_id(),
18128-
reason: events::NegotiationFailureReason::PeerDisconnected,
18129-
contribution: splice_funding_failed.contribution,
18130-
},
18131-
None,
18132-
));
1813318123
events.push_back((
1813418124
events::Event::DiscardFunding {
1813518125
channel_id: chan.context().channel_id(),
@@ -18140,6 +18130,16 @@ impl<
1814018130
},
1814118131
None,
1814218132
));
18133+
events.push_back((
18134+
events::Event::SpliceFailed {
18135+
channel_id: chan.context.channel_id(),
18136+
counterparty_node_id: chan.context.get_counterparty_node_id(),
18137+
user_channel_id: chan.context.get_user_id(),
18138+
reason: events::NegotiationFailureReason::PeerDisconnected,
18139+
contribution: splice_funding_failed.contribution,
18140+
},
18141+
None,
18142+
));
1814318143
}
1814418144
}
1814518145
}

lightning/src/ln/functional_test_utils.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3248,18 +3248,10 @@ pub fn expect_splice_failed_events<'a, 'b, 'c, 'd>(
32483248
let events = node.node.get_and_clear_pending_events();
32493249
assert_eq!(events.len(), 2);
32503250
match &events[0] {
3251-
Event::SpliceFailed { channel_id, reason, contribution, .. } => {
3252-
assert_eq!(*expected_channel_id, *channel_id);
3253-
assert_eq!(*reason, expected_reason);
3254-
assert_eq!(contribution.as_ref(), Some(&funding_contribution));
3255-
},
3256-
_ => panic!("Unexpected event"),
3257-
}
3258-
match &events[1] {
32593251
Event::DiscardFunding { funding_info, .. } => {
32603252
if let FundingInfo::Contribution { inputs, outputs } = &funding_info {
32613253
let (expected_inputs, expected_outputs) =
3262-
funding_contribution.into_contributed_inputs_and_outputs();
3254+
funding_contribution.clone().into_contributed_inputs_and_outputs();
32633255
assert_eq!(*inputs, expected_inputs);
32643256
assert_eq!(*outputs, expected_outputs);
32653257
} else {
@@ -3268,6 +3260,14 @@ pub fn expect_splice_failed_events<'a, 'b, 'c, 'd>(
32683260
},
32693261
_ => panic!("Unexpected event"),
32703262
}
3263+
match &events[1] {
3264+
Event::SpliceFailed { channel_id, reason, contribution, .. } => {
3265+
assert_eq!(*expected_channel_id, *channel_id);
3266+
assert_eq!(*reason, expected_reason);
3267+
assert_eq!(contribution.as_ref(), Some(&funding_contribution));
3268+
},
3269+
_ => panic!("Unexpected event"),
3270+
}
32713271
}
32723272

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

0 commit comments

Comments
 (0)