feat: Namecoin NIP-05 identity resolution (.bit domains) — proof of concept#662
Open
mstrofnone wants to merge 1 commit intocoracle-social:masterfrom
Open
feat: Namecoin NIP-05 identity resolution (.bit domains) — proof of concept#662mstrofnone wants to merge 1 commit intocoracle-social:masterfrom
mstrofnone wants to merge 1 commit intocoracle-social:masterfrom
Conversation
Add decentralised NIP-05 identity verification via the Namecoin blockchain. When a user's NIP-05 identifier ends in .bit (e.g. alice@example.bit), Coracle resolves it directly from the Namecoin blockchain via ElectrumX servers — no centralised HTTP server needed for identity verification. Ported from Amethyst's Kotlin implementation with browser-specific adaptations. ## Architecture Browsers cannot make raw TCP/TLS connections to ElectrumX servers (see https://gitlab.torproject.org/tpo/applications/tor-browser/-/issues/30558 for prior art on this constraint in Tor Browser's Namecoin integration). This implementation uses a lightweight HTTP proxy that bridges browser fetch() calls to ElectrumX JSON-RPC over TCP: Browser → HTTP GET /api/namecoin/name/d/testls → Proxy → ElectrumX TCP The proxy handles all protocol details: scripthash computation, transaction fetching, NAME_UPDATE script parsing, and expiry checks. ### Zero-setup development The proxy is embedded as a Vite plugin (proxy/vite-plugin-namecoin.mjs) that serves /api/namecoin/* during development. Running `npm run dev` works with no additional setup — the browser resolves .bit names through the same-origin dev server. ### Production deployment For production, set VITE_NAMECOIN_PROXY_URL to a hosted proxy instance. The proxy is a standalone Node.js server (proxy/electrumx-proxy.mjs) that can be deployed anywhere (VPS, Cloudflare Worker, Vercel, etc.). When no proxy URL is configured, the browser falls back to the same-origin /api/namecoin/* path. ## New files - src/util/namecoin.ts — Browser-side resolver (HTTP client, identifier parsing, value extraction, LRU cache, settings helpers) - src/app/views/NamecoinSettings.svelte — Settings UI (enable/disable, custom proxy URL, test resolution) - tests/namecoin.test.ts — 25 unit tests mirroring Amethyst's test suite - proxy/electrumx-client.mjs — Server-side ElectrumX TCP client (scripthash computation, transaction parsing, NAME_UPDATE extraction) - proxy/electrumx-proxy.mjs — Standalone HTTP proxy server - proxy/vite-plugin-namecoin.mjs — Vite dev middleware plugin ## Modified files - vite.config.js — Register namecoin proxy plugin - .env.template — Add VITE_NAMECOIN_PROXY_URL - src/util/nostr.ts — Route .bit identifiers to Namecoin resolver - src/engine/state.ts — User settings + env var + settings accessor - src/app/App.svelte — Register /settings/namecoin route - src/app/MenuDesktop.svelte — Namecoin link in desktop settings - src/app/MenuMobile.svelte — Namecoin link in mobile settings - src/app/shared/PersonHandle.svelte — .bit badge on verified handles - src/app/shared/SearchResults.svelte — Trigger entity parsing for .bit - src/app/views/PersonInfo.svelte — Blockchain verification status - src/app/views/UserProfile.svelte — Mention .bit support in NIP-05 info ## Supported identifier formats - alice@example.bit → d/example, looks up 'alice' in nostr.names - _@example.bit / example.bit → root entry - d/example → direct Namecoin domain name lookup - id/alice → Namecoin identity namespace lookup
e896781 to
0d43742
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Proof of Concept: Decentralised NIP-05 via Namecoin
This PR is a proof of concept demonstrating what becomes possible when Nostr clients can verify identities directly against the Namecoin blockchain — no centralised HTTP servers, no single points of failure.
The goal is to show developers what decentralised NIP-05 verification looks like in practice and to highlight the browser-level constraints that currently require workarounds.
What this enables
When a user's NIP-05 identifier ends in
.bit(e.g.alice@example.bit), Coracle resolves it directly from the Namecoin blockchain via ElectrumX servers. The identity mapping lives on-chain — censorship-resistant, self-sovereign, and persistent without any web server.Namecoin is the oldest blockchain fork (2011), purpose-built for decentralised naming. It solves Zooko's triangle — names that are simultaneously human-meaningful, decentralised, and secure.
Ported from Amethyst's production Namecoin implementation (Kotlin → TypeScript).
The browser constraint
This is where it gets interesting — and where the proof of concept hits real-world friction.
Amethyst (Android) connects directly to ElectrumX servers over raw TCP/TLS sockets. It works beautifully. But browsers cannot make raw TCP connections. This is the same constraint that blocked Namecoin integration in Tor Browser — a project that aimed to resolve
.bitdomains to.onionaddresses directly in the browser.The ElectrumX protocol is a simple JSON-RPC protocol over TCP. Browsers have
WebSocket,fetch(), andWebRTC— but no raw TCP. The Raw Sockets API was proposed but never standardised. The Direct Sockets API exists in Chrome's Isolated Web Apps but isn't available to regular web pages.This means any browser-based Namecoin client currently needs a proxy layer:
If browsers gained the ability to make raw TCP connections (even in a sandboxed, permission-gated way like
navigator.tcpSocket()), this entire proxy layer disappears and the browser talks directly to ElectrumX — truly peer-to-peer, no intermediary.What's in this PR
Despite the proxy requirement, this implementation works end-to-end:
Zero-setup development — the ElectrumX proxy is embedded as a Vite plugin.
npm run devresolves.bitnames with no additional setup:npm run dev # Search for testls.bit, seed@testls.bit, m@testls.bit — they resolve to Nostr profilesArchitecture:
New files:
src/util/namecoin.tssrc/app/views/NamecoinSettings.sveltetests/namecoin.test.tsproxy/electrumx-client.mjsproxy/electrumx-proxy.mjsproxy/vite-plugin-namecoin.mjsModified files:
vite.config.js.env.templateVITE_NAMECOIN_PROXY_URLsrc/util/nostr.ts.bitidentifiers to resolversrc/engine/state.tssrc/app/App.svelte/settings/namecoinroutesrc/app/MenuDesktop.sveltesrc/app/MenuMobile.sveltesrc/app/shared/PersonHandle.svelte.bitverification badgesrc/app/shared/SearchResults.svelte.bitsearch supportsrc/app/views/PersonInfo.sveltesrc/app/views/UserProfile.svelte.bitinfo in NIP-05 fieldSupported formats
alice@example.bitd/examplenostr.names.alice_@example.bit/example.bitd/exampled/exampled/exampleid/aliceid/aliceTesting
The bigger picture
Standard NIP-05 relies on HTTP servers — a centralisation pressure point. If the server goes down or is censored, verification breaks. Namecoin stores these mappings on a proof-of-work blockchain that has been running continuously since 2011.
The technologies that would make this work natively in browsers:
Until then, the proxy layer is a practical workaround that keeps the architecture clean and the user experience seamless.
Related work
.bit→.onionresolution