From 0017cf64d957dff29011515964503439861cedcd Mon Sep 17 00:00:00 2001 From: EthanYuan Date: Tue, 25 Mar 2025 00:30:55 +0800 Subject: [PATCH 1/4] impl method validate_peer_connections. --- mutiny-core/src/lib.rs | 17 ++++++---- mutiny-core/src/lsp/lndchannel.rs | 1 + mutiny-core/src/peermanager.rs | 56 ++++++++++++++++++++++++++++--- 3 files changed, 63 insertions(+), 11 deletions(-) diff --git a/mutiny-core/src/lib.rs b/mutiny-core/src/lib.rs index 7d07e83cb..818c0d5a9 100644 --- a/mutiny-core/src/lib.rs +++ b/mutiny-core/src/lib.rs @@ -46,7 +46,9 @@ pub use crate::ldkstorage::{ ACTIVE_NODE_ID_KEY, CHANNEL_CLOSURE_BUMP_PREFIX, CHANNEL_CLOSURE_PREFIX, CHANNEL_MANAGER_KEY, MONITORS_PREFIX_KEY, }; -use crate::lsp::lndchannel::fetch_lnd_channels_snapshot; +use crate::lsp::lndchannel::{ + fetch_lnd_channels, fetch_lnd_channels_snapshot, LndChannelsSnapshot, +}; use crate::messagehandler::CommonLnEventCallback; use crate::nodemanager::NodeManager; use crate::nodemanager::{ChannelClosure, MutinyBip21RawMaterials}; @@ -835,11 +837,12 @@ impl MutinyWalletBuilder { return; }; - let first_lnd_snapshot = - match fetch_lnd_channels_snapshot(&Client::new(), lsp_url, &node_id, &logger).await { - Ok(snapshot) => { - log_debug!(logger, "First fetched lnd snapshot: {:?}", snapshot); - snapshot + let (lnd_channels, first_lnd_snapshot) = + match fetch_lnd_channels(&Client::new(), lsp_url, &node_id, &logger).await { + Ok(lnd_channels) => { + let lnd_snapshot: LndChannelsSnapshot = lnd_channels.clone().into(); + log_debug!(logger, "First fetched lnd snapshot: {:?}", lnd_snapshot); + (lnd_channels, lnd_snapshot) } Err(e) => { log_error!(logger, "First lnd snapshot fetch failed: {e}"); @@ -851,7 +854,7 @@ impl MutinyWalletBuilder { let only_device_lock_vss_pending = pending.len() == 1 && pending.iter().any(|(key, _)| key == DEVICE_LOCK_KEY); let can_update_snapshot = (pending.is_empty() || only_device_lock_vss_pending) - && CONNECTED_PEER_MANAGER.is_any_connected(); + && CONNECTED_PEER_MANAGER.validate_peer_connections(&lnd_channels); if can_update_snapshot { let second_lnd_snapshot = match fetch_lnd_channels_snapshot(&Client::new(), lsp_url, &node_id, &logger).await diff --git a/mutiny-core/src/lsp/lndchannel.rs b/mutiny-core/src/lsp/lndchannel.rs index 52effeb77..ec39d58f0 100644 --- a/mutiny-core/src/lsp/lndchannel.rs +++ b/mutiny-core/src/lsp/lndchannel.rs @@ -23,6 +23,7 @@ pub struct ChannelConstraints { #[derive(Debug, Serialize, Deserialize, Clone)] pub struct LndChannel { pub active: bool, + pub local_pubkey: String, pub remote_pubkey: String, pub channel_point: String, pub chan_id: String, diff --git a/mutiny-core/src/peermanager.rs b/mutiny-core/src/peermanager.rs index ab387f46b..c023f83fd 100644 --- a/mutiny-core/src/peermanager.rs +++ b/mutiny-core/src/peermanager.rs @@ -1,4 +1,5 @@ use crate::keymanager::PhantomKeysManager; +use crate::lsp::lndchannel::LndChannel; use crate::messagehandler::CommonLnEvent; use crate::messagehandler::MutinyMessageHandler; #[cfg(target_arch = "wasm32")] @@ -24,7 +25,8 @@ use lightning::routing::gossip::NodeId; use lightning::util::logger::Logger; use lightning::{ln::msgs::SocketAddress, log_warn}; use lightning::{log_debug, log_error}; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; +use std::str::FromStr; use std::sync::atomic::AtomicBool; use std::sync::Arc; use utils::Mutex; @@ -660,8 +662,54 @@ impl ConnectedPeerManager { } } - pub fn is_any_connected(&self) -> bool { - let lock = self.peers.lock().unwrap(); - !lock.is_empty() + pub fn validate_peer_connections(&self, channels: &[LndChannel]) -> bool { + let (channel_pks, peer_pks) = { + let chan_set = channels + .iter() + .fold( + (HashSet::new(), true), + |(mut s, valid), c| match PublicKey::from_str(&c.local_pubkey) { + Ok(k) => { + s.insert(k); + (s, valid) + } + Err(e) => { + if let Some(l) = &*self.logger.lock().unwrap() { + log_warn!(l, "Invalid local_pubkey in {}: {}", c.chan_id, e); + } + (s, false) + } + }, + ); + if !chan_set.1 { + return false; + } + + let peers = self.peers.lock().unwrap(); + (chan_set.0, peers.keys().cloned().collect::>()) + }; + + let is_match = channel_pks == peer_pks; + if !is_match { + if let Some(l) = &*self.logger.lock().unwrap() { + peer_pks + .difference(&channel_pks) + .for_each(|pk| log_warn!(l, "Redundant peer: {}", pk)); + channel_pks.difference(&peer_pks).for_each(|pk| { + log_warn!( + l, + "Missing peer: {} in channels {:?}", + pk, + channels + .iter() + .filter(|c| c.local_pubkey == pk.to_string()) + .map(|c| &c.chan_id) + .collect::>() + ) + }); + } + } + + is_match } } From e439471a7a7e1e1aee9da8ecd7fca0f2868308ea Mon Sep 17 00:00:00 2001 From: EthanYuan Date: Tue, 25 Mar 2025 00:32:30 +0800 Subject: [PATCH 2/4] bump version to 1.14.6 --- Cargo.lock | 2 +- mutiny-wasm/Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2aec593a3..28a6a4374 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1525,7 +1525,7 @@ dependencies = [ [[package]] name = "mutiny-wasm" -version = "1.14.5" +version = "1.14.6" dependencies = [ "anyhow", "async-trait", diff --git a/mutiny-wasm/Cargo.toml b/mutiny-wasm/Cargo.toml index 70b648f08..8eb9ad3d2 100644 --- a/mutiny-wasm/Cargo.toml +++ b/mutiny-wasm/Cargo.toml @@ -2,7 +2,7 @@ cargo-features = ["per-package-target"] [package] name = "mutiny-wasm" -version = "1.14.5" +version = "1.14.6" edition = "2021" authors = ["utxostack"] forced-target = "wasm32-unknown-unknown" From a53b9c46bf78339bf5e3be15964383debbae1266 Mon Sep 17 00:00:00 2001 From: EthanYuan Date: Tue, 25 Mar 2025 14:07:58 +0800 Subject: [PATCH 3/4] change validate logic: check that peers from lnd are included in the peers in manager --- mutiny-core/src/peermanager.rs | 33 +++++++++++---------------------- 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/mutiny-core/src/peermanager.rs b/mutiny-core/src/peermanager.rs index c023f83fd..b5d30cbdd 100644 --- a/mutiny-core/src/peermanager.rs +++ b/mutiny-core/src/peermanager.rs @@ -663,8 +663,8 @@ impl ConnectedPeerManager { } pub fn validate_peer_connections(&self, channels: &[LndChannel]) -> bool { - let (channel_pks, peer_pks) = { - let chan_set = channels + let (peers_from_lnd, valid) = + channels .iter() .fold( (HashSet::new(), true), @@ -681,32 +681,21 @@ impl ConnectedPeerManager { } }, ); - if !chan_set.1 { - return false; - } + if !valid { + return false; + } + let peers_in_manager = { let peers = self.peers.lock().unwrap(); - (chan_set.0, peers.keys().cloned().collect::>()) + peers.keys().cloned().collect::>() }; - let is_match = channel_pks == peer_pks; + let is_match = peers_from_lnd.is_subset(&peers_in_manager); if !is_match { if let Some(l) = &*self.logger.lock().unwrap() { - peer_pks - .difference(&channel_pks) - .for_each(|pk| log_warn!(l, "Redundant peer: {}", pk)); - channel_pks.difference(&peer_pks).for_each(|pk| { - log_warn!( - l, - "Missing peer: {} in channels {:?}", - pk, - channels - .iter() - .filter(|c| c.local_pubkey == pk.to_string()) - .map(|c| &c.chan_id) - .collect::>() - ) - }); + peers_from_lnd + .difference(&peers_in_manager) + .for_each(|pk| log_warn!(l, "Missing peer: {}", pk)); } } From e546c347020cbd7d5092cc540e445455f9d149a0 Mon Sep 17 00:00:00 2001 From: EthanYuan Date: Tue, 25 Mar 2025 15:32:37 +0800 Subject: [PATCH 4/4] refactoring: rename peers_from_lnd to peers_of_active_channels --- mutiny-core/src/peermanager.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mutiny-core/src/peermanager.rs b/mutiny-core/src/peermanager.rs index b5d30cbdd..d6b84a309 100644 --- a/mutiny-core/src/peermanager.rs +++ b/mutiny-core/src/peermanager.rs @@ -663,7 +663,7 @@ impl ConnectedPeerManager { } pub fn validate_peer_connections(&self, channels: &[LndChannel]) -> bool { - let (peers_from_lnd, valid) = + let (peers_of_active_channels, valid) = channels .iter() .fold( @@ -690,10 +690,10 @@ impl ConnectedPeerManager { peers.keys().cloned().collect::>() }; - let is_match = peers_from_lnd.is_subset(&peers_in_manager); + let is_match = peers_of_active_channels.is_subset(&peers_in_manager); if !is_match { if let Some(l) = &*self.logger.lock().unwrap() { - peers_from_lnd + peers_of_active_channels .difference(&peers_in_manager) .for_each(|pk| log_warn!(l, "Missing peer: {}", pk)); }