@@ -11,7 +11,6 @@ use bitcoin::amount::Amount;
1111use bitcoin::constants::ChainHash;
1212use bitcoin::script::{Script, ScriptBuf, Builder, WScriptHash};
1313use bitcoin::transaction::{Transaction, TxIn};
14- use bitcoin::sighash;
1514use bitcoin::sighash::EcdsaSighashType;
1615use bitcoin::consensus::encode;
1716use bitcoin::absolute::LockTime;
@@ -25,7 +24,7 @@ use bitcoin::hash_types::{Txid, BlockHash};
2524use bitcoin::secp256k1::constants::PUBLIC_KEY_SIZE;
2625use bitcoin::secp256k1::{PublicKey,SecretKey};
2726use bitcoin::secp256k1::{Secp256k1,ecdsa::Signature};
28- use bitcoin::secp256k1;
27+ use bitcoin::{ secp256k1, sighash} ;
2928
3029use crate::ln::types::ChannelId;
3130use crate::types::payment::{PaymentPreimage, PaymentHash};
@@ -1182,6 +1181,30 @@ impl UnfundedChannelContext {
11821181 }
11831182}
11841183
1184+ /// Info about a pending splice, used in the pre-splice channel
1185+ #[cfg(splicing)]
1186+ #[derive(Clone)]
1187+ struct PendingSplice {
1188+ pub our_funding_contribution: i64,
1189+ }
1190+
1191+ #[cfg(splicing)]
1192+ impl PendingSplice {
1193+ #[inline]
1194+ fn add_checked(base: u64, delta: i64) -> u64 {
1195+ if delta >= 0 {
1196+ base.saturating_add(delta as u64)
1197+ } else {
1198+ base.saturating_sub(delta.abs() as u64)
1199+ }
1200+ }
1201+
1202+ /// Compute the post-splice channel value from the pre-splice values and the peer contributions
1203+ pub fn compute_post_value(pre_channel_value: u64, our_funding_contribution: i64, their_funding_contribution: i64) -> u64 {
1204+ Self::add_checked(pre_channel_value, our_funding_contribution.saturating_add(their_funding_contribution))
1205+ }
1206+ }
1207+
11851208/// Contains everything about the channel including state, and various flags.
11861209pub(super) struct ChannelContext<SP: Deref> where SP::Target: SignerProvider {
11871210 config: LegacyChannelConfig,
@@ -3623,6 +3646,33 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
36233646 (context.holder_selected_channel_reserve_satoshis, context.counterparty_selected_channel_reserve_satoshis)
36243647 }
36253648
3649+ /// Check that a balance value meets the channel reserve requirements or violates them (below reserve).
3650+ /// The channel value is an input as opposed to using from self, so that this can be used in case of splicing
3651+ /// to checks with new channel value (before being comitted to it).
3652+ #[cfg(splicing)]
3653+ pub fn check_balance_meets_reserve_requirements(&self, balance: u64, channel_value: u64) -> Result<(), ChannelError> {
3654+ if balance == 0 {
3655+ return Ok(());
3656+ }
3657+ let holder_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
3658+ channel_value, self.holder_dust_limit_satoshis);
3659+ if balance < holder_selected_channel_reserve_satoshis {
3660+ return Err(ChannelError::Warn(format!(
3661+ "Balance below reserve mandated by holder, {} vs {}",
3662+ balance, holder_selected_channel_reserve_satoshis,
3663+ )));
3664+ }
3665+ let counterparty_selected_channel_reserve_satoshis = get_v2_channel_reserve_satoshis(
3666+ channel_value, self.counterparty_dust_limit_satoshis);
3667+ if balance < counterparty_selected_channel_reserve_satoshis {
3668+ return Err(ChannelError::Warn(format!(
3669+ "Balance below reserve mandated by counterparty, {} vs {}",
3670+ balance, counterparty_selected_channel_reserve_satoshis,
3671+ )));
3672+ }
3673+ Ok(())
3674+ }
3675+
36263676 /// Get the commitment tx fee for the local's (i.e. our) next commitment transaction based on the
36273677 /// number of pending HTLCs that are on track to be in our next commitment tx.
36283678 ///
@@ -4093,6 +4143,38 @@ impl<SP: Deref> ChannelContext<SP> where SP::Target: SignerProvider {
40934143 self.channel_transaction_parameters = channel_transaction_parameters;
40944144 self.get_initial_counterparty_commitment_signature(logger)
40954145 }
4146+
4147+ /// Get the splice message that can be sent during splice initiation.
4148+ #[cfg(splicing)]
4149+ pub fn get_splice_init(&self, our_funding_contribution_satoshis: i64,
4150+ funding_feerate_perkw: u32, locktime: u32,
4151+ ) -> msgs::SpliceInit {
4152+ // Reuse the existing funding pubkey, in spite of the channel value changing
4153+ // (though at this point we don't know the new value yet, due tue the optional counterparty contribution)
4154+ // Note that channel_keys_id is supposed NOT to change
4155+ let funding_pubkey = self.get_holder_pubkeys().funding_pubkey.clone();
4156+ msgs::SpliceInit {
4157+ channel_id: self.channel_id,
4158+ funding_contribution_satoshis: our_funding_contribution_satoshis,
4159+ funding_feerate_perkw,
4160+ locktime,
4161+ funding_pubkey,
4162+ require_confirmed_inputs: None,
4163+ }
4164+ }
4165+
4166+ /// Get the splice_ack message that can be sent in response to splice initiation.
4167+ #[cfg(splicing)]
4168+ pub fn get_splice_ack(&self, our_funding_contribution_satoshis: i64) -> msgs::SpliceAck {
4169+ // Reuse the existing funding pubkey, in spite of the channel value changing
4170+ let funding_pubkey = self.get_holder_pubkeys().funding_pubkey;
4171+ msgs::SpliceAck {
4172+ channel_id: self.channel_id,
4173+ funding_contribution_satoshis: our_funding_contribution_satoshis,
4174+ funding_pubkey,
4175+ require_confirmed_inputs: None,
4176+ }
4177+ }
40964178}
40974179
40984180// Internal utility functions for channels
@@ -4214,6 +4296,9 @@ pub(super) struct DualFundingChannelContext {
42144296pub(super) struct Channel<SP: Deref> where SP::Target: SignerProvider {
42154297 pub context: ChannelContext<SP>,
42164298 pub interactive_tx_signing_session: Option<InteractiveTxSigningSession>,
4299+ /// Info about an in-progress, pending splice (if any), on the pre-splice channel
4300+ #[cfg(splicing)]
4301+ pending_splice_pre: Option<PendingSplice>,
42174302}
42184303
42194304#[cfg(any(test, fuzzing))]
@@ -7815,6 +7900,135 @@ impl<SP: Deref> Channel<SP> where
78157900 }
78167901 }
78177902
7903+ /// Initiate splicing
7904+ #[cfg(splicing)]
7905+ pub fn splice_channel(&mut self, our_funding_contribution_satoshis: i64,
7906+ our_funding_inputs: Vec<(TxIn, Transaction)>, funding_feerate_perkw: u32, locktime: u32,
7907+ ) -> Result<msgs::SpliceInit, ChannelError> {
7908+ // Check if a splice has been initiated already.
7909+ // Note: this could be handled more nicely, and support multiple outstanding splice's, the incoming splice_ack matters anyways.
7910+ if let Some(splice_info) = &self.pending_splice_pre {
7911+ return Err(ChannelError::Warn(format!(
7912+ "Channel has already a splice pending, contribution {}", splice_info.our_funding_contribution
7913+ )));
7914+ }
7915+
7916+ if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) {
7917+ return Err(ChannelError::Warn(format!("Cannot initiate splicing, as channel is not Ready")));
7918+ }
7919+
7920+ let pre_channel_value = self.context.get_value_satoshis();
7921+ // Sanity check: capacity cannot decrease below 0
7922+ if (pre_channel_value as i64).saturating_add(our_funding_contribution_satoshis) < 0 {
7923+ return Err(ChannelError::Warn(format!(
7924+ "Post-splicing channel value cannot be negative. It was {} + {}",
7925+ pre_channel_value, our_funding_contribution_satoshis
7926+ )));
7927+ }
7928+
7929+ if our_funding_contribution_satoshis < 0 {
7930+ return Err(ChannelError::Warn(format!(
7931+ "TODO(splicing): Splice-out not supported, only splice in, contribution {}",
7932+ our_funding_contribution_satoshis,
7933+ )));
7934+ }
7935+
7936+ // Note: post-splice channel value is not yet known at this point, counterpary contribution is not known
7937+ // (Cannot test for miminum required post-splice channel value)
7938+
7939+ // Check that inputs are sufficient to cover our contribution
7940+ let sum_input: i64 = our_funding_inputs.into_iter().map(
7941+ |(txin, tx)| tx.output.get(txin.previous_output.vout as usize).map(|tx| tx.value.to_sat() as i64).unwrap_or(0)
7942+ ).sum();
7943+ if sum_input < our_funding_contribution_satoshis {
7944+ return Err(ChannelError::Warn(format!(
7945+ "Provided inputs are insufficient for our contribution, {} {}",
7946+ sum_input, our_funding_contribution_satoshis,
7947+ )));
7948+ }
7949+
7950+ self.pending_splice_pre = Some(PendingSplice {
7951+ our_funding_contribution: our_funding_contribution_satoshis,
7952+ });
7953+
7954+ let msg = self.context.get_splice_init(our_funding_contribution_satoshis, funding_feerate_perkw, locktime);
7955+ Ok(msg)
7956+ }
7957+
7958+ /// Handle splice_init
7959+ #[cfg(splicing)]
7960+ pub fn splice_init(&mut self, msg: &msgs::SpliceInit) -> Result<msgs::SpliceAck, ChannelError> {
7961+ let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
7962+ // TODO(splicing): Currently not possible to contribute on the splicing-acceptor side
7963+ let our_funding_contribution_satoshis = 0i64;
7964+
7965+ // Check if a splice has been initiated already.
7966+ // Note: this could be handled more nicely, and support multiple outstanding splice's, the incoming splice_ack matters anyways.
7967+ if let Some(splice_info) = &self.pending_splice_pre {
7968+ return Err(ChannelError::Warn(format!(
7969+ "Channel has already a splice pending, contribution {}", splice_info.our_funding_contribution,
7970+ )));
7971+ }
7972+
7973+ if !matches!(self.context.channel_state, ChannelState::ChannelReady(_)) {
7974+ return Err(ChannelError::Warn(format!("Splicing requested on a channel that is not Ready")));
7975+ }
7976+
7977+ let pre_channel_value = self.context.get_value_satoshis();
7978+ // Sanity check: capacity cannot decrease below 0
7979+ if (pre_channel_value as i64)
7980+ .saturating_add(their_funding_contribution_satoshis)
7981+ .saturating_add(our_funding_contribution_satoshis) < 0
7982+ {
7983+ return Err(ChannelError::Warn(format!(
7984+ "Post-splicing channel value cannot be negative. It was {} + {} + {}",
7985+ pre_channel_value, their_funding_contribution_satoshis, our_funding_contribution_satoshis,
7986+ )));
7987+ }
7988+
7989+ if their_funding_contribution_satoshis.saturating_add(our_funding_contribution_satoshis) < 0 {
7990+ return Err(ChannelError::Warn(format!(
7991+ "Splice-out not supported, only splice in, relative {} + {}",
7992+ their_funding_contribution_satoshis, our_funding_contribution_satoshis,
7993+ )));
7994+ }
7995+
7996+ let post_channel_value = PendingSplice::compute_post_value(pre_channel_value, their_funding_contribution_satoshis, our_funding_contribution_satoshis);
7997+ let post_balance = PendingSplice::add_checked(self.context.value_to_self_msat, our_funding_contribution_satoshis);
7998+ // Early check for reserve requirement, assuming maximum balance of full channel value
7999+ // This will also be checked later at tx_complete
8000+ let _res = self.context.check_balance_meets_reserve_requirements(post_balance, post_channel_value)?;
8001+
8002+ // TODO(splicing): Store msg.funding_pubkey
8003+ // TODO(splicing): Apply start of splice (splice_start)
8004+
8005+ let splice_ack_msg = self.context.get_splice_ack(our_funding_contribution_satoshis);
8006+ // TODO(splicing): start interactive funding negotiation
8007+ Ok(splice_ack_msg)
8008+ }
8009+
8010+ /// Handle splice_ack
8011+ #[cfg(splicing)]
8012+ pub fn splice_ack(&mut self, msg: &msgs::SpliceAck) -> Result<(), ChannelError> {
8013+ let their_funding_contribution_satoshis = msg.funding_contribution_satoshis;
8014+
8015+ // check if splice is pending
8016+ let pending_splice = if let Some(pending_splice) = &self.pending_splice_pre {
8017+ pending_splice
8018+ } else {
8019+ return Err(ChannelError::Warn(format!("Channel is not in pending splice")));
8020+ };
8021+
8022+ let our_funding_contribution = pending_splice.our_funding_contribution;
8023+
8024+ let pre_channel_value = self.context.get_value_satoshis();
8025+ let post_channel_value = PendingSplice::compute_post_value(pre_channel_value, our_funding_contribution, their_funding_contribution_satoshis);
8026+ let post_balance = PendingSplice::add_checked(self.context.value_to_self_msat, our_funding_contribution);
8027+ // Early check for reserve requirement, assuming maximum balance of full channel value
8028+ // This will also be checked later at tx_complete
8029+ let _res = self.context.check_balance_meets_reserve_requirements(post_balance, post_channel_value)?;
8030+ Ok(())
8031+ }
78188032
78198033 // Send stuff to our remote peers:
78208034
@@ -8491,6 +8705,8 @@ impl<SP: Deref> OutboundV1Channel<SP> where SP::Target: SignerProvider {
84918705 let mut channel = Channel {
84928706 context: self.context,
84938707 interactive_tx_signing_session: None,
8708+ #[cfg(splicing)]
8709+ pending_splice_pre: None,
84948710 };
84958711
84968712 let need_channel_ready = channel.check_get_channel_ready(0, logger).is_some();
@@ -8716,6 +8932,8 @@ impl<SP: Deref> InboundV1Channel<SP> where SP::Target: SignerProvider {
87168932 let mut channel = Channel {
87178933 context: self.context,
87188934 interactive_tx_signing_session: None,
8935+ #[cfg(splicing)]
8936+ pending_splice_pre: None,
87198937 };
87208938 let need_channel_ready = channel.check_get_channel_ready(0, logger).is_some();
87218939 channel.monitor_updating_paused(false, false, need_channel_ready, Vec::new(), Vec::new(), Vec::new());
@@ -8861,6 +9079,8 @@ impl<SP: Deref> OutboundV2Channel<SP> where SP::Target: SignerProvider {
88619079 let channel = Channel {
88629080 context: self.context,
88639081 interactive_tx_signing_session: Some(signing_session),
9082+ #[cfg(splicing)]
9083+ pending_splice_pre: None,
88649084 };
88659085
88669086 Ok(channel)
@@ -9055,6 +9275,8 @@ impl<SP: Deref> InboundV2Channel<SP> where SP::Target: SignerProvider {
90559275 let channel = Channel {
90569276 context: self.context,
90579277 interactive_tx_signing_session: Some(signing_session),
9278+ #[cfg(splicing)]
9279+ pending_splice_pre: None,
90589280 };
90599281
90609282 Ok(channel)
@@ -10133,6 +10355,8 @@ impl<'a, 'b, 'c, ES: Deref, SP: Deref> ReadableArgs<(&'a ES, &'b SP, u32, &'c Ch
1013310355 next_funding_txid: None,
1013410356 },
1013510357 interactive_tx_signing_session: None,
10358+ #[cfg(splicing)]
10359+ pending_splice_pre: None,
1013610360 })
1013710361 }
1013810362}
@@ -11915,4 +12139,69 @@ mod tests {
1191512139 assert_eq!(node_a_chan.context.channel_state, ChannelState::AwaitingChannelReady(AwaitingChannelReadyFlags::THEIR_CHANNEL_READY));
1191612140 assert!(node_a_chan.check_get_channel_ready(0, &&logger).is_some());
1191712141 }
12142+
12143+ #[cfg(all(test, splicing))]
12144+ fn get_pre_and_post(pre_channel_value: u64, our_funding_contribution: i64, their_funding_contribution: i64) -> (u64, u64) {
12145+ use crate::ln::channel::PendingSplice;
12146+
12147+ let post_channel_value = PendingSplice::compute_post_value(pre_channel_value, our_funding_contribution, their_funding_contribution);
12148+ (pre_channel_value, post_channel_value)
12149+ }
12150+
12151+ #[cfg(all(test, splicing))]
12152+ #[test]
12153+ fn test_splice_compute_post_value() {
12154+ {
12155+ // increase, small amounts
12156+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, 6_000, 0);
12157+ assert_eq!(pre_channel_value, 9_000);
12158+ assert_eq!(post_channel_value, 15_000);
12159+ }
12160+ {
12161+ // increase, small amounts
12162+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, 4_000, 2_000);
12163+ assert_eq!(pre_channel_value, 9_000);
12164+ assert_eq!(post_channel_value, 15_000);
12165+ }
12166+ {
12167+ // increase, small amounts
12168+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, 0, 6_000);
12169+ assert_eq!(pre_channel_value, 9_000);
12170+ assert_eq!(post_channel_value, 15_000);
12171+ }
12172+ {
12173+ // decrease, small amounts
12174+ let (pre_channel_value, post_channel_value) = get_pre_and_post(15_000, -6_000, 0);
12175+ assert_eq!(pre_channel_value, 15_000);
12176+ assert_eq!(post_channel_value, 9_000);
12177+ }
12178+ {
12179+ // decrease, small amounts
12180+ let (pre_channel_value, post_channel_value) = get_pre_and_post(15_000, -4_000, -2_000);
12181+ assert_eq!(pre_channel_value, 15_000);
12182+ assert_eq!(post_channel_value, 9_000);
12183+ }
12184+ {
12185+ // increase and decrease
12186+ let (pre_channel_value, post_channel_value) = get_pre_and_post(15_000, 4_000, -2_000);
12187+ assert_eq!(pre_channel_value, 15_000);
12188+ assert_eq!(post_channel_value, 17_000);
12189+ }
12190+ let base2: u64 = 2;
12191+ let huge63i3 = (base2.pow(63) - 3) as i64;
12192+ assert_eq!(huge63i3, 9223372036854775805);
12193+ assert_eq!(-huge63i3, -9223372036854775805);
12194+ {
12195+ // increase, large amount
12196+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, huge63i3, 3);
12197+ assert_eq!(pre_channel_value, 9_000);
12198+ assert_eq!(post_channel_value, 9223372036854784807);
12199+ }
12200+ {
12201+ // increase, large amounts
12202+ let (pre_channel_value, post_channel_value) = get_pre_and_post(9_000, huge63i3, huge63i3);
12203+ assert_eq!(pre_channel_value, 9_000);
12204+ assert_eq!(post_channel_value, 9223372036854784807);
12205+ }
12206+ }
1191812207}
0 commit comments