Skip to content

The socket nothing was watching, and a 500 that should have been a 404

Latest

Choose a tag to compare

@bitcoinuniverseadmin bitcoinuniverseadmin released this 29 Aug 13:17
521a091

Two fixes for defects found after the multichain release went live, and the gate
that stops one of them recurring.

The live socket was refused for every real browser, and nothing saw it. The
overlay rejects a WebSocket upgrade whose Origin is not on its allowlist. The
deployed overlay had no allowlist configured, which under NODE_ENV=production
refuses every origin with 403. A handshake sent with no Origin header at all
is allowed, and that is exactly what curl sends, so every probe reported the
socket healthy while the frontend reconnected in a loop and fell back to its
fifteen second poll.

Pages stayed correct throughout, because the poll keeps the freshness reading
honest and the status rail reports when it last observed the chain rather than
claiming to be live. So this was wasted reconnects and console noise rather
than a page that lied. It was still invisible, and that is the part worth
fixing: a check that talks to a service differently from the way a browser does
can report health the browser never sees. The cutover now sends a handshake
carrying a browser Origin and refuses the release on anything but 101.

An unknown block hash answered 500 instead of 404. Bitcoin Core reports a
hash it does not know as the message "Block not found" rather than as a status,
and the backend turned that into a server error. The overlay's search asks the
block route about every 64 character hex query in order to decide whether it is
a block, so a 500 there made search report the entire Bitcoin chain as
unavailable, on every transaction search, while Bitcoin was healthy and had
already answered definitively. It answers 404 now, matching the convention the
transaction routes in the same file already used.

Both are the same shape, and it is worth naming because it accounts for most of
what was found on release day: somewhere, "I do not know" and "I know, and the
answer is no" were the same value. A missing Origin read as permission. A
definitive negative read as a failure.

What each chain can answer, at publication

Read from /api/v1/chains at 2026-08-29T13:16Z, which is where the live answer
always is. This will go stale and the pages will not.

Bitcoin. Unregressed and at the tip. The Ord authority behind Ordinals,
Rare Sats and Runes is rebuilding its index, so protocol coverage reports
unavailable and every page that uses it states how far behind it is.

Zcash. Fully ready, with Zerdinals, ZRunes and ZRC-20 all reporting ready
and complete coverage, and no degraded reasons. Two defects behind that were
fixed the same day: a synced node reporting itself as still downloading for most
of every block interval, and readiness being withheld by five separate facts
while the reason list was derived from only one of them, so a chain could
withhold readiness and publish an empty list of reasons. A chain that cannot
say why it is not ready is worse than one that is not ready.

Dogecoin. The pending set is live and complete. Confirmed history, address
history and all protocol families remain unavailable: the ord-dogecoin
authority is backfilling a large index and the Doge TAP authority cannot build
against it until their tips agree. The overview states each of these per
protocol rather than showing an empty result as an answer.

Verifying this build

curl -s https://explorer.bitcoinuniverse.io/resources/config.js | grep GIT_COMMIT_HASH
curl -s https://explorer.bitcoinuniverse.io/api/v1/backend-info
curl -s https://explorer.bitcoinuniverse.io/api/v1/chains

The frontend and the backend both publish the commit they were built from, and
they must agree with the tag on this release.