@@ -1253,7 +1253,14 @@ impl<SP: Deref> Channel<SP> where
12531253 pub fn unfunded_context_mut(&mut self) -> Option<&mut UnfundedChannelContext> {
12541254 match &mut self.phase {
12551255 ChannelPhase::Undefined => unreachable!(),
1256- ChannelPhase::Funded(_) => { debug_assert!(false); None },
1256+ #[cfg(not(splicing))]
1257+ ChannelPhase::Funded(_) => { debug_assert!(false); None }
1258+ #[cfg(splicing)]
1259+ ChannelPhase::Funded(chan) => {
1260+ chan.pending_splice.as_mut().map(|splice|
1261+ splice.refunding_scope.as_mut().map(|refunding_scope| &mut refunding_scope.pending_unfunded_context)
1262+ ).flatten()
1263+ }
12571264 ChannelPhase::UnfundedOutboundV1(chan) => Some(&mut chan.unfunded_context),
12581265 ChannelPhase::UnfundedInboundV1(chan) => Some(&mut chan.unfunded_context),
12591266 ChannelPhase::UnfundedV2(chan) => Some(&mut chan.unfunded_context),
@@ -1801,12 +1808,19 @@ impl FundingScope {
18011808 }
18021809}
18031810
1804- /// Info about a pending splice , used in the pre-splice channel
1811+ /// Info about a pending splice_init , used in the pre-splice channel
18051812#[cfg(splicing)]
1806- struct PendingSplice {
1813+ struct PendingSpliceInit {
18071814 pub our_funding_contribution: i64,
18081815}
18091816
1817+ /// Info about a pending splice
1818+ #[cfg(splicing)]
1819+ struct PendingSplice {
1820+ pub pending_splice_init: Option<PendingSpliceInit>,
1821+ pub refunding_scope: Option<RefundingScope>,
1822+ }
1823+
18101824/// Contains everything about the channel including state, and various flags.
18111825pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
18121826 config: LegacyChannelConfig,
@@ -2302,6 +2316,81 @@ impl<SP: Deref> InitialRemoteCommitmentReceiver<SP> for FundedChannel<SP> where
23022316 }
23032317}
23042318
2319+ /// [`FundedChannel`] can act as a [`FundingTxConstructorV2`], but properly only when its
2320+ /// [`RefundingScope`] is present.
2321+ #[cfg(splicing)]
2322+ impl<SP: Deref> FundingTxConstructorV2<SP> for FundedChannel<SP> where SP::Target: SignerProvider {
2323+ #[inline]
2324+ fn pending_funding(&self) -> Result<&FundingScope, &'static str> {
2325+ self.pending_splice.as_ref().map(|splice|
2326+ splice.refunding_scope.as_ref().map(|refunding| &refunding.pending_funding)
2327+ ).flatten().ok_or("Not re-funding")
2328+ }
2329+
2330+ #[inline]
2331+ fn pending_funding_mut(&mut self) -> Result<&mut FundingScope, &'static str> {
2332+ self.pending_splice.as_mut().map(|splice|
2333+ splice.refunding_scope.as_mut().map(|refunding| &mut refunding.pending_funding)
2334+ ).flatten().ok_or("Not re-funding")
2335+ }
2336+
2337+ #[inline]
2338+ fn pending_funding_and_context_mut(&mut self) -> Result<(&FundingScope, &mut ChannelContext<SP>), &'static str> {
2339+ let context_mut = &mut self.context;
2340+ self.pending_splice.as_ref().map(|splice|
2341+ splice.refunding_scope.as_ref().map(|refunding| (&refunding.pending_funding, context_mut))
2342+ ).flatten().ok_or("Not re-funding")
2343+ }
2344+
2345+ #[inline]
2346+ fn dual_funding_context(&self) -> Result<&DualFundingChannelContext, &'static str> {
2347+ self.pending_splice.as_ref().map(|splice|
2348+ splice.refunding_scope.as_ref().map(|refunding| &refunding.pending_dual_funding_context)
2349+ ).flatten().ok_or("Not re-funding")
2350+ }
2351+
2352+ fn swap_out_dual_funding_context_inputs(&mut self, funding_inputs: &mut Vec<(TxIn, TransactionU16LenLimited)>) -> Result<(), &'static str> {
2353+ if let Some(pending_splice) = &mut self.pending_splice {
2354+ if let Some(refunding) = &mut pending_splice.refunding_scope {
2355+ mem::swap(&mut refunding.pending_dual_funding_context.our_funding_inputs, funding_inputs);
2356+ Ok(())
2357+ } else {
2358+ Err("Not re-funding")
2359+ }
2360+ } else {
2361+ Err("Not re-funding")
2362+ }
2363+ }
2364+
2365+ #[inline]
2366+ fn unfunded_context(&self) -> Result<&UnfundedChannelContext, &'static str> {
2367+ self.pending_splice.as_ref().map(|splice|
2368+ splice.refunding_scope.as_ref().map(|refunding| &refunding.pending_unfunded_context)
2369+ ).flatten().ok_or("Not re-funding")
2370+ }
2371+
2372+ #[inline]
2373+ fn interactive_tx_constructor(&self) -> Result<Option<&InteractiveTxConstructor>, &'static str> {
2374+ self.pending_splice.as_ref().map(|splice|
2375+ splice.refunding_scope.as_ref().map(|refunding| refunding.pending_interactive_tx_constructor.as_ref())
2376+ ).flatten().ok_or("Not re-funding")
2377+ }
2378+
2379+ #[inline]
2380+ fn interactive_tx_constructor_mut(&mut self) -> Result<&mut Option<InteractiveTxConstructor>, &'static str> {
2381+ self.pending_splice.as_mut().map(|splice|
2382+ splice.refunding_scope.as_mut().map(|refunding| &mut refunding.pending_interactive_tx_constructor)
2383+ ).flatten().ok_or("Not re-funding")
2384+ }
2385+
2386+ #[inline]
2387+ fn interactive_tx_signing_session_mut(&mut self) -> Result<&mut Option<InteractiveTxSigningSession>, &'static str> {
2388+ self.pending_splice.as_mut().map(|splice|
2389+ splice.refunding_scope.as_mut().map(|refunding| &mut refunding.pending_interactive_tx_signing_session)
2390+ ).flatten().ok_or("Not re-funding")
2391+ }
2392+ }
2393+
23052394/// A channel struct implementing this trait can perform V2 transaction negotiation,
23062395/// either at channel open or during splicing.
23072396/// Accessors return a Result, because [`FundedChannel`] can act like a TX constructor,
@@ -2659,6 +2748,19 @@ impl<SP: Deref> FundingTxConstructorV2<SP> for PendingV2Channel<SP> where SP::Ta
26592748 }
26602749}
26612750
2751+ /// Data needed during splicing --
2752+ /// when the funding transaction is being renegotiated in a funded channel.
2753+ #[cfg(splicing)]
2754+ struct RefundingScope {
2755+ // Fields belonging for [`PendingV2Channel`], except the context
2756+ pending_funding: FundingScope,
2757+ pending_unfunded_context: UnfundedChannelContext,
2758+ pending_dual_funding_context: DualFundingChannelContext,
2759+ /// The current interactive transaction construction session under negotiation.
2760+ pending_interactive_tx_constructor: Option<InteractiveTxConstructor>,
2761+ pending_interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
2762+ }
2763+
26622764impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
26632765 fn new_for_inbound_channel<'a, ES: Deref, F: Deref, L: Deref>(
26642766 fee_estimator: &'a LowerBoundedFeeEstimator<F>,
@@ -8726,10 +8828,11 @@ impl<SP: Deref> FundedChannel<SP> where
87268828 ) -> Result<msgs::SpliceInit, APIError> {
87278829 // Check if a splice has been initiated already.
87288830 // Note: only a single outstanding splice is supported (per spec)
8729- if let Some(splice_info ) = &self.pending_splice {
8831+ if let Some(pending_splice ) = &self.pending_splice {
87308832 return Err(APIError::APIMisuseError { err: format!(
87318833 "Channel {} cannot be spliced, as it has already a splice pending (contribution {})",
8732- self.context.channel_id(), splice_info.our_funding_contribution
8834+ self.context.channel_id(),
8835+ pending_splice.pending_splice_init.as_ref().map(|ps| ps.our_funding_contribution).unwrap_or_default(),
87338836 )});
87348837 }
87358838
@@ -8762,9 +8865,13 @@ impl<SP: Deref> FundedChannel<SP> where
87628865 self.context.channel_id(), err,
87638866 )})?;
87648867
8765- self.pending_splice = Some(PendingSplice {
8868+ let pending_splice_init = Some(PendingSpliceInit {
87668869 our_funding_contribution: our_funding_contribution_satoshis,
87678870 });
8871+ self.pending_splice = Some(PendingSplice {
8872+ pending_splice_init,
8873+ refunding_scope: None,
8874+ });
87688875
87698876 let msg = self.get_splice_init(our_funding_contribution_satoshis, funding_feerate_per_kw, locktime);
87708877 Ok(msg)
@@ -8796,9 +8903,11 @@ impl<SP: Deref> FundedChannel<SP> where
87968903 let our_funding_contribution_satoshis = 0i64;
87978904
87988905 // Check if a splice has been initiated already.
8799- if let Some(splice_info ) = &self.pending_splice {
8906+ if let Some(pending_splice ) = &self.pending_splice {
88008907 return Err(ChannelError::Warn(format!(
8801- "Channel has already a splice pending, contribution {}", splice_info.our_funding_contribution,
8908+ "Channel {} has already a splice pending, contribution {}",
8909+ self.context.channel_id(),
8910+ pending_splice.pending_splice_init.as_ref().map(|si| si.our_funding_contribution).unwrap_or_default(),
88028911 )));
88038912 }
88048913
@@ -8843,7 +8952,11 @@ impl<SP: Deref> FundedChannel<SP> where
88438952 #[cfg(splicing)]
88448953 pub fn splice_ack(&mut self, _msg: &msgs::SpliceAck) -> Result<(), ChannelError> {
88458954 // check if splice is pending
8846- if self.pending_splice.is_none() {
8955+ if let Some(pending_splice) = &self.pending_splice {
8956+ if pending_splice.pending_splice_init.is_none() {
8957+ return Err(ChannelError::Warn(format!("Channel is not in pending splice_init")));
8958+ }
8959+ } else {
88478960 return Err(ChannelError::Warn(format!("Channel is not in pending splice")));
88488961 };
88498962
0 commit comments