@@ -1522,7 +1522,7 @@ impl<SP: Deref> Channel<SP> where
1522
1522
holder_commitment_point,
1523
1523
is_v2_established: true,
1524
1524
#[cfg(splicing)]
1525
- pending_splice : None,
1525
+ pending_splice_pre : None,
1526
1526
};
1527
1527
let res = funded_channel.commitment_signed_initial_v2(msg, best_block, signer_provider, logger)
1528
1528
.map(|monitor| (Some(monitor), None))
@@ -1727,8 +1727,30 @@ impl FundingScope {
1727
1727
1728
1728
/// Info about a pending splice, used in the pre-splice channel
1729
1729
#[cfg(splicing)]
1730
+ #[derive(Clone)]
1730
1731
struct PendingSplice {
1731
1732
pub our_funding_contribution: i64,
1733
+ pub funding_feerate_per_kw: u32,
1734
+ pub locktime: u32,
1735
+ /// The funding inputs that we plan to contributing to the splice.
1736
+ pub our_funding_inputs: Vec<(TxIn, TransactionU16LenLimited)>,
1737
+ }
1738
+
1739
+ #[cfg(splicing)]
1740
+ impl PendingSplice {
1741
+ #[inline]
1742
+ fn add_checked(base: u64, delta: i64) -> u64 {
1743
+ if delta >= 0 {
1744
+ base.saturating_add(delta as u64)
1745
+ } else {
1746
+ base.saturating_sub(delta.abs() as u64)
1747
+ }
1748
+ }
1749
+
1750
+ /// Compute the post-splice channel value from the pre-splice values and the peer contributions
1751
+ pub fn compute_post_value(pre_channel_value: u64, our_funding_contribution: i64, their_funding_contribution: i64) -> u64 {
1752
+ Self::add_checked(pre_channel_value, our_funding_contribution.saturating_add(their_funding_contribution))
1753
+ }
1732
1754
}
1733
1755
1734
1756
/// Contains everything about the channel including state, and various flags.
@@ -4981,7 +5003,7 @@ pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
4981
5003
is_v2_established: bool,
4982
5004
/// Info about an in-progress, pending splice (if any), on the pre-splice channel
4983
5005
#[cfg(splicing)]
4984
- pending_splice : Option<PendingSplice>,
5006
+ pending_splice_pre : Option<PendingSplice>,
4985
5007
}
4986
5008
4987
5009
#[cfg(any(test, fuzzing))]
@@ -8516,7 +8538,7 @@ impl<SP: Deref> FundedChannel<SP> where
8516
8538
) -> Result<msgs::SpliceInit, APIError> {
8517
8539
// Check if a splice has been initiated already.
8518
8540
// Note: only a single outstanding splice is supported (per spec)
8519
- if let Some(splice_info) = &self.pending_splice {
8541
+ if let Some(splice_info) = &self.pending_splice_pre {
8520
8542
return Err(APIError::APIMisuseError { err: format!(
8521
8543
"Channel {} cannot be spliced, as it has already a splice pending (contribution {})",
8522
8544
self.context.channel_id(), splice_info.our_funding_contribution
@@ -8552,8 +8574,20 @@ impl<SP: Deref> FundedChannel<SP> where
8552
8574
self.context.channel_id(), err,
8553
8575
)})?;
8554
8576
8555
- self.pending_splice = Some(PendingSplice {
8577
+ // convert inputs
8578
+ let mut funding_inputs = Vec::new();
8579
+ for (tx_in, tx, _w) in our_funding_inputs.into_iter() {
8580
+ let tx16 = TransactionU16LenLimited::new(tx.clone()).map_err(
8581
+ |e| APIError::APIMisuseError { err: format!("Too large transaction, {:?}", e)}
8582
+ )?;
8583
+ funding_inputs.push((tx_in.clone(), tx16));
8584
+ }
8585
+
8586
+ self.pending_splice_pre = Some(PendingSplice {
8556
8587
our_funding_contribution: our_funding_contribution_satoshis,
8588
+ funding_feerate_per_kw,
8589
+ locktime,
8590
+ our_funding_inputs: funding_inputs,
8557
8591
});
8558
8592
8559
8593
let msg = self.get_splice_init(our_funding_contribution_satoshis, funding_feerate_per_kw, locktime);
@@ -8580,13 +8614,13 @@ impl<SP: Deref> FundedChannel<SP> where
8580
8614
8581
8615
/// Handle splice_init
8582
8616
#[cfg(splicing)]
8583
- pub fn splice_init(&mut self, msg: &msgs::SpliceInit) -> Result<msgs::SpliceAck, ChannelError> {
8617
+ pub fn splice_init<L: Deref> (&mut self, msg: &msgs::SpliceInit, logger: &L ) -> Result<msgs::SpliceAck, ChannelError> where L::Target: Logger {
8584
8618
let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
8585
8619
// TODO(splicing): Currently not possible to contribute on the splicing-acceptor side
8586
8620
let our_funding_contribution_satoshis = 0i64;
8587
8621
8588
8622
// Check if a splice has been initiated already.
8589
- if let Some(splice_info) = &self.pending_splice {
8623
+ if let Some(splice_info) = &self.pending_splice_pre {
8590
8624
return Err(ChannelError::Warn(format!(
8591
8625
"Channel has already a splice pending, contribution {}", splice_info.our_funding_contribution,
8592
8626
)));
@@ -8615,7 +8649,8 @@ impl<SP: Deref> FundedChannel<SP> where
8615
8649
// TODO(splicing): Once splice acceptor can contribute, add reserve pre-check, similar to the one in `splice_ack`.
8616
8650
8617
8651
// TODO(splicing): Store msg.funding_pubkey
8618
- // TODO(splicing): Apply start of splice (splice_start)
8652
+ // Apply start of splice change in the state
8653
+ self.splice_start(false, logger);
8619
8654
8620
8655
// TODO(splicing): The exisiting pubkey is reused, but a new one should be generated. See #3542.
8621
8656
// Note that channel_keys_id is supposed NOT to change
@@ -8626,22 +8661,55 @@ impl<SP: Deref> FundedChannel<SP> where
8626
8661
require_confirmed_inputs: None,
8627
8662
};
8628
8663
// TODO(splicing): start interactive funding negotiation
8664
+ // let _msg = self.begin_interactive_funding_tx_construction(signer_provider, entropy_source, holder_node_id)
8665
+ // .map_err(|err| ChannelError::Warn(format!("Failed to start interactive transaction construction, {:?}", err)))?;
8666
+
8629
8667
Ok(splice_ack_msg)
8630
8668
}
8631
8669
8632
8670
/// Handle splice_ack
8633
8671
#[cfg(splicing)]
8634
- pub fn splice_ack(&mut self, _msg : &msgs::SpliceAck) -> Result<(), ChannelError> {
8672
+ pub fn splice_ack<L: Deref> (&mut self, msg : &msgs::SpliceAck, logger: &L ) -> Result<(), ChannelError> where L::Target: Logger {
8635
8673
// check if splice is pending
8636
- if self.pending_splice.is_none() {
8674
+ let pending_splice = if let Some(pending_splice) = &self.pending_splice_pre {
8675
+ pending_splice
8676
+ } else {
8637
8677
return Err(ChannelError::Warn(format!("Channel is not in pending splice")));
8638
8678
};
8639
8679
8680
+
8681
+ let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
8682
+ let our_funding_contribution = pending_splice.our_funding_contribution;
8683
+
8684
+ let pre_channel_value = self.funding.get_value_satoshis();
8685
+ let post_channel_value = PendingSplice::compute_post_value(pre_channel_value, our_funding_contribution, their_funding_contribution_satoshis);
8686
+ let post_balance = PendingSplice::add_checked(self.funding.value_to_self_msat, our_funding_contribution);
8687
+
8640
8688
// TODO(splicing): Pre-check for reserve requirement
8641
8689
// (Note: It should also be checked later at tx_complete)
8690
+
8691
+ // Apply start of splice change in the state
8692
+ self.splice_start(true, logger);
8693
+
8694
+ // TODO(splicing): start interactive funding negotiation
8695
+ // let tx_msg_opt = self.begin_interactive_funding_tx_construction(signer_provider, entropy_source, holder_node_id)
8696
+ // .map_err(|err| ChannelError::Warn(format!("V2 channel rejected due to sender error, {:?}", err)))?;
8697
+ // Ok(tx_msg_opt)
8642
8698
Ok(())
8643
8699
}
8644
8700
8701
+ /// Splice process starting; update state, log, etc.
8702
+ #[cfg(splicing)]
8703
+ pub(crate) fn splice_start<L: Deref>(&mut self, is_outgoing: bool, logger: &L) where L::Target: Logger {
8704
+ // Set state, by this point splice_init/splice_ack handshake is complete
8705
+ // TODO(splicing)
8706
+ // self.channel_state = ChannelState::NegotiatingFunding(
8707
+ // NegotiatingFundingFlags::OUR_INIT_SENT | NegotiatingFundingFlags::THEIR_INIT_SENT
8708
+ // );
8709
+ log_info!(logger, "Splicing process started, old channel value {}, outgoing {}, channel_id {}",
8710
+ self.funding.get_value_satoshis(), is_outgoing, self.context.channel_id);
8711
+ }
8712
+
8645
8713
// Send stuff to our remote peers:
8646
8714
8647
8715
/// Queues up an outbound HTLC to send by placing it in the holding cell. You should call
@@ -9565,7 +9633,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
9565
9633
is_v2_established: false,
9566
9634
holder_commitment_point,
9567
9635
#[cfg(splicing)]
9568
- pending_splice : None,
9636
+ pending_splice_pre : None,
9569
9637
};
9570
9638
9571
9639
let need_channel_ready = channel.check_get_channel_ready(0, logger).is_some()
@@ -9841,7 +9909,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
9841
9909
is_v2_established: false,
9842
9910
holder_commitment_point,
9843
9911
#[cfg(splicing)]
9844
- pending_splice : None,
9912
+ pending_splice_pre : None,
9845
9913
};
9846
9914
let need_channel_ready = channel.check_get_channel_ready(0, logger).is_some()
9847
9915
|| channel.context.signer_pending_channel_ready;
@@ -11224,7 +11292,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
11224
11292
is_v2_established,
11225
11293
holder_commitment_point,
11226
11294
#[cfg(splicing)]
11227
- pending_splice : None,
11295
+ pending_splice_pre : None,
11228
11296
})
11229
11297
}
11230
11298
}
@@ -13146,4 +13214,69 @@ mod tests {
13146
13214
);
13147
13215
}
13148
13216
}
13217
+
13218
+ #[cfg(all(test, splicing))]
13219
+ fn get_pre_and_post(pre_channel_value: u64, our_funding_contribution: i64, their_funding_contribution: i64) -> (u64, u64) {
13220
+ use crate::ln::channel::PendingSplice;
13221
+
13222
+ let post_channel_value = PendingSplice::compute_post_value(pre_channel_value, our_funding_contribution, their_funding_contribution);
13223
+ (pre_channel_value, post_channel_value)
13224
+ }
13225
+
13226
+ #[cfg(all(test, splicing))]
13227
+ #[test]
13228
+ fn test_splice_compute_post_value() {
13229
+ {
13230
+ // increase, small amounts
13231
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, 6_000, 0);
13232
+ assert_eq!(pre_channel_value, 9_000);
13233
+ assert_eq!(post_channel_value, 15_000);
13234
+ }
13235
+ {
13236
+ // increase, small amounts
13237
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, 4_000, 2_000);
13238
+ assert_eq!(pre_channel_value, 9_000);
13239
+ assert_eq!(post_channel_value, 15_000);
13240
+ }
13241
+ {
13242
+ // increase, small amounts
13243
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, 0, 6_000);
13244
+ assert_eq!(pre_channel_value, 9_000);
13245
+ assert_eq!(post_channel_value, 15_000);
13246
+ }
13247
+ {
13248
+ // decrease, small amounts
13249
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(15_000, -6_000, 0);
13250
+ assert_eq!(pre_channel_value, 15_000);
13251
+ assert_eq!(post_channel_value, 9_000);
13252
+ }
13253
+ {
13254
+ // decrease, small amounts
13255
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(15_000, -4_000, -2_000);
13256
+ assert_eq!(pre_channel_value, 15_000);
13257
+ assert_eq!(post_channel_value, 9_000);
13258
+ }
13259
+ {
13260
+ // increase and decrease
13261
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(15_000, 4_000, -2_000);
13262
+ assert_eq!(pre_channel_value, 15_000);
13263
+ assert_eq!(post_channel_value, 17_000);
13264
+ }
13265
+ let base2: u64 = 2;
13266
+ let huge63i3 = (base2.pow(63) - 3) as i64;
13267
+ assert_eq!(huge63i3, 9223372036854775805);
13268
+ assert_eq!(-huge63i3, -9223372036854775805);
13269
+ {
13270
+ // increase, large amount
13271
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, huge63i3, 3);
13272
+ assert_eq!(pre_channel_value, 9_000);
13273
+ assert_eq!(post_channel_value, 9223372036854784807);
13274
+ }
13275
+ {
13276
+ // increase, large amounts
13277
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, huge63i3, huge63i3);
13278
+ assert_eq!(pre_channel_value, 9_000);
13279
+ assert_eq!(post_channel_value, 9223372036854784807);
13280
+ }
13281
+ }
13149
13282
}
0 commit comments