@@ -1686,27 +1686,20 @@ where
16861686 let logger = WithChannelContext::from(logger, &self.context(), None);
16871687 log_info!(logger, "Failed interactive transaction negotiation: {reason}");
16881688
1689- let _interactive_tx_constructor = match &mut self.phase {
1689+ match &mut self.phase {
16901690 ChannelPhase::Undefined => unreachable!(),
1691- ChannelPhase::UnfundedOutboundV1(_) | ChannelPhase::UnfundedInboundV1(_) => None ,
1691+ ChannelPhase::UnfundedOutboundV1(_) | ChannelPhase::UnfundedInboundV1(_) => {} ,
16921692 ChannelPhase::UnfundedV2(pending_v2_channel) => {
1693- pending_v2_channel.interactive_tx_constructor.take()
1693+ pending_v2_channel.interactive_tx_constructor.take();
1694+ },
1695+ ChannelPhase::Funded(funded_channel) => {
1696+ if funded_channel.should_reset_pending_splice_funding_negotiation().unwrap_or(true)
1697+ {
1698+ funded_channel.reset_pending_splice_state();
1699+ } else {
1700+ debug_assert!(false, "We should never fail an interactive funding negotiation once we're exchanging tx_signatures");
1701+ }
16941702 },
1695- ChannelPhase::Funded(funded_channel) => funded_channel
1696- .pending_splice
1697- .as_mut()
1698- .and_then(|pending_splice| pending_splice.funding_negotiation.take())
1699- .and_then(|funding_negotiation| {
1700- if let FundingNegotiation::ConstructingTransaction {
1701- interactive_tx_constructor,
1702- ..
1703- } = funding_negotiation
1704- {
1705- Some(interactive_tx_constructor)
1706- } else {
1707- None
1708- }
1709- }),
17101703 };
17111704
17121705 reason.into_tx_abort_msg(self.context().channel_id)
@@ -1818,11 +1811,11 @@ where
18181811 where
18191812 L::Target: Logger,
18201813 {
1821- // This checks for and resets the interactive negotiation state by `take()`ing it from the channel.
1822- // The existence of the `tx_constructor` indicates that we have not moved into the signing
1823- // phase for this interactively constructed transaction and hence we have not exchanged
1824- // `tx_signatures`. Either way, we never close the channel upon receiving a `tx_abort`:
1825- // https://github.com/lightning/bolts/blob/247e83d/02-peer-protocol.md?plain=1#L574-L576
1814+ // If we have not sent a `tx_abort` message for this negotiation previously, we need to echo
1815+ // back a tx_abort message according to the spec:
1816+ // https://github.com/lightning/bolts/blob/247e83d/02-peer-protocol.md?plain=1#L560-L561
1817+ // For rationale why we echo back `tx_abort`:
1818+ // https://github.com/lightning/bolts/blob/247e83d/02-peer-protocol.md?plain=1#L578-L580
18261819 let should_ack = match &mut self.phase {
18271820 ChannelPhase::Undefined => unreachable!(),
18281821 ChannelPhase::UnfundedOutboundV1(_) | ChannelPhase::UnfundedInboundV1(_) => {
@@ -1832,19 +1825,27 @@ where
18321825 ChannelPhase::UnfundedV2(pending_v2_channel) => {
18331826 pending_v2_channel.interactive_tx_constructor.take().is_some()
18341827 },
1835- ChannelPhase::Funded(funded_channel) => funded_channel
1836- .pending_splice
1837- .as_mut()
1838- .and_then(|pending_splice| pending_splice.funding_negotiation.take())
1839- .is_some(),
1828+ ChannelPhase::Funded(funded_channel) => {
1829+ if let Some(should_reset) =
1830+ funded_channel.should_reset_pending_splice_funding_negotiation()
1831+ {
1832+ if should_reset {
1833+ // We may have still tracked the pending funding negotiation state, so we
1834+ // should ack with our own `tx_abort`.
1835+ funded_channel.reset_pending_splice_state()
1836+ } else {
1837+ return Err(ChannelError::close(
1838+ "Received tx_abort while awaiting tx_signatures exchange".to_owned(),
1839+ ));
1840+ }
1841+ } else {
1842+ // We were not tracking the pending funding negotiation state anymore, likely
1843+ // due to a disconnection or already having sent our own `tx_abort`.
1844+ false
1845+ }
1846+ },
18401847 };
18411848
1842- // NOTE: Since at this point we have not sent a `tx_abort` message for this negotiation
1843- // previously (tx_constructor was `Some`), we need to echo back a tx_abort message according
1844- // to the spec:
1845- // https://github.com/lightning/bolts/blob/247e83d/02-peer-protocol.md?plain=1#L560-L561
1846- // For rationale why we echo back `tx_abort`:
1847- // https://github.com/lightning/bolts/blob/247e83d/02-peer-protocol.md?plain=1#L578-L580
18481849 Ok(should_ack.then(|| {
18491850 let logger = WithChannelContext::from(logger, &self.context(), None);
18501851 let reason =
@@ -2554,6 +2555,15 @@ impl FundingNegotiation {
25542555}
25552556
25562557impl PendingFunding {
2558+ fn can_abandon_funding_negotiation(&self) -> bool {
2559+ self.funding_negotiation
2560+ .as_ref()
2561+ .map(|funding_negotiation| {
2562+ !matches!(funding_negotiation, FundingNegotiation::AwaitingSignatures { .. })
2563+ })
2564+ .unwrap_or(true)
2565+ }
2566+
25572567 fn check_get_splice_locked<SP: Deref>(
25582568 &mut self, context: &ChannelContext<SP>, confirmed_funding_index: usize, height: u32,
25592569 ) -> Option<msgs::SpliceLocked>
@@ -6739,6 +6749,45 @@ where
67396749 )
67406750 }
67416751
6752+ /// Returns `None` if there is no [`FundedChannel::pending_splice`], otherwise a boolean
6753+ /// indicating whether we should reset the splice's [`PendingFunding::funding_negotiation`].
6754+ fn should_reset_pending_splice_funding_negotiation(&self) -> Option<bool> {
6755+ self.pending_splice.as_ref().map(|pending_splice| {
6756+ if pending_splice.can_abandon_funding_negotiation() {
6757+ true
6758+ } else {
6759+ self.context
6760+ .interactive_tx_signing_session
6761+ .as_ref()
6762+ .map(|signing_session| !signing_session.has_received_commitment_signed())
6763+ .unwrap_or_else(|| {
6764+ debug_assert!(false);
6765+ false
6766+ })
6767+ }
6768+ })
6769+ }
6770+
6771+ fn should_reset_pending_splice_state(&self) -> bool {
6772+ self.should_reset_pending_splice_funding_negotiation().unwrap_or(true)
6773+ && self.pending_funding().is_empty()
6774+ }
6775+
6776+ fn reset_pending_splice_state(&mut self) -> bool {
6777+ debug_assert!(self.should_reset_pending_splice_funding_negotiation().unwrap_or(true));
6778+ self.context.channel_state.clear_quiescent();
6779+ self.context.interactive_tx_signing_session.take();
6780+ let has_funding_negotiation = self
6781+ .pending_splice
6782+ .as_mut()
6783+ .and_then(|pending_splice| pending_splice.funding_negotiation.take())
6784+ .is_some();
6785+ if self.should_reset_pending_splice_state() {
6786+ self.pending_splice.take();
6787+ }
6788+ has_funding_negotiation
6789+ }
6790+
67426791 #[rustfmt::skip]
67436792 fn check_remote_fee<F: Deref, L: Deref>(
67446793 channel_type: &ChannelTypeFeatures, fee_estimator: &LowerBoundedFeeEstimator<F>,
@@ -8864,7 +8913,14 @@ where
88648913 }
88658914 self.context.channel_state.clear_local_stfu_sent();
88668915 self.context.channel_state.clear_remote_stfu_sent();
8867- self.context.channel_state.clear_quiescent();
8916+ if self.should_reset_pending_splice_funding_negotiation().unwrap_or(true) {
8917+ // If we were in quiescence but a splice was never negotiated, or the negotiation
8918+ // failed due to disconnecting, we shouldn't be quiescent anymore upon reconnecting.
8919+ // If there was a pending splice negotiation that has failed due to disconnecting,
8920+ // we also take the opportunity to clean up our state.
8921+ self.reset_pending_splice_state();
8922+ debug_assert!(!self.context.channel_state.is_quiescent());
8923+ }
88688924 }
88698925
88708926 self.context.channel_state.set_peer_disconnected();
@@ -13875,7 +13931,12 @@ where
1387513931 }
1387613932 channel_state.clear_local_stfu_sent();
1387713933 channel_state.clear_remote_stfu_sent();
13878- channel_state.clear_quiescent();
13934+ if self.should_reset_pending_splice_funding_negotiation().unwrap_or(true) {
13935+ // If we were in quiescence but a splice was never negotiated, or the
13936+ // negotiation failed due to disconnecting, we shouldn't be quiescent
13937+ // anymore upon reconnecting.
13938+ channel_state.clear_quiescent();
13939+ }
1387913940 },
1388013941 ChannelState::FundingNegotiated(_)
1388113942 if self.context.interactive_tx_signing_session.is_some() => {},
@@ -14238,6 +14299,20 @@ where
1423814299 let holder_commitment_point_next = self.holder_commitment_point.next_point();
1423914300 let holder_commitment_point_pending_next = self.holder_commitment_point.pending_next_point;
1424014301
14302+ let interactive_tx_signing_session =
14303+ if self.should_reset_pending_splice_funding_negotiation().unwrap_or(false) {
14304+ None
14305+ } else {
14306+ self.context.interactive_tx_signing_session.as_ref()
14307+ };
14308+ let pending_splice = if self.should_reset_pending_splice_state() {
14309+ None
14310+ } else {
14311+ // We don't have to worry about resetting the pending `FundingNegotiation` because we
14312+ // can only read `FundingNegotiation::AwaitingSignatures` variants anyway.
14313+ self.pending_splice.as_ref()
14314+ };
14315+
1424114316 write_tlv_fields!(writer, {
1424214317 (0, self.context.announcement_sigs, option),
1424314318 // minimum_depth and counterparty_selected_channel_reserve_satoshis used to have a
@@ -14281,12 +14356,12 @@ where
1428114356 (53, funding_tx_broadcast_safe_event_emitted, option), // Added in 0.0.124
1428214357 (55, removed_htlc_attribution_data, optional_vec), // Added in 0.2
1428314358 (57, holding_cell_attribution_data, optional_vec), // Added in 0.2
14284- (58, self.context. interactive_tx_signing_session, option), // Added in 0.2
14359+ (58, interactive_tx_signing_session, option), // Added in 0.2
1428514360 (59, self.funding.minimum_depth_override, option), // Added in 0.2
1428614361 (60, self.context.historical_scids, optional_vec), // Added in 0.2
1428714362 (61, fulfill_attribution_data, optional_vec), // Added in 0.2
1428814363 (63, holder_commitment_point_current, option), // Added in 0.2
14289- (64, self. pending_splice, option), // Added in 0.2
14364+ (64, pending_splice, option), // Added in 0.2
1429014365 (65, self.quiescent_action, option), // Added in 0.2
1429114366 (67, pending_outbound_held_htlc_flags, optional_vec), // Added in 0.2
1429214367 (69, holding_cell_held_htlc_flags, optional_vec), // Added in 0.2
@@ -14950,6 +15025,15 @@ where
1495015025 }
1495115026 };
1495215027
15028+ if let Some(funding_negotiation) = pending_splice
15029+ .as_ref()
15030+ .and_then(|pending_splice| pending_splice.funding_negotiation.as_ref())
15031+ {
15032+ if !matches!(funding_negotiation, FundingNegotiation::AwaitingSignatures { .. }) {
15033+ return Err(DecodeError::InvalidValue);
15034+ }
15035+ }
15036+
1495315037 Ok(FundedChannel {
1495415038 funding: FundingScope {
1495515039 value_to_self_msat,
0 commit comments