go-dns/docs/RFC.md
2026-04-03 20:47:37 +01:00

4.1 KiB

module repo lang tier depends tags
dappco.re/go/dns core/go-dns go lib
code/core/go
dns
resolution
networking
query

go-dns — .lthn DNS Resolution as a Core Primitive

Any CoreApp calls c.Action("dns.resolve", opts) to resolve .lthn names. Backed by chain aliases + HSD sidechain. No dig/nslookup needed.

Actions

Action Params Returns
dns.resolve name (e.g. "charon.lthn") {addresses: ["10.69.69.165"]}
dns.resolve.txt name {txt: ["v=lthn1 type=gateway..."]}
dns.resolve.all name {a: [], aaaa: [], txt: [], ns: []}
dns.reverse ip {names: ["charon.lthn"]}
dns.serve port, bind starts DNS server
dns.health {status, names_cached, tree_root}
dns.discover re-scan chain for aliases → HNS names

Resolution Chain

1. Query main chain: get_all_alias_details
   → Find aliases, parse hns= from comments
2. Query HSD sidechain: getnameresource for each
   → Get A, AAAA, TXT, NS records
3. Cache with tree-root invalidation
   → Only regenerate when HSD tree root changes (15s check)
4. Serve via DNS protocol (UDP+TCP port 53)
   → Standard dig queries work

Non-Obvious Needs

1. Chain Action Dependency

dns.discover calls blockchain.chain.aliases to get alias list. Need Core action cross-service calls:

// Inside dns service:
aliases := c.Action("blockchain.chain.aliases").Run(ctx, core.NewOptions())
// Then for each alias, query HSD

If blockchain service isn't running, fall back to direct RPC to C++ daemon.

2. HSD Sidechain Client

The DNS service needs an HSD JSON-RPC client for getnameresource and getblockchaininfo. This is different from the main chain RPC — different port (14037), different auth (Basic), different methods.

Ask: Should this be in go-dns or a separate go-hsd package? The sidechain is also used by:

  • LNS (current implementation at ~/Code/lthn/lns/)
  • Zone cache daemon (alias-dns-bridge)
  • Bob Wallet (lthnDNS)

A shared go-hsd client would prevent 4 implementations of the same RPC calls.

3. DNS Protocol Server

The current LNS uses github.com/miekg/dns for the UDP+TCP server. For go-dns as a Core package:

Option A: Keep miekg/dns as dependency (battle-tested, full RFC compliance) Option B: Minimal DNS wire encoder in pure Go (only A/AAAA/TXT/NS/SOA/PTR — the 6 types we serve)

Recommend Option A — DNS protocol edge cases (EDNS0, TCP fallback, compression) are not worth reimplementing.

4. Reverse Index

PTR records need an IP→name reverse index. Currently built by scanning the forward cache. For efficiency:

type ReverseIndex struct {
    ipToNames map[string][]string // "10.69.69.165" → ["charon.lthn", "gateway.lthn", ...]
}

Rebuilt atomically when tree root changes. Stored in go-cache with same TTL as forward records.

5. Wildcard Support

Name owners can set *.name.lthn records. The DNS server needs wildcard matching:

Query: foo.charon.lthn → no exact match → check *.charon.lthn → match → return wildcard A record

6. DNSSEC (Future)

HSD supports DS records. Full DNSSEC chain:

ITNS sidechain (tree root = trust anchor)
  → DS record per name
    → DNSKEY in zone
      → RRSIG on records

Not blocking beta.1. The current implementation serves unsigned records which is fine for internal resolution. DNSSEC is a beta.2 feature.

Existing Implementation

The LNS at ~/Code/lthn/lns/ (672 lines Go, dappco.re/go/core@v0.8.0-alpha.1) already implements:

  • DNS over UDP+TCP (A, AAAA, TXT, NS, SOA, PTR)
  • Chain-based discovery via get_all_alias_details
  • Tree-root invalidation via getblockchaininfo
  • hns= alias comment override
  • Zone apex SOA
  • Reverse DNS (PTR)
  • Health endpoint
  • 14/14 names resolving on testnet

This code moves into go-dns with Core service registration.

Service Registration

dnsSvc := dns.NewService(c, dns.Options{
    HSDUrl:    "http://127.0.0.1:14037",
    HSDApiKey: "testkey",
    DNSPort:   53,
    HTTPPort:  5554,
})
// Auto-registers: dns.resolve, dns.resolve.txt, dns.reverse, dns.serve, dns.health, dns.discover