Compare commits

...
Author SHA1 Message Date
ssmithxandClaude Sonnet 5 dc7b598558 fix(tor): un-alias bitcoin-core's hidden-service name; add regression tests
read_tor_address("bitcoin-core") was resolving through tor_service_name to
the shared "bitcoin" alias, but enrollment (install.rs auto-enroll and the
tor.create-service RPC) always names HiddenServiceDir/tor-hostnames entries
using the raw package_id verbatim — never canonicalized. On a real node
that's hidden_service_bitcoin-core, which the aliased lookup never found,
so the per-app UI Tor badge stayed empty even after the previous commit
made bitcoin-core auto-enrollable.

Give bitcoin-core its own identity-mapped arm instead of folding it into
the legacy bitcoin/bitcoin-knots/bitcoind alias, and pin all three lookup
tables (known_service_port, is_protocol_service, tor_service_name) with
regression tests so this alias-drift class of bug can't recur silently.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WxfWiFfnBkdSxwKUuV2tNy
2026-09-10 16:26:59 +00:00
ssmithxandClaude Sonnet 5 69f3a355c7 fix(tor): recognize bitcoin-core in Tor auto-enrollment tables
apps/bitcoin-core/manifest.yml uses id "bitcoin-core", but
known_service_port/is_protocol_service (tor/mod.rs) and
tor_service_name (docker_packages.rs) only matched "bitcoin" and
"bitcoin-knots", so the app silently never got auto-enrolled for a
P2P (8333) hidden service at install time, and the UI's Tor address
lookup for it always returned None.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WxfWiFfnBkdSxwKUuV2tNy
2026-09-10 15:28:17 +00:00
archipelago db52c06a72 chore(catalog): sign Cuprate registry update 2026-09-07 05:12:05 -04:00
archipelago 4b14b62e74 chore: publish release v1.8.11-alpha
Demo images / Build & push demo images (push) Successful in 3m40s
2026-09-07 04:35:48 -04:00
6 changed files with 3329 additions and 3307 deletions
+19 -2
View File
@@ -377,6 +377,23 @@ async fn write_staged_torrc(content: &str, staging: &str) -> Result<()> {
Ok(())
}
#[cfg(test)]
mod known_service_tests {
use super::{is_protocol_service, known_service_port};
#[test]
fn bitcoin_core_is_a_protocol_service_on_the_p2p_port() {
// Regression: apps/bitcoin-core/manifest.yml uses id "bitcoin-core",
// distinct from the legacy "bitcoin"/"bitcoin-knots" ids. Missing
// here means auto-enrollment silently skips it (known_service_port
// returns 0) and, separately, regenerate_torrc falls back to the
// web-app HiddenServicePort-80 default instead of forwarding 8333
// straight through.
assert_eq!(known_service_port("bitcoin-core"), 8333);
assert!(is_protocol_service("bitcoin-core"));
}
}
#[cfg(test)]
mod torrc_tests {
use super::app_hidden_service_port_line;
@@ -594,7 +611,7 @@ fn is_valid_v3_onion(s: &str) -> bool {
pub(in crate::api::rpc) fn known_service_port(name: &str) -> u16 {
match name {
"archipelago" => 80,
"bitcoin" | "bitcoin-knots" => 8333,
"bitcoin" | "bitcoin-core" | "bitcoin-knots" => 8333,
"electrs" | "electrumx" => 50001,
"lnd" => 8080,
"btcpay" | "btcpay-server" | "btcpayserver" => 23000,
@@ -619,7 +636,7 @@ pub(in crate::api::rpc) fn known_service_port(name: &str) -> u16 {
pub(in crate::api::rpc) fn is_protocol_service(name: &str) -> bool {
matches!(
name,
"bitcoin" | "bitcoin-knots" | "electrs" | "electrumx" | "lnd"
"bitcoin" | "bitcoin-core" | "bitcoin-knots" | "electrs" | "electrumx" | "lnd"
)
}
@@ -657,9 +657,19 @@ fn apply_dynamic_metadata(app_id: &str, meta: &mut AppMetadata) {
/// Map app_id to Tor hidden service directory name.
/// "archipelago" is the main web UI (nginx port 80).
/// Supports container names from deploy (archy-*, btcpay-server, etc.).
///
/// This must match what enrollment actually names the hidden service dir
/// with — both the install-time auto-enroll (`install.rs`) and the manual
/// `tor.create-service` RPC write `HiddenServiceDir` using the raw
/// `package_id`/`name` verbatim, with no canonicalization. So `bitcoin-core`
/// gets its own identity arm rather than folding into the "bitcoin" alias:
/// aliasing it here without also canonicalizing the write side would point
/// this lookup at `hidden_service_bitcoin`, which never gets created — the
/// on-disk dir is always `hidden_service_bitcoin-core` for this app id.
fn tor_service_name(app_id: &str) -> Option<&'static str> {
match app_id {
"archipelago" => Some("archipelago"),
"bitcoin-core" => Some("bitcoin-core"),
"bitcoin" | "bitcoin-knots" | "bitcoind" => Some("bitcoin"),
"electrumx" | "electrs" | "electrum" => Some("electrumx"),
"lnd" | "lnd-ui" => Some("lnd"),
@@ -906,6 +916,28 @@ mod launch_url_port_tests {
}
}
#[cfg(test)]
mod tor_service_name_tests {
use super::tor_service_name;
#[test]
fn bitcoin_core_resolves_to_its_own_hidden_service_dir() {
// Regression: enrollment (install.rs, tor.create-service) writes
// HiddenServiceDir/tor-hostnames entries using the raw package_id
// verbatim, never canonicalized. Aliasing "bitcoin-core" to the
// shared "bitcoin" name here would point reads at a directory
// enrollment never creates.
assert_eq!(tor_service_name("bitcoin-core"), Some("bitcoin-core"));
}
#[test]
fn legacy_bitcoin_ids_share_the_bitcoin_alias() {
assert_eq!(tor_service_name("bitcoin"), Some("bitcoin"));
assert_eq!(tor_service_name("bitcoin-knots"), Some("bitcoin"));
assert_eq!(tor_service_name("bitcoind"), Some("bitcoin"));
}
}
#[cfg(test)]
mod extract_lan_address_tests {
use super::extract_lan_address;
+17 -17
View File
@@ -1,29 +1,29 @@
{
"changelog": [
"**Lightning sends work again — v1.8.9's payment switch lost the fee budget.** Moving payments to LND 0.21's supported route (Router.SendPaymentV2) shipped without a fee limit, and the v2 API treats an absent limit as **zero allowed fees**: every real route carries a routing fee, so the pathfinder rejected them all and the wallet answered \"No route to the recipient\" on every send — all day, on healthy channels with plenty of liquidity. The router debug log made it unambiguous (`fee_limit=0 mSAT` on every failing wallet payment; the same payment succeeded by hand the moment a fee limit was set). Payments now carry lncli's default budget (the payment amount), the wallet's amount handling for zero-value invoices is preserved, and a unit test pins the limit can never be zero again.",
"**A channel that drops its peer link now heals itself — on every node.** Restarting LND (an app update, a reboot, container churn) can leave a channel's peer connection down for hours while both endpoints keep the channel flagged disabled in the routing graph: the node looks perfectly healthy, the wallet shows balance, and every payment in either direction fails \"no route to the recipient\". Observed live: a node's only channel sat unroutable for ~17 hours after the LND 0.21.2 update, with no sign of it in any dashboard. The daemon now watches the channel graph as desired state — every open channel should have a live peer — and reconnects any that don't, using the peer's advertised addresses. Nodes without LND are untouched; an unreachable peer is retried gently, not hammered.",
"**The Lightning wallet states the node's real funding state instead of \"you have no channel.\"** Trying to send while a freshly opened channel was still waiting for on-chain confirmations — or when all its balance sits on the far side — raised a modal that claimed the node had NO channel at all (the outbound sum is legitimately zero in both states), pointed the user at opening a second channel, and — for payment routing failures — even showed the *receiving* copy. The funding gate now reads the channel list it already fetched: a confirming channel gets \"it unlocks automatically once confirmed, nothing is needed from you\", a far-side balance gets \"you can receive, but there's nothing to send right now\", a routing/liquidity payment failure says so instead of claiming channel problems, and only a genuinely channel-less node keeps the open-one guidance."
"**Cuprate now syncs without burning a core for days.** The app's shipped config now enables Cuprate's checkpoint-backed `fast_sync` path, raises the database cache to 8 GiB, and gives the container a 10 GiB memory limit so the cache has real headroom. A live comparison that motivated the change saw the affected node sit around 45% CPU while the corrected config held near low single digits at the same chain height and block rate. The restricted RPC remains fronted through the safe app gate/Tor path.",
"**OpenWrt Gateway setup is documented from a real install, and two setup bugs are fixed.** The new guide walks a node operator through flashing a GL.iNet AX3000 to stock OpenWrt, pairing it with Archipelago, and installing TollGate pay-as-you-go WiFi. The installer now finds `opkg`/`apk` through the router's actual `PATH` instead of assuming `/usr/bin`, the UI no longer sends an empty password over a saved router connection, and the pinned TollGate package moves to `v0.5.0` with a native `.apk` install path where upstream provides one.",
"**Release publishing now checks the public Gitea download links before a manifest goes live.** The publisher already fetched every artifact back and verified its size and SHA-256; this release adds a second guard for the release page itself, so a bad Gitea `ROOT_URL` or proxy setting cannot publish working files behind broken public HTTPS download links."
],
"components": [
{
"current_version": "1.8.10-alpha",
"download_url": "https://source.archipelago-foundation.org/lfg2025/archy/releases/download/v1.8.10-alpha/archipelago",
"current_version": "1.8.11-alpha",
"download_url": "https://source.archipelago-foundation.org/lfg2025/archy/releases/download/v1.8.11-alpha/archipelago",
"name": "archipelago",
"new_version": "1.8.10-alpha",
"sha256": "6c8bd41fed44cd999cb360c00e1b66a2d19d19812cc2b0c8a1677eec2a9579e6",
"size_bytes": 64178056
"new_version": "1.8.11-alpha",
"sha256": "ae569054edd6b2491beb101815f6809bc00c95a7dbe86bd084bcb9a7c36e1853",
"size_bytes": 64179264
},
{
"current_version": "1.8.10-alpha",
"download_url": "https://source.archipelago-foundation.org/lfg2025/archy/releases/download/v1.8.10-alpha/archipelago-frontend-1.8.10-alpha.tar.gz",
"name": "archipelago-frontend-1.8.10-alpha.tar.gz",
"new_version": "1.8.10-alpha",
"sha256": "6b25de8a8e1a4f7fe51594f9bbbe21f5820f417af47a8b309c2dbf8f8723b719",
"size_bytes": 97736297
"current_version": "1.8.11-alpha",
"download_url": "https://source.archipelago-foundation.org/lfg2025/archy/releases/download/v1.8.11-alpha/archipelago-frontend-1.8.11-alpha.tar.gz",
"name": "archipelago-frontend-1.8.11-alpha.tar.gz",
"new_version": "1.8.11-alpha",
"sha256": "192fd0470b6ccf66e78c80b4a4c3af5468882b85d81959362a3bd11f88b9d71d",
"size_bytes": 97741740
}
],
"release_date": "2026-09-01",
"signature": "b69926bcb1851ff7d6a5b24519cd4a8015aab4ed4b588ee989d8ce6e3beaeb2cc0eb38078f522ded0d389fe53b7dbcdbf3f40c534b4bfafa5cf4a2ab2c59e40f",
"release_date": "2026-09-07",
"signature": "6449ce6ef35a4ef4fa6d0923bb58a2bff52ea5430d5532496e8f0af9ed52eaec293f19d7bec272dc9bc1af5fb2cdfa0e46068c827a9a4dd9cbef92d1c5845301",
"signed_by": "did:key:z6Mkfu5LT8d4DjETtrkATvHh9Dvcbnr7zBCUwfau8Sw7DLWT",
"version": "1.8.10-alpha"
"version": "1.8.11-alpha"
}
+3244 -3242
View File
File diff suppressed because one or more lines are too long
+17 -17
View File
@@ -1,29 +1,29 @@
{
"changelog": [
"**Lightning sends work again — v1.8.9's payment switch lost the fee budget.** Moving payments to LND 0.21's supported route (Router.SendPaymentV2) shipped without a fee limit, and the v2 API treats an absent limit as **zero allowed fees**: every real route carries a routing fee, so the pathfinder rejected them all and the wallet answered \"No route to the recipient\" on every send — all day, on healthy channels with plenty of liquidity. The router debug log made it unambiguous (`fee_limit=0 mSAT` on every failing wallet payment; the same payment succeeded by hand the moment a fee limit was set). Payments now carry lncli's default budget (the payment amount), the wallet's amount handling for zero-value invoices is preserved, and a unit test pins the limit can never be zero again.",
"**A channel that drops its peer link now heals itself — on every node.** Restarting LND (an app update, a reboot, container churn) can leave a channel's peer connection down for hours while both endpoints keep the channel flagged disabled in the routing graph: the node looks perfectly healthy, the wallet shows balance, and every payment in either direction fails \"no route to the recipient\". Observed live: a node's only channel sat unroutable for ~17 hours after the LND 0.21.2 update, with no sign of it in any dashboard. The daemon now watches the channel graph as desired state — every open channel should have a live peer — and reconnects any that don't, using the peer's advertised addresses. Nodes without LND are untouched; an unreachable peer is retried gently, not hammered.",
"**The Lightning wallet states the node's real funding state instead of \"you have no channel.\"** Trying to send while a freshly opened channel was still waiting for on-chain confirmations — or when all its balance sits on the far side — raised a modal that claimed the node had NO channel at all (the outbound sum is legitimately zero in both states), pointed the user at opening a second channel, and — for payment routing failures — even showed the *receiving* copy. The funding gate now reads the channel list it already fetched: a confirming channel gets \"it unlocks automatically once confirmed, nothing is needed from you\", a far-side balance gets \"you can receive, but there's nothing to send right now\", a routing/liquidity payment failure says so instead of claiming channel problems, and only a genuinely channel-less node keeps the open-one guidance."
"**Cuprate now syncs without burning a core for days.** The app's shipped config now enables Cuprate's checkpoint-backed `fast_sync` path, raises the database cache to 8 GiB, and gives the container a 10 GiB memory limit so the cache has real headroom. A live comparison that motivated the change saw the affected node sit around 45% CPU while the corrected config held near low single digits at the same chain height and block rate. The restricted RPC remains fronted through the safe app gate/Tor path.",
"**OpenWrt Gateway setup is documented from a real install, and two setup bugs are fixed.** The new guide walks a node operator through flashing a GL.iNet AX3000 to stock OpenWrt, pairing it with Archipelago, and installing TollGate pay-as-you-go WiFi. The installer now finds `opkg`/`apk` through the router's actual `PATH` instead of assuming `/usr/bin`, the UI no longer sends an empty password over a saved router connection, and the pinned TollGate package moves to `v0.5.0` with a native `.apk` install path where upstream provides one.",
"**Release publishing now checks the public Gitea download links before a manifest goes live.** The publisher already fetched every artifact back and verified its size and SHA-256; this release adds a second guard for the release page itself, so a bad Gitea `ROOT_URL` or proxy setting cannot publish working files behind broken public HTTPS download links."
],
"components": [
{
"current_version": "1.8.10-alpha",
"download_url": "https://source.archipelago-foundation.org/lfg2025/archy/releases/download/v1.8.10-alpha/archipelago",
"current_version": "1.8.11-alpha",
"download_url": "https://source.archipelago-foundation.org/lfg2025/archy/releases/download/v1.8.11-alpha/archipelago",
"name": "archipelago",
"new_version": "1.8.10-alpha",
"sha256": "6c8bd41fed44cd999cb360c00e1b66a2d19d19812cc2b0c8a1677eec2a9579e6",
"size_bytes": 64178056
"new_version": "1.8.11-alpha",
"sha256": "ae569054edd6b2491beb101815f6809bc00c95a7dbe86bd084bcb9a7c36e1853",
"size_bytes": 64179264
},
{
"current_version": "1.8.10-alpha",
"download_url": "https://source.archipelago-foundation.org/lfg2025/archy/releases/download/v1.8.10-alpha/archipelago-frontend-1.8.10-alpha.tar.gz",
"name": "archipelago-frontend-1.8.10-alpha.tar.gz",
"new_version": "1.8.10-alpha",
"sha256": "6b25de8a8e1a4f7fe51594f9bbbe21f5820f417af47a8b309c2dbf8f8723b719",
"size_bytes": 97736297
"current_version": "1.8.11-alpha",
"download_url": "https://source.archipelago-foundation.org/lfg2025/archy/releases/download/v1.8.11-alpha/archipelago-frontend-1.8.11-alpha.tar.gz",
"name": "archipelago-frontend-1.8.11-alpha.tar.gz",
"new_version": "1.8.11-alpha",
"sha256": "192fd0470b6ccf66e78c80b4a4c3af5468882b85d81959362a3bd11f88b9d71d",
"size_bytes": 97741740
}
],
"release_date": "2026-09-01",
"signature": "b69926bcb1851ff7d6a5b24519cd4a8015aab4ed4b588ee989d8ce6e3beaeb2cc0eb38078f522ded0d389fe53b7dbcdbf3f40c534b4bfafa5cf4a2ab2c59e40f",
"release_date": "2026-09-07",
"signature": "6449ce6ef35a4ef4fa6d0923bb58a2bff52ea5430d5532496e8f0af9ed52eaec293f19d7bec272dc9bc1af5fb2cdfa0e46068c827a9a4dd9cbef92d1c5845301",
"signed_by": "did:key:z6Mkfu5LT8d4DjETtrkATvHh9Dvcbnr7zBCUwfau8Sw7DLWT",
"version": "1.8.10-alpha"
"version": "1.8.11-alpha"
}
@@ -1,29 +0,0 @@
{
"changelog": [
"**Cuprate now syncs without burning a core for days.** The app's shipped config now enables Cuprate's checkpoint-backed `fast_sync` path, raises the database cache to 8 GiB, and gives the container a 10 GiB memory limit so the cache has real headroom. A live comparison that motivated the change saw the affected node sit around 45% CPU while the corrected config held near low single digits at the same chain height and block rate. The restricted RPC remains fronted through the safe app gate/Tor path.",
"**OpenWrt Gateway setup is documented from a real install, and two setup bugs are fixed.** The new guide walks a node operator through flashing a GL.iNet AX3000 to stock OpenWrt, pairing it with Archipelago, and installing TollGate pay-as-you-go WiFi. The installer now finds `opkg`/`apk` through the router's actual `PATH` instead of assuming `/usr/bin`, the UI no longer sends an empty password over a saved router connection, and the pinned TollGate package moves to `v0.5.0` with a native `.apk` install path where upstream provides one.",
"**Release publishing now checks the public Gitea download links before a manifest goes live.** The publisher already fetched every artifact back and verified its size and SHA-256; this release adds a second guard for the release page itself, so a bad Gitea `ROOT_URL` or proxy setting cannot publish working files behind broken public HTTPS download links."
],
"components": [
{
"current_version": "1.8.11-alpha",
"download_url": "https://source.archipelago-foundation.org/lfg2025/archy/releases/download/v1.8.11-alpha/archipelago",
"name": "archipelago",
"new_version": "1.8.11-alpha",
"sha256": "ae569054edd6b2491beb101815f6809bc00c95a7dbe86bd084bcb9a7c36e1853",
"size_bytes": 64179264
},
{
"current_version": "1.8.11-alpha",
"download_url": "https://source.archipelago-foundation.org/lfg2025/archy/releases/download/v1.8.11-alpha/archipelago-frontend-1.8.11-alpha.tar.gz",
"name": "archipelago-frontend-1.8.11-alpha.tar.gz",
"new_version": "1.8.11-alpha",
"sha256": "192fd0470b6ccf66e78c80b4a4c3af5468882b85d81959362a3bd11f88b9d71d",
"size_bytes": 97741740
}
],
"release_date": "2026-09-07",
"signature": "6449ce6ef35a4ef4fa6d0923bb58a2bff52ea5430d5532496e8f0af9ed52eaec293f19d7bec272dc9bc1af5fb2cdfa0e46068c827a9a4dd9cbef92d1c5845301",
"signed_by": "did:key:z6Mkfu5LT8d4DjETtrkATvHh9Dvcbnr7zBCUwfau8Sw7DLWT",
"version": "1.8.11-alpha"
}