@@ -1738,6 +1738,23 @@ struct PendingSplice {
1738
1738
pub our_funding_contribution: i64,
1739
1739
}
1740
1740
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
+
1741
1758
/// Contains everything about the channel including state, and various flags.
1742
1759
pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
1743
1760
config: LegacyChannelConfig,
@@ -8592,7 +8609,11 @@ impl<SP: Deref> FundedChannel<SP> where
8592
8609
8593
8610
// Note on channel reserve requirement pre-check: as the splice acceptor does not contribute,
8594
8611
// 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
8596
8617
8597
8618
// TODO(splicing): Store msg.funding_pubkey
8598
8619
// TODO(splicing): Apply start of splice (splice_start)
@@ -8611,14 +8632,24 @@ impl<SP: Deref> FundedChannel<SP> where
8611
8632
8612
8633
/// Handle splice_ack
8613
8634
#[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> {
8615
8636
// 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 {
8617
8640
return Err(ChannelError::Warn(format!("Channel is not in pending splice")));
8618
8641
};
8619
8642
8620
8643
// TODO(splicing): Pre-check for reserve requirement
8621
8644
// (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
8622
8653
Ok(())
8623
8654
}
8624
8655
@@ -13206,4 +13237,69 @@ mod tests {
13206
13237
);
13207
13238
}
13208
13239
}
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
+ }
13209
13305
}
0 commit comments