@@ -11,7 +11,6 @@ use bitcoin::amount::Amount;
11
11
use bitcoin::constants::ChainHash;
12
12
use bitcoin::script::{Script, ScriptBuf, Builder};
13
13
use bitcoin::transaction::Transaction;
14
- use bitcoin::sighash;
15
14
use bitcoin::sighash::EcdsaSighashType;
16
15
use bitcoin::consensus::encode;
17
16
@@ -23,7 +22,9 @@ use bitcoin::hash_types::{Txid, BlockHash};
23
22
use bitcoin::secp256k1::constants::PUBLIC_KEY_SIZE;
24
23
use bitcoin::secp256k1::{PublicKey,SecretKey};
25
24
use bitcoin::secp256k1::{Secp256k1,ecdsa::Signature};
26
- use bitcoin::secp256k1;
25
+ use bitcoin::{secp256k1, sighash};
26
+ #[cfg(splicing)]
27
+ use bitcoin::TxIn;
27
28
28
29
use crate::ln::types::ChannelId;
29
30
use crate::types::payment::{PaymentPreimage, PaymentHash};
@@ -1179,6 +1180,34 @@ impl UnfundedChannelContext {
1179
1180
}
1180
1181
}
1181
1182
1183
+ /// Info about a pending splice, used in the pre-splice channel
1184
+ #[cfg(splicing)]
1185
+ #[derive(Clone)]
1186
+ pub(crate) struct PendingSpliceInfoPre {
1187
+ pub our_funding_contribution: i64,
1188
+ pub funding_feerate_perkw: u32,
1189
+ pub locktime: u32,
1190
+ /// The funding inputs we will be contributing to the splice.
1191
+ /// TODO(splice): will be changed to TransactionU16LenLimited
1192
+ pub our_funding_inputs: Vec<(TxIn, Transaction)>,
1193
+ }
1194
+
1195
+ #[cfg(splicing)]
1196
+ impl PendingSpliceInfoPre {
1197
+ fn add_checked(base: u64, delta: i64) -> u64 {
1198
+ if delta >= 0 {
1199
+ base.saturating_add(delta as u64)
1200
+ } else {
1201
+ base.saturating_sub(delta.abs() as u64)
1202
+ }
1203
+ }
1204
+
1205
+ /// Compute the post-splice channel value from the pre-splice values and the peer contributions
1206
+ pub fn compute_post_value(pre_channel_value: u64, our_funding_contribution: i64, their_funding_contribution: i64) -> u64 {
1207
+ Self::add_checked(pre_channel_value, our_funding_contribution.saturating_add(their_funding_contribution))
1208
+ }
1209
+ }
1210
+
1182
1211
/// Contains everything about the channel including state, and various flags.
1183
1212
pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
1184
1213
config: LegacyChannelConfig,
@@ -1214,6 +1243,10 @@ pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
1214
1243
secp_ctx: Secp256k1<secp256k1::All>,
1215
1244
channel_value_satoshis: u64,
1216
1245
1246
+ /// Info about an in-progress, pending splice (if any), on the pre-splice channel
1247
+ #[cfg(splicing)]
1248
+ pub(crate) pending_splice_pre: Option<PendingSpliceInfoPre>,
1249
+
1217
1250
latest_monitor_update_id: u64,
1218
1251
1219
1252
holder_signer: ChannelSignerType<SP>,
@@ -1980,6 +2013,9 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
1980
2013
blocked_monitor_updates: Vec::new(),
1981
2014
1982
2015
is_manual_broadcast: false,
2016
+
2017
+ #[cfg(splicing)]
2018
+ pending_splice_pre: None,
1983
2019
};
1984
2020
1985
2021
Ok(channel_context)
@@ -2211,6 +2247,9 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
2211
2247
blocked_monitor_updates: Vec::new(),
2212
2248
local_initiated_shutdown: None,
2213
2249
is_manual_broadcast: false,
2250
+
2251
+ #[cfg(splicing)]
2252
+ pending_splice_pre: None,
2214
2253
})
2215
2254
}
2216
2255
@@ -3771,6 +3810,72 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
3771
3810
self.channel_transaction_parameters.channel_type_features = self.channel_type.clone();
3772
3811
Ok(())
3773
3812
}
3813
+
3814
+ // /// Splice process starting; update state; update capacity, state, reset funding tx
3815
+ // #[cfg(splicing)]
3816
+ // pub(crate) fn splice_start<L: Deref>(&mut self, is_outgoing: bool, logger: &L) where L::Target: Logger {
3817
+ // // Set state, by this point handshake is complete
3818
+ // self.channel_state = ChannelState::NegotiatingFunding(NegotiatingFundingFlags::OUR_INIT_SENT | NegotiatingFundingFlags::THEIR_INIT_SENT);
3819
+
3820
+ // log_info!(logger,
3821
+ // "Splicing process started, new channel value {}, outgoing {}, channel_id {}",
3822
+ // self.channel_value_satoshis, is_outgoing, self.channel_id,
3823
+ // );
3824
+ // }
3825
+
3826
+ /// Get the splice message that can be sent during splice initiation.
3827
+ #[cfg(splicing)]
3828
+ pub fn get_splice_init(&self, our_funding_contribution_satoshis: i64, signer_provider: &SP,
3829
+ funding_feerate_perkw: u32, locktime: u32,
3830
+ ) -> msgs::SpliceInit {
3831
+ if !self.is_outbound() {
3832
+ panic!("Tried to initiate a splice on an inbound channel!");
3833
+ }
3834
+
3835
+ // At this point we are not committed to the new channel value yet, but the funding pubkey
3836
+ // depends on the channel value, so we create here a new funding pubkey with the new
3837
+ // channel value.
3838
+ // Note that channel_keys_id is supposed NOT to change
3839
+ let funding_pubkey = {
3840
+ // TODO: Funding pubkey generation requires the post channel value, but that is not known yet,
3841
+ // the acceptor contribution is missing. There is a need for a way to generate a new funding pubkey,
3842
+ // not based on the channel value
3843
+ let pre_channel_value = self.channel_value_satoshis;
3844
+ let placeholder_counterparty_contribution = 0;
3845
+ let incomplete_post_splice_channel_value = PendingSpliceInfoPre::compute_post_value(pre_channel_value,
3846
+ our_funding_contribution_satoshis, placeholder_counterparty_contribution);
3847
+ let holder_signer = signer_provider.derive_channel_signer(incomplete_post_splice_channel_value, self.channel_keys_id);
3848
+ holder_signer.pubkeys().funding_pubkey
3849
+ };
3850
+
3851
+ msgs::SpliceInit {
3852
+ channel_id: self.channel_id,
3853
+ funding_contribution_satoshis: our_funding_contribution_satoshis,
3854
+ funding_feerate_perkw,
3855
+ locktime,
3856
+ funding_pubkey,
3857
+ require_confirmed_inputs: None,
3858
+ }
3859
+ }
3860
+
3861
+ /// Get the splice_ack message that can be sent in response to splice initiation.
3862
+ #[cfg(splicing)]
3863
+ pub fn get_splice_ack(&mut self, our_funding_contribution_satoshis: i64) -> Result<msgs::SpliceAck, ChannelError> {
3864
+ if self.is_outbound() {
3865
+ panic!("Tried to accept a splice on an outound channel!");
3866
+ }
3867
+
3868
+ // TODO(splicing): checks
3869
+
3870
+ // Note: at this point keys are already updated
3871
+ let funding_pubkey = self.get_holder_pubkeys().funding_pubkey;
3872
+ Ok(msgs::SpliceAck {
3873
+ channel_id: self.channel_id,
3874
+ funding_contribution_satoshis: our_funding_contribution_satoshis,
3875
+ funding_pubkey,
3876
+ require_confirmed_inputs: None,
3877
+ })
3878
+ }
3774
3879
}
3775
3880
3776
3881
// Internal utility functions for channels
@@ -7350,6 +7455,28 @@ impl<SP: Deref> Channel<SP> where
7350
7455
}
7351
7456
}
7352
7457
7458
+ #[cfg(splicing)]
7459
+ pub fn splice_init<ES: Deref, L: Deref>(
7460
+ &mut self, our_funding_contribution_satoshis: i64,
7461
+ _signer_provider: &SP, _entropy_source: &ES, _holder_node_id: PublicKey, logger: &L
7462
+ )
7463
+ -> Result<msgs::SpliceAck, ChannelError>
7464
+ where ES::Target: EntropySource, L::Target: Logger
7465
+ {
7466
+ if !self.context.is_outbound() {
7467
+ // TODO(splicing): Enable starting in the line below
7468
+ // Apply start of splice change in the state
7469
+ // self.context.splice_start(false, logger);
7470
+
7471
+ let splice_ack_msg = self.context.get_splice_ack(our_funding_contribution_satoshis)?;
7472
+ // TODO(splicing): start interactive funding negotiation
7473
+ // let _msg = post_chan.begin_interactive_funding_tx_construction(signer_provider, entropy_source, holder_node_id)
7474
+ // .map_err(|err| ChannelError::Warn(format!("Failed to start interactive transaction construction, {:?}", err)))?;
7475
+ Ok(splice_ack_msg)
7476
+ } else {
7477
+ Err(ChannelError::Warn("Internal consistency error: splice_init on inbound channel".into()))
7478
+ }
7479
+ }
7353
7480
7354
7481
// Send stuff to our remote peers:
7355
7482
@@ -9618,6 +9745,9 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
9618
9745
9619
9746
blocked_monitor_updates: blocked_monitor_updates.unwrap(),
9620
9747
is_manual_broadcast: is_manual_broadcast.unwrap_or(false),
9748
+
9749
+ #[cfg(splicing)]
9750
+ pending_splice_pre: None,
9621
9751
},
9622
9752
#[cfg(any(dual_funding, splicing))]
9623
9753
dual_funding_channel_context: None,
@@ -11403,4 +11533,69 @@ mod tests {
11403
11533
assert_eq!(node_a_chan.context.channel_state, ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::THEIR_CHANNEL_READY));
11404
11534
assert!(node_a_chan.check_get_channel_ready(0, &&logger).is_some());
11405
11535
}
11536
+
11537
+ #[cfg(all(test, splicing))]
11538
+ fn get_pre_and_post(pre_channel_value: u64, our_funding_contribution: i64, their_funding_contribution: i64) -> (u64, u64) {
11539
+ use crate::ln::channel::PendingSpliceInfoPre;
11540
+
11541
+ let post_channel_value = PendingSpliceInfoPre::compute_post_value(pre_channel_value, our_funding_contribution, their_funding_contribution);
11542
+ (pre_channel_value, post_channel_value)
11543
+ }
11544
+
11545
+ #[cfg(all(test, splicing))]
11546
+ #[test]
11547
+ fn test_splice_compute_post_value() {
11548
+ {
11549
+ // increase, small amounts
11550
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, 6_000, 0);
11551
+ assert_eq!(pre_channel_value, 9_000);
11552
+ assert_eq!(post_channel_value, 15_000);
11553
+ }
11554
+ {
11555
+ // increase, small amounts
11556
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, 4_000, 2_000);
11557
+ assert_eq!(pre_channel_value, 9_000);
11558
+ assert_eq!(post_channel_value, 15_000);
11559
+ }
11560
+ {
11561
+ // increase, small amounts
11562
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, 0, 6_000);
11563
+ assert_eq!(pre_channel_value, 9_000);
11564
+ assert_eq!(post_channel_value, 15_000);
11565
+ }
11566
+ {
11567
+ // decrease, small amounts
11568
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(15_000, -6_000, 0);
11569
+ assert_eq!(pre_channel_value, 15_000);
11570
+ assert_eq!(post_channel_value, 9_000);
11571
+ }
11572
+ {
11573
+ // decrease, small amounts
11574
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(15_000, -4_000, -2_000);
11575
+ assert_eq!(pre_channel_value, 15_000);
11576
+ assert_eq!(post_channel_value, 9_000);
11577
+ }
11578
+ {
11579
+ // increase and decrease
11580
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(15_000, 4_000, -2_000);
11581
+ assert_eq!(pre_channel_value, 15_000);
11582
+ assert_eq!(post_channel_value, 17_000);
11583
+ }
11584
+ let base2: u64 = 2;
11585
+ let huge63i3 = (base2.pow(63) - 3) as i64;
11586
+ assert_eq!(huge63i3, 9223372036854775805);
11587
+ assert_eq!(-huge63i3, -9223372036854775805);
11588
+ {
11589
+ // increase, large amount
11590
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, huge63i3, 3);
11591
+ assert_eq!(pre_channel_value, 9_000);
11592
+ assert_eq!(post_channel_value, 9223372036854784807);
11593
+ }
11594
+ {
11595
+ // increase, large amounts
11596
+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, huge63i3, huge63i3);
11597
+ assert_eq!(pre_channel_value, 9_000);
11598
+ assert_eq!(post_channel_value, 9223372036854784807);
11599
+ }
11600
+ }
11406
11601
}
0 commit comments