@@ -1519,7 +1519,7 @@ impl<SP: Deref> Channel<SP> where
15191519 holder_commitment_point,
15201520 is_v2_established: true,
15211521 #[cfg(splicing)]
1522- pending_splice : None,
1522+ pending_splice_pre : None,
15231523 };
15241524 let res = funded_channel.commitment_signed_initial_v2(msg, best_block, signer_provider, logger)
15251525 .map(|monitor| (Some(monitor), None))
@@ -1724,8 +1724,30 @@ impl FundingScope {
17241724
17251725/// Info about a pending splice, used in the pre-splice channel
17261726#[cfg(splicing)]
1727+ #[derive(Clone)]
17271728struct PendingSplice {
17281729 pub our_funding_contribution: i64,
1730+ pub funding_feerate_per_kw: u32,
1731+ pub locktime: u32,
1732+ /// The funding inputs that we plan to contributing to the splice.
1733+ pub our_funding_inputs: Vec<(TxIn, TransactionU16LenLimited)>,
1734+ }
1735+
1736+ #[cfg(splicing)]
1737+ impl PendingSplice {
1738+ #[inline]
1739+ fn add_checked(base: u64, delta: i64) -> u64 {
1740+ if delta >= 0 {
1741+ base.saturating_add(delta as u64)
1742+ } else {
1743+ base.saturating_sub(delta.abs() as u64)
1744+ }
1745+ }
1746+
1747+ /// Compute the post-splice channel value from the pre-splice values and the peer contributions
1748+ pub fn compute_post_value(pre_channel_value: u64, our_funding_contribution: i64, their_funding_contribution: i64) -> u64 {
1749+ Self::add_checked(pre_channel_value, our_funding_contribution.saturating_add(their_funding_contribution))
1750+ }
17291751}
17301752
17311753/// Contains everything about the channel including state, and various flags.
@@ -5007,7 +5029,7 @@ pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
50075029 is_v2_established: bool,
50085030 /// Info about an in-progress, pending splice (if any), on the pre-splice channel
50095031 #[cfg(splicing)]
5010- pending_splice : Option<PendingSplice>,
5032+ pending_splice_pre : Option<PendingSplice>,
50115033}
50125034
50135035#[cfg(any(test, fuzzing))]
@@ -8540,7 +8562,7 @@ impl<SP: Deref> FundedChannel<SP> where
85408562 ) -> Result<msgs::SpliceInit, APIError> {
85418563 // Check if a splice has been initiated already.
85428564 // Note: only a single outstanding splice is supported (per spec)
8543- if let Some(splice_info) = &self.pending_splice {
8565+ if let Some(splice_info) = &self.pending_splice_pre {
85448566 return Err(APIError::APIMisuseError { err: format!(
85458567 "Channel {} cannot be spliced, as it has already a splice pending (contribution {})",
85468568 self.context.channel_id(), splice_info.our_funding_contribution
@@ -8576,8 +8598,20 @@ impl<SP: Deref> FundedChannel<SP> where
85768598 self.context.channel_id(), err,
85778599 )})?;
85788600
8579- self.pending_splice = Some(PendingSplice {
8601+ // convert inputs
8602+ let mut funding_inputs = Vec::new();
8603+ for (tx_in, tx, _w) in our_funding_inputs.into_iter() {
8604+ let tx16 = TransactionU16LenLimited::new(tx.clone()).map_err(
8605+ |e| APIError::APIMisuseError { err: format!("Too large transaction, {:?}", e)}
8606+ )?;
8607+ funding_inputs.push((tx_in.clone(), tx16));
8608+ }
8609+
8610+ self.pending_splice_pre = Some(PendingSplice {
85808611 our_funding_contribution: our_funding_contribution_satoshis,
8612+ funding_feerate_per_kw,
8613+ locktime,
8614+ our_funding_inputs: funding_inputs,
85818615 });
85828616
85838617 let msg = self.get_splice_init(our_funding_contribution_satoshis, funding_feerate_per_kw, locktime);
@@ -8604,13 +8638,13 @@ impl<SP: Deref> FundedChannel<SP> where
86048638
86058639 /// Handle splice_init
86068640 #[cfg(splicing)]
8607- pub fn splice_init(&mut self, msg: &msgs::SpliceInit) -> Result<msgs::SpliceAck, ChannelError> {
8641+ pub fn splice_init<L: Deref> (&mut self, msg: &msgs::SpliceInit, logger: &L ) -> Result<msgs::SpliceAck, ChannelError> where L::Target: Logger {
86088642 let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
86098643 // TODO(splicing): Currently not possible to contribute on the splicing-acceptor side
86108644 let our_funding_contribution_satoshis = 0i64;
86118645
86128646 // Check if a splice has been initiated already.
8613- if let Some(splice_info) = &self.pending_splice {
8647+ if let Some(splice_info) = &self.pending_splice_pre {
86148648 return Err(ChannelError::Warn(format!(
86158649 "Channel has already a splice pending, contribution {}", splice_info.our_funding_contribution,
86168650 )));
@@ -8639,7 +8673,8 @@ impl<SP: Deref> FundedChannel<SP> where
86398673 // TODO(splicing): Once splice acceptor can contribute, add reserve pre-check, similar to the one in `splice_ack`.
86408674
86418675 // TODO(splicing): Store msg.funding_pubkey
8642- // TODO(splicing): Apply start of splice (splice_start)
8676+ // Apply start of splice change in the state
8677+ self.splice_start(false, logger);
86438678
86448679 // TODO(splicing): The exisiting pubkey is reused, but a new one should be generated. See #3542.
86458680 // Note that channel_keys_id is supposed NOT to change
@@ -8650,22 +8685,55 @@ impl<SP: Deref> FundedChannel<SP> where
86508685 require_confirmed_inputs: None,
86518686 };
86528687 // TODO(splicing): start interactive funding negotiation
8688+ // let _msg = self.begin_interactive_funding_tx_construction(signer_provider, entropy_source, holder_node_id)
8689+ // .map_err(|err| ChannelError::Warn(format!("Failed to start interactive transaction construction, {:?}", err)))?;
8690+
86538691 Ok(splice_ack_msg)
86548692 }
86558693
86568694 /// Handle splice_ack
86578695 #[cfg(splicing)]
8658- pub fn splice_ack(&mut self, _msg : &msgs::SpliceAck) -> Result<(), ChannelError> {
8696+ pub fn splice_ack<L: Deref> (&mut self, msg : &msgs::SpliceAck, logger: &L ) -> Result<(), ChannelError> where L::Target: Logger {
86598697 // check if splice is pending
8660- if self.pending_splice.is_none() {
8698+ let pending_splice = if let Some(pending_splice) = &self.pending_splice_pre {
8699+ pending_splice
8700+ } else {
86618701 return Err(ChannelError::Warn(format!("Channel is not in pending splice")));
86628702 };
86638703
8704+
8705+ let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
8706+ let our_funding_contribution = pending_splice.our_funding_contribution;
8707+
8708+ let pre_channel_value = self.funding.get_value_satoshis();
8709+ let post_channel_value = PendingSplice::compute_post_value(pre_channel_value, our_funding_contribution, their_funding_contribution_satoshis);
8710+ let post_balance = PendingSplice::add_checked(self.funding.value_to_self_msat, our_funding_contribution);
8711+
86648712 // TODO(splicing): Pre-check for reserve requirement
86658713 // (Note: It should also be checked later at tx_complete)
8714+
8715+ // Apply start of splice change in the state
8716+ self.splice_start(true, logger);
8717+
8718+ // TODO(splicing): start interactive funding negotiation
8719+ // let tx_msg_opt = self.begin_interactive_funding_tx_construction(signer_provider, entropy_source, holder_node_id)
8720+ // .map_err(|err| ChannelError::Warn(format!("V2 channel rejected due to sender error, {:?}", err)))?;
8721+ // Ok(tx_msg_opt)
86668722 Ok(())
86678723 }
86688724
8725+ /// Splice process starting; update state, log, etc.
8726+ #[cfg(splicing)]
8727+ pub(crate) fn splice_start<L: Deref>(&mut self, is_outgoing: bool, logger: &L) where L::Target: Logger {
8728+ // Set state, by this point splice_init/splice_ack handshake is complete
8729+ // TODO(splicing)
8730+ // self.channel_state = ChannelState::NegotiatingFunding(
8731+ // NegotiatingFundingFlags::OUR_INIT_SENT | NegotiatingFundingFlags::THEIR_INIT_SENT
8732+ // );
8733+ log_info!(logger, "Splicing process started, old channel value {}, outgoing {}, channel_id {}",
8734+ self.funding.get_value_satoshis(), is_outgoing, self.context.channel_id);
8735+ }
8736+
86698737 // Send stuff to our remote peers:
86708738
86718739 /// Queues up an outbound HTLC to send by placing it in the holding cell. You should call
@@ -9586,7 +9654,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
95869654 is_v2_established: false,
95879655 holder_commitment_point,
95889656 #[cfg(splicing)]
9589- pending_splice : None,
9657+ pending_splice_pre : None,
95909658 };
95919659
95929660 let need_channel_ready = channel.check_get_channel_ready(0, logger).is_some()
@@ -9863,7 +9931,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
98639931 is_v2_established: false,
98649932 holder_commitment_point,
98659933 #[cfg(splicing)]
9866- pending_splice : None,
9934+ pending_splice_pre : None,
98679935 };
98689936 let need_channel_ready = channel.check_get_channel_ready(0, logger).is_some()
98699937 || channel.context.signer_pending_channel_ready;
@@ -11227,7 +11295,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1122711295 is_v2_established,
1122811296 holder_commitment_point,
1122911297 #[cfg(splicing)]
11230- pending_splice : None,
11298+ pending_splice_pre : None,
1123111299 })
1123211300 }
1123311301}
@@ -13157,4 +13225,69 @@ mod tests {
1315713225 );
1315813226 }
1315913227 }
13228+
13229+ #[cfg(all(test, splicing))]
13230+ fn get_pre_and_post(pre_channel_value: u64, our_funding_contribution: i64, their_funding_contribution: i64) -> (u64, u64) {
13231+ use crate::ln::channel::PendingSplice;
13232+
13233+ let post_channel_value = PendingSplice::compute_post_value(pre_channel_value, our_funding_contribution, their_funding_contribution);
13234+ (pre_channel_value, post_channel_value)
13235+ }
13236+
13237+ #[cfg(all(test, splicing))]
13238+ #[test]
13239+ fn test_splice_compute_post_value() {
13240+ {
13241+ // increase, small amounts
13242+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, 6_000, 0);
13243+ assert_eq!(pre_channel_value, 9_000);
13244+ assert_eq!(post_channel_value, 15_000);
13245+ }
13246+ {
13247+ // increase, small amounts
13248+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, 4_000, 2_000);
13249+ assert_eq!(pre_channel_value, 9_000);
13250+ assert_eq!(post_channel_value, 15_000);
13251+ }
13252+ {
13253+ // increase, small amounts
13254+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, 0, 6_000);
13255+ assert_eq!(pre_channel_value, 9_000);
13256+ assert_eq!(post_channel_value, 15_000);
13257+ }
13258+ {
13259+ // decrease, small amounts
13260+ let (pre_channel_value, post_channel_value) = get_pre_and_post(15_000, -6_000, 0);
13261+ assert_eq!(pre_channel_value, 15_000);
13262+ assert_eq!(post_channel_value, 9_000);
13263+ }
13264+ {
13265+ // decrease, small amounts
13266+ let (pre_channel_value, post_channel_value) = get_pre_and_post(15_000, -4_000, -2_000);
13267+ assert_eq!(pre_channel_value, 15_000);
13268+ assert_eq!(post_channel_value, 9_000);
13269+ }
13270+ {
13271+ // increase and decrease
13272+ let (pre_channel_value, post_channel_value) = get_pre_and_post(15_000, 4_000, -2_000);
13273+ assert_eq!(pre_channel_value, 15_000);
13274+ assert_eq!(post_channel_value, 17_000);
13275+ }
13276+ let base2: u64 = 2;
13277+ let huge63i3 = (base2.pow(63) - 3) as i64;
13278+ assert_eq!(huge63i3, 9223372036854775805);
13279+ assert_eq!(-huge63i3, -9223372036854775805);
13280+ {
13281+ // increase, large amount
13282+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, huge63i3, 3);
13283+ assert_eq!(pre_channel_value, 9_000);
13284+ assert_eq!(post_channel_value, 9223372036854784807);
13285+ }
13286+ {
13287+ // increase, large amounts
13288+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, huge63i3, huge63i3);
13289+ assert_eq!(pre_channel_value, 9_000);
13290+ assert_eq!(post_channel_value, 9223372036854784807);
13291+ }
13292+ }
1316013293}
0 commit comments