@@ -1196,6 +1196,14 @@ pub(crate) struct ShutdownResult {
11961196 pub(crate) splice_funding_failed: Option<SpliceFundingFailed>,
11971197}
11981198
1199+ /// The result of a peer disconnection.
1200+ pub(crate) struct DisconnectResult {
1201+ pub(crate) is_resumable: bool,
1202+ /// If a splice was in progress when the channel was shut down, this contains
1203+ /// the splice funding information for emitting a SpliceFailed event.
1204+ pub(crate) splice_funding_failed: Option<SpliceFundingFailed>,
1205+ }
1206+
11991207/// Tracks the transaction number, along with current and next commitment points.
12001208/// This consolidates the logic to advance our commitment number and request new
12011209/// commitment points from our signer.
@@ -1588,11 +1596,15 @@ where
15881596 /// Should be called when the peer is disconnected. Returns true if the channel can be resumed
15891597 /// when the peer reconnects (via [`Self::peer_connected_get_handshake`]). If not, the channel
15901598 /// must be immediately closed.
1591- #[rustfmt::skip]
1592- pub fn peer_disconnected_is_resumable<L: Deref>(&mut self, logger: &L) -> bool where L::Target: Logger {
1593- match &mut self.phase {
1599+ pub fn peer_disconnected_is_resumable<L: Deref>(&mut self, logger: &L) -> DisconnectResult
1600+ where
1601+ L::Target: Logger,
1602+ {
1603+ let is_resumable = match &mut self.phase {
15941604 ChannelPhase::Undefined => unreachable!(),
1595- ChannelPhase::Funded(chan) => chan.remove_uncommitted_htlcs_and_mark_paused(logger).is_ok(),
1605+ ChannelPhase::Funded(chan) => {
1606+ chan.remove_uncommitted_htlcs_and_mark_paused(logger).is_ok()
1607+ },
15961608 // If we get disconnected and haven't yet committed to a funding
15971609 // transaction, we can replay the `open_channel` on reconnection, so don't
15981610 // bother dropping the channel here. However, if we already committed to
@@ -1602,7 +1614,40 @@ where
16021614 ChannelPhase::UnfundedOutboundV1(chan) => chan.is_resumable(),
16031615 ChannelPhase::UnfundedInboundV1(_) => false,
16041616 ChannelPhase::UnfundedV2(_) => false,
1605- }
1617+ };
1618+
1619+ let splice_funding_failed = if let ChannelPhase::Funded(chan) = &mut self.phase {
1620+ // Reset any quiescence-related state as it is implicitly terminated once disconnected.
1621+ if matches!(chan.context.channel_state, ChannelState::ChannelReady(_)) {
1622+ if chan.quiescent_action.is_some() {
1623+ // If we were trying to get quiescent, try again after reconnection.
1624+ chan.context.channel_state.set_awaiting_quiescence();
1625+ }
1626+ chan.context.channel_state.clear_local_stfu_sent();
1627+ chan.context.channel_state.clear_remote_stfu_sent();
1628+ if chan.should_reset_pending_splice_state() {
1629+ // If there was a pending splice negotiation that failed due to disconnecting, we
1630+ // also take the opportunity to clean up our state.
1631+ let splice_funding_failed = chan.reset_pending_splice_state();
1632+ debug_assert!(!chan.context.channel_state.is_quiescent());
1633+ splice_funding_failed
1634+ } else if !chan.has_pending_splice_awaiting_signatures() {
1635+ // We shouldn't be quiescent anymore upon reconnecting if:
1636+ // - We were in quiescence but a splice/RBF was never negotiated or
1637+ // - We were in quiescence but the splice negotiation failed due to disconnecting
1638+ chan.context.channel_state.clear_quiescent();
1639+ None
1640+ } else {
1641+ None
1642+ }
1643+ } else {
1644+ None
1645+ }
1646+ } else {
1647+ None
1648+ };
1649+
1650+ DisconnectResult { is_resumable, splice_funding_failed }
16061651 }
16071652
16081653 /// Should be called when the peer re-connects, returning an initial message which we should
@@ -6837,40 +6882,42 @@ where
68376882 }
68386883
68396884 pub fn force_shutdown(&mut self, closure_reason: ClosureReason) -> ShutdownResult {
6840- let splice_funding_failed =
6841- if matches!(self.context.channel_state, ChannelState::ChannelReady(_)) {
6842- if self.should_reset_pending_splice_state() {
6843- self.reset_pending_splice_state()
6844- } else {
6845- match self.quiescent_action.take() {
6846- Some(QuiescentAction::Splice(instructions)) => {
6847- self.context.channel_state.clear_awaiting_quiescence();
6848- let (inputs, outputs) =
6849- instructions.into_contributed_inputs_and_outputs();
6850- Some(SpliceFundingFailed {
6851- funding_txo: None,
6852- channel_type: None,
6853- contributed_inputs: inputs,
6854- contributed_outputs: outputs,
6855- })
6856- },
6857- #[cfg(any(test, fuzzing))]
6858- Some(quiescent_action) => {
6859- self.quiescent_action = Some(quiescent_action);
6860- None
6861- },
6862- None => None,
6863- }
6864- }
6865- } else {
6866- None
6867- };
6885+ let splice_funding_failed = self.maybe_fail_splice_negotiation();
68686886
68696887 let mut shutdown_result = self.context.force_shutdown(&self.funding, closure_reason);
68706888 shutdown_result.splice_funding_failed = splice_funding_failed;
68716889 shutdown_result
68726890 }
68736891
6892+ fn maybe_fail_splice_negotiation(&mut self) -> Option<SpliceFundingFailed> {
6893+ if matches!(self.context.channel_state, ChannelState::ChannelReady(_)) {
6894+ if self.should_reset_pending_splice_state() {
6895+ self.reset_pending_splice_state()
6896+ } else {
6897+ match self.quiescent_action.take() {
6898+ Some(QuiescentAction::Splice(instructions)) => {
6899+ self.context.channel_state.clear_awaiting_quiescence();
6900+ let (inputs, outputs) = instructions.into_contributed_inputs_and_outputs();
6901+ Some(SpliceFundingFailed {
6902+ funding_txo: None,
6903+ channel_type: None,
6904+ contributed_inputs: inputs,
6905+ contributed_outputs: outputs,
6906+ })
6907+ },
6908+ #[cfg(any(test, fuzzing))]
6909+ Some(quiescent_action) => {
6910+ self.quiescent_action = Some(quiescent_action);
6911+ None
6912+ },
6913+ None => None,
6914+ }
6915+ }
6916+ } else {
6917+ None
6918+ }
6919+ }
6920+
68746921 fn interactive_tx_constructor_mut(&mut self) -> Option<&mut InteractiveTxConstructor> {
68756922 self.pending_splice
68766923 .as_mut()
@@ -9130,27 +9177,6 @@ where
91309177 }
91319178 }
91329179
9133- // Reset any quiescence-related state as it is implicitly terminated once disconnected.
9134- if matches!(self.context.channel_state, ChannelState::ChannelReady(_)) {
9135- if self.quiescent_action.is_some() {
9136- // If we were trying to get quiescent, try again after reconnection.
9137- self.context.channel_state.set_awaiting_quiescence();
9138- }
9139- self.context.channel_state.clear_local_stfu_sent();
9140- self.context.channel_state.clear_remote_stfu_sent();
9141- if self.should_reset_pending_splice_state() {
9142- // If there was a pending splice negotiation that failed due to disconnecting, we
9143- // also take the opportunity to clean up our state.
9144- self.reset_pending_splice_state();
9145- debug_assert!(!self.context.channel_state.is_quiescent());
9146- } else if !self.has_pending_splice_awaiting_signatures() {
9147- // We shouldn't be quiescent anymore upon reconnecting if:
9148- // - We were in quiescence but a splice/RBF was never negotiated or
9149- // - We were in quiescence but the splice negotiation failed due to disconnecting
9150- self.context.channel_state.clear_quiescent();
9151- }
9152- }
9153-
91549180 self.context.channel_state.set_peer_disconnected();
91559181 log_trace!(logger, "Peer disconnection resulted in {} remote-announced HTLC drops on channel {}", inbound_drop_count, &self.context.channel_id());
91569182 Ok(())
@@ -11823,9 +11849,9 @@ where
1182311849 .map_err(|e| APIError::APIMisuseError { err: e.to_owned() })
1182411850 }
1182511851
11826- fn send_splice_init(
11827- &mut self, instructions: SpliceInstructions,
11828- ) -> Result<msgs::SpliceInit, String> {
11852+ fn send_splice_init(&mut self, instructions: SpliceInstructions) -> msgs::SpliceInit {
11853+ debug_assert!( self.pending_splice.is_none());
11854+
1182911855 let SpliceInstructions {
1183011856 adjusted_funding_contribution,
1183111857 our_funding_inputs,
@@ -11835,15 +11861,6 @@ where
1183511861 locktime,
1183611862 } = instructions;
1183711863
11838- // Check if a splice has been initiated already.
11839- // Note: only a single outstanding splice is supported (per spec)
11840- if self.pending_splice.is_some() {
11841- return Err(format!(
11842- "Channel {} cannot be spliced, as it has already a splice pending",
11843- self.context.channel_id(),
11844- ));
11845- }
11846-
1184711864 let prev_funding_input = self.funding.to_splice_funding_input();
1184811865 let context = FundingNegotiationContext {
1184911866 is_initiator: true,
@@ -11867,14 +11884,14 @@ where
1186711884 let prev_funding_txid = self.funding.get_funding_txid();
1186811885 let funding_pubkey = self.context.holder_pubkeys(prev_funding_txid).funding_pubkey;
1186911886
11870- Ok( msgs::SpliceInit {
11887+ msgs::SpliceInit {
1187111888 channel_id: self.context.channel_id,
1187211889 funding_contribution_satoshis: adjusted_funding_contribution.to_sat(),
1187311890 funding_feerate_per_kw,
1187411891 locktime,
1187511892 funding_pubkey,
1187611893 require_confirmed_inputs: None,
11877- })
11894+ }
1187811895 }
1187911896
1188011897 #[cfg(test)]
@@ -13045,10 +13062,20 @@ where
1304513062 "Internal Error: Didn't have anything to do after reaching quiescence".to_owned()
1304613063 ));
1304713064 },
13048- Some(QuiescentAction::Splice(_instructions)) => {
13049- return self.send_splice_init(_instructions)
13050- .map(|splice_init| Some(StfuResponse::SpliceInit(splice_init)))
13051- .map_err(|e| ChannelError::WarnAndDisconnect(e.to_owned()));
13065+ Some(QuiescentAction::Splice(instructions)) => {
13066+ if self.pending_splice.is_some() {
13067+ self.quiescent_action = Some(QuiescentAction::Splice(instructions));
13068+
13069+ return Err(ChannelError::WarnAndDisconnect(
13070+ format!(
13071+ "Channel {} cannot be spliced as it already has a splice pending",
13072+ self.context.channel_id(),
13073+ ),
13074+ ));
13075+ }
13076+
13077+ let splice_init = self.send_splice_init(instructions);
13078+ return Ok(Some(StfuResponse::SpliceInit(splice_init)));
1305213079 },
1305313080 #[cfg(any(test, fuzzing))]
1305413081 Some(QuiescentAction::DoNothing) => {
0 commit comments