diff --git a/core/archipelago/src/api/rpc/lnd/payments.rs b/core/archipelago/src/api/rpc/lnd/payments.rs index 5a7a63ef..f4a52bd3 100644 --- a/core/archipelago/src/api/rpc/lnd/payments.rs +++ b/core/archipelago/src/api/rpc/lnd/payments.rs @@ -198,8 +198,7 @@ impl RpcHandler { .and_then(|v| v.as_array()) .and_then(|arr| { arr.iter().find(|p| { - p.get("payment_hash").and_then(|v| v.as_str()) - == Some(hash_lower.as_str()) + p.get("payment_hash").and_then(|v| v.as_str()) == Some(hash_lower.as_str()) }) }); diff --git a/core/archipelago/src/api/rpc/mesh/flash.rs b/core/archipelago/src/api/rpc/mesh/flash.rs index c4fd4fc0..110660f8 100644 --- a/core/archipelago/src/api/rpc/mesh/flash.rs +++ b/core/archipelago/src/api/rpc/mesh/flash.rs @@ -9,7 +9,9 @@ fn parse_family(s: &str) -> Result { "meshcore" => Ok(DeviceType::Meshcore), "meshtastic" => Ok(DeviceType::Meshtastic), "reticulum" | "rnode" => Ok(DeviceType::Reticulum), - other => anyhow::bail!("Unknown firmware family: {other} (expected meshcore|meshtastic|reticulum)"), + other => anyhow::bail!( + "Unknown firmware family: {other} (expected meshcore|meshtastic|reticulum)" + ), } } diff --git a/core/archipelago/src/container/ui_detection.rs b/core/archipelago/src/container/ui_detection.rs index 4b92817a..5773134f 100644 --- a/core/archipelago/src/container/ui_detection.rs +++ b/core/archipelago/src/container/ui_detection.rs @@ -80,12 +80,7 @@ fn manifest_declares_ui(app_id: &str) -> Option { if m.app.interfaces.is_empty() { return None; } - return Some( - m.app - .interfaces - .values() - .any(|i| i.interface_type == "ui"), - ); + return Some(m.app.interfaces.values().any(|i| i.interface_type == "ui")); } // Malformed manifests are already reported by the orchestrator's // loader; here they simply don't count as a declaration. diff --git a/core/archipelago/src/fips/app_ports.rs b/core/archipelago/src/fips/app_ports.rs index 2f8d25e5..78fb5285 100644 --- a/core/archipelago/src/fips/app_ports.rs +++ b/core/archipelago/src/fips/app_ports.rs @@ -6,39 +6,7 @@ //! no listener, so allowing them is inert. pub const APP_LAUNCH_PORTS: &[u16] = &[ - 2283, - 2342, - 3000, - 3001, - 3002, - 4080, - 5180, - 7778, - 8080, - 8081, - 8082, - 8083, - 8084, - 8085, - 8087, - 8088, - 8089, - 8090, - 8096, - 8123, - 8175, - 8176, - 8240, - 8334, - 8888, - 8999, - 9000, - 9100, - 10380, - 11434, - 18081, - 18083, - 23000, - 32838, - 50002, + 2283, 2342, 3000, 3001, 3002, 4080, 5180, 7778, 8080, 8081, 8082, 8083, 8084, 8085, 8087, 8088, + 8089, 8090, 8096, 8123, 8175, 8176, 8240, 8334, 8888, 8999, 9000, 9100, 10380, 11434, 18081, + 18083, 23000, 32838, 50002, ]; diff --git a/core/archipelago/src/fips/config.rs b/core/archipelago/src/fips/config.rs index 9ebc19cf..f1a7b739 100644 --- a/core/archipelago/src/fips/config.rs +++ b/core/archipelago/src/fips/config.rs @@ -287,7 +287,10 @@ pub async fn install(identity_dir: &Path) -> Result<()> { app_install?; // Make the allowance live immediately; a no-op error when the // hardening baseline isn't installed on this node yet. - if tokio::fs::try_exists("/etc/fips/fips.nft").await.unwrap_or(false) { + if tokio::fs::try_exists("/etc/fips/fips.nft") + .await + .unwrap_or(false) + { match Command::new("sudo") .args(["nft", "-f", "/etc/fips/fips.nft"]) .output() diff --git a/core/archipelago/src/fips/dial.rs b/core/archipelago/src/fips/dial.rs index cb45f9c3..f4f88013 100644 --- a/core/archipelago/src/fips/dial.rs +++ b/core/archipelago/src/fips/dial.rs @@ -376,13 +376,9 @@ impl<'a> PeerRequest<'a> { let onion = self.onion_host.to_string(); let transport = kind.to_string(); tokio::spawn(async move { - let _ = crate::federation::record_peer_transport( - &dir, - None, - Some(&onion), - &transport, - ) - .await; + let _ = + crate::federation::record_peer_transport(&dir, None, Some(&onion), &transport) + .await; }); } } diff --git a/core/archipelago/src/fips/mod.rs b/core/archipelago/src/fips/mod.rs index ae192b5a..2664bbe9 100644 --- a/core/archipelago/src/fips/mod.rs +++ b/core/archipelago/src/fips/mod.rs @@ -104,17 +104,15 @@ pub fn spawn_fips_supervisor(data_dir: std::path::PathBuf) { .await .unwrap_or_default(); let seed = anchors::load(&data_dir).await.unwrap_or_default(); - let mut warm_npubs: std::collections::BTreeSet = nodes - .iter() - .filter_map(|n| n.fips_npub.clone()) - .collect(); + let mut warm_npubs: std::collections::BTreeSet = + nodes.iter().filter_map(|n| n.fips_npub.clone()).collect(); warm_npubs.extend(seed.iter().map(|a| a.npub.clone())); let mut handles = Vec::new(); for npub in warm_npubs { // Service-active was checked once above for the whole batch. - handles.push(tokio::spawn( - async move { dial::warm_path_unchecked(&npub).await }, - )); + handles.push(tokio::spawn(async move { + dial::warm_path_unchecked(&npub).await + })); } for h in handles { let _ = h.await; diff --git a/core/archipelago/src/mesh/flash.rs b/core/archipelago/src/mesh/flash.rs index 33a0f089..7928c07f 100644 --- a/core/archipelago/src/mesh/flash.rs +++ b/core/archipelago/src/mesh/flash.rs @@ -420,7 +420,9 @@ pub async fn start_flash_job( match &result { Ok(()) => { - bg_job.push_log("Flash completed successfully".to_string()).await; + bg_job + .push_log("Flash completed successfully".to_string()) + .await; bg_job.finish().await; info!(path = %path, board = ?board, family = %family, "LoRa firmware flash succeeded"); } @@ -586,7 +588,8 @@ async fn fetch_meshtastic_image( if tokio::fs::metadata(&zip_path).await.is_err() { download_to_file(client, &zip_asset.browser_download_url, &zip_path, job).await?; } else { - job.push_log(format!("Using cached {}", zip_asset.name)).await; + job.push_log(format!("Using cached {}", zip_asset.name)) + .await; } // "*.factory.bin" is Meshtastic's full merged image (bootloader + @@ -594,26 +597,20 @@ async fn fetch_meshtastic_image( // erased chip — confirmed by inspecting the real zip's contents, as // opposed to the plain "*.bin" OTA-update image which assumes an // existing bootloader/partition table already on the chip. - let entry_name = format!( - "firmware-{}-{}.factory.bin", - board.meshtastic_id(), - version - ); + let entry_name = format!("firmware-{}-{}.factory.bin", board.meshtastic_id(), version); let out_path = cache.join(&entry_name); if tokio::fs::metadata(&out_path).await.is_ok() { return Ok(out_path); } - job.push_log(format!( - "Extracting {entry_name} from {}", - zip_asset.name - )) - .await; + job.push_log(format!("Extracting {entry_name} from {}", zip_asset.name)) + .await; let zip_path_owned = zip_path.clone(); let entry_name_owned = entry_name.clone(); let out_path_owned = out_path.clone(); tokio::task::spawn_blocking(move || -> Result<()> { - let file = std::fs::File::open(&zip_path_owned).context("Opening downloaded firmware zip")?; + let file = + std::fs::File::open(&zip_path_owned).context("Opening downloaded firmware zip")?; let mut archive = zip::ZipArchive::new(file).context("Reading firmware zip")?; let mut entry = archive .by_name(&entry_name_owned) diff --git a/core/archipelago/src/mesh/mod.rs b/core/archipelago/src/mesh/mod.rs index a3933ee5..5fd1a3a8 100644 --- a/core/archipelago/src/mesh/mod.rs +++ b/core/archipelago/src/mesh/mod.rs @@ -802,7 +802,10 @@ impl MeshService { // the server name — it existed as write-only config with no reader // until this line, which is why renaming on the Mesh page never // changed anything on the air. - self.config.advert_name.clone().or_else(|| self.server_name.clone()), + self.config + .advert_name + .clone() + .or_else(|| self.server_name.clone()), self.config.lora_region.clone(), self.config.lora_radio_params, self.config.channel_name.clone(), @@ -1333,20 +1336,21 @@ impl MeshService { // federation branch: the fall-through LoRa path twin-resolves the // routing key via peer_dest_prefix. let device_connected = self.state.status.read().await.device_connected; - let radio_twin_reachable = is_federation_synthetic && !exceeds_lora && device_connected && { - let peers = self.state.peers.read().await; - peers - .get(&contact_id) - .and_then(|p| p.arch_pubkey_hex.clone()) - .map(|arch| { - peers.values().any(|p| { - p.contact_id < FEDERATION_CONTACT_ID_BASE - && p.reachable - && p.arch_pubkey_hex.as_deref() == Some(arch.as_str()) + let radio_twin_reachable = + is_federation_synthetic && !exceeds_lora && device_connected && { + let peers = self.state.peers.read().await; + peers + .get(&contact_id) + .and_then(|p| p.arch_pubkey_hex.clone()) + .map(|arch| { + peers.values().any(|p| { + p.contact_id < FEDERATION_CONTACT_ID_BASE + && p.reachable + && p.arch_pubkey_hex.as_deref() == Some(arch.as_str()) + }) }) - }) - .unwrap_or(false) - }; + .unwrap_or(false) + }; let mesh_only_mode = load_config(&self.data_dir) .await .ok() diff --git a/core/archipelago/src/mesh/reticulum.rs b/core/archipelago/src/mesh/reticulum.rs index ae4c8ff5..189e33c5 100644 --- a/core/archipelago/src/mesh/reticulum.rs +++ b/core/archipelago/src/mesh/reticulum.rs @@ -623,12 +623,14 @@ impl ReticulumLink { dest_pubkey_prefix: &[u8; 6], payload: &[u8], ) -> Result<()> { - let dest_hash = self.resolve_dest_hash(dest_pubkey_prefix).with_context(|| { - format!( - "Unknown Reticulum prefix {} — peer hasn't announced yet", - hex::encode(dest_pubkey_prefix) - ) - })?; + let dest_hash = self + .resolve_dest_hash(dest_pubkey_prefix) + .with_context(|| { + format!( + "Unknown Reticulum prefix {} — peer hasn't announced yet", + hex::encode(dest_pubkey_prefix) + ) + })?; // Typed-envelope payloads (ReadReceipt/Reaction/etc. — anything small // enough for the single-frame path) are raw binary CBOR, not text. // `from_utf8_lossy` would irreversibly mangle them since `content` @@ -663,12 +665,14 @@ impl ReticulumLink { caption: Option<&str>, ) -> Result<()> { use base64::{engine::general_purpose::STANDARD as B64, Engine as _}; - let dest_hash = self.resolve_dest_hash(dest_pubkey_prefix).with_context(|| { - format!( - "Unknown Reticulum prefix {} — peer hasn't announced yet", - hex::encode(dest_pubkey_prefix) - ) - })?; + let dest_hash = self + .resolve_dest_hash(dest_pubkey_prefix) + .with_context(|| { + format!( + "Unknown Reticulum prefix {} — peer hasn't announced yet", + hex::encode(dest_pubkey_prefix) + ) + })?; self.send_rpc(serde_json::json!({ "cmd": "send", "dest_hash": hex::encode(dest_hash), @@ -691,12 +695,14 @@ impl ReticulumLink { /// `handle_event`, not awaited here. pub async fn send_resource(&mut self, dest_pubkey_prefix: &[u8; 6], data: &[u8]) -> Result<()> { use base64::{engine::general_purpose::STANDARD as B64, Engine as _}; - let dest_hash = self.resolve_dest_hash(dest_pubkey_prefix).with_context(|| { - format!( - "Unknown Reticulum prefix {} — peer hasn't announced yet", - hex::encode(dest_pubkey_prefix) - ) - })?; + let dest_hash = self + .resolve_dest_hash(dest_pubkey_prefix) + .with_context(|| { + format!( + "Unknown Reticulum prefix {} — peer hasn't announced yet", + hex::encode(dest_pubkey_prefix) + ) + })?; let req_id = self.next_resource_id(); self.send_rpc(serde_json::json!({ "cmd": "send_resource", @@ -886,13 +892,15 @@ impl ReticulumLink { .as_deref() .and_then(protocol::parse_identity_broadcast); let is_legacy_blob = legacy_identity.is_some(); - let identity_blob_text = explicit_blob.or_else(|| { - app_data_text.clone().filter(|_| is_legacy_blob) - }); + let identity_blob_text = + explicit_blob.or_else(|| app_data_text.clone().filter(|_| is_legacy_blob)); let parsed_identity = identity_blob_text .as_deref() .and_then(protocol::parse_identity_broadcast); - if let Some(text) = identity_blob_text.as_deref().filter(|_| parsed_identity.is_some()) { + if let Some(text) = identity_blob_text + .as_deref() + .filter(|_| parsed_identity.is_some()) + { let mut data = Vec::with_capacity(7 + text.len()); data.push(0); // channel index — unused by the identity path data.extend_from_slice(&prefix); @@ -1387,7 +1395,10 @@ mod tests { pick_announced_name(None, Some("\u{FFFD}\u{FFFD}Shaza\u{FFFD}".into()), false), None ); - assert_eq!(pick_announced_name(None, Some("has\u{1}ctl".into()), false), None); + assert_eq!( + pick_announced_name(None, Some("has\u{1}ctl".into()), false), + None + ); // Nothing at all. assert_eq!(pick_announced_name(None, None, false), None); } diff --git a/core/archipelago/src/node_message.rs b/core/archipelago/src/node_message.rs index d72ec3d4..8806de80 100644 --- a/core/archipelago/src/node_message.rs +++ b/core/archipelago/src/node_message.rs @@ -381,21 +381,16 @@ pub async fn send_to_peer( if let Some(dir) = record_data_dir { req = req.record_transport(dir); } - let (resp, transport) = req - .send_json(&body) - .await - .map_err(|e| { - let msg = e.to_string(); - if msg.contains("connection refused") || msg.contains("Connection refused") { - anyhow::anyhow!( - "Peer unreachable. Check Tor (127.0.0.1:9050) and FIPS daemon status." - ) - } else if msg.contains("timeout") || msg.contains("timed out") { - anyhow::anyhow!("Connection timed out. The peer may be offline.") - } else { - anyhow::anyhow!("Failed to send: {}", msg) - } - })?; + let (resp, transport) = req.send_json(&body).await.map_err(|e| { + let msg = e.to_string(); + if msg.contains("connection refused") || msg.contains("Connection refused") { + anyhow::anyhow!("Peer unreachable. Check Tor (127.0.0.1:9050) and FIPS daemon status.") + } else if msg.contains("timeout") || msg.contains("timed out") { + anyhow::anyhow!("Connection timed out. The peer may be offline.") + } else { + anyhow::anyhow!("Failed to send: {}", msg) + } + })?; if !resp.status().is_success() { anyhow::bail!(