From 14dfc72a49e9917ec4010ee253b1c7cd36e5b136 Mon Sep 17 00:00:00 2001
From: optout <13562139+optout21@users.noreply.github.com>
Date: Wed, 4 Dec 2024 10:37:23 +0100
Subject: [PATCH] Sort out PendingSplicePre and -Post, new spliced for
 ChannelContext and OutboundV2Channel

---
 lightning/src/ln/channel.rs                 | 90 +++++++++++++++++++--
 lightning/src/ln/functional_tests_splice.rs | 12 ++-
 2 files changed, 91 insertions(+), 11 deletions(-)

diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs
index 46bc8bc9aee..92578ab1bc4 100644
--- a/lightning/src/ln/channel.rs
+++ b/lightning/src/ln/channel.rs
@@ -4503,7 +4503,7 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
 		// self.channel_state = ChannelState::NegotiatingFunding(
 		// 	NegotiatingFundingFlags::OUR_INIT_SENT | NegotiatingFundingFlags::THEIR_INIT_SENT
 		// );
-		log_info!(logger, "Splicing process started, old channel value {}, outgoing {}, channel_id {}",
+		log_info!(logger, "Splicing process started, new channel value {}, outgoing {}, channel_id {}",
 			self.channel_value_satoshis, is_outgoing, self.channel_id);
 	}
 
@@ -8913,7 +8913,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
 				pubkeys,
 				logger,
 			)?,
-			unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 }
+			unfunded_context: UnfundedChannelContext::default(),
 		};
 		Ok(chan)
 	}
@@ -9221,7 +9221,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
 				msg.push_msat,
 				msg.common_fields.clone(),
 			)?,
-			unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 },
+			unfunded_context: UnfundedChannelContext::default(),
 		};
 		Ok(chan)
 	}
@@ -9434,7 +9434,7 @@ impl<SP: Deref> OutboundV2Channel<SP> where SP::Target: SignerProvider {
 				pubkeys,
 				logger,
 			)?,
-			unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 },
+			unfunded_context: UnfundedChannelContext::default(),
 			dual_funding_context: DualFundingChannelContext {
 				our_funding_satoshis: funding_satoshis,
 				their_funding_satoshis: None,
@@ -9443,6 +9443,7 @@ impl<SP: Deref> OutboundV2Channel<SP> where SP::Target: SignerProvider {
 				our_funding_inputs: Some(funding_inputs),
 			},
 			interactive_tx_constructor: None,
+			#[cfg(splicing)]
 			pending_splice_post: None,
 		};
 		Ok(chan)
@@ -9452,7 +9453,7 @@ impl<SP: Deref> OutboundV2Channel<SP> where SP::Target: SignerProvider {
 	#[cfg(splicing)]
 	pub fn new_spliced<L: Deref>(
 		is_outbound: bool,
-		pre_splice_channel: &mut Channel<SP>,
+		pre_splice_channel: &Channel<SP>,
 		signer_provider: &SP,
 		counterparty_funding_pubkey: &PublicKey,
 		our_funding_contribution: i64,
@@ -9602,6 +9603,9 @@ pub(super) struct InboundV2Channel<SP: Deref> where SP::Target: SignerProvider {
 	pub dual_funding_context: DualFundingChannelContext,
 	/// The current interactive transaction construction session under negotiation.
 	interactive_tx_constructor: Option<InteractiveTxConstructor>,
+	/// Info about an in-progress, pending splice (if any), on the post-splice channel
+	#[cfg(splicing)]
+	pending_splice_post: Option<PendingSplicePost>,
 }
 
 impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
@@ -9704,10 +9708,82 @@ impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
 			context,
 			dual_funding_context,
 			interactive_tx_constructor,
-			unfunded_context: UnfundedChannelContext { unfunded_channel_age_ticks: 0 },
+			unfunded_context: UnfundedChannelContext::default(),
+			#[cfg(splicing)]
+			pending_splice_post: None,
 		})
 	}
 
+	/// Create new channel for splicing
+	#[cfg(splicing)]
+	pub fn new_spliced<L: Deref>(
+		is_outbound: bool,
+		pre_splice_channel: &Channel<SP>,
+		signer_provider: &SP,
+		counterparty_funding_pubkey: &PublicKey,
+		our_funding_contribution: i64,
+		their_funding_contribution: i64,
+		funding_inputs: Vec<(TxIn, TransactionU16LenLimited)>,
+		funding_tx_locktime: LockTime,
+		funding_feerate_sat_per_1000_weight: u32,
+		logger: &L,
+	) -> Result<Self, ChannelError> where L::Target: Logger
+	{
+		if pre_splice_channel.is_splice_pending() {
+			return Err(ChannelError::Warn(format!("Internal error: Channel is already splicing, channel_id {}", pre_splice_channel.context.channel_id)));
+		}
+
+		let pre_channel_value = pre_splice_channel.context.get_value_satoshis();
+
+		// Save the current funding transaction
+		let pre_funding_transaction = pre_splice_channel.context.funding_transaction.clone();
+		let pre_funding_txo = pre_splice_channel.context.get_funding_txo().clone();
+
+		let pending_splice_post = PendingSplicePost::new(
+			pre_channel_value, our_funding_contribution, their_funding_contribution,
+			pre_funding_transaction, pre_funding_txo,
+		);
+		let post_channel_value = pending_splice_post.post_channel_value();
+
+		// Create new signer, using the new channel value.
+		// Note: channel_keys_id is not changed
+		let holder_signer = signer_provider.derive_channel_signer(post_channel_value, pre_splice_channel.context.channel_keys_id);
+
+		let context = ChannelContext::new_for_splice(
+			&pre_splice_channel.context,
+			false,
+			counterparty_funding_pubkey,
+			our_funding_contribution,
+			their_funding_contribution,
+			holder_signer,
+			logger,
+		)?;
+
+		let (our_funding_satoshis, their_funding_satoshis) = calculate_funding_values(
+			pre_channel_value,
+			our_funding_contribution,
+			their_funding_contribution,
+			is_outbound,
+		)?;
+
+		let dual_funding_context = DualFundingChannelContext {
+			our_funding_satoshis,
+			their_funding_satoshis: Some(their_funding_satoshis),
+			funding_tx_locktime,
+			funding_feerate_sat_per_1000_weight,
+			our_funding_inputs: Some(funding_inputs),
+		};
+		let unfunded_context = UnfundedChannelContext::default();
+		let post_chan = Self {
+			context,
+			dual_funding_context,
+			unfunded_context,
+			interactive_tx_constructor: None,
+			pending_splice_post: Some(pending_splice_post),
+		};
+		Ok(post_chan)
+	}
+
 	/// Marks an inbound channel as accepted and generates a [`msgs::AcceptChannelV2`] message which
 	/// should be sent back to the counterparty node.
 	///
@@ -9787,7 +9863,7 @@ impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
 			#[cfg(splicing)]
 			pending_splice_pre: None,
 			#[cfg(splicing)]
-			pending_splice_post: None,
+			pending_splice_post: self.pending_splice_post,
 		};
 
 		Ok(channel)
diff --git a/lightning/src/ln/functional_tests_splice.rs b/lightning/src/ln/functional_tests_splice.rs
index 061d509cdf7..824a7cfebcc 100644
--- a/lightning/src/ln/functional_tests_splice.rs
+++ b/lightning/src/ln/functional_tests_splice.rs
@@ -221,6 +221,10 @@ fn test_v1_splice_in() {
 
 	// ==== Channel is now ready for normal operation
 
+	// Expected balances
+	let mut exp_balance1 = 1000 * channel_value_sat;
+	let mut exp_balance2 = 0;
+	
 	// === Start of Splicing
 	println!("Start of Splicing ..., channel_id {}", channel_id2);
 
@@ -276,8 +280,8 @@ fn test_v1_splice_in() {
 		assert!(channel.is_usable);
 		assert!(channel.is_channel_ready);
 		assert_eq!(channel.channel_value_satoshis, channel_value_sat);
-		assert_eq!(channel.outbound_capacity_msat, 0);
-		assert!(channel.funding_txo.is_some());
+		assert_eq!(channel.outbound_capacity_msat, exp_balance2);
+		assert_eq!(channel.funding_txo.unwrap().txid, funding_tx.compute_txid());
 		assert!(channel.confirmations.unwrap() > 0);
 	}
 
@@ -295,9 +299,9 @@ fn test_v1_splice_in() {
 		assert_eq!(channel.channel_value_satoshis, channel_value_sat);
 		assert_eq!(
 			channel.outbound_capacity_msat,
-			1000 * (channel_value_sat - channel_reserve_amnt_sat)
+			exp_balance1 - 1000 * channel_reserve_amnt_sat
 		);
-		assert!(channel.funding_txo.is_some());
+		assert_eq!(channel.funding_txo.unwrap().txid, funding_tx.compute_txid());
 		assert!(channel.confirmations.unwrap() > 0);
 	}