From ec8d88a6924b09bd8d718bac01628755ec9b4015 Mon Sep 17 00:00:00 2001 From: archipelago Date: Sun, 9 Aug 2026 04:26:27 -0400 Subject: [PATCH] fix(bitcoin): pin Knots to an explicit build; :latest could stall the fleet MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The catalog's default version was {"version": "latest", image: bitcoin-knots:29.3.knots20260508, default: true}, so a fresh install — or anyone selecting "latest" — silently got the BIP110/RDTS build. Meanwhile the manifest's own :latest tag resolves to 29.3.knots20260210 in the registry, so the two paths installed different daemons. That matters because 20260508 does not merely enable RDTS, it HALTS until an operator sets consensusrules=rdts. Node 100.64.204.114 runs it and is frozen at block 961,692 — blocks AND headers static across 30s, 11 peers, unpruned — while reporting initialblockdownload=false and verificationprogress 0.99998, i.e. "synced". The two nodes on 20260210 sit at the tip, 961,706. Re-pointing a tag could have done that to every node at once. Pinned in all three places that would otherwise re-introduce a moving tag: the manifest, image-versions.sh, and the catalog VERSIONS table. The "latest" pseudo-version is removed outright — a moving default is not appropriate for a consensus-critical app — and the default is now the explicit non-RDTS 29.3.knots20260210. 20260508 remains selectable, so adopting RDTS stays possible but becomes deliberate. Verified: both tags' daemons read via `bitcoind --version` — :latest and :29.3.knots20260210 are both v29.3.knots20260210, so this pin is behaviour-neutral on nodes already running latest. NOT DONE HERE: releases/app-catalog.json still carries the old signed entry. It must be regenerated and re-signed by the operator before it takes effect — catalog entries override on-disk manifests (origin-wins). Co-Authored-By: Claude Opus 5 (1M context) --- apps/bitcoin-knots/manifest.yml | 8 +++++++- scripts/generate-app-catalog.sh | 16 ++++++++++++---- scripts/image-versions.sh | 5 ++++- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/apps/bitcoin-knots/manifest.yml b/apps/bitcoin-knots/manifest.yml index 5a305b1a..0c9ddd65 100644 --- a/apps/bitcoin-knots/manifest.yml +++ b/apps/bitcoin-knots/manifest.yml @@ -7,7 +7,13 @@ app: container_name: bitcoin-knots container: - image: source.archipelago-foundation.org/lfg2025/bitcoin-knots:latest + # Pinned deliberately — NEVER use :latest for a consensus-critical app. + # Knots 20260508 applies the BIP110/RDTS network upgrade and HALTS until an + # operator explicitly sets consensusrules=rdts: a node running it sits frozen + # (blocks and headers both static) while reporting itself synced. A moving + # :latest tag can therefore stop the whole fleet following the chain without + # anyone choosing that. Changing this line is a consensus decision. + image: source.archipelago-foundation.org/lfg2025/bitcoin-knots:29.3.knots20260210 pull_policy: if-not-present network: archy-net entrypoint: ["sh", "-lc"] diff --git a/scripts/generate-app-catalog.sh b/scripts/generate-app-catalog.sh index c0f8f72a..265691f6 100755 --- a/scripts/generate-app-catalog.sh +++ b/scripts/generate-app-catalog.sh @@ -204,15 +204,23 @@ VERSIONS = { # the manifest's floating :latest tag (kept on the legacy image until the # entrypoint-render fix is fleet-deployed — see # the bitcoin multi-version design). + # NO "latest" pseudo-version here, and the default is pinned. The entry + # marked default:true used to be {"version": "latest"} pointing at + # 29.3.knots20260508 — so a fresh install, or anyone picking "latest", + # silently got the BIP110/RDTS build. That build HALTS until an operator + # sets consensusrules=rdts: node 100.64.204.114 runs it and is frozen at + # block 961,692 (blocks AND headers static, 11 peers, unpruned) while + # reporting itself synced, whereas the nodes on 20260210 sit at the tip. + # A default that can move across a consensus boundary is a fleet-wide + # stall waiting to happen, so the default is an explicit, non-RDTS build + # and moving it is a deliberate consensus decision. "bitcoin-knots": [ - {"version": "latest", - "image": f"{REGISTRY}/bitcoin-knots:29.3.knots20260508", "default": True}, + {"version": "29.3.knots20260210", + "image": f"{REGISTRY}/bitcoin-knots:29.3.knots20260210", "default": True}, {"version": "29.3.knots20260508", "image": f"{REGISTRY}/bitcoin-knots:29.3.knots20260508"}, {"version": "29.3.knots20260507", "image": f"{REGISTRY}/bitcoin-knots:29.3.knots20260507"}, - {"version": "29.3.knots20260210", - "image": f"{REGISTRY}/bitcoin-knots:29.3.knots20260210"}, {"version": "29.2.knots20251110", "image": f"{REGISTRY}/bitcoin-knots:29.2.knots20251110"}, ], diff --git a/scripts/image-versions.sh b/scripts/image-versions.sh index f1e3c24b..1a5b4f11 100644 --- a/scripts/image-versions.sh +++ b/scripts/image-versions.sh @@ -15,7 +15,10 @@ ARCHY_REGISTRY="source.archipelago-foundation.org/lfg2025" ARCHY_REGISTRY_FALLBACK="" # Bitcoin stack -BITCOIN_KNOTS_IMAGE="$ARCHY_REGISTRY/bitcoin-knots:latest" +# Pinned, not :latest — see apps/bitcoin-knots/manifest.yml. Knots 20260508 +# halts pending the BIP110/RDTS consensus decision, so a moving tag can freeze +# the fleet's chain sync. Bumping this is a consensus decision. +BITCOIN_KNOTS_IMAGE="$ARCHY_REGISTRY/bitcoin-knots:29.3.knots20260210" LND_IMAGE="$ARCHY_REGISTRY/lnd:v0.18.4-beta" ELECTRUMX_IMAGE="$ARCHY_REGISTRY/electrumx:v1.18.0"