@@ -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,
@@ -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 {
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
@@ -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