@@ -60,7 +60,8 @@ use crate::ln::funding::{FundingTxInput, SpliceContribution};
60
60
use crate::ln::interactivetxs::{
61
61
calculate_change_output_value, get_output_weight, AbortReason, HandleTxCompleteValue,
62
62
InteractiveTxConstructor, InteractiveTxConstructorArgs, InteractiveTxMessageSend,
63
- InteractiveTxSigningSession, SharedOwnedInput, SharedOwnedOutput, TX_COMMON_FIELDS_WEIGHT,
63
+ InteractiveTxSigningSession, NegotiationError, SharedOwnedInput, SharedOwnedOutput,
64
+ TX_COMMON_FIELDS_WEIGHT,
64
65
};
65
66
use crate::ln::msgs;
66
67
use crate::ln::msgs::{ClosingSigned, ClosingSignedFeeRange, DecodeError, OnionErrorPacket};
@@ -1787,20 +1788,22 @@ where
1787
1788
1788
1789
let (interactive_tx_msg_send, negotiation_complete) = match tx_complete_action {
1789
1790
HandleTxCompleteValue::SendTxMessage(interactive_tx_msg_send) => {
1790
- (Some(interactive_tx_msg_send), false )
1791
+ (Some(interactive_tx_msg_send), None )
1791
1792
},
1792
- HandleTxCompleteValue::SendTxComplete (
1793
+ HandleTxCompleteValue::NegotiationComplete (
1793
1794
interactive_tx_msg_send,
1794
- negotiation_complete,
1795
- ) => (Some(interactive_tx_msg_send), negotiation_complete),
1796
- HandleTxCompleteValue::NegotiationComplete => (None, true),
1795
+ funding_outpoint,
1796
+ ) => (interactive_tx_msg_send, Some(funding_outpoint)),
1797
1797
};
1798
- if !negotiation_complete {
1798
+
1799
+ let funding_outpoint = if let Some(funding_outpoint) = negotiation_complete {
1800
+ funding_outpoint
1801
+ } else {
1799
1802
return Ok((interactive_tx_msg_send, None));
1800
- }
1803
+ };
1801
1804
1802
1805
let commitment_signed = self
1803
- .funding_tx_constructed(logger)
1806
+ .funding_tx_constructed(funding_outpoint, logger)
1804
1807
.map_err(|abort_reason| self.fail_interactive_tx_negotiation(abort_reason, logger))?;
1805
1808
Ok((interactive_tx_msg_send, Some(commitment_signed)))
1806
1809
}
@@ -1891,13 +1894,13 @@ where
1891
1894
}
1892
1895
1893
1896
fn funding_tx_constructed<L: Deref>(
1894
- &mut self, logger: &L,
1897
+ &mut self, funding_outpoint: OutPoint, logger: &L,
1895
1898
) -> Result<msgs::CommitmentSigned, AbortReason>
1896
1899
where
1897
1900
L::Target: Logger,
1898
1901
{
1899
1902
let logger = WithChannelContext::from(logger, self.context(), None);
1900
- match &mut self.phase {
1903
+ let (interactive_tx_constructor, commitment_signed) = match &mut self.phase {
1901
1904
ChannelPhase::UnfundedV2(chan) => {
1902
1905
debug_assert_eq!(
1903
1906
chan.context.channel_state,
@@ -1907,60 +1910,85 @@ where
1907
1910
),
1908
1911
);
1909
1912
1910
- let signing_session = chan
1913
+ let interactive_tx_constructor = chan
1911
1914
.interactive_tx_constructor
1912
1915
.take()
1913
- .expect("PendingV2Channel::interactive_tx_constructor should be set")
1914
- .into_signing_session();
1916
+ .expect("PendingV2Channel::interactive_tx_constructor should be set");
1915
1917
let commitment_signed = chan.context.funding_tx_constructed(
1916
1918
&mut chan.funding,
1917
- signing_session ,
1919
+ funding_outpoint ,
1918
1920
false,
1919
1921
chan.unfunded_context.transaction_number(),
1920
1922
&&logger,
1921
1923
)?;
1922
1924
1923
- return Ok( commitment_signed);
1925
+ (interactive_tx_constructor, commitment_signed)
1924
1926
},
1925
1927
ChannelPhase::Funded(chan) => {
1926
1928
if let Some(pending_splice) = chan.pending_splice.as_mut() {
1927
- if let Some(funding_negotiation) = pending_splice.funding_negotiation.take() {
1928
- if let FundingNegotiation::ConstructingTransaction {
1929
- mut funding,
1930
- interactive_tx_constructor,
1931
- } = funding_negotiation
1932
- {
1933
- let signing_session = interactive_tx_constructor.into_signing_session();
1934
- let commitment_signed = chan.context.funding_tx_constructed(
1929
+ pending_splice
1930
+ .funding_negotiation
1931
+ .take()
1932
+ .and_then(|funding_negotiation| {
1933
+ if let FundingNegotiation::ConstructingTransaction {
1934
+ funding,
1935
+ interactive_tx_constructor,
1936
+ } = funding_negotiation
1937
+ {
1938
+ Some((funding, interactive_tx_constructor))
1939
+ } else {
1940
+ // Replace the taken state for later error handling
1941
+ pending_splice.funding_negotiation = Some(funding_negotiation);
1942
+ None
1943
+ }
1944
+ })
1945
+ .ok_or_else(|| {
1946
+ AbortReason::InternalError(
1947
+ "Got a tx_complete message in an invalid state",
1948
+ )
1949
+ })
1950
+ .and_then(|(mut funding, interactive_tx_constructor)| {
1951
+ match chan.context.funding_tx_constructed(
1935
1952
&mut funding,
1936
- signing_session ,
1953
+ funding_outpoint ,
1937
1954
true,
1938
1955
chan.holder_commitment_point.next_transaction_number(),
1939
1956
&&logger,
1940
- )?;
1941
-
1942
- pending_splice.funding_negotiation =
1943
- Some(FundingNegotiation::AwaitingSignatures { funding });
1944
-
1945
- return Ok(commitment_signed);
1946
- } else {
1947
- // Replace the taken state
1948
- pending_splice.funding_negotiation = Some(funding_negotiation);
1949
- }
1950
- }
1957
+ ) {
1958
+ Ok(commitment_signed) => {
1959
+ // Advance the state
1960
+ pending_splice.funding_negotiation =
1961
+ Some(FundingNegotiation::AwaitingSignatures { funding });
1962
+ Ok((interactive_tx_constructor, commitment_signed))
1963
+ },
1964
+ Err(e) => {
1965
+ // Restore the taken state for later error handling
1966
+ pending_splice.funding_negotiation =
1967
+ Some(FundingNegotiation::ConstructingTransaction {
1968
+ funding,
1969
+ interactive_tx_constructor,
1970
+ });
1971
+ Err(e)
1972
+ },
1973
+ }
1974
+ })?
1975
+ } else {
1976
+ return Err(AbortReason::InternalError(
1977
+ "Got a tx_complete message in an invalid state",
1978
+ ));
1951
1979
}
1952
-
1953
- return Err(AbortReason::InternalError(
1954
- "Got a tx_complete message in an invalid state",
1955
- ));
1956
1980
},
1957
1981
_ => {
1958
1982
debug_assert!(false);
1959
1983
return Err(AbortReason::InternalError(
1960
1984
"Got a tx_complete message in an invalid phase",
1961
1985
));
1962
1986
},
1963
- }
1987
+ };
1988
+
1989
+ let signing_session = interactive_tx_constructor.into_signing_session();
1990
+ self.context_mut().interactive_tx_signing_session = Some(signing_session);
1991
+ Ok(commitment_signed)
1964
1992
}
1965
1993
1966
1994
pub fn force_shutdown(&mut self, closure_reason: ClosureReason) -> ShutdownResult {
@@ -6061,30 +6089,13 @@ where
6061
6089
6062
6090
#[rustfmt::skip]
6063
6091
fn funding_tx_constructed<L: Deref>(
6064
- &mut self, funding: &mut FundingScope, signing_session: InteractiveTxSigningSession ,
6065
- is_splice: bool, holder_commitment_transaction_number: u64, logger: &L
6092
+ &mut self, funding: &mut FundingScope, funding_outpoint: OutPoint, is_splice: bool ,
6093
+ holder_commitment_transaction_number: u64, logger: &L,
6066
6094
) -> Result<msgs::CommitmentSigned, AbortReason>
6067
6095
where
6068
6096
L::Target: Logger
6069
6097
{
6070
- let mut output_index = None;
6071
- let expected_spk = funding.get_funding_redeemscript().to_p2wsh();
6072
- for (idx, outp) in signing_session.unsigned_tx().tx().output.iter().enumerate() {
6073
- if outp.script_pubkey == expected_spk && outp.value.to_sat() == funding.get_value_satoshis() {
6074
- if output_index.is_some() {
6075
- return Err(AbortReason::DuplicateFundingOutput);
6076
- }
6077
- output_index = Some(idx as u16);
6078
- }
6079
- }
6080
- let outpoint = if let Some(output_index) = output_index {
6081
- OutPoint { txid: signing_session.unsigned_tx().compute_txid(), index: output_index }
6082
- } else {
6083
- return Err(AbortReason::MissingFundingOutput);
6084
- };
6085
- funding
6086
- .channel_transaction_parameters.funding_outpoint = Some(outpoint);
6087
- self.interactive_tx_signing_session = Some(signing_session);
6098
+ funding.channel_transaction_parameters.funding_outpoint = Some(funding_outpoint);
6088
6099
6089
6100
if is_splice {
6090
6101
debug_assert_eq!(
@@ -6101,7 +6112,6 @@ where
6101
6112
Some(commitment_signed) => commitment_signed,
6102
6113
// TODO(splicing): Support async signing
6103
6114
None => {
6104
- funding.channel_transaction_parameters.funding_outpoint = None;
6105
6115
return Err(AbortReason::InternalError("Failed to compute commitment_signed signatures"));
6106
6116
},
6107
6117
};
@@ -6177,8 +6187,6 @@ where
6177
6187
SP::Target: SignerProvider,
6178
6188
L::Target: Logger,
6179
6189
{
6180
- debug_assert!(self.interactive_tx_signing_session.is_some());
6181
-
6182
6190
let signatures = self.get_initial_counterparty_commitment_signatures(funding, logger);
6183
6191
if let Some((signature, htlc_signatures)) = signatures {
6184
6192
log_info!(
@@ -6518,9 +6526,9 @@ impl FundingNegotiationContext {
6518
6526
/// Prepare and start interactive transaction negotiation.
6519
6527
/// If error occurs, it is caused by our side, not the counterparty.
6520
6528
fn into_interactive_tx_constructor<SP: Deref, ES: Deref>(
6521
- self, context: &ChannelContext<SP>, funding: &FundingScope, signer_provider: &SP,
6529
+ mut self, context: &ChannelContext<SP>, funding: &FundingScope, signer_provider: &SP,
6522
6530
entropy_source: &ES, holder_node_id: PublicKey,
6523
- ) -> Result<InteractiveTxConstructor, AbortReason >
6531
+ ) -> Result<InteractiveTxConstructor, NegotiationError >
6524
6532
where
6525
6533
SP::Target: SignerProvider,
6526
6534
ES::Target: EntropySource,
@@ -6546,25 +6554,32 @@ impl FundingNegotiationContext {
6546
6554
6547
6555
// Optionally add change output
6548
6556
let change_value_opt = if self.our_funding_contribution > SignedAmount::ZERO {
6549
- calculate_change_output_value(
6557
+ match calculate_change_output_value(
6550
6558
&self,
6551
6559
self.shared_funding_input.is_some(),
6552
6560
&shared_funding_output.script_pubkey,
6553
6561
context.holder_dust_limit_satoshis,
6554
- )?
6562
+ ) {
6563
+ Ok(change_value_opt) => change_value_opt,
6564
+ Err(reason) => {
6565
+ return Err(self.into_negotiation_error(reason));
6566
+ },
6567
+ }
6555
6568
} else {
6556
6569
None
6557
6570
};
6558
6571
6559
- let mut funding_outputs = self.our_funding_outputs;
6560
-
6561
6572
if let Some(change_value) = change_value_opt {
6562
6573
let change_script = if let Some(script) = self.change_script {
6563
6574
script
6564
6575
} else {
6565
- signer_provider
6566
- .get_destination_script(context.channel_keys_id)
6567
- .map_err(|_err| AbortReason::InternalError("Error getting change script"))?
6576
+ match signer_provider.get_destination_script(context.channel_keys_id) {
6577
+ Ok(script) => script,
6578
+ Err(_) => {
6579
+ let reason = AbortReason::InternalError("Error getting change script");
6580
+ return Err(self.into_negotiation_error(reason));
6581
+ },
6582
+ }
6568
6583
};
6569
6584
let mut change_output =
6570
6585
TxOut { value: Amount::from_sat(change_value), script_pubkey: change_script };
@@ -6575,7 +6590,7 @@ impl FundingNegotiationContext {
6575
6590
// Check dust limit again
6576
6591
if change_value_decreased_with_fee > context.holder_dust_limit_satoshis {
6577
6592
change_output.value = Amount::from_sat(change_value_decreased_with_fee);
6578
- funding_outputs .push(change_output);
6593
+ self.our_funding_outputs .push(change_output);
6579
6594
}
6580
6595
}
6581
6596
@@ -6593,10 +6608,19 @@ impl FundingNegotiationContext {
6593
6608
shared_funding_output,
6594
6609
funding.value_to_self_msat / 1000,
6595
6610
),
6596
- outputs_to_contribute: funding_outputs ,
6611
+ outputs_to_contribute: self.our_funding_outputs ,
6597
6612
};
6598
6613
InteractiveTxConstructor::new(constructor_args)
6599
6614
}
6615
+
6616
+ fn into_negotiation_error(self, reason: AbortReason) -> NegotiationError {
6617
+ let contributed_inputs =
6618
+ self.our_funding_inputs.into_iter().map(|input| input.utxo.outpoint).collect();
6619
+
6620
+ let contributed_outputs = self.our_funding_outputs;
6621
+
6622
+ NegotiationError { reason, contributed_inputs, contributed_outputs }
6623
+ }
6600
6624
}
6601
6625
6602
6626
// Holder designates channel data owned for the benefit of the user client.
@@ -13737,8 +13761,8 @@ where
13737
13761
outputs_to_contribute: funding_negotiation_context.our_funding_outputs.clone(),
13738
13762
}
13739
13763
).map_err(|err| {
13740
- let reason = ClosureReason::ProcessingError { err: err.to_string() };
13741
- ChannelError::Close((err.to_string(), reason))
13764
+ let reason = ClosureReason::ProcessingError { err: err.reason. to_string() };
13765
+ ChannelError::Close((err.reason. to_string(), reason))
13742
13766
})?);
13743
13767
13744
13768
let unfunded_context = UnfundedChannelContext {
0 commit comments