Files
amethyst/quartz/src/jvmTest
mstrofnone 3835622fc5 feat(namecoin): resolve import items per ifa-0001 (NIP-05 only)
Adds a new `NamecoinImportResolver` that follows the `import` field of a
Namecoin Domain Name Object value, recursively merging the imported
values into the importing object before `NamecoinNameResolver` reads
the `nostr` field.

Why
---
The 520-byte per-name limit on Namecoin is tight when a single record
needs `ip`, NIP-05 names, TLS, and per-subdomain map entries. A common
workaround (used by `testls.bit` and others) is to keep the apex record
small by delegating shared blocks into a sibling name via
`"import":"dd/<name>"` per ifa-0001 §"import". Without import support,
NIP-05 search for `testls.bit` (and the like) fails: the resolver sees
no `nostr` field at `d/testls` and gives up before consulting the
imported `dd/testls` that actually carries the names block.

What
----
Per ifa-0001 §"import":
  * Importer items take precedence over imported items (including `null`,
    which suppresses the imported counterpart).
  * Recursion is supported up to 4 levels (the spec minimum) by default.
    Cycles are broken by a visited-set; over-budget chains are silently
    truncated, with the importer's own items still taking effect.
  * Multiple imports in one array merge later-wins (the array's own
    order), with the importing object on top of all of them.
  * Subdomain selectors (the optional 2nd element of each inner array)
    are resolved through a `map` walk inside the imported value, with
    the standard exact-label > `*` wildcard > `""` default rules.
  * Three short-hand value forms are accepted alongside the canonical
    array-of-arrays: `"import":"d/foo"`, `"import":["d/foo"]`, and
    `"import":["d/foo","selector"]`. They map onto the canonical
    representation losslessly.
  * A failed import lookup (name not found, malformed JSON, network
    error) is treated as `{}` rather than failing the whole record, so
    transient ElectrumX hiccups don't kill resolution. The importing
    object's own items still apply.

Wires the expander into `NamecoinNameResolver.performLookup` and
`performLookupDetailed`. Records without an `import` key skip the
resolver entirely (zero extra I/O), so non-import names pay no cost.

Tests
-----
20 new tests in `NamecoinImportTest`:
  * Unit (resolver in isolation): no-import passthrough, all four
    shorthand value forms, importer precedence, null suppression,
    depth-4 recursion happy path, over-budget truncation, lookup
    failure, malformed JSON, malformed `import` value, cycle
    protection, multi-label selector descending in DNS order, wildcard
    fallback.
  * Integration with `NamecoinNameResolver`: bare and named NIP-05 across
    an import (mirroring the real-world `testls.bit -> dd/testls`
    deployment); regression guard that no-import records issue exactly
    one ElectrumX query; importer-wins on `nostr.names`; lenient
    failure when the imported boilerplate is unreachable;
    `resolveDetailed` returns `Success` and `NoNostrField` correctly
    across imports.

All 15 existing `NamecoinNameResolverTest` cases continue to pass.

Scope note
----------
This PR is intentionally scoped to the NIP-05 / search path. The
relay-resolution path (#2595) also benefits from import support; that
wiring is left to land alongside #2595 so the two PRs can move
independently.
2026-05-03 09:53:10 +10:00
..