From 3c503754bfdfa664e5e3f50f6fe31650e33b7e61 Mon Sep 17 00:00:00 2001 From: Virgil Date: Fri, 3 Apr 2026 20:11:34 +0000 Subject: [PATCH] feat(dns): add discover aliases action entrypoint Co-Authored-By: Virgil --- service.go | 6 +++++ service_test.go | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/service.go b/service.go index 9f5f30e..035798d 100644 --- a/service.go +++ b/service.go @@ -326,6 +326,12 @@ func (service *Service) Discover() error { return nil } +// DiscoverAliases refreshes DNS records by scanning chain aliases through HSD RPC calls. +// This matches the RFC `dns.discover` behavior by reusing the configured chain alias discoverers and fallback clients. +func (service *Service) DiscoverAliases(ctx context.Context) error { + return service.DiscoverFromChainAliases(ctx, service.hsdClient) +} + func (service *Service) replaceRecords(discovered map[string]NameRecords) { cached := make(map[string]NameRecords, len(discovered)) for name, record := range discovered { diff --git a/service_test.go b/service_test.go index a00b54b..eb37cd5 100644 --- a/service_test.go +++ b/service_test.go @@ -296,6 +296,65 @@ func TestServiceDiscoverReplacesRecordsFromDiscoverer(t *testing.T) { } } +func TestServiceDiscoverAliasesUsesConfiguredAliasDiscovery(t *testing.T) { + var treeRootCalls int32 + var nameResourceCalls int32 + + server := httptest.NewServer(http.HandlerFunc(func(responseWriter http.ResponseWriter, request *http.Request) { + var payload struct { + Method string `json:"method"` + Params []any `json:"params"` + } + if err := json.NewDecoder(request.Body).Decode(&payload); err != nil { + t.Fatalf("unexpected request payload: %v", err) + } + + switch payload.Method { + case "getblockchaininfo": + atomic.AddInt32(&treeRootCalls, 1) + responseWriter.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(responseWriter).Encode(map[string]any{ + "result": map[string]any{ + "tree_root": "alias-root-1", + }, + }) + case "getnameresource": + atomic.AddInt32(&nameResourceCalls, 1) + if len(payload.Params) != 1 || payload.Params[0] != "gateway.charon.lthn" { + t.Fatalf("unexpected alias lookup: %#v", payload.Params) + } + responseWriter.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(responseWriter).Encode(map[string]any{ + "result": map[string]any{ + "a": []string{"10.10.10.10"}, + }, + }) + default: + t.Fatalf("unexpected method: %s", payload.Method) + } + })) + defer server.Close() + + service := NewService(ServiceOptions{ + ChainAliasDiscoverer: func(_ context.Context) ([]string, error) { + return []string{"gateway.charon.lthn"}, nil + }, + HSDClient: NewHSDClient(HSDClientOptions{URL: server.URL}), + }) + + if err := service.DiscoverAliases(context.Background()); err != nil { + t.Fatalf("expected DiscoverAliases action to run: %v", err) + } + + record, ok := service.Resolve("gateway.charon.lthn") + if !ok || len(record.A) != 1 || record.A[0] != "10.10.10.10" { + t.Fatalf("expected discovered gateway record, got %#v (ok=%t)", record, ok) + } + if atomic.LoadInt32(&treeRootCalls) != 1 || atomic.LoadInt32(&nameResourceCalls) != 1 { + t.Fatalf("expected discovery to perform chain and name-resource calls, got treeRoot=%d nameResource=%d", atomic.LoadInt32(&treeRootCalls), atomic.LoadInt32(&nameResourceCalls)) + } +} + func TestServiceDiscoverFallsBackWhenPrimaryDiscovererFails(t *testing.T) { primaryCalled := false fallbackCalled := false -- 2.45.3