@@ -1193,6 +1193,14 @@ pub(crate) struct ShutdownResult {
1193
1193
pub(crate) splice_funding_failed: Option<SpliceFundingFailed>,
1194
1194
}
1195
1195
1196
+ /// The result of a peer disconnection.
1197
+ pub(crate) struct DisconnectResult {
1198
+ pub(crate) is_resumable: bool,
1199
+ /// If a splice was in progress when the channel was shut down, this contains
1200
+ /// the splice funding information for emitting a SpliceFailed event.
1201
+ pub(crate) splice_funding_failed: Option<SpliceFundingFailed>,
1202
+ }
1203
+
1196
1204
/// Tracks the transaction number, along with current and next commitment points.
1197
1205
/// This consolidates the logic to advance our commitment number and request new
1198
1206
/// commitment points from our signer.
@@ -1585,11 +1593,15 @@ where
1585
1593
/// Should be called when the peer is disconnected. Returns true if the channel can be resumed
1586
1594
/// when the peer reconnects (via [`Self::peer_connected_get_handshake`]). If not, the channel
1587
1595
/// must be immediately closed.
1588
- #[rustfmt::skip]
1589
- pub fn peer_disconnected_is_resumable<L: Deref>(&mut self, logger: &L) -> bool where L::Target: Logger {
1590
- match &mut self.phase {
1596
+ pub fn peer_disconnected_is_resumable<L: Deref>(&mut self, logger: &L) -> DisconnectResult
1597
+ where
1598
+ L::Target: Logger,
1599
+ {
1600
+ let is_resumable = match &mut self.phase {
1591
1601
ChannelPhase::Undefined => unreachable!(),
1592
- ChannelPhase::Funded(chan) => chan.remove_uncommitted_htlcs_and_mark_paused(logger).is_ok(),
1602
+ ChannelPhase::Funded(chan) => {
1603
+ chan.remove_uncommitted_htlcs_and_mark_paused(logger).is_ok()
1604
+ },
1593
1605
// If we get disconnected and haven't yet committed to a funding
1594
1606
// transaction, we can replay the `open_channel` on reconnection, so don't
1595
1607
// bother dropping the channel here. However, if we already committed to
@@ -1599,7 +1611,34 @@ where
1599
1611
ChannelPhase::UnfundedOutboundV1(chan) => chan.is_resumable(),
1600
1612
ChannelPhase::UnfundedInboundV1(_) => false,
1601
1613
ChannelPhase::UnfundedV2(_) => false,
1602
- }
1614
+ };
1615
+
1616
+ let splice_funding_failed = if let ChannelPhase::Funded(chan) = &mut self.phase {
1617
+ // Reset any quiescence-related state as it is implicitly terminated once disconnected.
1618
+ if matches!(chan.context.channel_state, ChannelState::ChannelReady(_)) {
1619
+ if chan.quiescent_action.is_some() {
1620
+ // If we were trying to get quiescent, try again after reconnection.
1621
+ chan.context.channel_state.set_awaiting_quiescence();
1622
+ }
1623
+ chan.context.channel_state.clear_local_stfu_sent();
1624
+ chan.context.channel_state.clear_remote_stfu_sent();
1625
+ if chan.should_reset_pending_splice_funding_negotiation().unwrap_or(true) {
1626
+ // If we were in quiescence but a splice was never negotiated, or the negotiation
1627
+ // failed due to disconnecting, we shouldn't be quiescent anymore upon reconnecting.
1628
+ // If there was a pending splice negotiation that has failed due to disconnecting,
1629
+ // we also take the opportunity to clean up our state.
1630
+ chan.reset_pending_splice_state()
1631
+ } else {
1632
+ None
1633
+ }
1634
+ } else {
1635
+ None
1636
+ }
1637
+ } else {
1638
+ None
1639
+ };
1640
+
1641
+ DisconnectResult { is_resumable, splice_funding_failed }
1603
1642
}
1604
1643
1605
1644
/// Should be called when the peer re-connects, returning an initial message which we should
@@ -6808,37 +6847,38 @@ where
6808
6847
}
6809
6848
6810
6849
pub fn force_shutdown(&mut self, closure_reason: ClosureReason) -> ShutdownResult {
6811
- let splice_funding_failed =
6812
- if matches!(self.context.channel_state, ChannelState::ChannelReady(_)) {
6813
- self.reset_pending_splice_state().or_else(|| {
6814
- self.quiescent_action.take().and_then(|quiescent_action| match quiescent_action
6815
- {
6816
- QuiescentAction::Splice(instructions) => {
6817
- let (inputs, outputs) =
6818
- instructions.into_contributed_inputs_and_outputs();
6819
- Some(SpliceFundingFailed {
6820
- funding_txo: None,
6821
- channel_type: None,
6822
- contributed_inputs: inputs,
6823
- contributed_outputs: outputs,
6824
- })
6825
- },
6826
- #[cfg(any(test, fuzzing))]
6827
- _ => {
6828
- self.quiescent_action = Some(quiescent_action);
6829
- None
6830
- },
6831
- })
6832
- })
6833
- } else {
6834
- None
6835
- };
6850
+ let splice_funding_failed = self.maybe_fail_splice_negotiation();
6836
6851
6837
6852
let mut shutdown_result = self.context.force_shutdown(&self.funding, closure_reason);
6838
6853
shutdown_result.splice_funding_failed = splice_funding_failed;
6839
6854
shutdown_result
6840
6855
}
6841
6856
6857
+ fn maybe_fail_splice_negotiation(&mut self) -> Option<SpliceFundingFailed> {
6858
+ if matches!(self.context.channel_state, ChannelState::ChannelReady(_)) {
6859
+ self.reset_pending_splice_state().or_else(|| {
6860
+ self.quiescent_action.take().and_then(|quiescent_action| match quiescent_action {
6861
+ QuiescentAction::Splice(instructions) => {
6862
+ let (inputs, outputs) = instructions.into_contributed_inputs_and_outputs();
6863
+ Some(SpliceFundingFailed {
6864
+ funding_txo: None,
6865
+ channel_type: None,
6866
+ contributed_inputs: inputs,
6867
+ contributed_outputs: outputs,
6868
+ })
6869
+ },
6870
+ #[cfg(any(test, fuzzing))]
6871
+ _ => {
6872
+ self.quiescent_action = Some(quiescent_action);
6873
+ None
6874
+ },
6875
+ })
6876
+ })
6877
+ } else {
6878
+ None
6879
+ }
6880
+ }
6881
+
6842
6882
fn interactive_tx_constructor_mut(&mut self) -> Option<&mut InteractiveTxConstructor> {
6843
6883
self.pending_splice
6844
6884
.as_mut()
@@ -9095,24 +9135,6 @@ where
9095
9135
}
9096
9136
}
9097
9137
9098
- // Reset any quiescence-related state as it is implicitly terminated once disconnected.
9099
- if matches!(self.context.channel_state, ChannelState::ChannelReady(_)) {
9100
- if self.quiescent_action.is_some() {
9101
- // If we were trying to get quiescent, try again after reconnection.
9102
- self.context.channel_state.set_awaiting_quiescence();
9103
- }
9104
- self.context.channel_state.clear_local_stfu_sent();
9105
- self.context.channel_state.clear_remote_stfu_sent();
9106
- if self.should_reset_pending_splice_funding_negotiation().unwrap_or(true) {
9107
- // If we were in quiescence but a splice was never negotiated, or the negotiation
9108
- // failed due to disconnecting, we shouldn't be quiescent anymore upon reconnecting.
9109
- // If there was a pending splice negotiation that has failed due to disconnecting,
9110
- // we also take the opportunity to clean up our state.
9111
- self.reset_pending_splice_state();
9112
- debug_assert!(!self.context.channel_state.is_quiescent());
9113
- }
9114
- }
9115
-
9116
9138
self.context.channel_state.set_peer_disconnected();
9117
9139
log_trace!(logger, "Peer disconnection resulted in {} remote-announced HTLC drops on channel {}", inbound_drop_count, &self.context.channel_id());
9118
9140
Ok(())
@@ -11779,9 +11801,9 @@ where
11779
11801
.map_err(|e| APIError::APIMisuseError { err: e.to_owned() })
11780
11802
}
11781
11803
11782
- fn send_splice_init(
11783
- &mut self, instructions: SpliceInstructions,
11784
- ) -> Result<msgs::SpliceInit, String> {
11804
+ fn send_splice_init(&mut self, instructions: SpliceInstructions) -> msgs::SpliceInit {
11805
+ debug_assert!( self.pending_splice.is_none());
11806
+
11785
11807
let SpliceInstructions {
11786
11808
adjusted_funding_contribution,
11787
11809
our_funding_inputs,
@@ -11791,15 +11813,6 @@ where
11791
11813
locktime,
11792
11814
} = instructions;
11793
11815
11794
- // Check if a splice has been initiated already.
11795
- // Note: only a single outstanding splice is supported (per spec)
11796
- if self.pending_splice.is_some() {
11797
- return Err(format!(
11798
- "Channel {} cannot be spliced, as it has already a splice pending",
11799
- self.context.channel_id(),
11800
- ));
11801
- }
11802
-
11803
11816
let prev_funding_input = self.funding.to_splice_funding_input();
11804
11817
let context = FundingNegotiationContext {
11805
11818
is_initiator: true,
@@ -11823,14 +11836,14 @@ where
11823
11836
let prev_funding_txid = self.funding.get_funding_txid();
11824
11837
let funding_pubkey = self.context.holder_pubkeys(prev_funding_txid).funding_pubkey;
11825
11838
11826
- Ok( msgs::SpliceInit {
11839
+ msgs::SpliceInit {
11827
11840
channel_id: self.context.channel_id,
11828
11841
funding_contribution_satoshis: adjusted_funding_contribution.to_sat(),
11829
11842
funding_feerate_per_kw,
11830
11843
locktime,
11831
11844
funding_pubkey,
11832
11845
require_confirmed_inputs: None,
11833
- })
11846
+ }
11834
11847
}
11835
11848
11836
11849
/// Checks during handling splice_init
@@ -12975,10 +12988,21 @@ where
12975
12988
"Internal Error: Didn't have anything to do after reaching quiescence".to_owned()
12976
12989
));
12977
12990
},
12978
- Some(QuiescentAction::Splice(_instructions)) => {
12979
- return self.send_splice_init(_instructions)
12980
- .map(|splice_init| Some(StfuResponse::SpliceInit(splice_init)))
12981
- .map_err(|e| ChannelError::WarnAndDisconnect(e.to_owned()));
12991
+ Some(QuiescentAction::Splice(instructions)) => {
12992
+ if self.pending_splice.is_some() {
12993
+ debug_assert!(false);
12994
+ self.quiescent_action = Some(QuiescentAction::Splice(instructions));
12995
+
12996
+ return Err(ChannelError::WarnAndDisconnect(
12997
+ format!(
12998
+ "Channel {} cannot be spliced as it already has a splice pending",
12999
+ self.context.channel_id(),
13000
+ ),
13001
+ ));
13002
+ }
13003
+
13004
+ let splice_init = self.send_splice_init(instructions);
13005
+ return Ok(Some(StfuResponse::SpliceInit(splice_init)));
12982
13006
},
12983
13007
#[cfg(any(test, fuzzing))]
12984
13008
Some(QuiescentAction::DoNothing) => {
0 commit comments