Argus � the BNS public gateway (navigate.st) and its library layer. Serves BCNR names over HTTPS, verifies signed records, mints TLDs.
Find a file
Local Dev 83a8fff021 resolver: echo EDNS OPT record so strict clients stop failing
Root cause of the "Firefox 'Server Not Found' (github)" and Node
`getaddrinfo EAI_FAIL` reports against the shipped daemon: reply() in
bnsd.js built responses from scratch and never copied the query's EDNS0
OPT record from the additional section. RFC 6891 §6.1.1 requires the
response to echo OPT when the query carried one; strict clients (glibc
getaddrinfo, Firefox with TRR off) treat the missing OPT as FORMERR and
surface EAI_FAIL / "Server Not Found". Lenient clients (nslookup, Chrome
async-dns) tolerate the loss, which is why the bug looked flaky.

The prior commit (ef19db1) extracted src/lib/dns-server.js as a testable
surface but left bnsd.js still calling the old inline helpers. This
finishes the migration:

- src/lib/dns-server.js:
  - buildReply() now walks the additional section, finds the OPT RR by
    name=root/type=41, and appends it to the response. When the query
    had no OPT, none is fabricated (RFC 6891 §7). Preserves RD and
    opcode from the query rather than hardcoding 0x8580.
  - parseQuestion() rejects QDCOUNT != 1 and truncated labels early,
    and skipName() tolerates DNS compression pointers per RFC 1035
    §4.1.4 so the OPT walker doesn't trip on a compressed name.
  - forwardQuery() accepts "host" (default port 53) or "host:port" so
    it can be tested off port 53.

- src/daemon/bnsd.js: replaces the inline helpers with imports; the
  icann-first branch keeps its rcode-inspecting callback via a small
  forwardInspect() wrapper around the Promise-based forwardQuery.

- test/dns-server.test.mjs (new): 14 tests. Includes parseQuestion
  cases (plain / EDNS / bad QDCOUNT / truncated), buildReply invariants
  (OPT echoed / OPT never fabricated / RD preserved / NODATA still
  echoes OPT), full dns.Resolver round-trips against an in-process
  server (A / AAAA-NODATA / forward-to-mock-upstream), and two pinned
  regression tests that copy the OLD reply() verbatim and assert its
  OPT-dropping behavior so a future regression is caught immediately.

- AriadneResolver/ariadne-resolver/{src/daemon/bnsd.js, src/lib/dns-server.js}:
  synced from Argus so the packaged installer picks up the fix.

Pre-existing failures in test/portfolio-index.test.mjs (require is not
defined at src/lib/chain.js:54) are unrelated and predate this work.
2026-08-02 01:19:09 +02:00
setup Ariadne c5efae43: tlds.bch-driven install + BNS_POLICY, doc-aligned 2026-08-01 02:06:48 +02:00
src resolver: echo EDNS OPT record so strict clients stop failing 2026-08-02 01:19:09 +02:00
test resolver: echo EDNS OPT record so strict clients stop failing 2026-08-02 01:19:09 +02:00
.gitignore Initial commit — Silent Mode baseline (2026-07-29) 2026-07-29 13:54:34 +02:00
ariadne.config.json Initial commit — Silent Mode baseline (2026-07-29) 2026-07-29 13:54:34 +02:00
BROWSER-PROMPT.md Initial commit — Silent Mode baseline (2026-07-29) 2026-07-29 13:54:34 +02:00
build-web.mjs Initial commit — Silent Mode baseline (2026-07-29) 2026-07-29 13:54:34 +02:00
DESIGN-collision-modes.md Resolver 3438d558: ASCII-clean install.ps1 + multi-TLD NRPT + VPS-first electrum 2026-07-31 23:09:23 +02:00
DESIGN-hosting-pact.md Initial commit — Silent Mode baseline (2026-07-29) 2026-07-29 13:54:34 +02:00
DESIGN-root-tld-cert.md Theseus: Firefox-style lock icon, LLM search engines, reliable favicons 2026-08-01 01:26:51 +02:00
ENGINE.md Initial commit — Silent Mode baseline (2026-07-29) 2026-07-29 13:54:34 +02:00
namespaces.pdf Initial commit — Silent Mode baseline (2026-07-29) 2026-07-29 13:54:34 +02:00
OPERATIONS-electrum.md Initial commit — Silent Mode baseline (2026-07-29) 2026-07-29 13:54:34 +02:00
package-lock.json Initial commit — Silent Mode baseline (2026-07-29) 2026-07-29 13:54:34 +02:00
package.json Initial commit — Silent Mode baseline (2026-07-29) 2026-07-29 13:54:34 +02:00
PROTOCOL.md Initial commit — Silent Mode baseline (2026-07-29) 2026-07-29 13:54:34 +02:00
README.md Initial commit — Silent Mode baseline (2026-07-29) 2026-07-29 13:54:34 +02:00
ROADMAP.md Initial commit — Silent Mode baseline (2026-07-29) 2026-07-29 13:54:34 +02:00
sia-test.html Initial commit — Silent Mode baseline (2026-07-29) 2026-07-29 13:54:34 +02:00

BNS — Namecoin-style decentralized names on Bitcoin Cash (chipnet)

A working prototype of "Option 3": names are CashTokens name certificates on the BCH chain (no fork, no sidechain), records ride in OP_RETURN, discovery via a beacon address, and the resolver is embedded in a wallet app with a built-in browser pane — the Brave/MetaMask-browser architecture in miniature.

See PROTOCOL.md for the on-chain design and its honest limitations.

Layout

  • src/lib/bns.js — protocol core: payload codec, chain indexer/resolver, tx builders
  • src/wallet-app.js — wallet + embedded resolver + browser UI (npm run wallet → http://localhost:4626)
  • src/register.js / src/update.js / src/resolve.js — CLI equivalents
  • wallets.json — chipnet seed phrases (TESTNET ONLY — never reuse for real funds)
  • src/lib/gen-wallets.js — one-time wallet generation (already run)

Setup

  1. npm install
  2. Fund the wallet with free chipnet tBCH: go to https://tbch.googol.cash/, paste the wallet address (shown in the app sidebar or by node src/lib/gen-wallets.js), pick chipnet, solve the captcha. ~0.001 tBCH funds hundreds of registrations.
  3. npm run wallet and open http://localhost:4626

Standalone resolver daemon (make EVERY browser resolve .bch)

  • src/daemon/bnsd.js — DNS server (answers *.bch from the chain, forwards everything else upstream) + HTTP gateway that serves on-chain sites by Host header. Test unprivileged: node src/daemon/bnsd.js --dns-port 5354 --http-port 8081, then node src/daemon/dig.js hello.bch.
  • setup/install.ps1 — run from an elevated PowerShell. Installs the daemon as a boot-time scheduled task (SYSTEM, auto-restart) and wires the OS to it:
    • default (-Mode nrpt): adds an NRPT rule so only .bch queries reach the daemon; all other DNS is untouched.
    • -Mode full: points every adapter's DNS at 127.0.0.1 (daemon forwards non-.bch upstream, ncdns-style); original servers are saved and restored on uninstall.
  • setup/uninstall.ps1 — reverses everything (rule/adapters/task).

HTTPS for .bch: the "BNS Local Root CA" (created on demand in ca/, keep root-ca.key private) signs per-name certs. The daemon's :443 gateway mints them on the fly for locally-served names; node src/lib/issue-cert.js <name> issues one for a real server (see the coinspectrum.bch nginx vhost). The installer trusts the root machine-wide and enables Firefox's enterprise-roots policy; cert fingerprints are published in "tls" chain records for pinning.

Caveats: browsers with "secure DNS" (DoH) enabled bypass the OS resolver — disable it or add an exception; ports 53/80/443 must be free.

Try it

  • Register hello with inline HTML (a website stored entirely on-chain), then type hello.bch in the address bar — the app resolves it from the blockchain (not DNS) and renders it.
  • Or CLI: node src/register.js hello '{"h":"<h1>Served from the BCH chain</h1>"}' then node src/resolve.js hello