From 2295a34667dc0c552515a95e49f307e4c12b0ed2 Mon Sep 17 00:00:00 2001 From: Dorian Date: Fri, 20 Mar 2026 12:31:30 +0000 Subject: [PATCH] fix: LND and ElectrumX Tor onion address resolution - lnd.rs: check tor-hostnames readable copy, then /var/lib/tor/, then legacy /var/lib/archipelago/tor/ with sudo fallback for each - electrs_status.rs: same multi-path resolution for ElectrumX onion - Both servers: created /var/lib/archipelago/tor-hostnames/ with readable copies of onion addresses (avoids sudo on every API call) Co-Authored-By: Claude Opus 4.6 (1M context) --- core/archipelago/src/api/rpc/lnd.rs | 39 +++++++++++++++++++++----- core/archipelago/src/electrs_status.rs | 38 ++++++++++++++++++++----- 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/core/archipelago/src/api/rpc/lnd.rs b/core/archipelago/src/api/rpc/lnd.rs index 269561e9..3fb1982f 100644 --- a/core/archipelago/src/api/rpc/lnd.rs +++ b/core/archipelago/src/api/rpc/lnd.rs @@ -922,13 +922,38 @@ impl RpcHandler { let macaroon_b64url = base64::engine::general_purpose::URL_SAFE_NO_PAD.encode(&macaroon_bytes); - // Read Tor onion address if available - let tor_onion = tokio::fs::read_to_string( - "/var/lib/archipelago/tor/hidden_service_lnd/hostname", - ) - .await - .ok() - .map(|s| s.trim().to_string()); + // Read Tor onion address — check system Tor path first, then legacy + let tor_onion = { + let mut onion = None; + for path in &[ + "/var/lib/archipelago/tor-hostnames/lnd", + "/var/lib/tor/hidden_service_lnd/hostname", + "/var/lib/archipelago/tor/hidden_service_lnd/hostname", + ] { + if let Ok(addr) = tokio::fs::read_to_string(path).await { + let addr = addr.trim().to_string(); + if addr.ends_with(".onion") { + onion = Some(addr); + break; + } + } + // Try sudo for system Tor dirs (owned by debian-tor, 0700) + if let Ok(output) = tokio::process::Command::new("sudo") + .args(["cat", path]) + .output() + .await + { + if output.status.success() { + let addr = String::from_utf8_lossy(&output.stdout).trim().to_string(); + if addr.ends_with(".onion") { + onion = Some(addr); + break; + } + } + } + } + onion + }; Ok(serde_json::json!({ "cert_base64url": cert_b64url, diff --git a/core/archipelago/src/electrs_status.rs b/core/archipelago/src/electrs_status.rs index 8e521a7b..4055bc80 100644 --- a/core/archipelago/src/electrs_status.rs +++ b/core/archipelago/src/electrs_status.rs @@ -146,13 +146,37 @@ pub async fn get_electrs_sync_status() -> ElectrsSyncStatus { None }; - // Read Tor onion address if available - let tor_onion = tokio::fs::read_to_string( - "/var/lib/archipelago/tor/hidden_service_electrs/hostname", - ) - .await - .ok() - .map(|s| s.trim().to_string()); + // Read Tor onion address — check system Tor path first, then legacy + let tor_onion = { + let mut onion = None; + for path in &[ + "/var/lib/archipelago/tor-hostnames/electrs", + "/var/lib/tor/hidden_service_electrs/hostname", + "/var/lib/archipelago/tor/hidden_service_electrs/hostname", + ] { + if let Ok(addr) = tokio::fs::read_to_string(path).await { + let addr = addr.trim().to_string(); + if addr.ends_with(".onion") { + onion = Some(addr); + break; + } + } + if let Ok(output) = tokio::process::Command::new("sudo") + .args(["cat", path]) + .output() + .await + { + if output.status.success() { + let addr = String::from_utf8_lossy(&output.stdout).trim().to_string(); + if addr.ends_with(".onion") { + onion = Some(addr); + break; + } + } + } + } + onion + }; let network_height = match bitcoin_network_height().await { Ok(h) => h,