Skip to content

Mainnet prep 2026-09-23: network isolation, mining readiness, self-qualifying release artifact - #136

Merged
bitcoinuniverseadmin merged 11 commits into
developfrom
implement/mainnet-20260923
Sep 24, 2026
Merged

bitcoinuniverseadmin merged 11 commits into
developfrom
implement/mainnet-20260923

Conversation

@bitcoinuniverseadmin

Copy link
Copy Markdown

Implements the three code work packages from the 2026-09-23 mainnet preparation (audit/mainnet-prep-20260923-1745, 161b7bd). This is the code half only: it is not functional acceptance and not a release.

M23-NET, F-M23-02: explicit invalid network settings never read mainnet

  • chain-network.ts resolves each chain to a network or a typed unavailable result with a reason. Absent/omitted settings still read mainnet.
  • Keys and networks are pinned to backend-apis explorer-context.ts (dogecoin, zcash, fractal).
  • Chain reads are deferred and fail with ChainNetworkUnavailableError before any request. The picker skips the chain and labels it "Network setting invalid". No websocket is opened, and nothing is bookmarked under a substitute network. Dashboard, mining and chain pages show a recoverable configuration error.

M23-HEALTH, F-M23-03: mining readiness needs a current index

  • capabilities.mining.ts: ready only when the highest indexed block is within MEMPOOL.MINING_MAX_BEHIND_TIP (default 3) of a Core reading that is under 120 s old and from the served network.
  • New unknown state when the reference is missing, stale or from another network. syncing while Core is in IBD. Readiness is withheld while the index is ahead of Core (reorg).
  • The report now carries indexedTip, bitcoinCoreTip, lagBlocks and maxLagBlocks. The config key is added to the sample, fixture, docker template, start.sh and CONFIGURATION.md.

M23-PACK, F-M23-01: the artifact carries and proves its own acceptance

  • protocol-contract.mjs --stage-acceptance stages the manifest, the envelope and the full evidence closure under docs/, using the gate's own path and digest rules.
  • docs is now in the tar member list.
  • qualify-artifact.mjs qualifies the packed archive before upload. It refuses traversal, absolute names and links in the evidence tree, then extracts to an empty dir and runs the gate the archive carries.
  • release-artifact.test.mjs covers real gzip tar archives: a valid Signet-qualified Mainnet candidate, missing docs, missing nested evidence, tampered bytes, a symlink member, traversal and stale revisions.

Verification (Windows SERVER, Node 24.19.0 / npm 11.17.0)

  • Frontend: 219 files / 2516 tests pass; lint 0 errors; build:universe succeeds.
  • Backend: tsc clean; lint 0 errors. New capability tests and config.test.ts pass. Three untouched intelligence suites (message-signature, payjoin proposal-analysis, simplicity formal-checker) fail on this host because they spawn native verifier binaries it lacks; CI runs them on Linux.
  • Scripts: release-gates 38/38 (two need Python, run with the pgAdmin interpreter), release-artifact 11/11, protocol-contract 47/47, --check holds 39 protocols, acceptance-matrix --check passes after regeneration (still NO-GO, denominator unreconciled, 0 real passes), bash -n release.sh, text gate.

Operational note (separate from this diff)

The live address outage and stalled ingestion had one verified cause. Fulcrum (127.0.0.1:50001) stopped at 13:05 UTC on 2026-09-22 when Bitcoin Core migrated to the OVH node, and nothing restarted it. It was restarted with its data intact, caught up 175 blocks, and addressLookup reports ready again.

🤖 Generated with Claude Code

bitcoinuniverseadmin and others added 11 commits September 23, 2026 17:44
…of reading mainnet

M23-NET, F-M23-02. A malformed UNIVERSE_CHAIN_NETWORKS value or an
unsupported network used to be dropped with a warning, and the chain then
read mainnet. An explicit setting that is wrong now resolves to a typed
unavailable result with a reason; absent or omitted settings still read
mainnet. Keys and networks are pinned to the overlay's explorer-context
contract (dogecoin, zcash, fractal).

Every caller changes together: chain reads are deferred and fail with
ChainNetworkUnavailableError before any request, the picker skips the chain
and names the setting invalid, the websocket opens no socket, bookmarks and
visits are never filed under a substitute network, and the dashboard,
mining and chain pages render a recoverable configuration error.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…k Core reading

M23-HEALTH, F-M23-03. Mining was reported ready whenever the blocks and
pools tables had rows; production published ready with the index at
968172 and Core at 968299. Readiness now compares the highest indexed
block with Core's height, requiring the reading to be under 120 s old and
from the served network, within MEMPOOL.MINING_MAX_BEHIND_TIP (default 3).
A missing, stale or other-network reading is the new unknown state; Core
in initial block download is syncing; an index ahead of Core after a
reorganization withholds readiness. The report now carries indexedTip,
bitcoinCoreTip, lagBlocks and maxLagBlocks. backend-info records Core's
chain name so the comparison can be matched to a network.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…nd qualify the packed archive

M23-PACK, F-M23-01. The artifact workflow staged docs/ but left it out of
the tar member list, and never staged the evidence files the acceptance
envelope names, so a candidate qualified in the checkout could not
qualify on the host.

protocol-contract.mjs --stage-acceptance copies the manifest, envelope and
complete evidence closure under docs/, checking every file with the gate's
own rules (plain docs/ path, inside the root, not a symlink, recorded
SHA-256) before and after the copy. docs is now packed, and
qualify-artifact.mjs lists the archive (refusing traversal, absolute names
and links in the evidence tree), extracts it into an empty directory and
runs the gate the archive carries, before upload.

release-artifact.test.mjs proves it on real gzip tar archives: a valid
Signet-qualified Mainnet candidate, missing docs, missing nested evidence,
tampered bytes, a symlink member, traversal names and stale revisions.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…e changed sources

The prepared branch's annotation already left the matrix stale. Still
FUNCTIONAL NO-GO with operationDenominatorReconciled false and zero
real-network passes; nothing here is an acceptance result.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… verified Fulcrum outage cause

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ne read at a time

With an electrum or Core backend, restoring the RBF cache read every
unexpired cached transaction sequentially before the HTTP server listened.
On 2026-09-23 that was 8,044 reads through the new Core RPC tunnel, and
the explorer API stayed down for about half an hour on each restart while
the watchdog kept restarting a stalled block loop. Eight concurrent reads,
each still caught on its own, well inside the shared RPC budget.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…uest

Against Core (electrum or none backends), every block transaction missing
from the mempool cost two RPC round trips: the transaction and its block
header. Since Core moved behind a 115 ms tunnel on 2026-09-22 that is
about 0.5 s per transaction and roughly thirty minutes for a block the
mempool no longer holds, which is the main loop watchdog's whole budget.
The explorer stalled at 968172 and the watchdog restarted it repeatedly.

When more than 50 transactions are missing, $getTransactionsExtended now
builds them from one verbose getblock (status from the block, fee from
Core's own field, no prevouts, exactly as the per-transaction path did
with prevouts off), and falls back to per-transaction reads if that read
fails. Stale blocks and esplora keep their existing paths.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@bitcoinuniverseadmin
bitcoinuniverseadmin merged commit cb37d7f into develop Sep 24, 2026
32 of 35 checks passed
@bitcoinuniverseadmin
bitcoinuniverseadmin deleted the implement/mainnet-20260923 branch September 24, 2026 01:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant