@@ -1524,7 +1524,7 @@ impl<SP: Deref> Channel<SP> where
1524
1524
holder_commitment_point,
1525
1525
is_v2_established: true,
1526
1526
#[cfg(splicing)]
1527
- pending_splice : None,
1527
+ pending_splice_pre : None,
1528
1528
};
1529
1529
let res = funded_channel.commitment_signed_initial_v2(msg, best_block, signer_provider, logger)
1530
1530
.map(|monitor| (Some(monitor), None))
@@ -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,
@@ -4953,7 +4970,7 @@ pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
4953
4970
is_v2_established: bool,
4954
4971
/// Info about an in-progress, pending splice (if any), on the pre-splice channel
4955
4972
#[cfg(splicing)]
4956
- pending_splice : Option<PendingSplice>,
4973
+ pending_splice_pre : Option<PendingSplice>,
4957
4974
}
4958
4975
4959
4976
#[cfg(any(test, fuzzing))]
@@ -8496,7 +8513,7 @@ impl<SP: Deref> FundedChannel<SP> where
8496
8513
) -> Result<msgs::SpliceInit, APIError> {
8497
8514
// Check if a splice has been initiated already.
8498
8515
// 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 {
8500
8517
return Err(APIError::APIMisuseError { err: format!(
8501
8518
"Channel {} cannot be spliced, as it has already a splice pending (contribution {})",
8502
8519
self.context.channel_id(), splice_info.our_funding_contribution
@@ -8532,7 +8549,7 @@ impl<SP: Deref> FundedChannel<SP> where
8532
8549
self.context.channel_id(), err,
8533
8550
)})?;
8534
8551
8535
- self.pending_splice = Some(PendingSplice {
8552
+ self.pending_splice_pre = Some(PendingSplice {
8536
8553
our_funding_contribution: our_funding_contribution_satoshis,
8537
8554
});
8538
8555
@@ -8566,7 +8583,7 @@ impl<SP: Deref> FundedChannel<SP> where
8566
8583
let our_funding_contribution_satoshis = 0i64;
8567
8584
8568
8585
// 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 {
8570
8587
return Err(ChannelError::Warn(format!(
8571
8588
"Channel has already a splice pending, contribution {}", splice_info.our_funding_contribution,
8572
8589
)));
@@ -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_pre {
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
@@ -9553,7 +9584,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
9553
9584
is_v2_established: false,
9554
9585
holder_commitment_point,
9555
9586
#[cfg(splicing)]
9556
- pending_splice : None,
9587
+ pending_splice_pre : None,
9557
9588
};
9558
9589
9559
9590
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 {
9829
9860
is_v2_established: false,
9830
9861
holder_commitment_point,
9831
9862
#[cfg(splicing)]
9832
- pending_splice : None,
9863
+ pending_splice_pre : None,
9833
9864
};
9834
9865
let need_channel_ready = channel.check_get_channel_ready(0, logger).is_some()
9835
9866
|| 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
11266
11297
is_v2_established,
11267
11298
holder_commitment_point,
11268
11299
#[cfg(splicing)]
11269
- pending_splice : None,
11300
+ pending_splice_pre : None,
11270
11301
})
11271
11302
}
11272
11303
}
@@ -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