@@ -1732,6 +1732,19 @@ where
17321732 }
17331733 }
17341734
1735+ pub fn as_negotiating_channel(&mut self) -> Result<NegotiatingChannelView<SP>, ChannelError> {
1736+ match &mut self.phase {
1737+ ChannelPhase::UnfundedV2(chan) => Ok(chan.as_negotiating_channel()),
1738+ #[cfg(splicing)]
1739+ ChannelPhase::Funded(chan) => {
1740+ Ok(chan.as_renegotiating_channel().map_err(|err| ChannelError::Warn(err.into()))?)
1741+ },
1742+ _ => Err(ChannelError::Warn(
1743+ "Got a transaction negotiation message in an invalid phase".to_owned(),
1744+ )),
1745+ }
1746+ }
1747+
17351748 #[rustfmt::skip]
17361749 pub fn funding_signed<L: Deref>(
17371750 &mut self, msg: &msgs::FundingSigned, best_block: BestBlock, signer_provider: &SP, logger: &L
@@ -1770,9 +1783,11 @@ where
17701783 where
17711784 L::Target: Logger,
17721785 {
1773- if let ChannelPhase::UnfundedV2(chan) = &mut self.phase {
1774- let logger = WithChannelContext::from(logger, &chan.context, None);
1775- chan.funding_tx_constructed(signing_session, &&logger)
1786+ let logger = WithChannelContext::from(logger, self.context(), None);
1787+ if let Ok(mut negotiating_channel) = self.as_negotiating_channel() {
1788+ let (commitment_signed, event) =
1789+ negotiating_channel.funding_tx_constructed(signing_session, &&logger)?;
1790+ Ok((commitment_signed, event))
17761791 } else {
17771792 Err(ChannelError::Warn("Got a tx_complete message with no interactive transaction construction expected or in-progress".to_owned()))
17781793 }
@@ -2175,8 +2190,13 @@ impl FundingScope {
21752190/// Info about a pending splice, used in the pre-splice channel
21762191#[cfg(splicing)]
21772192struct PendingSplice {
2193+ /// Intended contributions to the splice from our end
21782194 pub our_funding_contribution: i64,
21792195 funding: Option<FundingScope>,
2196+ funding_negotiation_context: FundingNegotiationContext,
2197+ /// The current interactive transaction construction session under negotiation.
2198+ interactive_tx_constructor: Option<InteractiveTxConstructor>,
2199+ interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
21802200
21812201 /// The funding txid used in the `splice_locked` sent to the counterparty.
21822202 sent_funding_txid: Option<Txid>,
@@ -2757,7 +2777,23 @@ where
27572777 }
27582778}
27592779
2760- impl<SP: Deref> PendingV2Channel<SP>
2780+ /// A short-lived subset view of a channel, used for V2 funding negotiation or re-negotiation.
2781+ /// Can be produced by:
2782+ /// - [`PendingV2Channel`], at V2 channel open, and
2783+ /// - [`FundedChannel`], when splicing.
2784+ pub struct NegotiatingChannelView<'a, SP: Deref>
2785+ where
2786+ SP::Target: SignerProvider,
2787+ {
2788+ context: &'a mut ChannelContext<SP>,
2789+ funding: &'a mut FundingScope,
2790+ funding_negotiation_context: &'a mut FundingNegotiationContext,
2791+ interactive_tx_constructor: &'a mut Option<InteractiveTxConstructor>,
2792+ interactive_tx_signing_session: &'a mut Option<InteractiveTxSigningSession>,
2793+ holder_commitment_transaction_number: u64,
2794+ }
2795+
2796+ impl<'a, SP: Deref> NegotiatingChannelView<'a, SP>
27612797where
27622798 SP::Target: SignerProvider,
27632799{
@@ -2841,13 +2877,15 @@ where
28412877 let mut tx_constructor = InteractiveTxConstructor::new(constructor_args)?;
28422878 let msg = tx_constructor.take_initiator_first_message();
28432879
2844- self.interactive_tx_constructor = Some(tx_constructor);
2880+ * self.interactive_tx_constructor = Some(tx_constructor);
28452881
28462882 Ok(msg)
28472883 }
28482884
2849- pub fn tx_add_input(&mut self, msg: &msgs::TxAddInput) -> InteractiveTxMessageSendResult {
2850- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2885+ pub(super) fn tx_add_input(
2886+ &mut self, msg: &msgs::TxAddInput,
2887+ ) -> InteractiveTxMessageSendResult {
2888+ InteractiveTxMessageSendResult(match self.interactive_tx_constructor {
28512889 Some(ref mut tx_constructor) => tx_constructor
28522890 .handle_tx_add_input(msg)
28532891 .map_err(|reason| reason.into_tx_abort_msg(self.context.channel_id())),
@@ -2858,8 +2896,10 @@ where
28582896 })
28592897 }
28602898
2861- pub fn tx_add_output(&mut self, msg: &msgs::TxAddOutput) -> InteractiveTxMessageSendResult {
2862- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2899+ pub(super) fn tx_add_output(
2900+ &mut self, msg: &msgs::TxAddOutput,
2901+ ) -> InteractiveTxMessageSendResult {
2902+ InteractiveTxMessageSendResult(match self.interactive_tx_constructor {
28632903 Some(ref mut tx_constructor) => tx_constructor
28642904 .handle_tx_add_output(msg)
28652905 .map_err(|reason| reason.into_tx_abort_msg(self.context.channel_id())),
@@ -2870,8 +2910,10 @@ where
28702910 })
28712911 }
28722912
2873- pub fn tx_remove_input(&mut self, msg: &msgs::TxRemoveInput) -> InteractiveTxMessageSendResult {
2874- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2913+ pub(super) fn tx_remove_input(
2914+ &mut self, msg: &msgs::TxRemoveInput,
2915+ ) -> InteractiveTxMessageSendResult {
2916+ InteractiveTxMessageSendResult(match self.interactive_tx_constructor {
28752917 Some(ref mut tx_constructor) => tx_constructor
28762918 .handle_tx_remove_input(msg)
28772919 .map_err(|reason| reason.into_tx_abort_msg(self.context.channel_id())),
@@ -2882,10 +2924,10 @@ where
28822924 })
28832925 }
28842926
2885- pub fn tx_remove_output(
2927+ pub(super) fn tx_remove_output(
28862928 &mut self, msg: &msgs::TxRemoveOutput,
28872929 ) -> InteractiveTxMessageSendResult {
2888- InteractiveTxMessageSendResult(match &mut self.interactive_tx_constructor {
2930+ InteractiveTxMessageSendResult(match self.interactive_tx_constructor {
28892931 Some(ref mut tx_constructor) => tx_constructor
28902932 .handle_tx_remove_output(msg)
28912933 .map_err(|reason| reason.into_tx_abort_msg(self.context.channel_id())),
@@ -2896,9 +2938,9 @@ where
28962938 })
28972939 }
28982940
2899- pub fn tx_complete(&mut self, msg: &msgs::TxComplete) -> HandleTxCompleteResult {
2900- let tx_constructor = match &mut self.interactive_tx_constructor {
2901- Some(ref mut tx_constructor) => tx_constructor,
2941+ pub(super) fn tx_complete(&mut self, msg: &msgs::TxComplete) -> HandleTxCompleteResult {
2942+ let tx_constructor = match self.interactive_tx_constructor {
2943+ Some(tx_constructor) => tx_constructor,
29022944 None => {
29032945 let tx_abort = msgs::TxAbort {
29042946 channel_id: msg.channel_id,
@@ -2919,14 +2961,14 @@ where
29192961 }
29202962
29212963 #[rustfmt::skip]
2922- pub fn funding_tx_constructed<L: Deref>(
2964+ fn funding_tx_constructed<L: Deref>(
29232965 &mut self, mut signing_session: InteractiveTxSigningSession, logger: &L
29242966 ) -> Result<(msgs::CommitmentSigned, Option<Event>), ChannelError>
29252967 where
29262968 L::Target: Logger
29272969 {
2928- let our_funding_satoshis = self.funding_negotiation_context.our_funding_satoshis;
2929- let transaction_number = self.unfunded_context.transaction_number() ;
2970+ let our_funding_satoshis = self.funding_negotiation_context
2971+ .our_funding_satoshis ;
29302972
29312973 let mut output_index = None;
29322974 let expected_spk = self.funding.get_funding_redeemscript().to_p2wsh();
@@ -2947,9 +2989,10 @@ where
29472989 let reason = ClosureReason::ProcessingError { err: msg.to_owned() };
29482990 return Err(ChannelError::Close((msg.to_owned(), reason)));
29492991 };
2950- self.funding.channel_transaction_parameters.funding_outpoint = Some(outpoint);
2992+ self.funding
2993+ .channel_transaction_parameters.funding_outpoint = Some(outpoint);
29512994
2952- self.context.assert_no_commitment_advancement(transaction_number , "initial commitment_signed");
2995+ self.context.assert_no_commitment_advancement(self.holder_commitment_transaction_number , "initial commitment_signed");
29532996 let commitment_signed = self.context.get_initial_commitment_signed(&self.funding, logger);
29542997 let commitment_signed = match commitment_signed {
29552998 Ok(commitment_signed) => commitment_signed,
@@ -3000,8 +3043,8 @@ where
30003043 self.context.channel_state = channel_state;
30013044
30023045 // Clear the interactive transaction constructor
3003- self.interactive_tx_constructor.take() ;
3004- self.interactive_tx_signing_session = Some(signing_session);
3046+ * self.interactive_tx_constructor = None ;
3047+ * self.interactive_tx_signing_session = Some(signing_session);
30053048
30063049 Ok((commitment_signed, funding_ready_for_sig_event))
30073050 }
@@ -5997,6 +6040,42 @@ where
59976040 self.context.force_shutdown(&self.funding, closure_reason)
59986041 }
59996042
6043+ /// If we are in splicing/refunding, return a short-lived [`NegotiatingChannelView`].
6044+ #[cfg(splicing)]
6045+ fn as_renegotiating_channel(&mut self) -> Result<NegotiatingChannelView<SP>, &'static str> {
6046+ if let Some(ref mut pending_splice) = &mut self.pending_splice {
6047+ if let Some(ref mut funding) = &mut pending_splice.funding {
6048+ if pending_splice.funding_negotiation_context.our_funding_satoshis != 0
6049+ || pending_splice
6050+ .funding_negotiation_context
6051+ .their_funding_satoshis
6052+ .unwrap_or_default() != 0
6053+ {
6054+ Ok(NegotiatingChannelView {
6055+ context: &mut self.context,
6056+ funding,
6057+ funding_negotiation_context: &mut pending_splice
6058+ .funding_negotiation_context,
6059+ interactive_tx_constructor: &mut pending_splice.interactive_tx_constructor,
6060+ interactive_tx_signing_session: &mut pending_splice
6061+ .interactive_tx_signing_session,
6062+ holder_commitment_transaction_number: self
6063+ .holder_commitment_point
6064+ .transaction_number(),
6065+ })
6066+ } else {
6067+ Err("Received unexpected interactive transaction negotiation message: \
6068+ the channel is splicing, but splice_init/splice_ack has not been exchanged yet")
6069+ }
6070+ } else {
6071+ Err("Received unexpected interactive transaction negotiation message: \
6072+ the channel is splicing, but splice_init/splice_ack has not been exchanged yet")
6073+ }
6074+ } else {
6075+ Err("Received unexpected interactive transaction negotiation message: the channel is funded and not splicing")
6076+ }
6077+ }
6078+
60006079 #[rustfmt::skip]
60016080 fn check_remote_fee<F: Deref, L: Deref>(
60026081 channel_type: &ChannelTypeFeatures, fee_estimator: &LowerBoundedFeeEstimator<F>,
@@ -10181,10 +10260,11 @@ where
1018110260 ) -> Result<msgs::SpliceInit, APIError> {
1018210261 // Check if a splice has been initiated already.
1018310262 // Note: only a single outstanding splice is supported (per spec)
10184- if let Some(splice_info ) = &self.pending_splice {
10263+ if let Some(pending_splice ) = &self.pending_splice {
1018510264 return Err(APIError::APIMisuseError { err: format!(
1018610265 "Channel {} cannot be spliced, as it has already a splice pending (contribution {})",
10187- self.context.channel_id(), splice_info.our_funding_contribution
10266+ self.context.channel_id(),
10267+ pending_splice.our_funding_contribution,
1018810268 )});
1018910269 }
1019010270
@@ -10216,10 +10296,27 @@ where
1021610296 "Insufficient inputs for splicing; channel ID {}, err {}",
1021710297 self.context.channel_id(), err,
1021810298 )})?;
10299+ // Convert inputs
10300+ let mut funding_inputs = Vec::new();
10301+ for (tx_in, tx, _w) in our_funding_inputs.into_iter() {
10302+ let tx16 = TransactionU16LenLimited::new(tx.clone()).map_err(|_e| APIError::APIMisuseError { err: format!("Too large transaction")})?;
10303+ funding_inputs.push((tx_in.clone(), tx16));
10304+ }
1021910305
10306+ let funding_negotiation_context = FundingNegotiationContext {
10307+ is_initiator: true,
10308+ our_funding_satoshis: 0, // set at later phase
10309+ their_funding_satoshis: None, // set at later phase
10310+ funding_tx_locktime: LockTime::from_consensus(locktime),
10311+ funding_feerate_sat_per_1000_weight: funding_feerate_per_kw,
10312+ our_funding_inputs: funding_inputs,
10313+ };
1022010314 self.pending_splice = Some(PendingSplice {
1022110315 our_funding_contribution: our_funding_contribution_satoshis,
1022210316 funding: None,
10317+ funding_negotiation_context,
10318+ interactive_tx_constructor: None,
10319+ interactive_tx_signing_session: None,
1022310320 sent_funding_txid: None,
1022410321 received_funding_txid: None,
1022510322 });
@@ -12147,6 +12244,18 @@ where
1214712244 pub fn get_accept_channel_v2_message(&self) -> msgs::AcceptChannelV2 {
1214812245 self.generate_accept_channel_v2_message()
1214912246 }
12247+
12248+ /// Return a short-lived [`NegotiatingChannelView`].
12249+ fn as_negotiating_channel(&mut self) -> NegotiatingChannelView<SP> {
12250+ NegotiatingChannelView {
12251+ context: &mut self.context,
12252+ funding: &mut self.funding,
12253+ funding_negotiation_context: &mut self.funding_negotiation_context,
12254+ interactive_tx_constructor: &mut self.interactive_tx_constructor,
12255+ interactive_tx_signing_session: &mut self.interactive_tx_signing_session,
12256+ holder_commitment_transaction_number: self.unfunded_context.transaction_number(),
12257+ }
12258+ }
1215012259}
1215112260
1215212261// Unfunded channel utilities
0 commit comments