@@ -1519,7 +1519,7 @@ impl<SP: Deref> Channel<SP> where
1519
1519
holder_commitment_point,
1520
1520
is_v2_established: true,
1521
1521
#[cfg(splicing)]
1522
- pending_splice : None,
1522
+ pending_splice_pre : None,
1523
1523
};
1524
1524
let res = funded_channel.commitment_signed_initial_v2(msg, best_block, signer_provider, logger)
1525
1525
.map(|monitor| (Some(monitor), None))
@@ -1724,8 +1724,30 @@ impl FundingScope {
1724
1724
1725
1725
/// Info about a pending splice, used in the pre-splice channel
1726
1726
#[cfg(splicing)]
1727
+ #[derive(Clone)]
1727
1728
struct PendingSplice {
1728
1729
pub our_funding_contribution: i64,
1730
+ pub funding_feerate_per_kw: u32,
1731
+ pub locktime: u32,
1732
+ /// The funding inputs that we plan to contributing to the splice.
1733
+ pub our_funding_inputs: Vec<(TxIn, TransactionU16LenLimited)>,
1734
+ }
1735
+
1736
+ #[cfg(splicing)]
1737
+ impl PendingSplice {
1738
+ #[inline]
1739
+ fn add_checked(base: u64, delta: i64) -> u64 {
1740
+ if delta >= 0 {
1741
+ base.saturating_add(delta as u64)
1742
+ } else {
1743
+ base.saturating_sub(delta.abs() as u64)
1744
+ }
1745
+ }
1746
+
1747
+ /// Compute the post-splice channel value from the pre-splice values and the peer contributions
1748
+ pub fn compute_post_value(pre_channel_value: u64, our_funding_contribution: i64, their_funding_contribution: i64) -> u64 {
1749
+ Self::add_checked(pre_channel_value, our_funding_contribution.saturating_add(their_funding_contribution))
1750
+ }
1729
1751
}
1730
1752
1731
1753
/// Contains everything about the channel including state, and various flags.
@@ -5003,7 +5025,7 @@ pub(super) struct FundedChannel<SP: Deref> where SP::Target: SignerProvider {
5003
5025
is_v2_established: bool,
5004
5026
/// Info about an in-progress, pending splice (if any), on the pre-splice channel
5005
5027
#[cfg(splicing)]
5006
- pending_splice : Option<PendingSplice>,
5028
+ pending_splice_pre : Option<PendingSplice>,
5007
5029
}
5008
5030
5009
5031
#[cfg(any(test, fuzzing))]
@@ -8535,7 +8557,7 @@ impl<SP: Deref> FundedChannel<SP> where
8535
8557
) -> Result<msgs::SpliceInit, APIError> {
8536
8558
// Check if a splice has been initiated already.
8537
8559
// Note: only a single outstanding splice is supported (per spec)
8538
- if let Some(splice_info) = &self.pending_splice {
8560
+ if let Some(splice_info) = &self.pending_splice_pre {
8539
8561
return Err(APIError::APIMisuseError { err: format!(
8540
8562
"Channel {} cannot be spliced, as it has already a splice pending (contribution {})",
8541
8563
self.context.channel_id(), splice_info.our_funding_contribution
@@ -8571,8 +8593,20 @@ impl<SP: Deref> FundedChannel<SP> where
8571
8593
self.context.channel_id(), err,
8572
8594
)})?;
8573
8595
8574
- self.pending_splice = Some(PendingSplice {
8596
+ // convert inputs
8597
+ let mut funding_inputs = Vec::new();
8598
+ for (tx_in, tx, _w) in our_funding_inputs.into_iter() {
8599
+ let tx16 = TransactionU16LenLimited::new(tx.clone()).map_err(
8600
+ |e| APIError::APIMisuseError { err: format!("Too large transaction, {:?}", e)}
8601
+ )?;
8602
+ funding_inputs.push((tx_in.clone(), tx16));
8603
+ }
8604
+
8605
+ self.pending_splice_pre = Some(PendingSplice {
8575
8606
our_funding_contribution: our_funding_contribution_satoshis,
8607
+ funding_feerate_per_kw,
8608
+ locktime,
8609
+ our_funding_inputs: funding_inputs,
8576
8610
});
8577
8611
8578
8612
let msg = self.get_splice_init(our_funding_contribution_satoshis, funding_feerate_per_kw, locktime);
@@ -8599,13 +8633,13 @@ impl<SP: Deref> FundedChannel<SP> where
8599
8633
8600
8634
/// Handle splice_init
8601
8635
#[cfg(splicing)]
8602
- pub fn splice_init(&mut self, msg: &msgs::SpliceInit) -> Result<msgs::SpliceAck, ChannelError> {
8636
+ pub fn splice_init<L: Deref> (&mut self, msg: &msgs::SpliceInit, logger: &L ) -> Result<msgs::SpliceAck, ChannelError> where L::Target: Logger {
8603
8637
let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
8604
8638
// TODO(splicing): Currently not possible to contribute on the splicing-acceptor side
8605
8639
let our_funding_contribution_satoshis = 0i64;
8606
8640
8607
8641
// Check if a splice has been initiated already.
8608
- if let Some(splice_info) = &self.pending_splice {
8642
+ if let Some(splice_info) = &self.pending_splice_pre {
8609
8643
return Err(ChannelError::Warn(format!(
8610
8644
"Channel has already a splice pending, contribution {}", splice_info.our_funding_contribution,
8611
8645
)));
@@ -8634,7 +8668,8 @@ impl<SP: Deref> FundedChannel<SP> where
8634
8668
// TODO(splicing): Once splice acceptor can contribute, add reserve pre-check, similar to the one in `splice_ack`.
8635
8669
8636
8670
// TODO(splicing): Store msg.funding_pubkey
8637
- // TODO(splicing): Apply start of splice (splice_start)
8671
+ // Apply start of splice change in the state
8672
+ self.splice_start(false, logger);
8638
8673
8639
8674
// TODO(splicing): The exisiting pubkey is reused, but a new one should be generated. See #3542.
8640
8675
// Note that channel_keys_id is supposed NOT to change
@@ -8645,22 +8680,55 @@ impl<SP: Deref> FundedChannel<SP> where
8645
8680
require_confirmed_inputs: None,
8646
8681
};
8647
8682
// TODO(splicing): start interactive funding negotiation
8683
+ // let _msg = self.begin_interactive_funding_tx_construction(signer_provider, entropy_source, holder_node_id)
8684
+ // .map_err(|err| ChannelError::Warn(format!("Failed to start interactive transaction construction, {:?}", err)))?;
8685
+
8648
8686
Ok(splice_ack_msg)
8649
8687
}
8650
8688
8651
8689
/// Handle splice_ack
8652
8690
#[cfg(splicing)]
8653
- pub fn splice_ack(&mut self, _msg : &msgs::SpliceAck) -> Result<(), ChannelError> {
8691
+ pub fn splice_ack<L: Deref> (&mut self, msg : &msgs::SpliceAck, logger: &L ) -> Result<(), ChannelError> where L::Target: Logger {
8654
8692
// check if splice is pending
8655
- if self.pending_splice.is_none() {
8693
+ let pending_splice = if let Some(pending_splice) = &self.pending_splice_pre {
8694
+ pending_splice
8695
+ } else {
8656
8696
return Err(ChannelError::Warn(format!("Channel is not in pending splice")));
8657
8697
};
8658
8698
8699
+
8700
+ let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
8701
+ let our_funding_contribution = pending_splice.our_funding_contribution;
8702
+
8703
+ let pre_channel_value = self.funding.get_value_satoshis();
8704
+ let post_channel_value = PendingSplice::compute_post_value(pre_channel_value, our_funding_contribution, their_funding_contribution_satoshis);
8705
+ let post_balance = PendingSplice::add_checked(self.funding.value_to_self_msat, our_funding_contribution);
8706
+
8659
8707
// TODO(splicing): Pre-check for reserve requirement
8660
8708
// (Note: It should also be checked later at tx_complete)
8709
+
8710
+ // Apply start of splice change in the state
8711
+ self.splice_start(true, logger);
8712
+
8713
+ // TODO(splicing): start interactive funding negotiation
8714
+ // let tx_msg_opt = self.begin_interactive_funding_tx_construction(signer_provider, entropy_source, holder_node_id)
8715
+ // .map_err(|err| ChannelError::Warn(format!("V2 channel rejected due to sender error, {:?}", err)))?;
8716
+ // Ok(tx_msg_opt)
8661
8717
Ok(())
8662
8718
}
8663
8719
8720
+ /// Splice process starting; update state, log, etc.
8721
+ #[cfg(splicing)]
8722
+ pub(crate) fn splice_start<L: Deref>(&mut self, is_outgoing: bool, logger: &L) where L::Target: Logger {
8723
+ // Set state, by this point splice_init/splice_ack handshake is complete
8724
+ // TODO(splicing)
8725
+ // self.channel_state = ChannelState::NegotiatingFunding(
8726
+ // NegotiatingFundingFlags::OUR_INIT_SENT | NegotiatingFundingFlags::THEIR_INIT_SENT
8727
+ // );
8728
+ log_info!(logger, "Splicing process started, old channel value {}, outgoing {}, channel_id {}",
8729
+ self.funding.get_value_satoshis(), is_outgoing, self.context.channel_id);
8730
+ }
8731
+
8664
8732
// Send stuff to our remote peers:
8665
8733
8666
8734
/// Queues up an outbound HTLC to send by placing it in the holding cell. You should call
@@ -9582,7 +9650,7 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
9582
9650
is_v2_established: false,
9583
9651
holder_commitment_point,
9584
9652
#[cfg(splicing)]
9585
- pending_splice : None,
9653
+ pending_splice_pre : None,
9586
9654
};
9587
9655
9588
9656
let need_channel_ready = channel.check_get_channel_ready(0, logger).is_some()
@@ -9858,7 +9926,7 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
9858
9926
is_v2_established: false,
9859
9927
holder_commitment_point,
9860
9928
#[cfg(splicing)]
9861
- pending_splice : None,
9929
+ pending_splice_pre : None,
9862
9930
};
9863
9931
let need_channel_ready = channel.check_get_channel_ready(0, logger).is_some()
9864
9932
|| channel.context.signer_pending_channel_ready;
@@ -11241,7 +11309,7 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, &'c Channel
11241
11309
is_v2_established,
11242
11310
holder_commitment_point,
11243
11311
#[cfg(splicing)]
11244
- pending_splice : None,
11312
+ pending_splice_pre : None,
11245
11313
})
11246
11314
}
11247
11315
}
@@ -13172,4 +13240,69 @@ mod tests {
13172
13240
);
13173
13241
}
13174
13242
}
13243
+
13244
+ #[cfg(all(test, splicing))]
13245
+ fn get_pre_and_post(pre_channel_value: u64, our_funding_contribution: i64, their_funding_contribution: i64) -> (u64, u64) {
13246
+ use crate::ln::channel::PendingSplice;
13247
+
13248
+ let post_channel_value = PendingSplice::compute_post_value(pre_channel_value, our_funding_contribution, their_funding_contribution);
13249
+ (pre_channel_value, post_channel_value)
13250
+ }
13251
+
13252
+ #[cfg(all(test, splicing))]
13253
+ #[test]
13254
+ fn test_splice_compute_post_value() {
13255
+ {
13256
+ // increase, small amounts
13257
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, 6_000, 0);
13258
+ assert_eq!(pre_channel_value, 9_000);
13259
+ assert_eq!(post_channel_value, 15_000);
13260
+ }
13261
+ {
13262
+ // increase, small amounts
13263
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, 4_000, 2_000);
13264
+ assert_eq!(pre_channel_value, 9_000);
13265
+ assert_eq!(post_channel_value, 15_000);
13266
+ }
13267
+ {
13268
+ // increase, small amounts
13269
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, 0, 6_000);
13270
+ assert_eq!(pre_channel_value, 9_000);
13271
+ assert_eq!(post_channel_value, 15_000);
13272
+ }
13273
+ {
13274
+ // decrease, small amounts
13275
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(15_000, -6_000, 0);
13276
+ assert_eq!(pre_channel_value, 15_000);
13277
+ assert_eq!(post_channel_value, 9_000);
13278
+ }
13279
+ {
13280
+ // decrease, small amounts
13281
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(15_000, -4_000, -2_000);
13282
+ assert_eq!(pre_channel_value, 15_000);
13283
+ assert_eq!(post_channel_value, 9_000);
13284
+ }
13285
+ {
13286
+ // increase and decrease
13287
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(15_000, 4_000, -2_000);
13288
+ assert_eq!(pre_channel_value, 15_000);
13289
+ assert_eq!(post_channel_value, 17_000);
13290
+ }
13291
+ let base2: u64 = 2;
13292
+ let huge63i3 = (base2.pow(63) - 3) as i64;
13293
+ assert_eq!(huge63i3, 9223372036854775805);
13294
+ assert_eq!(-huge63i3, -9223372036854775805);
13295
+ {
13296
+ // increase, large amount
13297
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, huge63i3, 3);
13298
+ assert_eq!(pre_channel_value, 9_000);
13299
+ assert_eq!(post_channel_value, 9223372036854784807);
13300
+ }
13301
+ {
13302
+ // increase, large amounts
13303
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, huge63i3, huge63i3);
13304
+ assert_eq!(pre_channel_value, 9_000);
13305
+ assert_eq!(post_channel_value, 9223372036854784807);
13306
+ }
13307
+ }
13175
13308
}
0 commit comments