diff --git a/mutiny-core/src/error.rs b/mutiny-core/src/error.rs index 1f33e3bee..89f7640d5 100644 --- a/mutiny-core/src/error.rs +++ b/mutiny-core/src/error.rs @@ -95,6 +95,9 @@ pub enum MutinyError { /// A channel could not be opened. #[error("Failed to create channel.")] ChannelCreationFailed, + /// A channel could not be opened. + #[error("Failed to create channel. {0}")] + ChannelCreationFailedWithReason(String), /// A channel could not be closed. #[error("Failed to close channel.")] ChannelClosingFailed, @@ -237,6 +240,10 @@ impl PartialEq for MutinyError { (Self::RoutingFailed, Self::RoutingFailed) => true, (Self::PeerInfoParseFailed, Self::PeerInfoParseFailed) => true, (Self::ChannelCreationFailed, Self::ChannelCreationFailed) => true, + ( + Self::ChannelCreationFailedWithReason(x), + Self::ChannelCreationFailedWithReason(y), + ) => x == y, (Self::ChannelClosingFailed, Self::ChannelClosingFailed) => true, (Self::PersistenceFailed { source }, Self::PersistenceFailed { source: source2 }) => { source == source2 diff --git a/mutiny-core/src/event.rs b/mutiny-core/src/event.rs index 96cf57230..89200ed89 100644 --- a/mutiny-core/src/event.rs +++ b/mutiny-core/src/event.rs @@ -523,9 +523,20 @@ impl EventHandler { .. } => { // if we still have channel open params, then it was just a failed channel open - // we should not persist this as a closed channel and just delete the channel open params - if let Ok(Some(_)) = self.persister.get_channel_open_params(user_channel_id) { - let _ = self.persister.delete_channel_open_params(user_channel_id); + // we should not persist this as a closed channel and pass back the failure reason + if let Ok(Some(mut params)) = + self.persister.get_channel_open_params(user_channel_id) + { + // Remove the LDK fluff from the error message + let reason_str = reason.to_string().replace( + "Channel closed because counterparty force-closed with message: ", + "", + ); + + params.failure_reason = Some(reason_str); + let _ = self + .persister + .persist_channel_open_params(user_channel_id, params); return; }; diff --git a/mutiny-core/src/ldkstorage.rs b/mutiny-core/src/ldkstorage.rs index 3825a3772..4a3e9ea96 100644 --- a/mutiny-core/src/ldkstorage.rs +++ b/mutiny-core/src/ldkstorage.rs @@ -550,6 +550,8 @@ pub(crate) struct ChannelOpenParams { pub(crate) labels: Option>, #[serde(skip_serializing_if = "Option::is_none")] pub(crate) opening_tx: Option, + #[serde(skip_serializing_if = "Option::is_none")] + pub(crate) failure_reason: Option, } impl ChannelOpenParams { @@ -560,6 +562,7 @@ impl ChannelOpenParams { utxos: None, labels: None, opening_tx: None, + failure_reason: None, } } @@ -574,6 +577,7 @@ impl ChannelOpenParams { utxos: Some(utxos), labels: None, opening_tx: None, + failure_reason: None, } } } diff --git a/mutiny-core/src/node.rs b/mutiny-core/src/node.rs index e8ab0e6e2..d1bc0f664 100644 --- a/mutiny-core/src/node.rs +++ b/mutiny-core/src/node.rs @@ -1874,10 +1874,16 @@ impl Node { return Err(MutinyError::NotRunning); } - // We will get a channel closure event if the peer rejects the channel - // todo return closure reason to user - if let Ok(Some(_closure)) = self.persister.get_channel_closure(user_channel_id) { - return Err(MutinyError::ChannelCreationFailed); + // We'll set failure reason if the peer rejects the channel + if let Some(failure_reason) = self + .persister + .get_channel_open_params(user_channel_id)? + .and_then(|p| p.failure_reason) + { + log_error!(self.logger, "Channel funding tx failed: {failure_reason}"); + // can now safely delete the channel open params + let _ = self.persister.delete_channel_open_params(user_channel_id); + return Err(MutinyError::ChannelCreationFailedWithReason(failure_reason)); } let channels = self.channel_manager.list_channels_with_counterparty(pubkey); diff --git a/mutiny-wasm/src/error.rs b/mutiny-wasm/src/error.rs index 3e7b70ff8..4297049f4 100644 --- a/mutiny-wasm/src/error.rs +++ b/mutiny-wasm/src/error.rs @@ -86,6 +86,9 @@ pub enum MutinyJsError { /// A channel could not be opened. #[error("Failed to create channel.")] ChannelCreationFailed, + /// A channel could not be opened. + #[error("Failed to create channel. {0}")] + ChannelCreationFailedWithReason(String), /// A channel could not be closed. #[error("Failed to close channel.")] ChannelClosingFailed, @@ -203,6 +206,9 @@ impl From for MutinyJsError { MutinyError::RoutingFailed => MutinyJsError::RoutingFailed, MutinyError::PeerInfoParseFailed => MutinyJsError::PeerInfoParseFailed, MutinyError::ChannelCreationFailed => MutinyJsError::ChannelCreationFailed, + MutinyError::ChannelCreationFailedWithReason(x) => { + MutinyJsError::ChannelCreationFailedWithReason(x) + } MutinyError::ChannelClosingFailed => MutinyJsError::ChannelClosingFailed, MutinyError::PersistenceFailed { source: _ } => MutinyJsError::PersistenceFailed, MutinyError::ReadError { source: _ } => MutinyJsError::ReadError,