@@ -1686,27 +1686,27 @@ 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.context.channel_state.clear_quiescent();
1699
+ funded_channel
1700
+ .pending_splice
1701
+ .as_mut()
1702
+ .and_then(|pending_splice| pending_splice.funding_negotiation.take());
1703
+ } else {
1704
+ debug_assert!(false, "We should never fail an interactive funding negotiation once we're exchanging tx_signatures");
1705
+ }
1706
+ if funded_channel.should_reset_pending_splice_state() {
1707
+ funded_channel.pending_splice.take();
1708
+ }
1694
1709
},
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
1710
};
1711
1711
1712
1712
reason.into_tx_abort_msg(self.context().channel_id)
@@ -1818,11 +1818,11 @@ where
1818
1818
where
1819
1819
L::Target: Logger,
1820
1820
{
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
1821
+ // If we have not sent a `tx_abort` message for this negotiation previously, we need to echo
1822
+ // back a tx_abort message according to the spec:
1823
+ // https://github.com/lightning/bolts/blob/247e83d/02-peer-protocol.md?plain=1#L560-L561
1824
+ // For rationale why we echo back `tx_abort`:
1825
+ // https://github.com/lightning/bolts/blob/247e83d/02-peer-protocol.md?plain=1#L578-L580
1826
1826
let should_ack = match &mut self.phase {
1827
1827
ChannelPhase::Undefined => unreachable!(),
1828
1828
ChannelPhase::UnfundedOutboundV1(_) | ChannelPhase::UnfundedInboundV1(_) => {
@@ -1832,19 +1832,37 @@ where
1832
1832
ChannelPhase::UnfundedV2(pending_v2_channel) => {
1833
1833
pending_v2_channel.interactive_tx_constructor.take().is_some()
1834
1834
},
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(),
1835
+ ChannelPhase::Funded(funded_channel) => {
1836
+ if let Some(should_reset) =
1837
+ funded_channel.should_reset_pending_splice_funding_negotiation()
1838
+ {
1839
+ if should_reset {
1840
+ funded_channel.context.channel_state.clear_quiescent();
1841
+ let has_funding_negotiation = funded_channel
1842
+ .pending_splice
1843
+ .as_mut()
1844
+ .and_then(|pending_splice| pending_splice.funding_negotiation.take())
1845
+ .is_some();
1846
+ if funded_channel.should_reset_pending_splice_state() {
1847
+ funded_channel.pending_splice.take();
1848
+ }
1849
+
1850
+ // We may have still tracked the pending funding negotiation state, so we
1851
+ // should ack with our own `tx_abort`.
1852
+ has_funding_negotiation
1853
+ } else {
1854
+ return Err(ChannelError::close(
1855
+ "Received tx_abort while awaiting tx_signatures exchange".to_owned(),
1856
+ ));
1857
+ }
1858
+ } else {
1859
+ // We were not tracking the pending funding negotiation state anymore, likely
1860
+ // due to a disconnection or already having sent our own `tx_abort`.
1861
+ false
1862
+ }
1863
+ },
1840
1864
};
1841
1865
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
1866
Ok(should_ack.then(|| {
1849
1867
let logger = WithChannelContext::from(logger, &self.context(), None);
1850
1868
let reason =
@@ -2554,6 +2572,15 @@ impl FundingNegotiation {
2554
2572
}
2555
2573
2556
2574
impl PendingFunding {
2575
+ fn can_abandon_funding_negotiation(&self) -> bool {
2576
+ self.funding_negotiation
2577
+ .as_ref()
2578
+ .map(|funding_negotiation| {
2579
+ !matches!(funding_negotiation, FundingNegotiation::AwaitingSignatures { .. })
2580
+ })
2581
+ .unwrap_or(true)
2582
+ }
2583
+
2557
2584
fn check_get_splice_locked<SP: Deref>(
2558
2585
&mut self, context: &ChannelContext<SP>, confirmed_funding_index: usize, height: u32,
2559
2586
) -> Option<msgs::SpliceLocked>
@@ -6739,6 +6766,33 @@ where
6739
6766
)
6740
6767
}
6741
6768
6769
+ /// Returns `None` if there is no [`FundedChannel::pending_splice`], otherwise a boolean
6770
+ /// indicating whether we should reset the splice's [`PendingFunding::funding_negotiation`].
6771
+ fn should_reset_pending_splice_funding_negotiation(&self) -> Option<bool> {
6772
+ self.pending_splice.as_ref().map(|pending_splice| {
6773
+ if pending_splice.can_abandon_funding_negotiation() {
6774
+ true
6775
+ } else {
6776
+ self.context
6777
+ .interactive_tx_signing_session
6778
+ .as_ref()
6779
+ .map(|signing_session| {
6780
+ signing_session.holder_tx_signatures().is_some()
6781
+ || signing_session.has_received_tx_signatures()
6782
+ })
6783
+ .unwrap_or_else(|| {
6784
+ debug_assert!(false);
6785
+ false
6786
+ })
6787
+ }
6788
+ })
6789
+ }
6790
+
6791
+ fn should_reset_pending_splice_state(&self) -> bool {
6792
+ self.should_reset_pending_splice_funding_negotiation().unwrap_or(true)
6793
+ && self.pending_funding().is_empty()
6794
+ }
6795
+
6742
6796
#[rustfmt::skip]
6743
6797
fn check_remote_fee<F: Deref, L: Deref>(
6744
6798
channel_type: &ChannelTypeFeatures, fee_estimator: &LowerBoundedFeeEstimator<F>,
@@ -8864,7 +8918,21 @@ where
8864
8918
}
8865
8919
self.context.channel_state.clear_local_stfu_sent();
8866
8920
self.context.channel_state.clear_remote_stfu_sent();
8921
+ if self.pending_splice.is_none() {
8922
+ // If we were in quiescence but a splice was never negotiated, we shouldn't be
8923
+ // quiescent anymore upon reconnecting.
8924
+ self.context.channel_state.clear_quiescent();
8925
+ }
8926
+ }
8927
+
8928
+ if self.should_reset_pending_splice_funding_negotiation().unwrap_or(false) {
8867
8929
self.context.channel_state.clear_quiescent();
8930
+ self.pending_splice
8931
+ .as_mut()
8932
+ .and_then(|pending_splice| pending_splice.funding_negotiation.take());
8933
+ }
8934
+ if self.should_reset_pending_splice_state() {
8935
+ self.pending_splice.take();
8868
8936
}
8869
8937
8870
8938
self.context.channel_state.set_peer_disconnected();
@@ -13875,7 +13943,12 @@ where
13875
13943
}
13876
13944
channel_state.clear_local_stfu_sent();
13877
13945
channel_state.clear_remote_stfu_sent();
13878
- channel_state.clear_quiescent();
13946
+ if self.should_reset_pending_splice_funding_negotiation().unwrap_or(true) {
13947
+ // If we were in quiescence but a splice was never negotiated, or the
13948
+ // negotiation failed due to disconnecting, we shouldn't be quiescent
13949
+ // anymore upon reconnecting.
13950
+ channel_state.clear_quiescent();
13951
+ }
13879
13952
},
13880
13953
ChannelState::FundingNegotiated(_)
13881
13954
if self.context.interactive_tx_signing_session.is_some() => {},
@@ -14238,6 +14311,14 @@ where
14238
14311
let holder_commitment_point_next = self.holder_commitment_point.next_point();
14239
14312
let holder_commitment_point_pending_next = self.holder_commitment_point.pending_next_point;
14240
14313
14314
+ let pending_splice = if self.should_reset_pending_splice_state() {
14315
+ None
14316
+ } else {
14317
+ // We don't have to worry about resetting the pending `FundingNegotiation` because we
14318
+ // can only read `FundingNegotiation::AwaitingSignatures` variants anyway.
14319
+ self.pending_splice.as_ref()
14320
+ };
14321
+
14241
14322
write_tlv_fields!(writer, {
14242
14323
(0, self.context.announcement_sigs, option),
14243
14324
// minimum_depth and counterparty_selected_channel_reserve_satoshis used to have a
@@ -14286,7 +14367,7 @@ where
14286
14367
(60, self.context.historical_scids, optional_vec), // Added in 0.2
14287
14368
(61, fulfill_attribution_data, optional_vec), // Added in 0.2
14288
14369
(63, holder_commitment_point_current, option), // Added in 0.2
14289
- (64, self. pending_splice, option), // Added in 0.2
14370
+ (64, pending_splice, option), // Added in 0.2
14290
14371
(65, self.quiescent_action, option), // Added in 0.2
14291
14372
(67, pending_outbound_held_htlc_flags, optional_vec), // Added in 0.2
14292
14373
(69, holding_cell_held_htlc_flags, optional_vec), // Added in 0.2
@@ -14950,6 +15031,15 @@ where
14950
15031
}
14951
15032
};
14952
15033
15034
+ if let Some(funding_negotiation) = pending_splice
15035
+ .as_ref()
15036
+ .and_then(|pending_splice| pending_splice.funding_negotiation.as_ref())
15037
+ {
15038
+ if !matches!(funding_negotiation, FundingNegotiation::AwaitingSignatures { .. }) {
15039
+ return Err(DecodeError::InvalidValue);
15040
+ }
15041
+ }
15042
+
14953
15043
Ok(FundedChannel {
14954
15044
funding: FundingScope {
14955
15045
value_to_self_msat,
0 commit comments