@@ -31,6 +31,9 @@ use bitcoin::hash_types::{BlockHash, Txid};
3131use bitcoin::secp256k1::{SecretKey,PublicKey};
3232use bitcoin::secp256k1::Secp256k1;
3333use bitcoin::{secp256k1, Sequence};
34+ #[cfg(splicing)]
35+ use bitcoin::{TxIn, Weight};
36+
3437
3538use crate::events::FundingInfo;
3639use crate::blinded_path::message::{AsyncPaymentsContext, MessageContext, OffersContext};
@@ -49,7 +52,7 @@ use crate::ln::inbound_payment;
4952use crate::ln::types::ChannelId;
5053use crate::types::payment::{PaymentHash, PaymentPreimage, PaymentSecret};
5154use crate::ln::channel::{self, Channel, ChannelError, ChannelUpdateStatus, FundedChannel, ShutdownResult, UpdateFulfillCommitFetch, OutboundV1Channel, ReconnectionMsg, InboundV1Channel, WithChannelContext};
52- #[cfg(any( dual_funding, splicing) )]
55+ #[cfg(dual_funding)]
5356use crate::ln::channel::PendingV2Channel;
5457use crate::ln::channel_state::ChannelDetails;
5558use crate::types::features::{Bolt12InvoiceFeatures, ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
@@ -4278,6 +4281,88 @@ where
42784281 }
42794282 }
42804283
4284+ /// See [`splice_channel`]
4285+ #[cfg(splicing)]
4286+ fn internal_splice_channel(
4287+ &self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, our_funding_contribution_satoshis: i64,
4288+ our_funding_inputs: &Vec<(TxIn, Transaction, Weight)>,
4289+ funding_feerate_per_kw: u32, locktime: Option<u32>,
4290+ ) -> (Result<(), APIError>, NotifyOption) {
4291+ let per_peer_state = self.per_peer_state.read().unwrap();
4292+
4293+ let peer_state_mutex = match per_peer_state.get(counterparty_node_id)
4294+ .ok_or_else(|| APIError::ChannelUnavailable { err: format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id) }) {
4295+ Ok(p) => p,
4296+ Err(e) => return (Err(e), NotifyOption::SkipPersistNoEvents),
4297+ };
4298+
4299+ let mut peer_state_lock = peer_state_mutex.lock().unwrap();
4300+ let peer_state = &mut *peer_state_lock;
4301+
4302+ // Look for the channel
4303+ match peer_state.channel_by_id.entry(*channel_id) {
4304+ hash_map::Entry::Occupied(mut chan_phase_entry) => {
4305+ let locktime = locktime.unwrap_or(self.current_best_block().height);
4306+ if let Some(chan) = chan_phase_entry.get_mut().as_funded_mut() {
4307+ let msg = match chan.splice_channel(our_funding_contribution_satoshis, our_funding_inputs, funding_feerate_per_kw, locktime) {
4308+ Ok(m) => m,
4309+ Err(e) => return (Err(e), NotifyOption::SkipPersistNoEvents),
4310+ };
4311+
4312+ peer_state.pending_msg_events.push(events::MessageSendEvent::SendSpliceInit {
4313+ node_id: *counterparty_node_id,
4314+ msg,
4315+ });
4316+
4317+ (Ok(()), NotifyOption::SkipPersistHandleEvents)
4318+ } else {
4319+ (Err(APIError::ChannelUnavailable {
4320+ err: format!(
4321+ "Channel with id {} is not funded, cannot splice it",
4322+ channel_id
4323+ )
4324+ }), NotifyOption::SkipPersistNoEvents)
4325+ }
4326+ },
4327+ hash_map::Entry::Vacant(_) => {
4328+ (Err(APIError::ChannelUnavailable {
4329+ err: format!(
4330+ "Channel with id {} not found for the passed counterparty node_id {}",
4331+ channel_id, counterparty_node_id,
4332+ )
4333+ }), NotifyOption::SkipPersistNoEvents)
4334+ },
4335+ }
4336+ }
4337+
4338+ /// Initiate a splice, to change the channel capacity of an existing funded channel.
4339+ /// After completion of splicing, the funding transaction will be replaced by a new one, spending the old funding transaction,
4340+ /// with optional extra inputs (splice-in) and/or extra outputs (splice-out or change).
4341+ /// TODO(splicing): Implementation is currently incomplete.
4342+ ///
4343+ /// Note: Currently only splice-in is supported (increase in channel capacity), splice-out is not.
4344+ ///
4345+ /// - our_funding_contribution_satoshis: the amount contributed by us to the channel. This will increase our channel balance.
4346+ /// - our_funding_inputs: the funding inputs provided by us. If our contribution is positive, our funding inputs must cover at least that amount.
4347+ /// Includes the witness weight for this input (e.g. P2WPKH_WITNESS_WEIGHT=109 for typical P2WPKH inputs).
4348+ /// - locktime: Optional locktime for the new funding transaction. If None, set to the current block height.
4349+ #[cfg(splicing)]
4350+ pub fn splice_channel(
4351+ &self, channel_id: &ChannelId, counterparty_node_id: &PublicKey, our_funding_contribution_satoshis: i64,
4352+ our_funding_inputs: Vec<(TxIn, Transaction, Weight)>,
4353+ funding_feerate_per_kw: u32, locktime: Option<u32>,
4354+ ) -> Result<(), APIError> {
4355+ let mut res = Ok(());
4356+ PersistenceNotifierGuard::optionally_notify(self, || {
4357+ let (result, notify_option) = self.internal_splice_channel(
4358+ channel_id, counterparty_node_id, our_funding_contribution_satoshis, &our_funding_inputs, funding_feerate_per_kw, locktime
4359+ );
4360+ res = result;
4361+ notify_option
4362+ });
4363+ res
4364+ }
4365+
42814366 fn can_forward_htlc_to_outgoing_channel(
42824367 &self, chan: &mut FundedChannel<SP>, msg: &msgs::UpdateAddHTLC, next_packet: &NextPacketDetails
42834368 ) -> Result<(), (&'static str, u16)> {
@@ -9466,6 +9551,83 @@ This indicates a bug inside LDK. Please report this error at https://github.com/
94669551 Ok(NotifyOption::SkipPersistHandleEvents)
94679552 }
94689553
9554+ /// Handle incoming splice request, transition channel to splice-pending (unless some check fails).
9555+ #[cfg(splicing)]
9556+ fn internal_splice_init(&self, counterparty_node_id: &PublicKey, msg: &msgs::SpliceInit) -> Result<(), MsgHandleErrInternal> {
9557+ // TODO(splicing): if we accept splicing, quiescence
9558+
9559+ let per_peer_state = self.per_peer_state.read().unwrap();
9560+ let peer_state_mutex = per_peer_state.get(counterparty_node_id)
9561+ .ok_or_else(|| {
9562+ debug_assert!(false);
9563+ MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id)
9564+ })?;
9565+ let mut peer_state_lock = peer_state_mutex.lock().unwrap();
9566+ let peer_state = &mut *peer_state_lock;
9567+
9568+ // Look for the channel
9569+ match peer_state.channel_by_id.entry(msg.channel_id) {
9570+ hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close(format!(
9571+ "Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}, channel_id {}",
9572+ counterparty_node_id, msg.channel_id,
9573+ ), msg.channel_id)),
9574+ hash_map::Entry::Occupied(mut chan_entry) => {
9575+ if let Some(chan) = chan_entry.get_mut().as_funded_mut() {
9576+ let splice_ack_msg = try_channel_entry!(self, peer_state, chan.splice_init(msg), chan_entry);
9577+ peer_state.pending_msg_events.push(events::MessageSendEvent::SendSpliceAck {
9578+ node_id: *counterparty_node_id,
9579+ msg: splice_ack_msg,
9580+ });
9581+ } else {
9582+ return Err(MsgHandleErrInternal::send_err_msg_no_close("Channel is not funded, cannot be spliced".to_owned(), msg.channel_id));
9583+ }
9584+ },
9585+ };
9586+
9587+ // TODO(splicing):
9588+ // Change channel, change phase (remove and add)
9589+ // Create new post-splice channel
9590+ // etc.
9591+
9592+ Ok(())
9593+ }
9594+
9595+ /// Handle incoming splice request ack, transition channel to splice-pending (unless some check fails).
9596+ #[cfg(splicing)]
9597+ fn internal_splice_ack(&self, counterparty_node_id: &PublicKey, msg: &msgs::SpliceAck) -> Result<(), MsgHandleErrInternal> {
9598+ let per_peer_state = self.per_peer_state.read().unwrap();
9599+ let peer_state_mutex = per_peer_state.get(counterparty_node_id)
9600+ .ok_or_else(|| {
9601+ debug_assert!(false);
9602+ MsgHandleErrInternal::send_err_msg_no_close(format!("Can't find a peer matching the passed counterparty node_id {}", counterparty_node_id), msg.channel_id)
9603+ })?;
9604+ let mut peer_state_lock = peer_state_mutex.lock().unwrap();
9605+ let peer_state = &mut *peer_state_lock;
9606+
9607+ // Look for the channel
9608+ match peer_state.channel_by_id.entry(msg.channel_id) {
9609+ hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close(format!(
9610+ "Got a message for a channel from the wrong node! No such channel for the passed counterparty_node_id {}",
9611+ counterparty_node_id
9612+ ), msg.channel_id)),
9613+ hash_map::Entry::Occupied(mut chan_entry) => {
9614+ if let Some(chan) = chan_entry.get_mut().as_funded_mut() {
9615+ try_channel_entry!(self, peer_state, chan.splice_ack(msg), chan_entry);
9616+ } else {
9617+ return Err(MsgHandleErrInternal::send_err_msg_no_close("Channel is not funded, cannot splice".to_owned(), msg.channel_id));
9618+ }
9619+ },
9620+ };
9621+
9622+ // TODO(splicing):
9623+ // Change channel, change phase (remove and add)
9624+ // Create new post-splice channel
9625+ // Start splice funding transaction negotiation
9626+ // etc.
9627+
9628+ Err(MsgHandleErrInternal::send_err_msg_no_close("TODO(splicing): Splicing is not implemented (splice_ack)".to_owned(), msg.channel_id))
9629+ }
9630+
94699631 /// Process pending events from the [`chain::Watch`], returning whether any events were processed.
94709632 fn process_pending_monitor_events(&self) -> bool {
94719633 debug_assert!(self.total_consistency_lock.try_write().is_err()); // Caller holds read lock
@@ -11746,23 +11908,37 @@ where
1174611908
1174711909 #[cfg(splicing)]
1174811910 fn handle_splice_init(&self, counterparty_node_id: PublicKey, msg: &msgs::SpliceInit) {
11749- let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close(
11750- "Splicing not supported".to_owned(),
11751- msg.channel_id.clone())), counterparty_node_id);
11911+ let _persistence_guard = PersistenceNotifierGuard::optionally_notify(self, || {
11912+ let res = self.internal_splice_init(&counterparty_node_id, msg);
11913+ let persist = match &res {
11914+ Err(e) if e.closes_channel() => NotifyOption::DoPersist,
11915+ Err(_) => NotifyOption::SkipPersistHandleEvents,
11916+ Ok(()) => NotifyOption::SkipPersistHandleEvents,
11917+ };
11918+ let _ = handle_error!(self, res, counterparty_node_id);
11919+ persist
11920+ });
1175211921 }
1175311922
1175411923 #[cfg(splicing)]
1175511924 fn handle_splice_ack(&self, counterparty_node_id: PublicKey, msg: &msgs::SpliceAck) {
11756- let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close(
11757- "Splicing not supported (splice_ack)".to_owned(),
11758- msg.channel_id.clone())), counterparty_node_id);
11925+ let _persistence_guard = PersistenceNotifierGuard::optionally_notify(self, || {
11926+ let res = self.internal_splice_ack(&counterparty_node_id, msg);
11927+ let persist = match &res {
11928+ Err(e) if e.closes_channel() => NotifyOption::DoPersist,
11929+ Err(_) => NotifyOption::SkipPersistHandleEvents,
11930+ Ok(()) => NotifyOption::SkipPersistHandleEvents,
11931+ };
11932+ let _ = handle_error!(self, res, counterparty_node_id);
11933+ persist
11934+ });
1175911935 }
1176011936
1176111937 #[cfg(splicing)]
1176211938 fn handle_splice_locked(&self, counterparty_node_id: PublicKey, msg: &msgs::SpliceLocked) {
1176311939 let _: Result<(), _> = handle_error!(self, Err(MsgHandleErrInternal::send_err_msg_no_close(
1176411940 "Splicing not supported (splice_locked)".to_owned(),
11765- msg.channel_id.clone() )), counterparty_node_id);
11941+ msg.channel_id)), counterparty_node_id);
1176611942 }
1176711943
1176811944 fn handle_shutdown(&self, counterparty_node_id: PublicKey, msg: &msgs::Shutdown) {
0 commit comments