@@ -56,9 +56,9 @@ use crate::ln::channelmanager::{
5656 BREAKDOWN_TIMEOUT, MAX_LOCAL_BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA,
5757};
5858use crate::ln::interactivetxs::{
59- calculate_change_output_value, get_output_weight, AbortReason, HandleTxCompleteResult ,
60- InteractiveTxConstructor, InteractiveTxConstructorArgs, InteractiveTxMessageSendResult ,
61- InteractiveTxSigningSession, SharedOwnedInput, SharedOwnedOutput, TX_COMMON_FIELDS_WEIGHT,
59+ calculate_change_output_value, get_output_weight, AbortReason, InteractiveTxConstructor ,
60+ InteractiveTxConstructorArgs, InteractiveTxSigningSession, SharedOwnedInput, SharedOwnedOutput ,
61+ TX_COMMON_FIELDS_WEIGHT,
6262};
6363use crate::ln::msgs;
6464use crate::ln::msgs::{ClosingSigned, ClosingSignedFeeRange, DecodeError, OnionErrorPacket};
@@ -1731,6 +1731,15 @@ where
17311731 }
17321732 }
17331733
1734+ pub fn interactive_tx_constructor_mut(&mut self) -> Option<&mut InteractiveTxConstructor> {
1735+ match &mut self.phase {
1736+ ChannelPhase::UnfundedV2(chan) => chan.interactive_tx_constructor.as_mut(),
1737+ #[cfg(splicing)]
1738+ ChannelPhase::Funded(chan) => chan.interactive_tx_constructor_mut(),
1739+ _ => None,
1740+ }
1741+ }
1742+
17341743 #[rustfmt::skip]
17351744 pub fn funding_signed<L: Deref>(
17361745 &mut self, msg: &msgs::FundingSigned, best_block: BestBlock, signer_provider: &SP, logger: &L
@@ -1764,16 +1773,70 @@ where
17641773 }
17651774
17661775 pub fn funding_tx_constructed<L: Deref>(
1767- &mut self, signing_session: InteractiveTxSigningSession, logger: &L,
1776+ &mut self, logger: &L,
17681777 ) -> Result<(msgs::CommitmentSigned, Option<Event>), ChannelError>
17691778 where
17701779 L::Target: Logger,
17711780 {
1772- if let ChannelPhase::UnfundedV2(chan) = &mut self.phase {
1773- let logger = WithChannelContext::from(logger, &chan.context, None);
1774- chan.funding_tx_constructed(signing_session, &&logger)
1775- } else {
1776- Err(ChannelError::Warn("Got a tx_complete message with no interactive transaction construction expected or in-progress".to_owned()))
1781+ let logger = WithChannelContext::from(logger, self.context(), None);
1782+ match &mut self.phase {
1783+ ChannelPhase::UnfundedV2(chan) => {
1784+ let mut signing_session =
1785+ chan.interactive_tx_constructor.take().expect("TODO").into_signing_session();
1786+ let result = chan.context.funding_tx_constructed(
1787+ &mut chan.funding,
1788+ &mut signing_session,
1789+ false,
1790+ chan.unfunded_context.transaction_number(),
1791+ &&logger,
1792+ );
1793+
1794+ // FIXME: Should this remain None if result is an Err?
1795+ chan.interactive_tx_signing_session = Some(signing_session);
1796+
1797+ return result;
1798+ },
1799+ #[cfg(splicing)]
1800+ ChannelPhase::Funded(chan) => {
1801+ if let Some(pending_splice) = chan.pending_splice.as_mut() {
1802+ if let Some(funding_negotiation) = pending_splice.funding_negotiation.take() {
1803+ if let FundingNegotiation::Pending(
1804+ mut funding,
1805+ interactive_tx_constructor,
1806+ ) = funding_negotiation
1807+ {
1808+ let mut signing_session =
1809+ interactive_tx_constructor.into_signing_session();
1810+ let result = chan.context.funding_tx_constructed(
1811+ &mut funding,
1812+ &mut signing_session,
1813+ true,
1814+ chan.holder_commitment_point.transaction_number(),
1815+ &&logger,
1816+ );
1817+
1818+ // FIXME: Should these remain None if result is an Err?
1819+ chan.interactive_tx_signing_session = Some(signing_session);
1820+ pending_splice.funding_negotiation =
1821+ Some(FundingNegotiation::AwaitingSignatures(funding));
1822+
1823+ return result;
1824+ } else {
1825+ // Replace the taken state
1826+ pending_splice.funding_negotiation = Some(funding_negotiation);
1827+ }
1828+ }
1829+ }
1830+
1831+ return Err(ChannelError::Warn(
1832+ "Got a transaction negotiation message in an invalid state".to_owned(),
1833+ ));
1834+ },
1835+ _ => {
1836+ return Err(ChannelError::Warn(
1837+ "Got a transaction negotiation message in an invalid phase".to_owned(),
1838+ ))
1839+ },
17771840 }
17781841 }
17791842
@@ -2772,171 +2835,6 @@ where
27722835 }
27732836}
27742837
2775- impl<SP: Deref> PendingV2Channel<SP>
2776- where
2777- SP::Target: SignerProvider,
2778- {
2779- pub fn tx_add_input(&mut self, msg: &msgs::TxAddInput) -> InteractiveTxMessageSendResult {
2780- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2781- Some(ref mut tx_constructor) => tx_constructor
2782- .handle_tx_add_input(msg)
2783- .map_err(|reason| reason.into_tx_abort_msg(self.context.channel_id())),
2784- None => Err(msgs::TxAbort {
2785- channel_id: self.context.channel_id(),
2786- data: b"No interactive transaction negotiation in progress".to_vec(),
2787- }),
2788- })
2789- }
2790-
2791- pub fn tx_add_output(&mut self, msg: &msgs::TxAddOutput) -> InteractiveTxMessageSendResult {
2792- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2793- Some(ref mut tx_constructor) => tx_constructor
2794- .handle_tx_add_output(msg)
2795- .map_err(|reason| reason.into_tx_abort_msg(self.context.channel_id())),
2796- None => Err(msgs::TxAbort {
2797- channel_id: self.context.channel_id(),
2798- data: b"No interactive transaction negotiation in progress".to_vec(),
2799- }),
2800- })
2801- }
2802-
2803- pub fn tx_remove_input(&mut self, msg: &msgs::TxRemoveInput) -> InteractiveTxMessageSendResult {
2804- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2805- Some(ref mut tx_constructor) => tx_constructor
2806- .handle_tx_remove_input(msg)
2807- .map_err(|reason| reason.into_tx_abort_msg(self.context.channel_id())),
2808- None => Err(msgs::TxAbort {
2809- channel_id: self.context.channel_id(),
2810- data: b"No interactive transaction negotiation in progress".to_vec(),
2811- }),
2812- })
2813- }
2814-
2815- pub fn tx_remove_output(
2816- &mut self, msg: &msgs::TxRemoveOutput,
2817- ) -> InteractiveTxMessageSendResult {
2818- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2819- Some(ref mut tx_constructor) => tx_constructor
2820- .handle_tx_remove_output(msg)
2821- .map_err(|reason| reason.into_tx_abort_msg(self.context.channel_id())),
2822- None => Err(msgs::TxAbort {
2823- channel_id: self.context.channel_id(),
2824- data: b"No interactive transaction negotiation in progress".to_vec(),
2825- }),
2826- })
2827- }
2828-
2829- pub fn tx_complete(&mut self, msg: &msgs::TxComplete) -> HandleTxCompleteResult {
2830- let tx_constructor = match &mut self.interactive_tx_constructor {
2831- Some(ref mut tx_constructor) => tx_constructor,
2832- None => {
2833- let tx_abort = msgs::TxAbort {
2834- channel_id: msg.channel_id,
2835- data: b"No interactive transaction negotiation in progress".to_vec(),
2836- };
2837- return HandleTxCompleteResult(Err(tx_abort));
2838- },
2839- };
2840-
2841- let tx_complete = match tx_constructor.handle_tx_complete(msg) {
2842- Ok(tx_complete) => tx_complete,
2843- Err(reason) => {
2844- return HandleTxCompleteResult(Err(reason.into_tx_abort_msg(msg.channel_id)))
2845- },
2846- };
2847-
2848- HandleTxCompleteResult(Ok(tx_complete))
2849- }
2850-
2851- #[rustfmt::skip]
2852- pub fn funding_tx_constructed<L: Deref>(
2853- &mut self, mut signing_session: InteractiveTxSigningSession, logger: &L
2854- ) -> Result<(msgs::CommitmentSigned, Option<Event>), ChannelError>
2855- where
2856- L::Target: Logger
2857- {
2858- let our_funding_satoshis = self.funding_negotiation_context.our_funding_contribution_satoshis;
2859- let transaction_number = self.unfunded_context.transaction_number();
2860-
2861- let mut output_index = None;
2862- let expected_spk = self.funding.get_funding_redeemscript().to_p2wsh();
2863- for (idx, outp) in signing_session.unsigned_tx().outputs().enumerate() {
2864- if outp.script_pubkey() == &expected_spk && outp.value() == self.funding.get_value_satoshis() {
2865- if output_index.is_some() {
2866- let msg = "Multiple outputs matched the expected script and value";
2867- let reason = ClosureReason::ProcessingError { err: msg.to_owned() };
2868- return Err(ChannelError::Close((msg.to_owned(), reason)));
2869- }
2870- output_index = Some(idx as u16);
2871- }
2872- }
2873- let outpoint = if let Some(output_index) = output_index {
2874- OutPoint { txid: signing_session.unsigned_tx().compute_txid(), index: output_index }
2875- } else {
2876- let msg = "No output matched the funding script_pubkey";
2877- let reason = ClosureReason::ProcessingError { err: msg.to_owned() };
2878- return Err(ChannelError::Close((msg.to_owned(), reason)));
2879- };
2880- self.funding.channel_transaction_parameters.funding_outpoint = Some(outpoint);
2881-
2882- self.context.assert_no_commitment_advancement(transaction_number, "initial commitment_signed");
2883- let commitment_signed = self.context.get_initial_commitment_signed(&self.funding, logger);
2884- let commitment_signed = match commitment_signed {
2885- Ok(commitment_signed) => commitment_signed,
2886- Err(e) => {
2887- self.funding.channel_transaction_parameters.funding_outpoint = None;
2888- return Err(e)
2889- },
2890- };
2891-
2892- let funding_ready_for_sig_event = if signing_session.local_inputs_count() == 0 {
2893- debug_assert_eq!(our_funding_satoshis, 0);
2894- if signing_session.provide_holder_witnesses(self.context.channel_id, Vec::new()).is_err() {
2895- debug_assert!(
2896- false,
2897- "Zero inputs were provided & zero witnesses were provided, but a count mismatch was somehow found",
2898- );
2899- let msg = "V2 channel rejected due to sender error";
2900- let reason = ClosureReason::ProcessingError { err: msg.to_owned() };
2901- return Err(ChannelError::Close((msg.to_owned(), reason)));
2902- }
2903- None
2904- } else {
2905- // TODO(dual_funding): Send event for signing if we've contributed funds.
2906- // Inform the user that SIGHASH_ALL must be used for all signatures when contributing
2907- // inputs/signatures.
2908- // Also warn the user that we don't do anything to prevent the counterparty from
2909- // providing non-standard witnesses which will prevent the funding transaction from
2910- // confirming. This warning must appear in doc comments wherever the user is contributing
2911- // funds, whether they are initiator or acceptor.
2912- //
2913- // The following warning can be used when the APIs allowing contributing inputs become available:
2914- // <div class="warning">
2915- // WARNING: LDK makes no attempt to prevent the counterparty from using non-standard inputs which
2916- // will prevent the funding transaction from being relayed on the bitcoin network and hence being
2917- // confirmed.
2918- // </div>
2919- debug_assert!(
2920- false,
2921- "We don't support users providing inputs but somehow we had more than zero inputs",
2922- );
2923- let msg = "V2 channel rejected due to sender error";
2924- let reason = ClosureReason::ProcessingError { err: msg.to_owned() };
2925- return Err(ChannelError::Close((msg.to_owned(), reason)));
2926- };
2927-
2928- let mut channel_state = ChannelState::FundingNegotiated(FundingNegotiatedFlags::new());
2929- channel_state.set_interactive_signing();
2930- self.context.channel_state = channel_state;
2931-
2932- // Clear the interactive transaction constructor
2933- self.interactive_tx_constructor.take();
2934- self.interactive_tx_signing_session = Some(signing_session);
2935-
2936- Ok((commitment_signed, funding_ready_for_sig_event))
2937- }
2938- }
2939-
29402838impl<SP: Deref> ChannelContext<SP>
29412839where
29422840 SP::Target: SignerProvider,
@@ -5403,6 +5301,97 @@ where
54035301 Ok(())
54045302 }
54055303
5304+ #[rustfmt::skip]
5305+ fn funding_tx_constructed<L: Deref>(
5306+ &mut self, funding: &mut FundingScope, signing_session: &mut InteractiveTxSigningSession,
5307+ is_splice: bool, holder_commitment_transaction_number: u64, logger: &L
5308+ ) -> Result<(msgs::CommitmentSigned, Option<Event>), ChannelError>
5309+ where
5310+ L::Target: Logger
5311+ {
5312+ let mut output_index = None;
5313+ let expected_spk = funding.get_funding_redeemscript().to_p2wsh();
5314+ for (idx, outp) in signing_session.unsigned_tx().outputs().enumerate() {
5315+ if outp.script_pubkey() == &expected_spk && outp.value() == funding.get_value_satoshis() {
5316+ if output_index.is_some() {
5317+ let msg = "Multiple outputs matched the expected script and value";
5318+ let reason = ClosureReason::ProcessingError { err: msg.to_owned() };
5319+ return Err(ChannelError::Close((msg.to_owned(), reason)));
5320+ }
5321+ output_index = Some(idx as u16);
5322+ }
5323+ }
5324+ let outpoint = if let Some(output_index) = output_index {
5325+ OutPoint { txid: signing_session.unsigned_tx().compute_txid(), index: output_index }
5326+ } else {
5327+ let msg = "No output matched the funding script_pubkey";
5328+ let reason = ClosureReason::ProcessingError { err: msg.to_owned() };
5329+ return Err(ChannelError::Close((msg.to_owned(), reason)));
5330+ };
5331+ funding
5332+ .channel_transaction_parameters.funding_outpoint = Some(outpoint);
5333+
5334+ if is_splice {
5335+ let message = "TODO Forced error, incomplete implementation".to_owned();
5336+ // TODO(splicing) Forced error, as the use case is not complete
5337+ return Err(ChannelError::Close((
5338+ message.clone(),
5339+ ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false), message }
5340+ )));
5341+ }
5342+
5343+ self.assert_no_commitment_advancement(holder_commitment_transaction_number, "initial commitment_signed");
5344+ let commitment_signed = self.get_initial_commitment_signed(&funding, logger);
5345+ let commitment_signed = match commitment_signed {
5346+ Ok(commitment_signed) => commitment_signed,
5347+ Err(e) => {
5348+ funding.channel_transaction_parameters.funding_outpoint = None;
5349+ return Err(e)
5350+ },
5351+ };
5352+
5353+ let funding_ready_for_sig_event = if signing_session.local_inputs_count() == 0 {
5354+ if signing_session.provide_holder_witnesses(self.channel_id, Vec::new()).is_err() {
5355+ debug_assert!(
5356+ false,
5357+ "Zero inputs were provided & zero witnesses were provided, but a count mismatch was somehow found",
5358+ );
5359+ let msg = "V2 channel rejected due to sender error";
5360+ let reason = ClosureReason::ProcessingError { err: msg.to_owned() };
5361+ return Err(ChannelError::Close((msg.to_owned(), reason)));
5362+ }
5363+ None
5364+ } else {
5365+ // TODO(dual_funding): Send event for signing if we've contributed funds.
5366+ // Inform the user that SIGHASH_ALL must be used for all signatures when contributing
5367+ // inputs/signatures.
5368+ // Also warn the user that we don't do anything to prevent the counterparty from
5369+ // providing non-standard witnesses which will prevent the funding transaction from
5370+ // confirming. This warning must appear in doc comments wherever the user is contributing
5371+ // funds, whether they are initiator or acceptor.
5372+ //
5373+ // The following warning can be used when the APIs allowing contributing inputs become available:
5374+ // <div class="warning">
5375+ // WARNING: LDK makes no attempt to prevent the counterparty from using non-standard inputs which
5376+ // will prevent the funding transaction from being relayed on the bitcoin network and hence being
5377+ // confirmed.
5378+ // </div>
5379+ debug_assert!(
5380+ false,
5381+ "We don't support users providing inputs but somehow we had more than zero inputs",
5382+ );
5383+ let msg = "V2 channel rejected due to sender error";
5384+ let reason = ClosureReason::ProcessingError { err: msg.to_owned() };
5385+ return Err(ChannelError::Close((msg.to_owned(), reason)));
5386+ };
5387+
5388+ let mut channel_state = ChannelState::FundingNegotiated(FundingNegotiatedFlags::new());
5389+ channel_state.set_interactive_signing();
5390+ self.channel_state = channel_state;
5391+
5392+ Ok((commitment_signed, funding_ready_for_sig_event))
5393+ }
5394+
54065395 /// Asserts that the commitment tx numbers have not advanced from their initial number.
54075396 #[rustfmt::skip]
54085397 fn assert_no_commitment_advancement(&self, holder_commitment_transaction_number: u64, msg_name: &str) {
@@ -6003,6 +5992,22 @@ where
60035992 self.context.force_shutdown(&self.funding, closure_reason)
60045993 }
60055994
5995+ #[cfg(splicing)]
5996+ fn interactive_tx_constructor_mut(&mut self) -> Option<&mut InteractiveTxConstructor> {
5997+ self.pending_splice
5998+ .as_mut()
5999+ .and_then(|pending_splice| pending_splice.funding_negotiation.as_mut())
6000+ .and_then(|funding_negotiation| {
6001+ if let FundingNegotiation::Pending(_, interactive_tx_constructor) =
6002+ funding_negotiation
6003+ {
6004+ Some(interactive_tx_constructor)
6005+ } else {
6006+ None
6007+ }
6008+ })
6009+ }
6010+
60066011 #[rustfmt::skip]
60076012 fn check_remote_fee<F: Deref, L: Deref>(
60086013 channel_type: &ChannelTypeFeatures, fee_estimator: &LowerBoundedFeeEstimator<F>,
0 commit comments