@@ -1680,35 +1680,37 @@ where
1680
1680
1681
1681
fn fail_interactive_tx_negotiation<L: Deref>(
1682
1682
&mut self, reason: AbortReason, logger: &L,
1683
- ) -> msgs::TxAbort
1683
+ ) -> ( msgs::TxAbort, Option<SpliceFundingFailed>)
1684
1684
where
1685
1685
L::Target: Logger,
1686
1686
{
1687
1687
let logger = WithChannelContext::from(logger, &self.context(), None);
1688
1688
log_info!(logger, "Failed interactive transaction negotiation: {reason}");
1689
1689
1690
- match &mut self.phase {
1690
+ let splice_funding_failed = match &mut self.phase {
1691
1691
ChannelPhase::Undefined => unreachable!(),
1692
- ChannelPhase::UnfundedOutboundV1(_) | ChannelPhase::UnfundedInboundV1(_) => {} ,
1692
+ ChannelPhase::UnfundedOutboundV1(_) | ChannelPhase::UnfundedInboundV1(_) => None ,
1693
1693
ChannelPhase::UnfundedV2(pending_v2_channel) => {
1694
1694
pending_v2_channel.interactive_tx_constructor.take();
1695
+ None
1695
1696
},
1696
1697
ChannelPhase::Funded(funded_channel) => {
1697
1698
if funded_channel.should_reset_pending_splice_funding_negotiation().unwrap_or(true)
1698
1699
{
1699
- funded_channel.reset_pending_splice_state();
1700
+ funded_channel.reset_pending_splice_state()
1700
1701
} else {
1701
1702
debug_assert!(false, "We should never fail an interactive funding negotiation once we're exchanging tx_signatures");
1703
+ None
1702
1704
}
1703
1705
},
1704
1706
};
1705
1707
1706
- reason.into_tx_abort_msg(self.context().channel_id)
1708
+ ( reason.into_tx_abort_msg(self.context().channel_id), splice_funding_failed )
1707
1709
}
1708
1710
1709
1711
pub fn tx_add_input<L: Deref>(
1710
1712
&mut self, msg: &msgs::TxAddInput, logger: &L,
1711
- ) -> Result<InteractiveTxMessageSend, msgs::TxAbort>
1713
+ ) -> Result<InteractiveTxMessageSend, ( msgs::TxAbort, Option<SpliceFundingFailed>) >
1712
1714
where
1713
1715
L::Target: Logger,
1714
1716
{
@@ -1723,7 +1725,7 @@ where
1723
1725
1724
1726
pub fn tx_add_output<L: Deref>(
1725
1727
&mut self, msg: &msgs::TxAddOutput, logger: &L,
1726
- ) -> Result<InteractiveTxMessageSend, msgs::TxAbort>
1728
+ ) -> Result<InteractiveTxMessageSend, ( msgs::TxAbort, Option<SpliceFundingFailed>) >
1727
1729
where
1728
1730
L::Target: Logger,
1729
1731
{
@@ -1740,7 +1742,7 @@ where
1740
1742
1741
1743
pub fn tx_remove_input<L: Deref>(
1742
1744
&mut self, msg: &msgs::TxRemoveInput, logger: &L,
1743
- ) -> Result<InteractiveTxMessageSend, msgs::TxAbort>
1745
+ ) -> Result<InteractiveTxMessageSend, ( msgs::TxAbort, Option<SpliceFundingFailed>) >
1744
1746
where
1745
1747
L::Target: Logger,
1746
1748
{
@@ -1757,7 +1759,7 @@ where
1757
1759
1758
1760
pub fn tx_remove_output<L: Deref>(
1759
1761
&mut self, msg: &msgs::TxRemoveOutput, logger: &L,
1760
- ) -> Result<InteractiveTxMessageSend, msgs::TxAbort>
1762
+ ) -> Result<InteractiveTxMessageSend, ( msgs::TxAbort, Option<SpliceFundingFailed>) >
1761
1763
where
1762
1764
L::Target: Logger,
1763
1765
{
@@ -1774,7 +1776,10 @@ where
1774
1776
1775
1777
pub fn tx_complete<L: Deref>(
1776
1778
&mut self, msg: &msgs::TxComplete, logger: &L,
1777
- ) -> Result<(Option<InteractiveTxMessageSend>, Option<msgs::CommitmentSigned>), msgs::TxAbort>
1779
+ ) -> Result<
1780
+ (Option<InteractiveTxMessageSend>, Option<msgs::CommitmentSigned>),
1781
+ (msgs::TxAbort, Option<SpliceFundingFailed>),
1782
+ >
1778
1783
where
1779
1784
L::Target: Logger,
1780
1785
{
@@ -1835,7 +1840,13 @@ where
1835
1840
if should_reset {
1836
1841
// We may have still tracked the pending funding negotiation state, so we
1837
1842
// should ack with our own `tx_abort`.
1838
- funded_channel.reset_pending_splice_state()
1843
+ let has_funding_negotiation = funded_channel
1844
+ .pending_splice
1845
+ .as_ref()
1846
+ .map(|pending_splice| pending_splice.funding_negotiation.is_some())
1847
+ .unwrap_or(false);
1848
+ funded_channel.reset_pending_splice_state();
1849
+ has_funding_negotiation
1839
1850
} else {
1840
1851
return Err(ChannelError::close(
1841
1852
"Received tx_abort while awaiting tx_signatures exchange".to_owned(),
@@ -1935,7 +1946,8 @@ where
1935
1946
interactive_tx_constructor,
1936
1947
} = funding_negotiation
1937
1948
{
1938
- Some((funding, interactive_tx_constructor))
1949
+ let is_initiator = interactive_tx_constructor.is_initiator();
1950
+ Some((is_initiator, funding, interactive_tx_constructor))
1939
1951
} else {
1940
1952
// Replace the taken state for later error handling
1941
1953
pending_splice.funding_negotiation = Some(funding_negotiation);
@@ -1947,7 +1959,7 @@ where
1947
1959
"Got a tx_complete message in an invalid state",
1948
1960
)
1949
1961
})
1950
- .and_then(|(mut funding, interactive_tx_constructor)| {
1962
+ .and_then(|(is_initiator, mut funding, interactive_tx_constructor)| {
1951
1963
match chan.context.funding_tx_constructed(
1952
1964
&mut funding,
1953
1965
funding_outpoint,
@@ -1958,7 +1970,10 @@ where
1958
1970
Ok(commitment_signed) => {
1959
1971
// Advance the state
1960
1972
pending_splice.funding_negotiation =
1961
- Some(FundingNegotiation::AwaitingSignatures { funding });
1973
+ Some(FundingNegotiation::AwaitingSignatures {
1974
+ is_initiator,
1975
+ funding,
1976
+ });
1962
1977
Ok((interactive_tx_constructor, commitment_signed))
1963
1978
},
1964
1979
Err(e) => {
@@ -2562,12 +2577,14 @@ enum FundingNegotiation {
2562
2577
},
2563
2578
AwaitingSignatures {
2564
2579
funding: FundingScope,
2580
+ is_initiator: bool,
2565
2581
},
2566
2582
}
2567
2583
2568
2584
impl_writeable_tlv_based_enum_upgradable!(FundingNegotiation,
2569
2585
(0, AwaitingSignatures) => {
2570
2586
(1, funding, required),
2587
+ (3, is_initiator, required),
2571
2588
},
2572
2589
unread_variants: AwaitingAck, ConstructingTransaction
2573
2590
);
@@ -2577,7 +2594,17 @@ impl FundingNegotiation {
2577
2594
match self {
2578
2595
FundingNegotiation::AwaitingAck { .. } => None,
2579
2596
FundingNegotiation::ConstructingTransaction { funding, .. } => Some(funding),
2580
- FundingNegotiation::AwaitingSignatures { funding } => Some(funding),
2597
+ FundingNegotiation::AwaitingSignatures { funding, .. } => Some(funding),
2598
+ }
2599
+ }
2600
+
2601
+ fn is_initiator(&self) -> bool {
2602
+ match self {
2603
+ FundingNegotiation::AwaitingAck { context } => context.is_initiator,
2604
+ FundingNegotiation::ConstructingTransaction { interactive_tx_constructor, .. } => {
2605
+ interactive_tx_constructor.is_initiator()
2606
+ },
2607
+ FundingNegotiation::AwaitingSignatures { is_initiator, .. } => *is_initiator,
2581
2608
}
2582
2609
}
2583
2610
}
@@ -6614,12 +6641,15 @@ impl FundingNegotiationContext {
6614
6641
}
6615
6642
6616
6643
fn into_negotiation_error(self, reason: AbortReason) -> NegotiationError {
6644
+ let (contributed_inputs, contributed_outputs) = self.into_contributed_inputs_and_outputs();
6645
+ NegotiationError { reason, contributed_inputs, contributed_outputs }
6646
+ }
6647
+
6648
+ fn into_contributed_inputs_and_outputs(self) -> (Vec<bitcoin::OutPoint>, Vec<TxOut>) {
6617
6649
let contributed_inputs =
6618
6650
self.our_funding_inputs.into_iter().map(|input| input.utxo.outpoint).collect();
6619
-
6620
6651
let contributed_outputs = self.our_funding_outputs;
6621
-
6622
- NegotiationError { reason, contributed_inputs, contributed_outputs }
6652
+ (contributed_inputs, contributed_outputs)
6623
6653
}
6624
6654
}
6625
6655
@@ -6727,6 +6757,21 @@ pub struct SpliceFundingNegotiated {
6727
6757
pub channel_type: ChannelTypeFeatures,
6728
6758
}
6729
6759
6760
+ /// Information about a splice funding negotiation that has failed.
6761
+ pub struct SpliceFundingFailed {
6762
+ /// The outpoint of the channel's splice funding transaction, if one was created.
6763
+ pub funding_txo: Option<bitcoin::OutPoint>,
6764
+
6765
+ /// The features that this channel will operate with, if available.
6766
+ pub channel_type: Option<ChannelTypeFeatures>,
6767
+
6768
+ /// UTXOs spent as inputs contributed to the splice transaction.
6769
+ pub contributed_inputs: Vec<bitcoin::OutPoint>,
6770
+
6771
+ /// Outputs contributed to the splice transaction.
6772
+ pub contributed_outputs: Vec<bitcoin::TxOut>,
6773
+ }
6774
+
6730
6775
pub struct SpliceFundingPromotion {
6731
6776
pub funding_txo: OutPoint,
6732
6777
pub monitor_update: Option<ChannelMonitorUpdate>,
@@ -6806,19 +6851,58 @@ where
6806
6851
&& self.pending_funding().is_empty()
6807
6852
}
6808
6853
6809
- fn reset_pending_splice_state(&mut self) -> bool {
6854
+ fn reset_pending_splice_state(&mut self) -> Option<SpliceFundingFailed> {
6810
6855
debug_assert!(self.should_reset_pending_splice_funding_negotiation().unwrap_or(true));
6811
6856
self.context.channel_state.clear_quiescent();
6812
- self.context.interactive_tx_signing_session.take();
6813
- let has_funding_negotiation = self
6857
+
6858
+ let signing_session = self.context.interactive_tx_signing_session.take();
6859
+ let splice_funding_failed = self
6814
6860
.pending_splice
6815
6861
.as_mut()
6816
6862
.and_then(|pending_splice| pending_splice.funding_negotiation.take())
6817
- .is_some();
6863
+ .filter(|funding_negotiation| funding_negotiation.is_initiator())
6864
+ .map(|funding_negotiation| {
6865
+ let funding_txo = funding_negotiation
6866
+ .as_funding()
6867
+ .and_then(|funding| funding.get_funding_txo())
6868
+ .map(|txo| txo.into_bitcoin_outpoint());
6869
+
6870
+ let channel_type = funding_negotiation
6871
+ .as_funding()
6872
+ .map(|funding| funding.get_channel_type().clone());
6873
+
6874
+ let (contributed_inputs, contributed_outputs) = match funding_negotiation {
6875
+ FundingNegotiation::AwaitingAck { context } => {
6876
+ context.into_contributed_inputs_and_outputs()
6877
+ },
6878
+ FundingNegotiation::ConstructingTransaction {
6879
+ interactive_tx_constructor,
6880
+ ..
6881
+ } => interactive_tx_constructor.into_contributed_inputs_and_outputs(),
6882
+ FundingNegotiation::AwaitingSignatures { .. } => match signing_session {
6883
+ Some(signing_session) => {
6884
+ signing_session.into_contributed_inputs_and_outputs()
6885
+ },
6886
+ None => {
6887
+ debug_assert!(false);
6888
+ (Vec::new(), Vec::new())
6889
+ },
6890
+ },
6891
+ };
6892
+
6893
+ SpliceFundingFailed {
6894
+ funding_txo,
6895
+ channel_type,
6896
+ contributed_inputs,
6897
+ contributed_outputs,
6898
+ }
6899
+ });
6900
+
6818
6901
if self.should_reset_pending_splice_state() {
6819
6902
self.pending_splice.take();
6820
6903
}
6821
- has_funding_negotiation
6904
+
6905
+ splice_funding_failed
6822
6906
}
6823
6907
6824
6908
#[rustfmt::skip]
@@ -8658,7 +8742,7 @@ where
8658
8742
8659
8743
if let Some(pending_splice) = self.pending_splice.as_mut() {
8660
8744
self.context.channel_state.clear_quiescent();
8661
- if let Some(FundingNegotiation::AwaitingSignatures { mut funding }) =
8745
+ if let Some(FundingNegotiation::AwaitingSignatures { mut funding, .. }) =
8662
8746
pending_splice.funding_negotiation.take()
8663
8747
{
8664
8748
funding.funding_transaction = Some(funding_tx);
@@ -9585,7 +9669,7 @@ where
9585
9669
.as_ref()
9586
9670
.and_then(|pending_splice| pending_splice.funding_negotiation.as_ref())
9587
9671
.and_then(|funding_negotiation| {
9588
- if let FundingNegotiation::AwaitingSignatures { funding } = &funding_negotiation {
9672
+ if let FundingNegotiation::AwaitingSignatures { funding, .. } = &funding_negotiation {
9589
9673
Some(funding)
9590
9674
} else {
9591
9675
None
0 commit comments