@@ -1522,7 +1522,7 @@ impl<SP: Deref> Channel<SP> where
15221522 holder_commitment_point,
15231523 is_v2_established: true,
15241524 #[cfg(splicing)]
1525- pending_splice : None,
1525+ pending_splice_pre : None,
15261526 };
15271527 let res = funded_channel.commitment_signed_initial_v2(msg, best_block, signer_provider, logger)
15281528 .map(|monitor| (Some(monitor), None))
@@ -1727,8 +1727,30 @@ impl FundingScope {
17271727
17281728/// Info about a pending splice, used in the pre-splice channel
17291729#[cfg(splicing)]
1730+ #[derive(Clone)]
17301731struct PendingSplice {
17311732 pub our_funding_contribution: i64,
1733+ pub funding_feerate_per_kw: u32,
1734+ pub locktime: u32,
1735+ /// The funding inputs that we plan to contributing to the splice.
1736+ pub our_funding_inputs: Vec<(TxIn, TransactionU16LenLimited)>,
1737+ }
1738+
1739+ #[cfg(splicing)]
1740+ impl PendingSplice {
1741+ #[inline]
1742+ fn add_checked(base: u64, delta: i64) -> u64 {
1743+ if delta >= 0 {
1744+ base.saturating_add(delta as u64)
1745+ } else {
1746+ base.saturating_sub(delta.abs() as u64)
1747+ }
1748+ }
1749+
1750+ /// Compute the post-splice channel value from the pre-splice values and the peer contributions
1751+ pub fn compute_post_value(pre_channel_value: u64, our_funding_contribution: i64, their_funding_contribution: i64) -> u64 {
1752+ Self::add_checked(pre_channel_value, our_funding_contribution.saturating_add(their_funding_contribution))
1753+ }
17321754}
17331755
17341756/// Contains everything about the channel including state, and various flags.
@@ -4981,7 +5003,7 @@ pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
49815003 is_v2_established: bool,
49825004 /// Info about an in-progress, pending splice (if any), on the pre-splice channel
49835005 #[cfg(splicing)]
4984- pending_splice : Option<PendingSplice>,
5006+ pending_splice_pre : Option<PendingSplice>,
49855007}
49865008
49875009#[cfg(any(test, fuzzing))]
@@ -8516,7 +8538,7 @@ impl<SP: Deref> FundedChannel<SP> where
85168538 ) -> Result<msgs::SpliceInit, APIError> {
85178539 // Check if a splice has been initiated already.
85188540 // Note: only a single outstanding splice is supported (per spec)
8519- if let Some(splice_info) = &self.pending_splice {
8541+ if let Some(splice_info) = &self.pending_splice_pre {
85208542 return Err(APIError::APIMisuseError { err: format!(
85218543 "Channel {} cannot be spliced, as it has already a splice pending (contribution {})",
85228544 self.context.channel_id(), splice_info.our_funding_contribution
@@ -8552,8 +8574,20 @@ impl<SP: Deref> FundedChannel<SP> where
85528574 self.context.channel_id(), err,
85538575 )})?;
85548576
8555- self.pending_splice = Some(PendingSplice {
8577+ // convert inputs
8578+ let mut funding_inputs = Vec::new();
8579+ for (tx_in, tx, _w) in our_funding_inputs.into_iter() {
8580+ let tx16 = TransactionU16LenLimited::new(tx.clone()).map_err(
8581+ |e| APIError::APIMisuseError { err: format!("Too large transaction, {:?}", e)}
8582+ )?;
8583+ funding_inputs.push((tx_in.clone(), tx16));
8584+ }
8585+
8586+ self.pending_splice_pre = Some(PendingSplice {
85568587 our_funding_contribution: our_funding_contribution_satoshis,
8588+ funding_feerate_per_kw,
8589+ locktime,
8590+ our_funding_inputs: funding_inputs,
85578591 });
85588592
85598593 let msg = self.get_splice_init(our_funding_contribution_satoshis, funding_feerate_per_kw, locktime);
@@ -8580,13 +8614,13 @@ impl<SP: Deref> FundedChannel<SP> where
85808614
85818615 /// Handle splice_init
85828616 #[cfg(splicing)]
8583- pub fn splice_init(&mut self, msg: &msgs::SpliceInit) -> Result<msgs::SpliceAck, ChannelError> {
8617+ pub fn splice_init<L: Deref> (&mut self, msg: &msgs::SpliceInit, logger: &L ) -> Result<msgs::SpliceAck, ChannelError> where L::Target: Logger {
85848618 let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
85858619 // TODO(splicing): Currently not possible to contribute on the splicing-acceptor side
85868620 let our_funding_contribution_satoshis = 0i64;
85878621
85888622 // Check if a splice has been initiated already.
8589- if let Some(splice_info) = &self.pending_splice {
8623+ if let Some(splice_info) = &self.pending_splice_pre {
85908624 return Err(ChannelError::Warn(format!(
85918625 "Channel has already a splice pending, contribution {}", splice_info.our_funding_contribution,
85928626 )));
@@ -8615,7 +8649,8 @@ impl<SP: Deref> FundedChannel<SP> where
86158649 // TODO(splicing): Once splice acceptor can contribute, add reserve pre-check, similar to the one in `splice_ack`.
86168650
86178651 // TODO(splicing): Store msg.funding_pubkey
8618- // TODO(splicing): Apply start of splice (splice_start)
8652+ // Apply start of splice change in the state
8653+ self.splice_start(false, logger);
86198654
86208655 // TODO(splicing): The exisiting pubkey is reused, but a new one should be generated. See #3542.
86218656 // Note that channel_keys_id is supposed NOT to change
@@ -8626,22 +8661,55 @@ impl<SP: Deref> FundedChannel<SP> where
86268661 require_confirmed_inputs: None,
86278662 };
86288663 // TODO(splicing): start interactive funding negotiation
8664+ // let _msg = self.begin_interactive_funding_tx_construction(signer_provider, entropy_source, holder_node_id)
8665+ // .map_err(|err| ChannelError::Warn(format!("Failed to start interactive transaction construction, {:?}", err)))?;
8666+
86298667 Ok(splice_ack_msg)
86308668 }
86318669
86328670 /// Handle splice_ack
86338671 #[cfg(splicing)]
8634- pub fn splice_ack(&mut self, _msg : &msgs::SpliceAck) -> Result<(), ChannelError> {
8672+ pub fn splice_ack<L: Deref> (&mut self, msg : &msgs::SpliceAck, logger: &L ) -> Result<(), ChannelError> where L::Target: Logger {
86358673 // check if splice is pending
8636- if self.pending_splice.is_none() {
8674+ let pending_splice = if let Some(pending_splice) = &self.pending_splice_pre {
8675+ pending_splice
8676+ } else {
86378677 return Err(ChannelError::Warn(format!("Channel is not in pending splice")));
86388678 };
86398679
8680+
8681+ let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
8682+ let our_funding_contribution = pending_splice.our_funding_contribution;
8683+
8684+ let pre_channel_value = self.funding.get_value_satoshis();
8685+ let post_channel_value = PendingSplice::compute_post_value(pre_channel_value, our_funding_contribution, their_funding_contribution_satoshis);
8686+ let post_balance = PendingSplice::add_checked(self.funding.value_to_self_msat, our_funding_contribution);
8687+
86408688 // TODO(splicing): Pre-check for reserve requirement
86418689 // (Note: It should also be checked later at tx_complete)
8690+
8691+ // Apply start of splice change in the state
8692+ self.splice_start(true, logger);
8693+
8694+ // TODO(splicing): start interactive funding negotiation
8695+ // let tx_msg_opt = self.begin_interactive_funding_tx_construction(signer_provider, entropy_source, holder_node_id)
8696+ // .map_err(|err| ChannelError::Warn(format!("V2 channel rejected due to sender error, {:?}", err)))?;
8697+ // Ok(tx_msg_opt)
86428698 Ok(())
86438699 }
86448700
8701+ /// Splice process starting; update state, log, etc.
8702+ #[cfg(splicing)]
8703+ pub(crate) fn splice_start<L: Deref>(&mut self, is_outgoing: bool, logger: &L) where L::Target: Logger {
8704+ // Set state, by this point splice_init/splice_ack handshake is complete
8705+ // TODO(splicing)
8706+ // self.channel_state = ChannelState::NegotiatingFunding(
8707+ // NegotiatingFundingFlags::OUR_INIT_SENT | NegotiatingFundingFlags::THEIR_INIT_SENT
8708+ // );
8709+ log_info!(logger, "Splicing process started, old channel value {}, outgoing {}, channel_id {}",
8710+ self.funding.get_value_satoshis(), is_outgoing, self.context.channel_id);
8711+ }
8712+
86458713 // Send stuff to our remote peers:
86468714
86478715 /// Queues up an outbound HTLC to send by placing it in the holding cell. You should call
@@ -9565,7 +9633,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
95659633 is_v2_established: false,
95669634 holder_commitment_point,
95679635 #[cfg(splicing)]
9568- pending_splice : None,
9636+ pending_splice_pre : None,
95699637 };
95709638
95719639 let need_channel_ready = channel.check_get_channel_ready(0, logger).is_some()
@@ -9841,7 +9909,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
98419909 is_v2_established: false,
98429910 holder_commitment_point,
98439911 #[cfg(splicing)]
9844- pending_splice : None,
9912+ pending_splice_pre : None,
98459913 };
98469914 let need_channel_ready = channel.check_get_channel_ready(0, logger).is_some()
98479915 || channel.context.signer_pending_channel_ready;
@@ -11224,7 +11292,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1122411292 is_v2_established,
1122511293 holder_commitment_point,
1122611294 #[cfg(splicing)]
11227- pending_splice : None,
11295+ pending_splice_pre : None,
1122811296 })
1122911297 }
1123011298}
@@ -13146,4 +13214,69 @@ mod tests {
1314613214 );
1314713215 }
1314813216 }
13217+
13218+ #[cfg(all(test, splicing))]
13219+ fn get_pre_and_post(pre_channel_value: u64, our_funding_contribution: i64, their_funding_contribution: i64) -> (u64, u64) {
13220+ use crate::ln::channel::PendingSplice;
13221+
13222+ let post_channel_value = PendingSplice::compute_post_value(pre_channel_value, our_funding_contribution, their_funding_contribution);
13223+ (pre_channel_value, post_channel_value)
13224+ }
13225+
13226+ #[cfg(all(test, splicing))]
13227+ #[test]
13228+ fn test_splice_compute_post_value() {
13229+ {
13230+ // increase, small amounts
13231+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, 6_000, 0);
13232+ assert_eq!(pre_channel_value, 9_000);
13233+ assert_eq!(post_channel_value, 15_000);
13234+ }
13235+ {
13236+ // increase, small amounts
13237+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, 4_000, 2_000);
13238+ assert_eq!(pre_channel_value, 9_000);
13239+ assert_eq!(post_channel_value, 15_000);
13240+ }
13241+ {
13242+ // increase, small amounts
13243+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, 0, 6_000);
13244+ assert_eq!(pre_channel_value, 9_000);
13245+ assert_eq!(post_channel_value, 15_000);
13246+ }
13247+ {
13248+ // decrease, small amounts
13249+ let (pre_channel_value, post_channel_value) = get_pre_and_post(15_000, -6_000, 0);
13250+ assert_eq!(pre_channel_value, 15_000);
13251+ assert_eq!(post_channel_value, 9_000);
13252+ }
13253+ {
13254+ // decrease, small amounts
13255+ let (pre_channel_value, post_channel_value) = get_pre_and_post(15_000, -4_000, -2_000);
13256+ assert_eq!(pre_channel_value, 15_000);
13257+ assert_eq!(post_channel_value, 9_000);
13258+ }
13259+ {
13260+ // increase and decrease
13261+ let (pre_channel_value, post_channel_value) = get_pre_and_post(15_000, 4_000, -2_000);
13262+ assert_eq!(pre_channel_value, 15_000);
13263+ assert_eq!(post_channel_value, 17_000);
13264+ }
13265+ let base2: u64 = 2;
13266+ let huge63i3 = (base2.pow(63) - 3) as i64;
13267+ assert_eq!(huge63i3, 9223372036854775805);
13268+ assert_eq!(-huge63i3, -9223372036854775805);
13269+ {
13270+ // increase, large amount
13271+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, huge63i3, 3);
13272+ assert_eq!(pre_channel_value, 9_000);
13273+ assert_eq!(post_channel_value, 9223372036854784807);
13274+ }
13275+ {
13276+ // increase, large amounts
13277+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, huge63i3, huge63i3);
13278+ assert_eq!(pre_channel_value, 9_000);
13279+ assert_eq!(post_channel_value, 9223372036854784807);
13280+ }
13281+ }
1314913282}
0 commit comments