@@ -4841,96 +4841,103 @@ impl<
48414841 }
48424842 }
48434843
4844- #[cfg(test)]
4845- pub(crate) fn abandon_splice(
4846- &self, channel_id: &ChannelId, counterparty_node_id: &PublicKey,
4847- ) -> Result<(), APIError> {
4848- let mut res = Ok(());
4849- PersistenceNotifierGuard::optionally_notify(self, || {
4850- let result = self.internal_abandon_splice(channel_id, counterparty_node_id);
4851- res = result;
4852- match res {
4853- Ok(_) => NotifyOption::SkipPersistHandleEvents,
4854- Err(_) => NotifyOption::SkipPersistNoEvents,
4855- }
4856- });
4857- res
4858- }
4859-
4860- #[cfg(test)]
4861- fn internal_abandon_splice(
4844+ /// Cancels an in-flight [`FundingContribution`].
4845+ ///
4846+ /// This is primarily useful after receiving an [`Event::FundingTransactionReadyForSigning`] for
4847+ /// a [`FundingContribution`] you no longer wish to proceed with. Canceling is only allowed up
4848+ /// until [`ChannelManager::funding_transaction_signed`] is called for the corresponding
4849+ /// [`FundingContribution`].
4850+ ///
4851+ /// Returns [`ChannelUnavailable`] when a channel is not found or an incorrect
4852+ /// `counterparty_node_id` is provided, or [`APIMisuseError`] otherwise with the error details.
4853+ ///
4854+ /// [`Event::FundingTransactionReadyForSigning`]: events::Event::FundingTransactionReadyForSigning
4855+ /// [`ChannelUnavailable`]: APIError::ChannelUnavailable
4856+ /// [`APIMisuseError`]: APIError::APIMisuseError
4857+ pub fn cancel_funding_contributed(
48624858 &self, channel_id: &ChannelId, counterparty_node_id: &PublicKey,
48634859 ) -> Result<(), APIError> {
4864- let per_peer_state = self.per_peer_state.read().unwrap();
4865-
4866- let peer_state_mutex = match per_peer_state
4867- .get(counterparty_node_id)
4868- .ok_or_else(|| APIError::no_such_peer(counterparty_node_id))
4869- {
4870- Ok(p) => p,
4871- Err(e) => return Err(e),
4872- };
4873-
4874- let mut peer_state_lock = peer_state_mutex.lock().unwrap();
4875- let peer_state = &mut *peer_state_lock;
4860+ let mut result = Ok(());
4861+ PersistenceNotifierGuard::manually_notify(self, || {
4862+ let per_peer_state = self.per_peer_state.read().unwrap();
4863+ let peer_state_mutex = match per_peer_state
4864+ .get(counterparty_node_id)
4865+ .ok_or_else(|| APIError::no_such_peer(counterparty_node_id))
4866+ {
4867+ Ok(p) => p,
4868+ Err(e) => {
4869+ result = Err(e);
4870+ return;
4871+ },
4872+ };
4873+ let mut peer_state_lock = peer_state_mutex.lock().unwrap();
4874+ let peer_state = &mut *peer_state_lock;
48764875
4877- // Look for the channel
4878- match peer_state.channel_by_id.entry(*channel_id) {
4879- hash_map::Entry::Occupied(mut chan_phase_entry) => {
4880- if !chan_phase_entry.get().context().is_connected() {
4881- // TODO: We should probably support this, but right now `splice_channel` refuses when
4882- // the peer is disconnected, so we just check it here.
4883- return Err(APIError::ChannelUnavailable {
4884- err: "Cannot abandon splice while peer is disconnected".to_owned(),
4885- });
4886- }
4876+ match peer_state.channel_by_id.entry(*channel_id) {
4877+ hash_map::Entry::Occupied(mut chan_entry) => {
4878+ if let Some(channel) = chan_entry.get_mut().as_funded_mut() {
4879+ let InteractiveTxMsgError { err, splice_funding_failed, exited_quiescence } =
4880+ match channel.cancel_funding_contributed() {
4881+ Ok(v) => v,
4882+ Err(e) => {
4883+ result = Err(e);
4884+ return;
4885+ },
4886+ };
48874887
4888- if let Some(chan) = chan_phase_entry.get_mut().as_funded_mut() {
4889- let (tx_abort, splice_funding_failed) = chan.abandon_splice()?;
4888+ let splice_funding_failed = splice_funding_failed
4889+ .expect("Only splices with local contributions can be canceled");
4890+ {
4891+ let pending_events = &mut self.pending_events.lock().unwrap();
4892+ pending_events.push_back((
4893+ events::Event::SpliceFailed {
4894+ channel_id: *channel_id,
4895+ counterparty_node_id: *counterparty_node_id,
4896+ user_channel_id: channel.context().get_user_id(),
4897+ abandoned_funding_txo: splice_funding_failed.funding_txo,
4898+ channel_type: splice_funding_failed.channel_type.clone(),
4899+ },
4900+ None,
4901+ ));
4902+ pending_events.push_back((
4903+ events::Event::DiscardFunding {
4904+ channel_id: *channel_id,
4905+ funding_info: FundingInfo::Contribution {
4906+ inputs: splice_funding_failed.contributed_inputs,
4907+ outputs: splice_funding_failed.contributed_outputs,
4908+ },
4909+ },
4910+ None,
4911+ ));
4912+ }
48904913
4891- peer_state.pending_msg_events.push(MessageSendEvent::SendTxAbort {
4892- node_id: *counterparty_node_id,
4893- msg: tx_abort,
4894- });
4914+ mem::drop(peer_state_lock);
4915+ mem::drop(per_peer_state);
48954916
4896- if let Some(splice_funding_failed) = splice_funding_failed {
4897- let pending_events = &mut self.pending_events.lock().unwrap();
4898- pending_events.push_back((
4899- events::Event::SpliceFailed {
4900- channel_id: *channel_id,
4901- counterparty_node_id: *counterparty_node_id,
4902- user_channel_id: chan.context.get_user_id(),
4903- abandoned_funding_txo: splice_funding_failed.funding_txo,
4904- channel_type: splice_funding_failed.channel_type,
4905- },
4906- None,
4907- ));
4908- pending_events.push_back((
4909- events::Event::DiscardFunding {
4910- channel_id: *channel_id,
4911- funding_info: FundingInfo::Contribution {
4912- inputs: splice_funding_failed.contributed_inputs,
4913- outputs: splice_funding_failed.contributed_outputs,
4914- },
4915- },
4916- None,
4917- ));
4917+ self.needs_persist_flag.store(true, Ordering::Release);
4918+ self.event_persist_notifier.notify();
4919+ let err: Result<(), _> =
4920+ Err(MsgHandleErrInternal::from_chan_no_close(err, *channel_id)
4921+ .with_exited_quiescence(exited_quiescence));
4922+ let _ = self.handle_error(err, *counterparty_node_id);
4923+ } else {
4924+ result = Err(APIError::ChannelUnavailable {
4925+ err: format!(
4926+ "Channel with id {} is not funded, cannot cancel splice",
4927+ channel_id
4928+ ),
4929+ });
4930+ return;
49184931 }
4919-
4920- Ok(())
4921- } else {
4922- Err(APIError::ChannelUnavailable {
4923- err: format!(
4924- "Channel with id {} is not funded, cannot abandon splice",
4925- channel_id
4926- ),
4927- })
4928- }
4929- },
4930- hash_map::Entry::Vacant(_) => {
4931- Err(APIError::no_such_channel_for_peer(channel_id, counterparty_node_id))
4932- },
4933- }
4932+ },
4933+ hash_map::Entry::Vacant(_) => {
4934+ result =
4935+ Err(APIError::no_such_channel_for_peer(channel_id, counterparty_node_id));
4936+ return;
4937+ },
4938+ }
4939+ });
4940+ result
49344941 }
49354942
49364943 fn forward_needs_intercept_to_known_chan(
0 commit comments