@@ -1196,6 +1196,14 @@ pub(crate) struct ShutdownResult {
1196
1196
pub(crate) splice_funding_failed: Option<SpliceFundingFailed>,
1197
1197
}
1198
1198
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
+
1199
1207
/// Tracks the transaction number, along with current and next commitment points.
1200
1208
/// This consolidates the logic to advance our commitment number and request new
1201
1209
/// commitment points from our signer.
@@ -1588,11 +1596,15 @@ where
1588
1596
/// Should be called when the peer is disconnected. Returns true if the channel can be resumed
1589
1597
/// when the peer reconnects (via [`Self::peer_connected_get_handshake`]). If not, the channel
1590
1598
/// 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 {
1594
1604
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
+ },
1596
1608
// If we get disconnected and haven't yet committed to a funding
1597
1609
// transaction, we can replay the `open_channel` on reconnection, so don't
1598
1610
// bother dropping the channel here. However, if we already committed to
@@ -1602,7 +1614,40 @@ where
1602
1614
ChannelPhase::UnfundedOutboundV1(chan) => chan.is_resumable(),
1603
1615
ChannelPhase::UnfundedInboundV1(_) => false,
1604
1616
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 }
1606
1651
}
1607
1652
1608
1653
/// Should be called when the peer re-connects, returning an initial message which we should
@@ -6837,40 +6882,42 @@ where
6837
6882
}
6838
6883
6839
6884
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();
6868
6886
6869
6887
let mut shutdown_result = self.context.force_shutdown(&self.funding, closure_reason);
6870
6888
shutdown_result.splice_funding_failed = splice_funding_failed;
6871
6889
shutdown_result
6872
6890
}
6873
6891
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
+
6874
6921
fn interactive_tx_constructor_mut(&mut self) -> Option<&mut InteractiveTxConstructor> {
6875
6922
self.pending_splice
6876
6923
.as_mut()
@@ -9130,27 +9177,6 @@ where
9130
9177
}
9131
9178
}
9132
9179
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
-
9154
9180
self.context.channel_state.set_peer_disconnected();
9155
9181
log_trace!(logger, "Peer disconnection resulted in {} remote-announced HTLC drops on channel {}", inbound_drop_count, &self.context.channel_id());
9156
9182
Ok(())
@@ -11823,9 +11849,9 @@ where
11823
11849
.map_err(|e| APIError::APIMisuseError { err: e.to_owned() })
11824
11850
}
11825
11851
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
+
11829
11855
let SpliceInstructions {
11830
11856
adjusted_funding_contribution,
11831
11857
our_funding_inputs,
@@ -11835,15 +11861,6 @@ where
11835
11861
locktime,
11836
11862
} = instructions;
11837
11863
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
-
11847
11864
let prev_funding_input = self.funding.to_splice_funding_input();
11848
11865
let context = FundingNegotiationContext {
11849
11866
is_initiator: true,
@@ -11867,14 +11884,14 @@ where
11867
11884
let prev_funding_txid = self.funding.get_funding_txid();
11868
11885
let funding_pubkey = self.context.holder_pubkeys(prev_funding_txid).funding_pubkey;
11869
11886
11870
- Ok( msgs::SpliceInit {
11887
+ msgs::SpliceInit {
11871
11888
channel_id: self.context.channel_id,
11872
11889
funding_contribution_satoshis: adjusted_funding_contribution.to_sat(),
11873
11890
funding_feerate_per_kw,
11874
11891
locktime,
11875
11892
funding_pubkey,
11876
11893
require_confirmed_inputs: None,
11877
- })
11894
+ }
11878
11895
}
11879
11896
11880
11897
#[cfg(test)]
@@ -13045,10 +13062,21 @@ where
13045
13062
"Internal Error: Didn't have anything to do after reaching quiescence".to_owned()
13046
13063
));
13047
13064
},
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
+ debug_assert!(false);
13068
+ self.quiescent_action = Some(QuiescentAction::Splice(instructions));
13069
+
13070
+ return Err(ChannelError::WarnAndDisconnect(
13071
+ format!(
13072
+ "Channel {} cannot be spliced as it already has a splice pending",
13073
+ self.context.channel_id(),
13074
+ ),
13075
+ ));
13076
+ }
13077
+
13078
+ let splice_init = self.send_splice_init(instructions);
13079
+ return Ok(Some(StfuResponse::SpliceInit(splice_init)));
13052
13080
},
13053
13081
#[cfg(any(test, fuzzing))]
13054
13082
Some(QuiescentAction::DoNothing) => {
0 commit comments