Skip to content

Add OpenAlias for Monero sends - #1456

Draft
sneurlax wants to merge 33 commits into
stagingfrom
feat/openalias
Draft

sneurlax wants to merge 33 commits into
stagingfrom
feat/openalias

Conversation

@sneurlax

@sneurlax sneurlax commented Sep 30, 2026 •

Copy link
Copy Markdown
Member

Adds a DohOpenAlias class for handling DNS requests for OpenAlias records. Adds a DnsProxyConnection because of issues with socks5_proxy et al

@sneurlax
sneurlax marked this pull request as draft October 1, 2026 17:42
@codecov

codecov Bot commented Oct 1, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 83.25688% with 146 lines in your changes missing coverage. Please review.
✅ Project coverage is 9.05%. Comparing base (03ad880) to head (cca8fed).
⚠️ Report is 24 commits behind head on staging.

Files with missing lines Patch % Lines
lib/services/openalias/dns_proxy_socket.dart 66.94% 39 Missing ⚠️
lib/pages/send_view/send_view.dart 81.43% 31 Missing ⚠️
lib/pages/send_view/confirm_transaction_view.dart 68.75% 30 Missing ⚠️
...providers/ui/preview_tx_button_state_provider.dart 51.61% 15 Missing ⚠️
lib/services/openalias/doh_open_alias.dart 88.50% 10 Missing ⚠️
...ack_view/wallet_view/sub_widgets/desktop_send.dart 94.82% 6 Missing ⚠️
lib/services/openalias/open_alias_service.dart 62.50% 6 Missing ⚠️
..._view/sub_widgets/building_transaction_dialog.dart 25.00% 3 Missing ⚠️
lib/services/openalias/dns_proxy_connection.dart 96.22% 2 Missing ⚠️
lib/widgets/transaction_preview_dialog.dart 95.91% 2 Missing ⚠️
... and 2 more
Additional details and impacted files
@@             Coverage Diff             @@
##           staging    #1456      +/-   ##
===========================================
+ Coverage     6.72%    9.05%   +2.32%     
===========================================
  Files         1118     1130      +12     
  Lines       111939   113003    +1064     
===========================================
+ Hits          7533    10229    +2696     
+ Misses      104406   102774    -1632     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@sneurlax
sneurlax marked this pull request as ready for review October 1, 2026 18:23
Cover the trusted-validator policy, per-lookup Tor isolation, privacy
revocation between DNSSEC queries, wallet rejection rules, embedded
quotes in recipient names, and the alias named in not-found and
failed-query errors. A Flutter test loads the native validator, and the
opt-in live tests validate DNSSEC on the device and check the not-found
message for dan@cypherstack.
@sneurlax
sneurlax marked this pull request as draft October 7, 2026 02:17
@sneurlax

sneurlax commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

this is a valid impl but we are taking another approach that is WIP and the last few PRs merged in various cypherstack repos today indicate the approach (DYOR)

@sneurlax

sneurlax commented Oct 7, 2026

Copy link
Copy Markdown
Member Author

TODO: drop Util.debugIsDesktopOverride and its test because #1465 added Util.layoutPlatform for the same purpose. Port open_alias_preview_test.dart to use it.

Parse oa1:xmr records, rejecting separate payment IDs and aliases with more
than one distinct address. Records are resolved with Google DNS-over-HTTPS
and only accepted when authenticated (AD set, CD and TC clear, exact
question match). When Tor is enabled the lookup is tunnelled through its
SOCKS port to the numeric resolver address, with no clearnet fallback.
Add a Use OpenAlias lookup to the mobile and desktop send screens. The
accepted address is carried in TxData and shown on confirmation; editing the
destination drops it.
Record parsing, DoH response validation and transport, the lookup service,
the lookup dialog and the TxData recipient. The live lookup test is skipped
by default.
Retain the RawSocket across SOCKS negotiation and the TLS upgrade so a
lookup timeout can close the live connection before TLS completes. Expose
an independently completed result because closing a raw transport during
TLS can leave Dart's handshake future pending. Keep cancellation idempotent
and dispose of sockets that complete after cancellation.

Adapt raw sockets to the Socket/SecureSocket interfaces expected by
HttpClient, preserving stream backpressure, partial writes, certificate
inspection, dns.google verification and the numeric SOCKS destination.

Add regression tests that wait for ClientHello before cancellation and
assert peer disconnection before teardown, including repeated attempts
and the full lookup timeout. Cover immediate cancellation, a trusted local
TLS/HTTP exchange, and rejection of an untrusted certificate. The committed
certificate and private key are test-only fixtures, trusted only through
an isolated SecurityContext.

Validation: all 37 offline OpenAlias tests pass (3 opt-in live tests skipped);
static analysis of the changed Dart files reports no issues.

Remove the socks5_proxy comment from DnsProxyConnection and preserve its
rationale here: socks5_proxy resolves hostnames locally before CONNECT,
so the OpenAlias tunnel uses the numeric endpoint 8.8.8.8:443 instead.
TLS still verifies dns.google without performing a local hostname lookup.
Accept plausible OpenAlias input directly in the Monero destination field
without marking it as a valid literal address or looking it up while editing.
Combine screen-local alias eligibility with the existing amount/data gates
and retain each layout's applicable fee checks.

Resolve through OpenAliasService after Preview, validate the result for the
wallet, and prepare only the resolved literal address. Keep the source alias
in the field and attach attribution to that attempt's TxData. Returning from
confirmation resolves afresh; final send uses the prepared recipient.

Share a per-screen attempt controller to suppress duplicate previews and
ignore stale lookup/preparation results after edits, cancellation, disposal,
or wallet changes. A modal progress route protects the draft during lookup;
controller/provider edits invalidate it and source/wallet/fee checks guard
preparation and navigation. Close only the progress route owned by the
attempt, then reuse the existing transaction-failed presentation on errors.
Transactions prepared for a stale attempt are still released with
cancelSend.
Remove the separate OpenAlias buttons and acceptance handlers.

Add active tests of both real send screens and both confirmation layouts,
with injected DNS records and fake wallets. Cover eligibility, no lookup on
editing/fee estimation, duplicate clicks, fresh retries, error-route safety,
late success/failure, cancellation during preparation, wallet changes,
contact autofill, payment URIs, and final send without another lookup.
No address-book, token, transport, or literal-address validator changes.
Delete the unused lookup/accept dialog and its send-form attribution widget.
Confirmation continues to display attribution from the prepared TxData.
Remove the seven dialog-specific tests, now replaced by active mobile and
desktop tests of direct destination entry and Preview-time resolution.
Select mobile and desktop layouts explicitly in widget tests by faking Util.layoutPlatform, restored during teardown. This avoids relying on the host platform and the Linux-only small-screen exception.

Exercise the inline workflow at 390x844 and 1200x900 with a full-length Monero recipient. Constrain the balance columns and remove the unbounded destination-label row exposed by the phone viewport.
Aliases and CNAME targets are DNS names, not hostnames, and may contain
underscores (RFC 2181). A CNAME to a name such as _oa.pay.example
previously failed with the input validation message.
Names in a resolver answer were checked with the alias input validator,
so a malformed CNAME target told the user to enter a valid domain.
Replace the inline connection and lookup durations with named constants,
and let callers override them per DohOpenAlias instance.
Over Tor, the connection deadline covers the local SOCKS connect, the
exit stream to the resolver and the TLS handshake through Tor, so five
seconds was tight. Tor lookups now get 10 s to connect and 20 s overall;
direct lookups keep 5 s and 12 s. The overall deadline grows with the
connection deadline so a slow connect still leaves time for the response.
The confirmation showed the DNS name used for the lookup, so
dan@cypherstack.com appeared as dan.cypherstack.com. Keep the trimmed,
lowercased input for display; lookups and validation still use the DNS
name.
A failed alias lookup opened a "Transaction failed" dialog although no
transaction was built. Lookup failures now use "OpenAlias lookup
failed"; preparation failures keep the existing title.
The error asked users to enable external calls in privacy settings,
which has no such control. External calls follow the Stack Experience
choice under Advanced settings, so name that setting instead.
Include the DNS name that was looked up when no record exists, so a
typo such as dan@cypherstack (dan.cypherstack) is visible in the error.
Report a nonexistent name separately from other resolver failures.
Replace the in-tree DoH JSON client, SOCKS/TLS tunnel and record parser
with the openalias, doh_resolver, dnssec_resolver and socks_socket
packages. DNSSEC is validated on the device from wire responses, and
only evidence from DnssecResolver.validator is trusted, so a resolver's
AD bit is no longer enough. Each Tor lookup sends a random SOCKS
isolation token, so its queries share a circuit no other traffic uses.

Tor lookups keep 10 s to connect and 20 s per request (direct: 5 s and
12 s). A lookup makes several sequential requests, so the whole
validation gets 40 s over Tor and 20 s direct.

The alias stays as entered for display, the Incognito message still
points at Stack Experience, and missing-record errors name the alias,
reporting a nonexistent name apart from a failed query.

The DoH transport tests and their TLS certificates covered the removed
code and are dropped; the remaining tests mock authenticated TXT
results. scripts/dev/use_openalias_packages.dart points the generated
pubspec at a local package workspace.
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.

1 participant