feat: bitcoin-ui CSS fix, HTTPS proxy support, deploy script improvements
Bitcoin UI: - Replace cdn.tailwindcss.com with locally bundled tailwind.css (CSP blocks external scripts) - Make all asset paths relative for nginx proxy compatibility - Add bitcoin-ui build/deploy to deploy-to-target.sh (was missing entirely) - Use --network host (bitcoin-ui proxies Bitcoin RPC at 127.0.0.1:8332) HTTPS mixed content fix: - Add HTTPS_PROXY_PATHS in AppSession.vue — when parent page is HTTPS, iframe loads through nginx proxy instead of direct HTTP port - Prevents browser blocking HTTP iframes inside HTTPS pages - All Tailscale servers use HTTPS, this was breaking all app iframes Deploy & first-boot improvements: - first-boot-containers.sh auto-detects disk size for pruning vs txindex - first-boot-containers.sh checks fallback source path for UI containers - Added mempool-electrs to APP_PORTS mapping - ElectrumX container creation in first-boot - Podman doctor/fix/uptime skills added Also includes: session persistence, identity management, LND transactions, ElectrumX status UI, nostr-provider improvements, Web5 enhancements Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
//! Electrs sync status: fetches indexed height from Electrum RPC and network height from Bitcoin Core.
|
||||
//! ElectrumX sync status: fetches indexed height from Electrum RPC and network height from Bitcoin Core.
|
||||
|
||||
use anyhow::{Context, Result};
|
||||
use serde::Serialize;
|
||||
@@ -6,12 +6,12 @@ use std::io::{BufRead, BufReader, Write};
|
||||
use std::net::TcpStream;
|
||||
use std::time::Duration;
|
||||
|
||||
const ELECTRS_HOST: &str = "127.0.0.1";
|
||||
const ELECTRS_PORT: u16 = 50001;
|
||||
const ELECTRUMX_HOST: &str = "127.0.0.1";
|
||||
const ELECTRUMX_PORT: u16 = 50001;
|
||||
const BITCOIN_RPC_URL: &str = "http://127.0.0.1:8332/";
|
||||
const ELECTRS_DATA_DIR: &str = "/var/lib/archipelago/mempool-electrs";
|
||||
// Approximate final index size in bytes for mainnet with --lightmode (~35GB)
|
||||
const ESTIMATED_FULL_INDEX_BYTES: f64 = 35_000_000_000.0;
|
||||
const ELECTRUMX_DATA_DIR: &str = "/var/lib/archipelago/electrumx";
|
||||
// Approximate final index size in bytes for mainnet (~55GB for ElectrumX full index)
|
||||
const ESTIMATED_FULL_INDEX_BYTES: f64 = 55_000_000_000.0;
|
||||
|
||||
/// Build Bitcoin RPC Basic auth header from env vars.
|
||||
/// Falls back to cookie auth file if env vars are not set.
|
||||
@@ -61,10 +61,10 @@ fn format_bytes(bytes: u64) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
/// Fetch electrs indexed height via Electrum protocol (TCP JSON-RPC).
|
||||
fn electrs_indexed_height() -> Result<u64> {
|
||||
let mut stream = TcpStream::connect((ELECTRS_HOST, ELECTRS_PORT))
|
||||
.context("Failed to connect to electrs")?;
|
||||
/// Fetch ElectrumX indexed height via Electrum protocol (TCP JSON-RPC).
|
||||
fn electrumx_indexed_height() -> Result<u64> {
|
||||
let mut stream = TcpStream::connect((ELECTRUMX_HOST, ELECTRUMX_PORT))
|
||||
.context("Failed to connect to ElectrumX")?;
|
||||
stream
|
||||
.set_read_timeout(Some(Duration::from_secs(5)))
|
||||
.context("set_read_timeout")?;
|
||||
@@ -83,11 +83,11 @@ fn electrs_indexed_height() -> Result<u64> {
|
||||
reader.read_line(&mut line)?;
|
||||
let line = line.trim();
|
||||
if line.is_empty() {
|
||||
anyhow::bail!("Empty response from electrs");
|
||||
anyhow::bail!("Empty response from ElectrumX");
|
||||
}
|
||||
|
||||
let json: serde_json::Value = serde_json::from_str(line)?;
|
||||
// blockchain.numblocks.subscribe returns result as number; headers.subscribe returns {block_height: N}
|
||||
// blockchain.numblocks.subscribe returns result as number; headers.subscribe returns {block_height: N, hex: ...}
|
||||
let height = json
|
||||
.get("result")
|
||||
.and_then(|r| r.as_u64())
|
||||
@@ -96,7 +96,13 @@ fn electrs_indexed_height() -> Result<u64> {
|
||||
.and_then(|r| r.get("block_height"))
|
||||
.and_then(|h| h.as_u64())
|
||||
})
|
||||
.context("Missing height in electrs response")?;
|
||||
.or_else(|| {
|
||||
// ElectrumX returns {"result": {"height": N, "hex": "..."}}
|
||||
json.get("result")
|
||||
.and_then(|r| r.get("height"))
|
||||
.and_then(|h| h.as_u64())
|
||||
})
|
||||
.context("Missing height in ElectrumX response")?;
|
||||
Ok(height)
|
||||
}
|
||||
|
||||
@@ -130,10 +136,10 @@ async fn bitcoin_network_height() -> Result<u64> {
|
||||
Ok(height)
|
||||
}
|
||||
|
||||
/// Get electrs sync status. Runs blocking electrs call in spawn_blocking.
|
||||
/// Get ElectrumX sync status. Runs blocking ElectrumX call in spawn_blocking.
|
||||
pub async fn get_electrs_sync_status() -> ElectrsSyncStatus {
|
||||
// Get index data size (non-blocking, fast filesystem stat)
|
||||
let data_bytes = dir_size_bytes(ELECTRS_DATA_DIR);
|
||||
let data_bytes = dir_size_bytes(ELECTRUMX_DATA_DIR);
|
||||
let index_size = if data_bytes > 0 {
|
||||
Some(format_bytes(data_bytes))
|
||||
} else {
|
||||
@@ -154,10 +160,10 @@ pub async fn get_electrs_sync_status() -> ElectrsSyncStatus {
|
||||
}
|
||||
};
|
||||
|
||||
let indexed_height = match tokio::task::spawn_blocking(electrs_indexed_height).await {
|
||||
let indexed_height = match tokio::task::spawn_blocking(electrumx_indexed_height).await {
|
||||
Ok(Ok(h)) => h,
|
||||
Ok(Err(e)) => {
|
||||
// Electrs doesn't listen on 50001 until indexing completes (can take hours)
|
||||
// ElectrumX may not be ready on 50001 during initial sync
|
||||
let err_msg = e.to_string();
|
||||
let (status, error) = if err_msg.contains("connect") || err_msg.contains("Connection refused") {
|
||||
// Estimate progress from data directory size
|
||||
@@ -170,12 +176,12 @@ pub async fn get_electrs_sync_status() -> ElectrsSyncStatus {
|
||||
(
|
||||
"indexing".to_string(),
|
||||
Some(format!(
|
||||
"Building index ({} / ~35 GB estimated). Electrum RPC will be available when complete.",
|
||||
"Building index ({} / ~55 GB estimated). Electrum RPC will be available when complete.",
|
||||
size_str
|
||||
)),
|
||||
)
|
||||
} else {
|
||||
("error".to_string(), Some(format!("Electrs: {}", e)))
|
||||
("error".to_string(), Some(format!("ElectrumX: {}", e)))
|
||||
};
|
||||
// Use estimated progress when indexing
|
||||
let progress_pct = if status == "indexing" && data_bytes > 0 {
|
||||
|
||||
Reference in New Issue
Block a user