@@ -1253,7 +1253,14 @@ impl<SP: Deref> Channel<SP> where
1253
1253
pub fn unfunded_context_mut(&mut self) -> Option<&mut UnfundedChannelContext> {
1254
1254
match &mut self.phase {
1255
1255
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
+ }
1257
1264
ChannelPhase::UnfundedOutboundV1(chan) => Some(&mut chan.unfunded_context),
1258
1265
ChannelPhase::UnfundedInboundV1(chan) => Some(&mut chan.unfunded_context),
1259
1266
ChannelPhase::UnfundedV2(chan) => Some(&mut chan.unfunded_context),
@@ -1801,12 +1808,19 @@ impl FundingScope {
1801
1808
}
1802
1809
}
1803
1810
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
1805
1812
#[cfg(splicing)]
1806
- struct PendingSplice {
1813
+ struct PendingSpliceInit {
1807
1814
pub our_funding_contribution: i64,
1808
1815
}
1809
1816
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
+
1810
1824
/// Contains everything about the channel including state, and various flags.
1811
1825
pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
1812
1826
config: LegacyChannelConfig,
@@ -2302,6 +2316,81 @@ impl<SP: Deref> InitialRemoteCommitmentReceiver<SP> for FundedChannel<SP> where
2302
2316
}
2303
2317
}
2304
2318
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
+
2305
2394
/// A channel struct implementing this trait can perform V2 transaction negotiation,
2306
2395
/// either at channel open or during splicing.
2307
2396
/// 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
2659
2748
}
2660
2749
}
2661
2750
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
+
2662
2764
impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
2663
2765
fn new_for_inbound_channel<'a, ES: Deref, F: Deref, L: Deref>(
2664
2766
fee_estimator: &'a LowerBoundedFeeEstimator<F>,
@@ -8726,10 +8828,11 @@ impl<SP: Deref> FundedChannel<SP> where
8726
8828
) -> Result<msgs::SpliceInit, APIError> {
8727
8829
// Check if a splice has been initiated already.
8728
8830
// 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 {
8730
8832
return Err(APIError::APIMisuseError { err: format!(
8731
8833
"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(),
8733
8836
)});
8734
8837
}
8735
8838
@@ -8762,9 +8865,13 @@ impl<SP: Deref> FundedChannel<SP> where
8762
8865
self.context.channel_id(), err,
8763
8866
)})?;
8764
8867
8765
- self.pending_splice = Some(PendingSplice {
8868
+ let pending_splice_init = Some(PendingSpliceInit {
8766
8869
our_funding_contribution: our_funding_contribution_satoshis,
8767
8870
});
8871
+ self.pending_splice = Some(PendingSplice {
8872
+ pending_splice_init,
8873
+ refunding_scope: None,
8874
+ });
8768
8875
8769
8876
let msg = self.get_splice_init(our_funding_contribution_satoshis, funding_feerate_per_kw, locktime);
8770
8877
Ok(msg)
@@ -8796,9 +8903,11 @@ impl<SP: Deref> FundedChannel<SP> where
8796
8903
let our_funding_contribution_satoshis = 0i64;
8797
8904
8798
8905
// 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 {
8800
8907
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(),
8802
8911
)));
8803
8912
}
8804
8913
@@ -8843,7 +8952,11 @@ impl<SP: Deref> FundedChannel<SP> where
8843
8952
#[cfg(splicing)]
8844
8953
pub fn splice_ack(&mut self, _msg: &msgs::SpliceAck) -> Result<(), ChannelError> {
8845
8954
// 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 {
8847
8960
return Err(ChannelError::Warn(format!("Channel is not in pending splice")));
8848
8961
};
8849
8962
0 commit comments