Skip to content

Conversation

@agaffney
Copy link
Contributor

@agaffney agaffney commented Dec 9, 2025

Closes #263


Summary by cubic

Add Handshake resolver support as a fallback when Cardano records are missing. This improves DNS query handling and nameserver discovery for domains resolved via Handshake.

  • New Features
    • Query Handshake records in handleQuery when Cardano returns no results (A, AAAA, CNAME).
    • Support Handshake NS records in findNameserversForDomain, resolving their A/AAAA to IPs.
    • Cardano remains the primary source; Handshake is used only if Cardano returns nil.

Written for commit e757251. Summary will update automatically on new commits.

Summary by CodeRabbit

  • Bug Fixes
    • Improved DNS resolution reliability by adding a fallback to Handshake records when primary lookups return no results.
    • Nameserver resolution now also retrieves matching A/AAAA addresses from the fallback source so nameserver responses are complete when available.

✏️ Tip: You can customize this high-level summary in your review settings.

@agaffney agaffney requested a review from a team as a code owner December 9, 2025 21:33
@coderabbitai
Copy link

coderabbitai bot commented Dec 9, 2025

📝 Walkthrough

Walkthrough

The change updates DNS resolution in internal/dns/dns.go to add Handshake-based fallback lookups. If Cardano LookupRecords (or NS lookup via Cardano) returns no results, the code now calls LookupHandshakeRecords (and handshake-prefixed NS/A/AAAA lookups) and uses those results when present. Error handling for the new Handshake calls mirrors the existing Cardano error handling; response assembly logic is unchanged aside from using Handshake-sourced records when Cardano yielded none.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Areas requiring extra attention:

  • handleQuery: correctness of Handshake fallback invocation and error handling parity with Cardano path
  • findNameserversForDomain: NS fallback to Handshake and subsequent A/AAAA retrieval via Handshake lookups
  • Branching/precedence to ensure Cardano results remain primary and Handshake is only used when empty
  • Response assembly to confirm identical structure regardless of source

Possibly related PRs

Pre-merge checks and finishing touches

✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat: Handshake resolver support' directly and clearly summarizes the main change: adding Handshake resolver support as a fallback mechanism to the DNS resolution system.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/handshake-resolver

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@cubic-dev-ai cubic-dev-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 1 file

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (3)
internal/dns/dns.go (3)

128-139: Consider checking len(records) == 0 for consistency.

The condition records == nil may not trigger the Handshake fallback if LookupRecords returns an empty slice []Record{} instead of nil. Later in findNameserversForDomain (line 437), the code uses len(nsRecords) > 0 which handles both cases.

-		if records == nil {
+		if len(records) == 0 {

134-136: Differentiate error messages for better observability.

The error message is identical to the Cardano lookup error (line 123), making it difficult to distinguish which lookup source failed when debugging.

 			slog.Error(
-				fmt.Sprintf("failed to lookup records in state: %s", err),
+				fmt.Sprintf("failed to lookup Handshake records: %s", err),
 			)

455-478: Code duplication with Cardano NS lookup block.

This block is structurally identical to the Cardano lookup above (lines 437-454), differing only in the function calls (LookupHandshakeRecords vs LookupRecords).

This is acceptable for now given the straightforward logic, but if more resolver sources are added, consider extracting a helper function that accepts a lookup function as a parameter to reduce duplication.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6f0a3fd and eb62060.

📒 Files selected for processing (1)
  • internal/dns/dns.go (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
internal/dns/dns.go (1)
internal/state/state.go (1)
  • GetState (452-454)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: cubic · AI code reviewer
  • GitHub Check: docker
  • GitHub Check: Analyze (javascript-typescript)
  • GitHub Check: Analyze (actions)
  • GitHub Check: Analyze (go)
🔇 Additional comments (1)
internal/dns/dns.go (1)

116-139: LGTM on the overall Handshake fallback pattern.

The implementation correctly establishes Cardano as the primary resolver with Handshake as a fallback. The error handling appropriately mirrors the existing Cardano error handling, and the early return on error prevents cascading failures.

Signed-off-by: Aurora Gaffney <aurora@blinklabs.io>
@agaffney agaffney force-pushed the feat/handshake-resolver branch from eb62060 to e757251 Compare December 9, 2025 21:44
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
internal/dns/dns.go (1)

431-478: Duplicated NS/A/AAAA resolution for Cardano vs Handshake — candidate for small helper

The Handshake NS branch is effectively a copy of the Cardano branch with LookupHandshakeRecords substituted and the same net.ParseIP + aggregation logic. This is fine functionally, but it does mean any future change to how you build ret (e.g., validating ParseIP results, supporting additional RR types, TTL handling) must be done in two places.

If this area evolves further, consider extracting a helper that takes a lookup function and the domain name to resolve NS → A/AAAA, e.g.:

type recordLookupFn func([]string, string) ([]state.DomainRecord, error)

func resolveOnChainNS(lookup recordLookupFn, domain string) (string, map[string][]net.IP, error) {
    nsRecords, err := lookup([]string{"NS"}, domain)
    if err != nil || len(nsRecords) == 0 {
        return "", nil, err
    }
    ret := map[string][]net.IP{}
    for _, nsRecord := range nsRecords {
        aRecords, err := lookup([]string{"A", "AAAA"}, nsRecord.Rhs)
        if err != nil {
            return "", nil, err
        }
        for _, aRecord := range aRecords {
            ip := net.ParseIP(aRecord.Rhs)
            if ip != nil {
                ret[nsRecord.Rhs] = append(ret[nsRecord.Rhs], ip)
            }
        }
    }
    return dns.Fqdn(domain), ret, nil
}

Then findNameserversForDomain can call it once for Cardano and once for Handshake, keeping behavior in sync and reducing duplication.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between eb62060 and e757251.

📒 Files selected for processing (1)
  • internal/dns/dns.go (4 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
internal/dns/dns.go (1)
internal/state/state.go (1)
  • GetState (452-454)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Analyze (go)
🔇 Additional comments (1)
internal/dns/dns.go (1)

115-140: This review comment is based on an incorrect assumption about the return value semantics of LookupRecords and LookupHandshakeRecords. Both functions explicitly return nil (not an empty slice) when no records are found, as confirmed by the lookupRecords implementation which returns nil, nil when len(ret) == 0. The existing code using records == nil checks is semantically correct and aligns with the actual behavior. The suggested change to len(records) == 0 would not be an improvement and misrepresents how these functions work.

Likely an incorrect or invalid review comment.

@agaffney agaffney merged commit 05a279d into main Dec 9, 2025
11 checks passed
@agaffney agaffney deleted the feat/handshake-resolver branch December 9, 2025 21:57
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.

Create a Handshake resolver

3 participants