@@ -1729,6 +1729,19 @@ where
17291729 }
17301730 }
17311731
1732+ pub fn as_negotiating_channel(&mut self) -> Result<NegotiatingChannelView<SP>, ChannelError> {
1733+ match &mut self.phase {
1734+ ChannelPhase::UnfundedV2(chan) => Ok(chan.as_negotiating_channel()),
1735+ #[cfg(splicing)]
1736+ ChannelPhase::Funded(chan) => {
1737+ Ok(chan.as_renegotiating_channel().map_err(|err| ChannelError::Warn(err.into()))?)
1738+ },
1739+ _ => Err(ChannelError::Warn(
1740+ "Got a transaction negotiation message in an invalid phase".to_owned(),
1741+ )),
1742+ }
1743+ }
1744+
17321745 #[rustfmt::skip]
17331746 pub fn funding_signed<L: Deref>(
17341747 &mut self, msg: &msgs::FundingSigned, best_block: BestBlock, signer_provider: &SP, logger: &L
@@ -1767,9 +1780,11 @@ where
17671780 where
17681781 L::Target: Logger,
17691782 {
1770- if let ChannelPhase::UnfundedV2(chan) = &mut self.phase {
1771- let logger = WithChannelContext::from(logger, &chan.context, None);
1772- chan.funding_tx_constructed(signing_session, &&logger)
1783+ let logger = WithChannelContext::from(logger, self.context(), None);
1784+ if let Ok(mut negotiating_channel) = self.as_negotiating_channel() {
1785+ let (commitment_signed, event) =
1786+ negotiating_channel.funding_tx_constructed(signing_session, &&logger)?;
1787+ Ok((commitment_signed, event))
17731788 } else {
17741789 Err(ChannelError::Warn("Got a tx_complete message with no interactive transaction construction expected or in-progress".to_owned()))
17751790 }
@@ -2174,8 +2189,13 @@ impl FundingScope {
21742189/// Info about a pending splice, used in the pre-splice channel
21752190#[cfg(splicing)]
21762191struct PendingSplice {
2192+ /// Intended contributions to the splice from our end
21772193 pub our_funding_contribution: i64,
21782194 funding: Option<FundingScope>,
2195+ funding_negotiation_context: FundingNegotiationContext,
2196+ /// The current interactive transaction construction session under negotiation.
2197+ interactive_tx_constructor: Option<InteractiveTxConstructor>,
2198+ interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
21792199
21802200 /// The funding txid used in the `splice_locked` sent to the counterparty.
21812201 sent_funding_txid: Option<Txid>,
@@ -2756,7 +2776,23 @@ where
27562776 }
27572777}
27582778
2759- impl<SP: Deref> PendingV2Channel<SP>
2779+ /// A short-lived subset view of a channel, used for V2 funding negotiation or re-negotiation.
2780+ /// Can be produced by:
2781+ /// - [`PendingV2Channel`], at V2 channel open, and
2782+ /// - [`FundedChannel`], when splicing.
2783+ pub struct NegotiatingChannelView<'a, SP: Deref>
2784+ where
2785+ SP::Target: SignerProvider,
2786+ {
2787+ context: &'a mut ChannelContext<SP>,
2788+ funding: &'a mut FundingScope,
2789+ funding_negotiation_context: &'a mut FundingNegotiationContext,
2790+ interactive_tx_constructor: &'a mut Option<InteractiveTxConstructor>,
2791+ interactive_tx_signing_session: &'a mut Option<InteractiveTxSigningSession>,
2792+ holder_commitment_transaction_number: u64,
2793+ }
2794+
2795+ impl<'a, SP: Deref> NegotiatingChannelView<'a, SP>
27602796where
27612797 SP::Target: SignerProvider,
27622798{
@@ -2855,13 +2891,15 @@ where
28552891 let mut tx_constructor = InteractiveTxConstructor::new(constructor_args)?;
28562892 let msg = tx_constructor.take_initiator_first_message();
28572893
2858- self.interactive_tx_constructor = Some(tx_constructor);
2894+ * self.interactive_tx_constructor = Some(tx_constructor);
28592895
28602896 Ok(msg)
28612897 }
28622898
2863- pub fn tx_add_input(&mut self, msg: &msgs::TxAddInput) -> InteractiveTxMessageSendResult {
2864- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2899+ pub(super) fn tx_add_input(
2900+ &mut self, msg: &msgs::TxAddInput,
2901+ ) -> InteractiveTxMessageSendResult {
2902+ InteractiveTxMessageSendResult(match self.interactive_tx_constructor {
28652903 Some(ref mut tx_constructor) => tx_constructor
28662904 .handle_tx_add_input(msg)
28672905 .map_err(|reason| reason.into_tx_abort_msg(self.context.channel_id())),
@@ -2872,8 +2910,10 @@ where
28722910 })
28732911 }
28742912
2875- pub fn tx_add_output(&mut self, msg: &msgs::TxAddOutput) -> InteractiveTxMessageSendResult {
2876- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2913+ pub(super) fn tx_add_output(
2914+ &mut self, msg: &msgs::TxAddOutput,
2915+ ) -> InteractiveTxMessageSendResult {
2916+ InteractiveTxMessageSendResult(match self.interactive_tx_constructor {
28772917 Some(ref mut tx_constructor) => tx_constructor
28782918 .handle_tx_add_output(msg)
28792919 .map_err(|reason| reason.into_tx_abort_msg(self.context.channel_id())),
@@ -2884,8 +2924,10 @@ where
28842924 })
28852925 }
28862926
2887- pub fn tx_remove_input(&mut self, msg: &msgs::TxRemoveInput) -> InteractiveTxMessageSendResult {
2888- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2927+ pub(super) fn tx_remove_input(
2928+ &mut self, msg: &msgs::TxRemoveInput,
2929+ ) -> InteractiveTxMessageSendResult {
2930+ InteractiveTxMessageSendResult(match self.interactive_tx_constructor {
28892931 Some(ref mut tx_constructor) => tx_constructor
28902932 .handle_tx_remove_input(msg)
28912933 .map_err(|reason| reason.into_tx_abort_msg(self.context.channel_id())),
@@ -2896,10 +2938,10 @@ where
28962938 })
28972939 }
28982940
2899- pub fn tx_remove_output(
2941+ pub(super) fn tx_remove_output(
29002942 &mut self, msg: &msgs::TxRemoveOutput,
29012943 ) -> InteractiveTxMessageSendResult {
2902- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2944+ InteractiveTxMessageSendResult(match self.interactive_tx_constructor {
29032945 Some(ref mut tx_constructor) => tx_constructor
29042946 .handle_tx_remove_output(msg)
29052947 .map_err(|reason| reason.into_tx_abort_msg(self.context.channel_id())),
@@ -2910,9 +2952,9 @@ where
29102952 })
29112953 }
29122954
2913- pub fn tx_complete(&mut self, msg: &msgs::TxComplete) -> HandleTxCompleteResult {
2914- let tx_constructor = match &mut self.interactive_tx_constructor {
2915- Some(ref mut tx_constructor) => tx_constructor,
2955+ pub(super) fn tx_complete(&mut self, msg: &msgs::TxComplete) -> HandleTxCompleteResult {
2956+ let tx_constructor = match self.interactive_tx_constructor {
2957+ Some(tx_constructor) => tx_constructor,
29162958 None => {
29172959 let tx_abort = msgs::TxAbort {
29182960 channel_id: msg.channel_id,
@@ -2933,14 +2975,14 @@ where
29332975 }
29342976
29352977 #[rustfmt::skip]
2936- pub fn funding_tx_constructed<L: Deref>(
2978+ fn funding_tx_constructed<L: Deref>(
29372979 &mut self, mut signing_session: InteractiveTxSigningSession, logger: &L
29382980 ) -> Result<(msgs::CommitmentSigned, Option<Event>), ChannelError>
29392981 where
29402982 L::Target: Logger
29412983 {
2942- let our_funding_satoshis = self.funding_negotiation_context.our_funding_satoshis;
2943- let transaction_number = self.unfunded_context.transaction_number() ;
2984+ let our_funding_satoshis = self.funding_negotiation_context
2985+ .our_funding_satoshis ;
29442986
29452987 let mut output_index = None;
29462988 let expected_spk = self.funding.get_funding_redeemscript().to_p2wsh();
@@ -2965,14 +3007,16 @@ where
29653007 ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) },
29663008 )));
29673009 };
2968- self.funding.channel_transaction_parameters.funding_outpoint = Some(outpoint);
3010+ self.funding
3011+ .channel_transaction_parameters.funding_outpoint = Some(outpoint);
29693012
2970- self.context.assert_no_commitment_advancement(transaction_number , "initial commitment_signed");
3013+ self.context.assert_no_commitment_advancement(self.holder_commitment_transaction_number , "initial commitment_signed");
29713014 let commitment_signed = self.context.get_initial_commitment_signed(&self.funding, logger);
29723015 let commitment_signed = match commitment_signed {
29733016 Ok(commitment_signed) => commitment_signed,
29743017 Err(err) => {
2975- self.funding.channel_transaction_parameters.funding_outpoint = None;
3018+ self.funding
3019+ .channel_transaction_parameters.funding_outpoint = None;
29763020 return Err(ChannelError::Close((err.to_string(), ClosureReason::HolderForceClosed { broadcasted_latest_txn: Some(false) })));
29773021 },
29783022 };
@@ -3020,8 +3064,8 @@ where
30203064 self.context.channel_state = channel_state;
30213065
30223066 // Clear the interactive transaction constructor
3023- self.interactive_tx_constructor.take() ;
3024- self.interactive_tx_signing_session = Some(signing_session);
3067+ * self.interactive_tx_constructor = None ;
3068+ * self.interactive_tx_signing_session = Some(signing_session);
30253069
30263070 Ok((commitment_signed, funding_ready_for_sig_event))
30273071 }
@@ -6059,6 +6103,42 @@ where
60596103 SP::Target: SignerProvider,
60606104 <SP::Target as SignerProvider>::EcdsaSigner: EcdsaChannelSigner,
60616105{
6106+ /// If we are in splicing/refunding, return a short-lived [`NegotiatingChannelView`].
6107+ #[cfg(splicing)]
6108+ fn as_renegotiating_channel(&mut self) -> Result<NegotiatingChannelView<SP>, &'static str> {
6109+ if let Some(ref mut pending_splice) = &mut self.pending_splice {
6110+ if let Some(ref mut funding) = &mut pending_splice.funding {
6111+ if pending_splice.funding_negotiation_context.our_funding_satoshis != 0
6112+ || pending_splice
6113+ .funding_negotiation_context
6114+ .their_funding_satoshis
6115+ .unwrap_or_default() != 0
6116+ {
6117+ Ok(NegotiatingChannelView {
6118+ context: &mut self.context,
6119+ funding,
6120+ funding_negotiation_context: &mut pending_splice
6121+ .funding_negotiation_context,
6122+ interactive_tx_constructor: &mut pending_splice.interactive_tx_constructor,
6123+ interactive_tx_signing_session: &mut pending_splice
6124+ .interactive_tx_signing_session,
6125+ holder_commitment_transaction_number: self
6126+ .holder_commitment_point
6127+ .transaction_number(),
6128+ })
6129+ } else {
6130+ Err("Received unexpected interactive transaction negotiation message: \
6131+ the channel is splicing, but splice_init/splice_ack has not been exchanged yet")
6132+ }
6133+ } else {
6134+ Err("Received unexpected interactive transaction negotiation message: \
6135+ the channel is splicing, but splice_init/splice_ack has not been exchanged yet")
6136+ }
6137+ } else {
6138+ Err("Received unexpected interactive transaction negotiation message: the channel is funded and not splicing")
6139+ }
6140+ }
6141+
60626142 #[rustfmt::skip]
60636143 fn check_remote_fee<F: Deref, L: Deref>(
60646144 channel_type: &ChannelTypeFeatures, fee_estimator: &LowerBoundedFeeEstimator<F>,
@@ -10225,10 +10305,11 @@ where
1022510305 ) -> Result<msgs::SpliceInit, APIError> {
1022610306 // Check if a splice has been initiated already.
1022710307 // Note: only a single outstanding splice is supported (per spec)
10228- if let Some(splice_info ) = &self.pending_splice {
10308+ if let Some(pending_splice ) = &self.pending_splice {
1022910309 return Err(APIError::APIMisuseError { err: format!(
1023010310 "Channel {} cannot be spliced, as it has already a splice pending (contribution {})",
10231- self.context.channel_id(), splice_info.our_funding_contribution
10311+ self.context.channel_id(),
10312+ pending_splice.our_funding_contribution,
1023210313 )});
1023310314 }
1023410315
@@ -10260,10 +10341,26 @@ where
1026010341 "Insufficient inputs for splicing; channel ID {}, err {}",
1026110342 self.context.channel_id(), err,
1026210343 )})?;
10344+ // Convert inputs
10345+ let mut funding_inputs = Vec::new();
10346+ for (tx_in, tx, _w) in our_funding_inputs.into_iter() {
10347+ let tx16 = TransactionU16LenLimited::new(tx.clone()).map_err(|_e| APIError::APIMisuseError { err: format!("Too large transaction")})?;
10348+ funding_inputs.push((tx_in.clone(), tx16));
10349+ }
1026310350
10351+ let funding_negotiation_context = FundingNegotiationContext {
10352+ our_funding_satoshis: 0, // set at later phase
10353+ their_funding_satoshis: None, // set at later phase
10354+ funding_tx_locktime: LockTime::from_consensus(locktime),
10355+ funding_feerate_sat_per_1000_weight: funding_feerate_per_kw,
10356+ our_funding_inputs: funding_inputs,
10357+ };
1026410358 self.pending_splice = Some(PendingSplice {
1026510359 our_funding_contribution: our_funding_contribution_satoshis,
1026610360 funding: None,
10361+ funding_negotiation_context,
10362+ interactive_tx_constructor: None,
10363+ interactive_tx_signing_session: None,
1026710364 sent_funding_txid: None,
1026810365 received_funding_txid: None,
1026910366 });
@@ -12159,6 +12256,18 @@ where
1215912256 pub fn get_accept_channel_v2_message(&self) -> msgs::AcceptChannelV2 {
1216012257 self.generate_accept_channel_v2_message()
1216112258 }
12259+
12260+ /// Return a short-lived [`NegotiatingChannelView`].
12261+ fn as_negotiating_channel(&mut self) -> NegotiatingChannelView<SP> {
12262+ NegotiatingChannelView {
12263+ context: &mut self.context,
12264+ funding: &mut self.funding,
12265+ funding_negotiation_context: &mut self.funding_negotiation_context,
12266+ interactive_tx_constructor: &mut self.interactive_tx_constructor,
12267+ interactive_tx_signing_session: &mut self.interactive_tx_signing_session,
12268+ holder_commitment_transaction_number: self.unfunded_context.transaction_number(),
12269+ }
12270+ }
1216212271}
1216312272
1216412273// Unfunded channel utilities
0 commit comments