fix: resolve BIP353 via the system resolver; widen LNURL fallback gate - #7
Merged
Alex71btc merged 1 commit intoJul 27, 2026
Conversation
_new_resolver() pinned 1.1.1.1/8.8.8.8 and spoke to them directly, ignoring /etc/resolv.conf. Runtimes that require DNS to go through the resolver they configure drop those packets, so every BIP353 lookup times out. Default to the system resolver and keep an explicit list available via DNS_RESOLVER_NAMESERVERS. Deployments that pin resolvers with compose's dns: key are unaffected -- that key writes the same servers into resolv.conf. pay_address gated its LNURL fallback on a substring of the BIP353 error message, so only a 404 could reach it. A Lightning Address is indistinguishable from a BIP353 address at that point, so a transport failure (502/504) suppressed an LNURL payment that would have succeeded. Gate on status code instead. Neither change adds DNSSEC validation or alters which addresses are payable.
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.
Fixes the two issues traced in Start9-Community/bolt12-pay-startos#32. Two small, independent changes; neither adds DNSSEC validation or changes which addresses are payable.
1. Resolve BIP353 through the system resolver
_new_resolver()pinned["1.1.1.1", "8.8.8.8"]and spoke plain UDP/53 to them, ignoring/etc/resolv.conf. StartOS 0.4.0 requires container DNS to go through the resolver it configures and drops queries aimed at a public resolver, so every BIP353 lookup times out there (dns.exception.Timeout→ the 504 in_resolve_bip353_address).Now the resolver defaults to whatever the runtime configured, with
DNS_RESOLVER_NAMESERVERSavailable to pin an explicit list.This is a no-op for your Docker deployments.
app/docker-compose.ymlalready setsdns: [1.1.1.1, 8.8.8.8], and that key writes exactly those servers into the container's/etc/resolv.conf— so the new code reads back the same pair the old code hardcoded. Verified by running the patched module inpython:3.11-slim:If you'd rather keep the public resolvers as a hedge against ISP resolvers mangling underscore-label TXT lookups, the cleaner form is a fallback on NXDOMAIN/NoAnswer rather than an unconditional override — happy to add that instead if you prefer.
2. Gate the LNURL fallback on status code, not error text
pay_addressdecided whether to fall through to LNURL by string-matching the BIP353 error:Every
user@domainreaches_resolve_bip353_addressfirst —HRN_REcan't tell a Lightning Address from a BIP353 address — and only the 404 branch produces that string. So a transport failure suppressed an LNURL payment that would have succeeded. Now:Worth being explicit, since it came up: this is latent, not a live regression. With a reachable resolver,
sats@example.comreturns NOERROR/no-answer at both candidate FQDNs →NoAnswer→ 404 → fallback fires. That's why Lightning Addresses have always worked; the gate only bites once the lookup can't complete at all. Confirmed against your own records —sats.user._bitcoin-payment.alex71btc.comandsats._bitcoin-payment.alex71btc.comboth returnStatus=0, Answers=0.I deliberately left 422 (TXT present but no usable
lno) propagating rather than falling through. Adding it would let a domain with a malformed BIP353 record still get paid over LNURL, which may well be what you want — say the word and I'll include it.Verification
Ran the patched module in the app's own base image (
python:3.11-slim,pip install -r app/requirements.txt), importingbackend.appfor real rather than testing a copy of the logic:The 400/422 cases confirm caller errors still surface instead of being silently retried as LNURL.
Not covered: I haven't run a real payment end to end, since that needs a funded LND. Worth exercising one BIP353 and one Lightning Address payment before merging.
On DNSSEC
Nothing here validates DNSSEC or requires it, so the interop you described — paying offers on domains without DNSSEC, which Phoenix refuses — is unchanged. The DNSSEC point in the issue was only about what StartOS's own resolver can't currently supply if a client wanted to validate; it isn't a behaviour I'm proposing for this app, and I've filed it on our side (Start9Labs/start-technologies#3591) rather than pushing it here.