@@ -1686,27 +1686,20 @@ where
1686
1686
let logger = WithChannelContext::from(logger, &self.context(), None);
1687
1687
log_info!(logger, "Failed interactive transaction negotiation: {reason}");
1688
1688
1689
- let _interactive_tx_constructor = match &mut self.phase {
1689
+ match &mut self.phase {
1690
1690
ChannelPhase::Undefined => unreachable!(),
1691
- ChannelPhase::UnfundedOutboundV1(_) | ChannelPhase::UnfundedInboundV1(_) => None ,
1691
+ ChannelPhase::UnfundedOutboundV1(_) | ChannelPhase::UnfundedInboundV1(_) => {} ,
1692
1692
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
+ }
1694
1702
},
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
- }),
1710
1703
};
1711
1704
1712
1705
reason.into_tx_abort_msg(self.context().channel_id)
@@ -1818,11 +1811,11 @@ where
1818
1811
where
1819
1812
L::Target: Logger,
1820
1813
{
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
1826
1819
let should_ack = match &mut self.phase {
1827
1820
ChannelPhase::Undefined => unreachable!(),
1828
1821
ChannelPhase::UnfundedOutboundV1(_) | ChannelPhase::UnfundedInboundV1(_) => {
@@ -1832,19 +1825,27 @@ where
1832
1825
ChannelPhase::UnfundedV2(pending_v2_channel) => {
1833
1826
pending_v2_channel.interactive_tx_constructor.take().is_some()
1834
1827
},
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
+ },
1840
1847
};
1841
1848
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
1848
1849
Ok(should_ack.then(|| {
1849
1850
let logger = WithChannelContext::from(logger, &self.context(), None);
1850
1851
let reason =
@@ -2554,6 +2555,15 @@ impl FundingNegotiation {
2554
2555
}
2555
2556
2556
2557
impl 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
+
2557
2567
fn check_get_splice_locked<SP: Deref>(
2558
2568
&mut self, context: &ChannelContext<SP>, confirmed_funding_index: usize, height: u32,
2559
2569
) -> Option<msgs::SpliceLocked>
@@ -6739,6 +6749,45 @@ where
6739
6749
)
6740
6750
}
6741
6751
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
+
6742
6791
#[rustfmt::skip]
6743
6792
fn check_remote_fee<F: Deref, L: Deref>(
6744
6793
channel_type: &ChannelTypeFeatures, fee_estimator: &LowerBoundedFeeEstimator<F>,
@@ -8864,7 +8913,14 @@ where
8864
8913
}
8865
8914
self.context.channel_state.clear_local_stfu_sent();
8866
8915
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
+ }
8868
8924
}
8869
8925
8870
8926
self.context.channel_state.set_peer_disconnected();
@@ -13896,7 +13952,12 @@ where
13896
13952
}
13897
13953
channel_state.clear_local_stfu_sent();
13898
13954
channel_state.clear_remote_stfu_sent();
13899
- channel_state.clear_quiescent();
13955
+ if self.should_reset_pending_splice_funding_negotiation().unwrap_or(true) {
13956
+ // If we were in quiescence but a splice was never negotiated, or the
13957
+ // negotiation failed due to disconnecting, we shouldn't be quiescent
13958
+ // anymore upon reconnecting.
13959
+ channel_state.clear_quiescent();
13960
+ }
13900
13961
},
13901
13962
ChannelState::FundingNegotiated(_)
13902
13963
if self.context.interactive_tx_signing_session.is_some() => {},
@@ -14259,6 +14320,20 @@ where
14259
14320
let holder_commitment_point_next = self.holder_commitment_point.next_point();
14260
14321
let holder_commitment_point_pending_next = self.holder_commitment_point.pending_next_point;
14261
14322
14323
+ let interactive_tx_signing_session =
14324
+ if self.should_reset_pending_splice_funding_negotiation().unwrap_or(false) {
14325
+ None
14326
+ } else {
14327
+ self.context.interactive_tx_signing_session.as_ref()
14328
+ };
14329
+ let pending_splice = if self.should_reset_pending_splice_state() {
14330
+ None
14331
+ } else {
14332
+ // We don't have to worry about resetting the pending `FundingNegotiation` because we
14333
+ // can only read `FundingNegotiation::AwaitingSignatures` variants anyway.
14334
+ self.pending_splice.as_ref()
14335
+ };
14336
+
14262
14337
write_tlv_fields!(writer, {
14263
14338
(0, self.context.announcement_sigs, option),
14264
14339
// minimum_depth and counterparty_selected_channel_reserve_satoshis used to have a
@@ -14302,12 +14377,12 @@ where
14302
14377
(53, funding_tx_broadcast_safe_event_emitted, option), // Added in 0.0.124
14303
14378
(55, removed_htlc_attribution_data, optional_vec), // Added in 0.2
14304
14379
(57, holding_cell_attribution_data, optional_vec), // Added in 0.2
14305
- (58, self.context. interactive_tx_signing_session, option), // Added in 0.2
14380
+ (58, interactive_tx_signing_session, option), // Added in 0.2
14306
14381
(59, self.funding.minimum_depth_override, option), // Added in 0.2
14307
14382
(60, self.context.historical_scids, optional_vec), // Added in 0.2
14308
14383
(61, fulfill_attribution_data, optional_vec), // Added in 0.2
14309
14384
(63, holder_commitment_point_current, option), // Added in 0.2
14310
- (64, self. pending_splice, option), // Added in 0.2
14385
+ (64, pending_splice, option), // Added in 0.2
14311
14386
(65, self.quiescent_action, option), // Added in 0.2
14312
14387
(67, pending_outbound_held_htlc_flags, optional_vec), // Added in 0.2
14313
14388
(69, holding_cell_held_htlc_flags, optional_vec), // Added in 0.2
@@ -14971,6 +15046,15 @@ where
14971
15046
}
14972
15047
};
14973
15048
15049
+ if let Some(funding_negotiation) = pending_splice
15050
+ .as_ref()
15051
+ .and_then(|pending_splice| pending_splice.funding_negotiation.as_ref())
15052
+ {
15053
+ if !matches!(funding_negotiation, FundingNegotiation::AwaitingSignatures { .. }) {
15054
+ return Err(DecodeError::InvalidValue);
15055
+ }
15056
+ }
15057
+
14974
15058
Ok(FundedChannel {
14975
15059
funding: FundingScope {
14976
15060
value_to_self_msat,
0 commit comments