Skip to content

NIP-05 verification via Namecoin (.bit)#2349

Open
mstrofnone wants to merge 2 commits into
nostr-protocol:masterfrom
mstrofnone:feat/nip05-namecoin
Open

NIP-05 verification via Namecoin (.bit)#2349
mstrofnone wants to merge 2 commits into
nostr-protocol:masterfrom
mstrofnone:feat/nip05-namecoin

Conversation

@mstrofnone
Copy link
Copy Markdown

@mstrofnone mstrofnone commented May 16, 2026

NIP-05 verification via Namecoin (.bit)

Adds a new NIP specifying how clients verify, and publishers publish, a
NIP-05
identifier whose right-hand side is anchored in the Namecoin blockchain
rather than DNS + HTTPS. Strict complement to NIP-05; both can coexist
on the same identity.

This is the narrowest possible slice of the broader RFC track in
#2330 — NIP-05
verification only. Relay discovery via Namecoin, TLSA pinning of .bit
relay WebSockets, and service-attestation kinds are deliberately
out of scope and tracked separately (see §"Out of scope" at the
bottom of the spec).

Why this NIP

.bit is a top-level name that can't be taken down by a registrar, a
DNS root authority, or a public CA compromise. The wire format inside
the existing ifa-0001 Domain Name Object adds zero new top-level
Namecoin record keys — everything lives inside a new nostr object
that ifa-0001 consumers ignore. Adoption is therefore drop-in for any
client that already implements NIP-05: same kind:0 field, same
local-part / pubkey shape; only the right-hand-side resolver changes.

Implementation evidence

Eight wire-compatible reference implementations across six platforms
have shipped this NIP against the live Namecoin chain, with
byte-for-byte agreement on the same on-chain records:

Platform Implementation Status
Android / iOS / Desktop (Kotlin/KMP) vitorpamplona/amethyst#1734 + follow-ups merged
iOS (Swift) nostur-com/nostur-ios-public#60 open
TypeScript / Node (isomorphic) nbd-wtf/nostr-tools#533 open
Flutter / Dart (nostr on pub.dev) ethicnology/dart-nostr#44 merged
Web (browser-resident wss:// ElectrumX) CodyTseng/jumble#774 open
Web hzrd149/nostrudel#352 open
strfry NIP-05 sidecar (Rust + Node) mstrofnone/strfry-nip05-namecoin shipped
Go (drop-in for nostrlib) mstrofnone/nostrlib-nip05-namecoin per fiatjaf/nak#123 shipped

Live reference deployment at testls.bit / relay.testls.bit is
exercised by the test suites of every implementation above.

Scope discipline

Per the explicit "form preference" question in the
RFC issue, this
PR follows the one-NIP-per-PR option, starting with NIP-05 verification
because it has the deepest deployment evidence. The N0 ("Namecoin
record container") draft has been folded directly into this document
as a §"Namecoin record container" section, since a standalone
container NIP isn't useful without a consuming NIP.

The companion drafts (relay discovery / TLSA / service attestations)
live at https://github.com/mstrofnone/nips and are intentionally not
proposed here. Happy to open separate PRs for each, after this one
lands, if maintainers want to upstream them.

Notes for review

  • No new event kinds.
  • No new tags.
  • No changes to existing NIPs.
  • The nostr key inside the ifa-0001 Domain Name Object is currently
    unallocated; ifa-0001 §"Item Suppression Rules" requires existing
    consumers to ignore unknown keys, so there is no upgrade hazard for
    the Namecoin ecosystem either.
  • Numbering: assume merge order picks the next free XX.md slot;
    happy to rename to whatever the maintainer prefers.

CC: none — opening cold so the broadest set of reviewers can chime in.


For Nostr-side discoverability, this PR is also cross-posted as a NIP-23
long-form note (kind:30023):

The note links back to the original track long-form (#2330 announce
note)
for the broader Namecoin-track context and routes normative review back
to this PR thread, not the Nostr replies.

Currently propagated to:
wss://nostr.wine · wss://relay.damus.io · wss://nos.lol · wss://relay.primal.net
· wss://nostr.mom · wss://relay.nostr.net · wss://nostr-pub.wellorder.net
· wss://offchain.pub · wss://relay.testls.bit.

NIP-22 replies / Nostr-side comments are welcome and will be folded back
into the discussion here.

@mstrofnone
Copy link
Copy Markdown
Author

For anyone watching from Nostr rather than GitHub, this PR has been cross-posted as a NIP-23 long-form note (same npub and broadcast relay set as the original #2330 track announcement):

Normative review should still happen here on GitHub — the Nostr note is a discoverability surface, not a parallel review track.

m and others added 2 commits May 21, 2026 10:40
Specifies how Nostr clients verify, and publishers publish, a NIP-05
identifier whose right-hand side is anchored in the Namecoin
blockchain rather than DNS + HTTPS. Complement to NIP-05, not a
replacement.

Adds no new top-level Namecoin record keys; all Nostr-relevant data
lives inside a new 'nostr' item in the existing ifa-0001 Domain Name
Object, which existing ifa-0001 consumers ignore by spec.

Companion drafts (relay discovery, TLSA pinning, service
attestations) are out of scope for this PR and tracked separately
in https://github.com/mstrofnone/nips per the form-preference
question in nostr-protocol#2330.

Eight wire-compatible reference implementations across six platforms
have shipped this NIP against the live Namecoin chain with
byte-for-byte agreement on the same on-chain records (Amethyst,
Nostur, nostr-tools, dart-nostr, Jumble, noStrudel, strfry sidecar,
nostrlib drop-in).
…mpls

Refreshes the draft with three concrete implementation notes surfaced
by the spread of shipped reader-side implementations and the first
shipped signer-side enforcement:

- Opcode handling (new subsection under Wire format): scriptPubKey
  parsers MUST match both OP_NAME_FIRSTUPDATE (0x52) and
  OP_NAME_UPDATE (0x53). FIRSTUPDATE carries an extra 8-byte rand
  salt push between the name and the value. Several early
  implementations matched only 0x53 and silently returned no value
  for never-renewed names; this section documents the requirement
  and the stack shape.

- Bidirectional JSON-RPC (new subsection under Lookup transport):
  ElectrumX is bidirectional. The server is permitted to initiate
  its own RPC calls (server.banner, blockchain.headers.subscribe,
  blockchain.relayfee, blockchain.estimatefee) interleaved with the
  client's outstanding responses. Clients MUST id-match incoming
  frames against outstanding requests; a naive 'first frame back is
  my response' handler silently returns null.

- Signer-side enforcement (new section): documents the pre-sign
  verification pattern shipped in Aegis as an OPTIONAL complement
  to reader-side verification, with explicit fail-open guidance on
  network errors.

- Reference implementations: replaces the flat list with three
  grouped tables (reader-side / signer-side / server-side) spanning
  six runtimes (Kotlin, Swift, Dart, TypeScript, vanilla JavaScript,
  Haskell) and 16 PRs / repos. The reader-side table now lists nos
  (Swift), 0xchat / nostrmo / dart-nostr (Dart), nostter / lumilumi
  / nosotros / ants (TypeScript), alphaama (vanilla JS), and futr
  (Haskell) alongside the existing Amethyst / Nostur / nostr-tools
  / noStrudel / Jumble entries. Signer-side adds Aegis.

The live reference deployment paragraph now explicitly calls out
mstrofnone@testls.bit as the canonical end-to-end FIRSTUPDATE test
target.

No normative changes to identifier grammar, record container, import,
subdomain walking, expiry, caching, race-condition guidance, Tor, or
publishing.
@mstrofnone
Copy link
Copy Markdown
Author

Refreshed the draft with three new sections informed by the spread of shipped implementations and a few wire-format bugs that surfaced during cross-implementation testing.

New: §"Opcode handling" (under Wire format)

Resolvers that parse the scriptPubKey directly must match both name-operation opcodes:

  • OP_NAME_FIRSTUPDATE (0x52, also OP_2) — the first transaction in a name's lifetime.
  • OP_NAME_UPDATE (0x53, also OP_3) — every later update.

FIRSTUPDATE carries an extra 8-byte rand salt push between the name and the value. Several early implementations matched only 0x53 and silently returned no value for any identity that was never renewed (which is the common case for fresh registrations and short-lived experiments).

New: §"Bidirectional JSON-RPC" (under Lookup transport)

ElectrumX is a bidirectional JSON-RPC transport. The server is permitted to initiate its own method calls (server.banner, blockchain.headers.subscribe, blockchain.relayfee, blockchain.estimatefee) interleaved with — and often before — responses to the client's outstanding requests. Clients must id-match incoming frames against outstanding requests; a naive "first frame back is my response" handler silently returns null whenever the server pushes first.

This is independent of transport (TCP+TLS, WebSocket-plaintext, WebSocket-TLS) and has been observed in the wild against multiple public ElectrumX-NMC servers.

New: §"Signer-side enforcement (optional)"

Documents the pre-sign verification pattern shipped in Aegis as an optional complement to reader-side verification. The signer checks a .bit nip05 claim before signing the kind:0 event. Explicit guidance to fail open on network errors — signers that hard-block on ElectrumX unreachability are unusable on flaky networks.

Refreshed: §"Reference implementations"

The flat list is replaced with three grouped tables: reader-side, signer-side, server-side. The reader-side table now spans six runtimes:

  • Kotlin: Amethyst
  • Swift: Nostur, nos
  • Dart: dart-nostr (merged), 0xchat, nostrmo
  • TypeScript: nostr-tools, noStrudel, Jumble, nostter, lumilumi, nosotros, ants
  • Vanilla JS: alphaama
  • Haskell: futr

Signer-side adds Aegis.

mstrofnone@testls.bit is now called out explicitly as the canonical end-to-end FIRSTUPDATE test target.

No normative changes

Identifier grammar, record container, import, subdomain walking, expiry, caching, race-condition guidance, Tor, and publishing are unchanged. Existing implementations that pass the current draft will continue to pass.

Diff: +148 / −24 lines, head f5d0a26.

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