From 7f1a4faf41e8e178939c916af4c9589b0f694590 Mon Sep 17 00:00:00 2001 From: benthecarman Date: Mon, 10 Jun 2024 17:50:19 -0500 Subject: [PATCH 1/2] Make sure LSP url is a valid url when switching --- mutiny-core/src/lsp/voltage.rs | 6 +++--- mutiny-core/src/nodemanager.rs | 21 ++++++++++++++++++--- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/mutiny-core/src/lsp/voltage.rs b/mutiny-core/src/lsp/voltage.rs index 5d9ce7143..a5b3b3cab 100644 --- a/mutiny-core/src/lsp/voltage.rs +++ b/mutiny-core/src/lsp/voltage.rs @@ -152,7 +152,7 @@ impl LspClient { url: &str, logger: &MutinyLogger, ) -> Result<(PublicKey, String), MutinyError> { - let builder = http_client.get(format!("{}{}", url, GET_INFO_PATH)); + let builder = http_client.get(format!("{}{}", url.trim(), GET_INFO_PATH)); let request = add_x_auth_token_if_needed(url, builder)?; let response: reqwest::Response = utils::fetch_with_timeout(http_client, request) @@ -296,7 +296,7 @@ impl Lsp for LspClient { let builder = self .http_client - .post(format!("{}{}", &self.url, PROPOSAL_PATH)) + .post(format!("{}{}", &self.url.trim(), PROPOSAL_PATH)) .json(&payload); let request = add_x_auth_token_if_needed(&self.url, builder)?; @@ -353,7 +353,7 @@ impl Lsp for LspClient { async fn get_lsp_fee_msat(&self, fee_request: FeeRequest) -> Result { let builder = self .http_client - .post(format!("{}{}", &self.url, FEE_PATH)) + .post(format!("{}{}", &self.url.trim(), FEE_PATH)) .json(&fee_request); let request = add_x_auth_token_if_needed(&self.url, builder)?; diff --git a/mutiny-core/src/nodemanager.rs b/mutiny-core/src/nodemanager.rs index f7eb9b0c1..1d452bfb0 100644 --- a/mutiny-core/src/nodemanager.rs +++ b/mutiny-core/src/nodemanager.rs @@ -59,6 +59,7 @@ use std::sync::atomic::{AtomicBool, Ordering}; #[cfg(not(target_arch = "wasm32"))] use std::time::Instant; use std::{collections::HashMap, ops::Deref, sync::Arc}; +use url::Url; #[cfg(target_arch = "wasm32")] use web_time::Instant; @@ -347,7 +348,15 @@ impl NodeManagerBuilder { let lsp_config = if c.safe_mode { None } else { - create_lsp_config(c.lsp_url, c.lsp_connection_string, c.lsp_token)? + create_lsp_config(c.lsp_url, c.lsp_connection_string, c.lsp_token).unwrap_or_else( + |_| { + log_warn!( + logger, + "Failed to create lsp config, falling back to no LSP configured" + ); + None + }, + ) }; log_trace!(logger, "finished creating lsp config"); @@ -2036,8 +2045,14 @@ pub fn create_lsp_config( ) -> Result, MutinyError> { match (lsp_url.clone(), lsp_connection_string.clone()) { (Some(lsp_url), None) => { - if !lsp_url.is_empty() { - Ok(Some(LspConfig::new_voltage_flow(lsp_url))) + let trimmed = lsp_url.trim().to_string(); + if !trimmed.is_empty() { + // make sure url is valid + if Url::parse(&trimmed).is_err() { + return Err(MutinyError::InvalidArgumentsError); + } + + Ok(Some(LspConfig::new_voltage_flow(trimmed))) } else { Ok(None) } From eb8de4b5ced4260ce3dbb09cfa98009ecbd6cb5a Mon Sep 17 00:00:00 2001 From: benthecarman Date: Tue, 11 Jun 2024 11:18:01 -0500 Subject: [PATCH 2/2] Try to connect to LSP before changing --- mutiny-core/src/lsp/voltage.rs | 2 +- mutiny-core/src/nodemanager.rs | 25 ++++++++++++++++++++++++- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/mutiny-core/src/lsp/voltage.rs b/mutiny-core/src/lsp/voltage.rs index a5b3b3cab..92c8c3408 100644 --- a/mutiny-core/src/lsp/voltage.rs +++ b/mutiny-core/src/lsp/voltage.rs @@ -147,7 +147,7 @@ impl LspClient { } /// Get the pubkey and connection string from the LSP from the /info endpoint - async fn fetch_connection_info( + pub(crate) async fn fetch_connection_info( http_client: &Client, url: &str, logger: &MutinyLogger, diff --git a/mutiny-core/src/nodemanager.rs b/mutiny-core/src/nodemanager.rs index 1d452bfb0..43b0e2699 100644 --- a/mutiny-core/src/nodemanager.rs +++ b/mutiny-core/src/nodemanager.rs @@ -1,6 +1,7 @@ use crate::labels::LabelStorage; use crate::ldkstorage::CHANNEL_CLOSURE_PREFIX; use crate::logging::LOGGING_KEY; +use crate::lsp::voltage; use crate::utils::{sleep, spawn}; use crate::MutinyInvoice; use crate::MutinyWalletConfig; @@ -1347,7 +1348,7 @@ impl NodeManager { /// current LSP, it will fail to change the LSP. /// /// Requires a restart of the node manager to take effect. - pub async fn change_lsp(&self, lsp_config: Option) -> Result<(), MutinyError> { + pub async fn change_lsp(&self, mut lsp_config: Option) -> Result<(), MutinyError> { log_trace!(self.logger, "calling change_lsp"); // if we are in safe mode we don't load the lightning state so we can't know if it is safe to change the LSP. @@ -1371,6 +1372,28 @@ impl NodeManager { } drop(nodes); + // verify that the LSP config is valid + match lsp_config.as_mut() { + Some(LspConfig::VoltageFlow(config)) => { + let http_client = Client::new(); + + // try to connect to the LSP, update the config if successful + let (pk, str) = voltage::LspClient::fetch_connection_info( + &http_client, + &config.url, + &self.logger, + ) + .await?; + config.pubkey = Some(pk); + config.connection_string = Some(str); + } + Some(LspConfig::Lsps(config)) => { + // make sure a valid connection string was provided + PubkeyConnectionInfo::new(&config.connection_string)?; + } + None => {} // Nothing to verify + } + // edit node storage let mut node_storage = self.node_storage.write().await; node_storage.nodes.iter_mut().for_each(|(_, n)| {