@@ -58,9 +58,8 @@ use crate::ln::channelmanager::{
5858#[cfg(splicing)]
5959use crate::ln::interactivetxs::{calculate_change_output_value, AbortReason};
6060use crate::ln::interactivetxs::{
61- get_output_weight, HandleTxCompleteResult, InteractiveTxConstructor,
62- InteractiveTxConstructorArgs, InteractiveTxMessageSendResult, InteractiveTxSigningSession,
63- SharedOwnedInput, SharedOwnedOutput, TX_COMMON_FIELDS_WEIGHT,
61+ get_output_weight, InteractiveTxConstructor, InteractiveTxConstructorArgs,
62+ InteractiveTxSigningSession, SharedOwnedInput, SharedOwnedOutput, TX_COMMON_FIELDS_WEIGHT,
6463};
6564use crate::ln::msgs;
6665use crate::ln::msgs::{ClosingSigned, ClosingSignedFeeRange, DecodeError, OnionErrorPacket};
@@ -1728,6 +1727,15 @@ where
17281727 }
17291728 }
17301729
1730+ pub fn interactive_tx_constructor_mut(&mut self) -> Option<&mut InteractiveTxConstructor> {
1731+ match &mut self.phase {
1732+ ChannelPhase::UnfundedV2(chan) => chan.interactive_tx_constructor.as_mut(),
1733+ #[cfg(splicing)]
1734+ ChannelPhase::Funded(chan) => chan.interactive_tx_constructor_mut(),
1735+ _ => None,
1736+ }
1737+ }
1738+
17311739 #[rustfmt::skip]
17321740 pub fn funding_signed<L: Deref>(
17331741 &mut self, msg: &msgs::FundingSigned, best_block: BestBlock, signer_provider: &SP, logger: &L
@@ -1761,16 +1769,70 @@ where
17611769 }
17621770
17631771 pub fn funding_tx_constructed<L: Deref>(
1764- &mut self, signing_session: InteractiveTxSigningSession, logger: &L,
1772+ &mut self, logger: &L,
17651773 ) -> Result<(msgs::CommitmentSigned, Option<Event>), ChannelError>
17661774 where
17671775 L::Target: Logger,
17681776 {
1769- if let ChannelPhase::UnfundedV2(chan) = &mut self.phase {
1770- let logger = WithChannelContext::from(logger, &chan.context, None);
1771- chan.funding_tx_constructed(signing_session, &&logger)
1772- } else {
1773- Err(ChannelError::Warn("Got a tx_complete message with no interactive transaction construction expected or in-progress".to_owned()))
1777+ let logger = WithChannelContext::from(logger, self.context(), None);
1778+ match &mut self.phase {
1779+ ChannelPhase::UnfundedV2(chan) => {
1780+ let mut signing_session =
1781+ chan.interactive_tx_constructor.take().expect("TODO").into_signing_session();
1782+ let result = chan.context.funding_tx_constructed(
1783+ &mut chan.funding,
1784+ &mut signing_session,
1785+ false,
1786+ chan.unfunded_context.transaction_number(),
1787+ &&logger,
1788+ );
1789+
1790+ // FIXME: Should this remain None if result is an Err?
1791+ chan.interactive_tx_signing_session = Some(signing_session);
1792+
1793+ return result;
1794+ },
1795+ #[cfg(splicing)]
1796+ ChannelPhase::Funded(chan) => {
1797+ if let Some(pending_splice) = chan.pending_splice.as_mut() {
1798+ if let Some(funding_negotiation) = pending_splice.funding_negotiation.take() {
1799+ if let FundingNegotiation::Pending(
1800+ mut funding,
1801+ interactive_tx_constructor,
1802+ ) = funding_negotiation
1803+ {
1804+ let mut signing_session =
1805+ interactive_tx_constructor.into_signing_session();
1806+ let result = chan.context.funding_tx_constructed(
1807+ &mut funding,
1808+ &mut signing_session,
1809+ true,
1810+ chan.holder_commitment_point.transaction_number(),
1811+ &&logger,
1812+ );
1813+
1814+ // FIXME: Should these remain None if result is an Err?
1815+ chan.interactive_tx_signing_session = Some(signing_session);
1816+ pending_splice.funding_negotiation =
1817+ Some(FundingNegotiation::AwaitingSignatures(funding));
1818+
1819+ return result;
1820+ } else {
1821+ // Replace the taken state
1822+ pending_splice.funding_negotiation = Some(funding_negotiation);
1823+ }
1824+ }
1825+ }
1826+
1827+ return Err(ChannelError::Warn(
1828+ "Got a transaction negotiation message in an invalid state".to_owned(),
1829+ ));
1830+ },
1831+ _ => {
1832+ return Err(ChannelError::Warn(
1833+ "Got a transaction negotiation message in an invalid phase".to_owned(),
1834+ ))
1835+ },
17741836 }
17751837 }
17761838
@@ -2771,170 +2833,6 @@ where
27712833 }
27722834}
27732835
2774- impl<SP: Deref> PendingV2Channel<SP>
2775- where
2776- SP::Target: SignerProvider,
2777- {
2778- pub fn tx_add_input(&mut self, msg: &msgs::TxAddInput) -> InteractiveTxMessageSendResult {
2779- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2780- Some(ref mut tx_constructor) => tx_constructor
2781- .handle_tx_add_input(msg)
2782- .map_err(|reason| reason.into_tx_abort_msg(self.context.channel_id())),
2783- None => Err(msgs::TxAbort {
2784- channel_id: self.context.channel_id(),
2785- data: b"No interactive transaction negotiation in progress".to_vec(),
2786- }),
2787- })
2788- }
2789-
2790- pub fn tx_add_output(&mut self, msg: &msgs::TxAddOutput) -> InteractiveTxMessageSendResult {
2791- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2792- Some(ref mut tx_constructor) => tx_constructor
2793- .handle_tx_add_output(msg)
2794- .map_err(|reason| reason.into_tx_abort_msg(self.context.channel_id())),
2795- None => Err(msgs::TxAbort {
2796- channel_id: self.context.channel_id(),
2797- data: b"No interactive transaction negotiation in progress".to_vec(),
2798- }),
2799- })
2800- }
2801-
2802- pub fn tx_remove_input(&mut self, msg: &msgs::TxRemoveInput) -> InteractiveTxMessageSendResult {
2803- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2804- Some(ref mut tx_constructor) => tx_constructor
2805- .handle_tx_remove_input(msg)
2806- .map_err(|reason| reason.into_tx_abort_msg(self.context.channel_id())),
2807- None => Err(msgs::TxAbort {
2808- channel_id: self.context.channel_id(),
2809- data: b"No interactive transaction negotiation in progress".to_vec(),
2810- }),
2811- })
2812- }
2813-
2814- pub fn tx_remove_output(
2815- &mut self, msg: &msgs::TxRemoveOutput,
2816- ) -> InteractiveTxMessageSendResult {
2817- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2818- Some(ref mut tx_constructor) => tx_constructor
2819- .handle_tx_remove_output(msg)
2820- .map_err(|reason| reason.into_tx_abort_msg(self.context.channel_id())),
2821- None => Err(msgs::TxAbort {
2822- channel_id: self.context.channel_id(),
2823- data: b"No interactive transaction negotiation in progress".to_vec(),
2824- }),
2825- })
2826- }
2827-
2828- pub fn tx_complete(&mut self, msg: &msgs::TxComplete) -> HandleTxCompleteResult {
2829- let tx_constructor = match &mut self.interactive_tx_constructor {
2830- Some(ref mut tx_constructor) => tx_constructor,
2831- None => {
2832- let tx_abort = msgs::TxAbort {
2833- channel_id: msg.channel_id,
2834- data: b"No interactive transaction negotiation in progress".to_vec(),
2835- };
2836- return HandleTxCompleteResult(Err(tx_abort));
2837- },
2838- };
2839-
2840- let tx_complete = match tx_constructor.handle_tx_complete(msg) {
2841- Ok(tx_complete) => tx_complete,
2842- Err(reason) => {
2843- return HandleTxCompleteResult(Err(reason.into_tx_abort_msg(msg.channel_id)))
2844- },
2845- };
2846-
2847- HandleTxCompleteResult(Ok(tx_complete))
2848- }
2849-
2850- #[rustfmt::skip]
2851- pub fn funding_tx_constructed<L: Deref>(
2852- &mut self, mut signing_session: InteractiveTxSigningSession, logger: &L
2853- ) -> Result<(msgs::CommitmentSigned, Option<Event>), ChannelError>
2854- where
2855- L::Target: Logger
2856- {
2857- let transaction_number = self.unfunded_context.transaction_number();
2858-
2859- let mut output_index = None;
2860- let expected_spk = self.funding.get_funding_redeemscript().to_p2wsh();
2861- for (idx, outp) in signing_session.unsigned_tx().outputs().enumerate() {
2862- if outp.script_pubkey() == &expected_spk && outp.value() == self.funding.get_value_satoshis() {
2863- if output_index.is_some() {
2864- let msg = "Multiple outputs matched the expected script and value";
2865- let reason = ClosureReason::ProcessingError { err: msg.to_owned() };
2866- return Err(ChannelError::Close((msg.to_owned(), reason)));
2867- }
2868- output_index = Some(idx as u16);
2869- }
2870- }
2871- let outpoint = if let Some(output_index) = output_index {
2872- OutPoint { txid: signing_session.unsigned_tx().compute_txid(), index: output_index }
2873- } else {
2874- let msg = "No output matched the funding script_pubkey";
2875- let reason = ClosureReason::ProcessingError { err: msg.to_owned() };
2876- return Err(ChannelError::Close((msg.to_owned(), reason)));
2877- };
2878- self.funding.channel_transaction_parameters.funding_outpoint = Some(outpoint);
2879-
2880- self.context.assert_no_commitment_advancement(transaction_number, "initial commitment_signed");
2881- let commitment_signed = self.context.get_initial_commitment_signed(&self.funding, logger);
2882- let commitment_signed = match commitment_signed {
2883- Ok(commitment_signed) => commitment_signed,
2884- Err(e) => {
2885- self.funding.channel_transaction_parameters.funding_outpoint = None;
2886- return Err(e)
2887- },
2888- };
2889-
2890- let funding_ready_for_sig_event = if signing_session.local_inputs_count() == 0 {
2891- debug_assert_eq!(self.funding_negotiation_context.our_funding_contribution_satoshis, 0);
2892- if signing_session.provide_holder_witnesses(self.context.channel_id, Vec::new()).is_err() {
2893- debug_assert!(
2894- false,
2895- "Zero inputs were provided & zero witnesses were provided, but a count mismatch was somehow found",
2896- );
2897- let msg = "V2 channel rejected due to sender error";
2898- let reason = ClosureReason::ProcessingError { err: msg.to_owned() };
2899- return Err(ChannelError::Close((msg.to_owned(), reason)));
2900- }
2901- None
2902- } else {
2903- // TODO(dual_funding): Send event for signing if we've contributed funds.
2904- // Inform the user that SIGHASH_ALL must be used for all signatures when contributing
2905- // inputs/signatures.
2906- // Also warn the user that we don't do anything to prevent the counterparty from
2907- // providing non-standard witnesses which will prevent the funding transaction from
2908- // confirming. This warning must appear in doc comments wherever the user is contributing
2909- // funds, whether they are initiator or acceptor.
2910- //
2911- // The following warning can be used when the APIs allowing contributing inputs become available:
2912- // <div class="warning">
2913- // WARNING: LDK makes no attempt to prevent the counterparty from using non-standard inputs which
2914- // will prevent the funding transaction from being relayed on the bitcoin network and hence being
2915- // confirmed.
2916- // </div>
2917- debug_assert!(
2918- false,
2919- "We don't support users providing inputs but somehow we had more than zero inputs",
2920- );
2921- let msg = "V2 channel rejected due to sender error";
2922- let reason = ClosureReason::ProcessingError { err: msg.to_owned() };
2923- return Err(ChannelError::Close((msg.to_owned(), reason)));
2924- };
2925-
2926- let mut channel_state = ChannelState::FundingNegotiated(FundingNegotiatedFlags::new());
2927- channel_state.set_interactive_signing();
2928- self.context.channel_state = channel_state;
2929-
2930- // Clear the interactive transaction constructor
2931- self.interactive_tx_constructor.take();
2932- self.interactive_tx_signing_session = Some(signing_session);
2933-
2934- Ok((commitment_signed, funding_ready_for_sig_event))
2935- }
2936- }
2937-
29382836impl<SP: Deref> ChannelContext<SP>
29392837where
29402838 SP::Target: SignerProvider,
@@ -5418,6 +5316,97 @@ where
54185316 Ok(())
54195317 }
54205318
5319+ #[rustfmt::skip]
5320+ fn funding_tx_constructed<L: Deref>(
5321+ &mut self, funding: &mut FundingScope, signing_session: &mut InteractiveTxSigningSession,
5322+ is_splice: bool, holder_commitment_transaction_number: u64, logger: &L
5323+ ) -> Result<(msgs::CommitmentSigned, Option<Event>), ChannelError>
5324+ where
5325+ L::Target: Logger
5326+ {
5327+ let mut output_index = None;
5328+ let expected_spk = funding.get_funding_redeemscript().to_p2wsh();
5329+ for (idx, outp) in signing_session.unsigned_tx().outputs().enumerate() {
5330+ if outp.script_pubkey() == &expected_spk && outp.value() == funding.get_value_satoshis() {
5331+ if output_index.is_some() {
5332+ let msg = "Multiple outputs matched the expected script and value";
5333+ let reason = ClosureReason::ProcessingError { err: msg.to_owned() };
5334+ return Err(ChannelError::Close((msg.to_owned(), reason)));
5335+ }
5336+ output_index = Some(idx as u16);
5337+ }
5338+ }
5339+ let outpoint = if let Some(output_index) = output_index {
5340+ OutPoint { txid: signing_session.unsigned_tx().compute_txid(), index: output_index }
5341+ } else {
5342+ let msg = "No output matched the funding script_pubkey";
5343+ let reason = ClosureReason::ProcessingError { err: msg.to_owned() };
5344+ return Err(ChannelError::Close((msg.to_owned(), reason)));
5345+ };
5346+ funding
5347+ .channel_transaction_parameters.funding_outpoint = Some(outpoint);
5348+
5349+ if is_splice {
5350+ let message = "TODO Forced error, incomplete implementation".to_owned();
5351+ // TODO(splicing) Forced error, as the use case is not complete
5352+ return Err(ChannelError::Close((
5353+ message.clone(),
5354+ ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false), message }
5355+ )));
5356+ }
5357+
5358+ self.assert_no_commitment_advancement(holder_commitment_transaction_number, "initial commitment_signed");
5359+ let commitment_signed = self.get_initial_commitment_signed(&funding, logger);
5360+ let commitment_signed = match commitment_signed {
5361+ Ok(commitment_signed) => commitment_signed,
5362+ Err(e) => {
5363+ funding.channel_transaction_parameters.funding_outpoint = None;
5364+ return Err(e)
5365+ },
5366+ };
5367+
5368+ let funding_ready_for_sig_event = if signing_session.local_inputs_count() == 0 {
5369+ if signing_session.provide_holder_witnesses(self.channel_id, Vec::new()).is_err() {
5370+ debug_assert!(
5371+ false,
5372+ "Zero inputs were provided & zero witnesses were provided, but a count mismatch was somehow found",
5373+ );
5374+ let msg = "V2 channel rejected due to sender error";
5375+ let reason = ClosureReason::ProcessingError { err: msg.to_owned() };
5376+ return Err(ChannelError::Close((msg.to_owned(), reason)));
5377+ }
5378+ None
5379+ } else {
5380+ // TODO(dual_funding): Send event for signing if we've contributed funds.
5381+ // Inform the user that SIGHASH_ALL must be used for all signatures when contributing
5382+ // inputs/signatures.
5383+ // Also warn the user that we don't do anything to prevent the counterparty from
5384+ // providing non-standard witnesses which will prevent the funding transaction from
5385+ // confirming. This warning must appear in doc comments wherever the user is contributing
5386+ // funds, whether they are initiator or acceptor.
5387+ //
5388+ // The following warning can be used when the APIs allowing contributing inputs become available:
5389+ // <div class="warning">
5390+ // WARNING: LDK makes no attempt to prevent the counterparty from using non-standard inputs which
5391+ // will prevent the funding transaction from being relayed on the bitcoin network and hence being
5392+ // confirmed.
5393+ // </div>
5394+ debug_assert!(
5395+ false,
5396+ "We don't support users providing inputs but somehow we had more than zero inputs",
5397+ );
5398+ let msg = "V2 channel rejected due to sender error";
5399+ let reason = ClosureReason::ProcessingError { err: msg.to_owned() };
5400+ return Err(ChannelError::Close((msg.to_owned(), reason)));
5401+ };
5402+
5403+ let mut channel_state = ChannelState::FundingNegotiated(FundingNegotiatedFlags::new());
5404+ channel_state.set_interactive_signing();
5405+ self.channel_state = channel_state;
5406+
5407+ Ok((commitment_signed, funding_ready_for_sig_event))
5408+ }
5409+
54215410 /// Asserts that the commitment tx numbers have not advanced from their initial number.
54225411 #[rustfmt::skip]
54235412 fn assert_no_commitment_advancement(&self, holder_commitment_transaction_number: u64, msg_name: &str) {
@@ -6033,6 +6022,22 @@ where
60336022 self.context.force_shutdown(&self.funding, closure_reason)
60346023 }
60356024
6025+ #[cfg(splicing)]
6026+ fn interactive_tx_constructor_mut(&mut self) -> Option<&mut InteractiveTxConstructor> {
6027+ self.pending_splice
6028+ .as_mut()
6029+ .and_then(|pending_splice| pending_splice.funding_negotiation.as_mut())
6030+ .and_then(|funding_negotiation| {
6031+ if let FundingNegotiation::Pending(_, interactive_tx_constructor) =
6032+ funding_negotiation
6033+ {
6034+ Some(interactive_tx_constructor)
6035+ } else {
6036+ None
6037+ }
6038+ })
6039+ }
6040+
60366041 #[rustfmt::skip]
60376042 fn check_remote_fee<F: Deref, L: Deref>(
60386043 channel_type: &ChannelTypeFeatures, fee_estimator: &LowerBoundedFeeEstimator<F>,
0 commit comments