feat: verify .bit (Namecoin) NIP-05 identifiers#161
Draft
mstrofnone wants to merge 2 commits into
Draft
Conversation
…upport per ifa-0001) The underlying `nostrlib-nip05-namecoin` library now follows the ifa-0001 §"import" item of a Namecoin Domain Name Object, recursively merging values from imported sibling names (typically `dd/<name>") into the importing object before the `nostr" field is read. This unblocks NIP-05 verification for `.bit" domains that use the import pattern to stay under Namecoin's 520-byte per-name limit — notably `testls.bit", whose apex `d/testls" delegates its `nostr.names" block to `dd/testls". Previously the resolver saw no `nostr" field on the apex and gave up, so njump rendered such identifiers with the strike-through verified-failure indicator. No njump code changes: `QueryIdentifier" continues to return a `*nostr.ProfilePointer", and the import expansion happens entirely inside the library on the resolver path. Records that don't use `import" pay no extra I/O.
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.
What & why
Today every NIP-05 identifier on a Namecoin
.bitdomain — e.g.alice@me.bit— renders on njump with a line-through. The SDK'sNIP05Validdoes HTTPS/.well-known/nostr.json, which doesn't (and can't) resolve under.bit, so the verification check always fails and the most public surface a.bitidentity gets — every social-card preview njump renders fornevent/naddrcodes shared on Twitter/Mastodon/HN — actively signals "broken" instead of "verified".This PR adds a parallel verification path for
.bitidentifiers so they render with the correct green check when they really do point at the profile's pubkey on the Namecoin blockchain.Tracking NIP: nostr-protocol/nips#2349.
How
nip05_namecoin.goadds:verifyNip05Namecoin(ctx, id, pubkey) (verified, ok bool)—ok=falsemeans "not a.bit, defer to DNS path"; otherwise resolves the name on Namecoin via ElectrumX (5s timeout, same budget as the SDK's DNS path) and checkspp.PublicKey == pubkey.isNip05Valid(ctx, m)— single entry point used byprofile.templ: branches to Namecoin for.bit, falls back tom.NIP05Valid(ctx)otherwise.nip05IdentifierURL(identifier)/nip05NamecoinIdentifierToURL(identifier)— for.bit, links tohttps://explorer.namecoin.org/name/d/<name>(a sovereign explorer) instead of the dead HTTPS.well-knownURL the default NIP-05 helper produces.render_event.go: when the path code isn't valid bech32 and isn't a DNS NIP-05, also trynamecoin.IsDotBitbefore 404'ing, so/alice@me.bitroutes torenderProfile.profile.templ: swap the strike-through guard and the explorer link to the new helpers.No upstream
fiatjaf.com/nostr/sdkchanges required — this is purely an additive verification path inside njump.Library
Uses
github.com/mstrofnone/nostrlib-nip05-namecoin— a pure-Go port of the Kotlin reference implementation in Amethyst (vitorpamplona/amethyst#1937) and the Swift port in Nostur (nostur-com#60). It speaks ElectrumX over WSS with pinned certs for the default servers; the public API (IsValidIdentifier,IsDotBit,QueryIdentifierreturning*nostr.ProfilePointer) intentionally mirrorsfiatjaf.com/nostr/nip05so it slots in as a drop-in fall-through.Update —
importchain support (v0.3.0)The underlying library was extended with ifa-0001 §"import" support and njump now picks it up via the
v0.3.0bump.Real-world
.bitdeployments hit Namecoin's 520-byte per-name limit and split their records across two names: the apexd/<name>stays small and delegates shared blocks (NIP-05names,relays, TLS, map entries) into a sibling — by conventiondd/<name>— via an"import"item. Without import-chain handling, NIP-05 lookups for these records silently fail: the resolver sees the apex value, finds nonostrfield, and returns nothing — never consulting the imported sibling that actually carries thenostr.namesblock.The library now follows the
importitem per ifa-0001: importer-wins precedence (with JSONnullas a suppression marker), recursive merge up to four levels deep (the spec minimum), visited-set cycle protection, multi-label subdomain selectors resolved through the imported value'smaptree, the three accepted shorthand value forms ("d/foo",["d/foo"],["d/foo","sel"]), and lenient handling of failed imports so transient ElectrumX hiccups don't kill an otherwise-resolvable record. Records without animportkey short-circuit immediately and pay no extra I/O.The canonical demo target
testls.bitnow resolves end-to-end:d/testlscarries"import":"dd/testls"and the importeddd/testlscarries thenostr.namesblock; njump correctly identifies and verifies the identity.One new direct dep;
go mod tidyis clean.Tests
go test -run 'Nip05Namecoin|VerifyNip05|IsNip05' ./...— 12 cases pass (table-driven URL mapping,.bitvs DNS branch selection, match/mismatch/error against an injected resolver). The Namecoin resolver is unit-tested via a package-levelqueryNamecoinIdentifierindirection so the suite stays hermetic; live integration runs are gated behindNJUMP_NAMECOIN_INTEGRATION=1in the upstream library itself.The import-chain logic is covered by 22 new unit/integration tests in
nostrlib-nip05-namecoin(no-import passthrough, all four shorthand forms, importer precedence, null suppression, depth-4 happy path, over-budget truncation, lookup-nil/error/panic, malformed JSON, malformedimportvalue, A→B→A cycle protection, multi-label selector descending in DNS order, wildcard and empty-key fallbacks,testls.bit-style bare and named NIP-05 resolution across imports, regression guard that no-import records issue zero extra lookups, importer-wins on nestednostr.names).go build ./...is green.(The unrelated
opengraph_test.gotests fail onmasterfor me too — not touched here.)Diff size
Two commits on this branch: the original
.bitverification path, plus thenostrlib-nip05-namecoinv0.2.0 → v0.3.0 bump for import-chain support. No vendoring, noreplacedirectives — Go MVS happily picks njump's newerfiatjaf.com/nostrand theProfilePointertypes unify cleanly.Marking draft for review of the rendering / link policy before flipping to ready.