@@ -1524,7 +1524,7 @@ impl<SP: Deref> Channel<SP> where
15241524 holder_commitment_point,
15251525 is_v2_established: true,
15261526 #[cfg(splicing)]
1527- pending_splice : None,
1527+ pending_splice_pre : None,
15281528 };
15291529 let res = funded_channel.commitment_signed_initial_v2(msg, best_block, signer_provider, logger)
15301530 .map(|monitor| (Some(monitor), None))
@@ -1738,6 +1738,23 @@ struct PendingSplice {
17381738 pub our_funding_contribution: i64,
17391739}
17401740
1741+ #[cfg(splicing)]
1742+ impl PendingSplice {
1743+ #[inline]
1744+ fn add_checked(base: u64, delta: i64) -> u64 {
1745+ if delta >= 0 {
1746+ base.saturating_add(delta as u64)
1747+ } else {
1748+ base.saturating_sub(delta.abs() as u64)
1749+ }
1750+ }
1751+
1752+ /// Compute the post-splice channel value from the pre-splice values and the peer contributions
1753+ pub fn compute_post_value(pre_channel_value: u64, our_funding_contribution: i64, their_funding_contribution: i64) -> u64 {
1754+ Self::add_checked(pre_channel_value, our_funding_contribution.saturating_add(their_funding_contribution))
1755+ }
1756+ }
1757+
17411758/// Contains everything about the channel including state, and various flags.
17421759pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
17431760 config: LegacyChannelConfig,
@@ -4953,7 +4970,7 @@ pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
49534970 is_v2_established: bool,
49544971 /// Info about an in-progress, pending splice (if any), on the pre-splice channel
49554972 #[cfg(splicing)]
4956- pending_splice : Option<PendingSplice>,
4973+ pending_splice_pre : Option<PendingSplice>,
49574974}
49584975
49594976#[cfg(any(test, fuzzing))]
@@ -8496,7 +8513,7 @@ impl<SP: Deref> FundedChannel<SP> where
84968513 ) -> Result<msgs::SpliceInit, APIError> {
84978514 // Check if a splice has been initiated already.
84988515 // Note: only a single outstanding splice is supported (per spec)
8499- if let Some(splice_info) = &self.pending_splice {
8516+ if let Some(splice_info) = &self.pending_splice_pre {
85008517 return Err(APIError::APIMisuseError { err: format!(
85018518 "Channel {} cannot be spliced, as it has already a splice pending (contribution {})",
85028519 self.context.channel_id(), splice_info.our_funding_contribution
@@ -8532,7 +8549,7 @@ impl<SP: Deref> FundedChannel<SP> where
85328549 self.context.channel_id(), err,
85338550 )})?;
85348551
8535- self.pending_splice = Some(PendingSplice {
8552+ self.pending_splice_pre = Some(PendingSplice {
85368553 our_funding_contribution: our_funding_contribution_satoshis,
85378554 });
85388555
@@ -8566,7 +8583,7 @@ impl<SP: Deref> FundedChannel<SP> where
85668583 let our_funding_contribution_satoshis = 0i64;
85678584
85688585 // Check if a splice has been initiated already.
8569- if let Some(splice_info) = &self.pending_splice {
8586+ if let Some(splice_info) = &self.pending_splice_pre {
85708587 return Err(ChannelError::Warn(format!(
85718588 "Channel has already a splice pending, contribution {}", splice_info.our_funding_contribution,
85728589 )));
@@ -8592,7 +8609,11 @@ impl<SP: Deref> FundedChannel<SP> where
85928609
85938610 // Note on channel reserve requirement pre-check: as the splice acceptor does not contribute,
85948611 // it can't go below reserve, therefore no pre-check is done here.
8595- // TODO(splicing): Once splice acceptor can contribute, add reserve pre-check, similar to the one in `splice_ack`.
8612+
8613+ let pre_channel_value = self.funding.value_to_self_msat;
8614+ let _post_channel_value = PendingSplice::compute_post_value(pre_channel_value, their_funding_contribution_satoshis, our_funding_contribution_satoshis);
8615+ let _post_balance = PendingSplice::add_checked(self.funding.value_to_self_msat, our_funding_contribution_satoshis);
8616+ // TODO: Early check for reserve requirement
85968617
85978618 // TODO(splicing): Store msg.funding_pubkey
85988619 // TODO(splicing): Apply start of splice (splice_start)
@@ -8611,14 +8632,24 @@ impl<SP: Deref> FundedChannel<SP> where
86118632
86128633 /// Handle splice_ack
86138634 #[cfg(splicing)]
8614- pub fn splice_ack(&mut self, _msg : &msgs::SpliceAck) -> Result<(), ChannelError> {
8635+ pub fn splice_ack(&mut self, msg : &msgs::SpliceAck) -> Result<(), ChannelError> {
86158636 // check if splice is pending
8616- if self.pending_splice.is_none() {
8637+ let pending_splice = if let Some(pending_splice) = &self.pending_splice_pre {
8638+ pending_splice
8639+ } else {
86178640 return Err(ChannelError::Warn(format!("Channel is not in pending splice")));
86188641 };
86198642
86208643 // TODO(splicing): Pre-check for reserve requirement
86218644 // (Note: It should also be checked later at tx_complete)
8645+
8646+ let our_funding_contribution = pending_splice.our_funding_contribution;
8647+ let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
8648+
8649+ let pre_channel_value = self.funding.get_value_satoshis();
8650+ let _post_channel_value = PendingSplice::compute_post_value(pre_channel_value, our_funding_contribution, their_funding_contribution_satoshis);
8651+ let _post_balance = PendingSplice::add_checked(self.funding.value_to_self_msat, our_funding_contribution);
8652+ // TODO: Early check for reserve requirement
86228653 Ok(())
86238654 }
86248655
@@ -9553,7 +9584,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
95539584 is_v2_established: false,
95549585 holder_commitment_point,
95559586 #[cfg(splicing)]
9556- pending_splice : None,
9587+ pending_splice_pre : None,
95579588 };
95589589
95599590 let need_channel_ready = channel.check_get_channel_ready(0, logger).is_some()
@@ -9829,7 +9860,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
98299860 is_v2_established: false,
98309861 holder_commitment_point,
98319862 #[cfg(splicing)]
9832- pending_splice : None,
9863+ pending_splice_pre : None,
98339864 };
98349865 let need_channel_ready = channel.check_get_channel_ready(0, logger).is_some()
98359866 || channel.context.signer_pending_channel_ready;
@@ -11266,7 +11297,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
1126611297 is_v2_established,
1126711298 holder_commitment_point,
1126811299 #[cfg(splicing)]
11269- pending_splice : None,
11300+ pending_splice_pre : None,
1127011301 })
1127111302 }
1127211303}
@@ -13206,4 +13237,69 @@ mod tests {
1320613237 );
1320713238 }
1320813239 }
13240+
13241+ #[cfg(all(test, splicing))]
13242+ fn get_pre_and_post(pre_channel_value: u64, our_funding_contribution: i64, their_funding_contribution: i64) -> (u64, u64) {
13243+ use crate::ln::channel::PendingSplice;
13244+
13245+ let post_channel_value = PendingSplice::compute_post_value(pre_channel_value, our_funding_contribution, their_funding_contribution);
13246+ (pre_channel_value, post_channel_value)
13247+ }
13248+
13249+ #[cfg(all(test, splicing))]
13250+ #[test]
13251+ fn test_splice_compute_post_value() {
13252+ {
13253+ // increase, small amounts
13254+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, 6_000, 0);
13255+ assert_eq!(pre_channel_value, 9_000);
13256+ assert_eq!(post_channel_value, 15_000);
13257+ }
13258+ {
13259+ // increase, small amounts
13260+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, 4_000, 2_000);
13261+ assert_eq!(pre_channel_value, 9_000);
13262+ assert_eq!(post_channel_value, 15_000);
13263+ }
13264+ {
13265+ // increase, small amounts
13266+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, 0, 6_000);
13267+ assert_eq!(pre_channel_value, 9_000);
13268+ assert_eq!(post_channel_value, 15_000);
13269+ }
13270+ {
13271+ // decrease, small amounts
13272+ let (pre_channel_value, post_channel_value) = get_pre_and_post(15_000, -6_000, 0);
13273+ assert_eq!(pre_channel_value, 15_000);
13274+ assert_eq!(post_channel_value, 9_000);
13275+ }
13276+ {
13277+ // decrease, small amounts
13278+ let (pre_channel_value, post_channel_value) = get_pre_and_post(15_000, -4_000, -2_000);
13279+ assert_eq!(pre_channel_value, 15_000);
13280+ assert_eq!(post_channel_value, 9_000);
13281+ }
13282+ {
13283+ // increase and decrease
13284+ let (pre_channel_value, post_channel_value) = get_pre_and_post(15_000, 4_000, -2_000);
13285+ assert_eq!(pre_channel_value, 15_000);
13286+ assert_eq!(post_channel_value, 17_000);
13287+ }
13288+ let base2: u64 = 2;
13289+ let huge63i3 = (base2.pow(63) - 3) as i64;
13290+ assert_eq!(huge63i3, 9223372036854775805);
13291+ assert_eq!(-huge63i3, -9223372036854775805);
13292+ {
13293+ // increase, large amount
13294+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, huge63i3, 3);
13295+ assert_eq!(pre_channel_value, 9_000);
13296+ assert_eq!(post_channel_value, 9223372036854784807);
13297+ }
13298+ {
13299+ // increase, large amounts
13300+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, huge63i3, huge63i3);
13301+ assert_eq!(pre_channel_value, 9_000);
13302+ assert_eq!(post_channel_value, 9223372036854784807);
13303+ }
13304+ }
1320913305}
0 commit comments