@@ -11,7 +11,6 @@ use bitcoin::amount::Amount;
1111use bitcoin::constants::ChainHash;
1212use bitcoin::script::{Script, ScriptBuf, Builder};
1313use bitcoin::transaction::Transaction;
14- use bitcoin::sighash;
1514use bitcoin::sighash::EcdsaSighashType;
1615use bitcoin::consensus::encode;
1716
@@ -23,7 +22,9 @@ use bitcoin::hash_types::{Txid, BlockHash};
2322use bitcoin::secp256k1::constants::PUBLIC_KEY_SIZE;
2423use bitcoin::secp256k1::{PublicKey,SecretKey};
2524use bitcoin::secp256k1::{Secp256k1,ecdsa::Signature};
26- use bitcoin::secp256k1;
25+ use bitcoin::{secp256k1, sighash};
26+ #[cfg(splicing)]
27+ use bitcoin::TxIn;
2728
2829use crate::ln::types::ChannelId;
2930use crate::types::payment::{PaymentPreimage, PaymentHash};
@@ -1179,6 +1180,34 @@ impl UnfundedChannelContext {
11791180 }
11801181}
11811182
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+
11821211/// Contains everything about the channel including state, and various flags.
11831212pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
11841213 config: LegacyChannelConfig,
@@ -1214,6 +1243,10 @@ pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
12141243 secp_ctx: Secp256k1<secp256k1::All>,
12151244 channel_value_satoshis: u64,
12161245
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+
12171250 latest_monitor_update_id: u64,
12181251
12191252 holder_signer: ChannelSignerType<SP>,
@@ -1980,6 +2013,9 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
19802013 blocked_monitor_updates: Vec::new(),
19812014
19822015 is_manual_broadcast: false,
2016+
2017+ #[cfg(splicing)]
2018+ pending_splice_pre: None,
19832019 };
19842020
19852021 Ok(channel_context)
@@ -2211,6 +2247,9 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
22112247 blocked_monitor_updates: Vec::new(),
22122248 local_initiated_shutdown: None,
22132249 is_manual_broadcast: false,
2250+
2251+ #[cfg(splicing)]
2252+ pending_splice_pre: None,
22142253 })
22152254 }
22162255
@@ -3771,6 +3810,72 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
37713810 self.channel_transaction_parameters.channel_type_features = self.channel_type.clone();
37723811 Ok(())
37733812 }
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+ }
37743879}
37753880
37763881// Internal utility functions for channels
@@ -7350,6 +7455,28 @@ impl<SP: Deref> Channel<SP> where
73507455 }
73517456 }
73527457
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+ }
73537480
73547481 // Send stuff to our remote peers:
73557482
@@ -9618,6 +9745,9 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
96189745
96199746 blocked_monitor_updates: blocked_monitor_updates.unwrap(),
96209747 is_manual_broadcast: is_manual_broadcast.unwrap_or(false),
9748+
9749+ #[cfg(splicing)]
9750+ pending_splice_pre: None,
96219751 },
96229752 #[cfg(any(dual_funding, splicing))]
96239753 dual_funding_channel_context: None,
@@ -11403,4 +11533,69 @@ mod tests {
1140311533 assert_eq!(node_a_chan.context.channel_state, ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::THEIR_CHANNEL_READY));
1140411534 assert!(node_a_chan.check_get_channel_ready(0, &&logger).is_some());
1140511535 }
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+ }
1140611601}
0 commit comments