Uh oh!
There was an error while loading. Please reload this page.
fix: improve platform wallet UTXO checks and DPNS parsing - #3595
Conversation
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughTwo independent changes across wallet and SDK packages: broadcast transaction validation now checks UTXOs against a pre-captured spendable set instead of re-deriving it, with updated error handling for missing wallets post-broadcast; DPNS label extraction is refactored into a private helper function with comprehensive unit tests. ChangesBroadcast Transaction Validation & Registration
DPNS Label Extraction Helper
🎯 3 (Moderate) | ⏱️ ~25 minutes
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
thepastaclaw
commented
May 5, 2026
@coderabbitai review |
✅ Actions performedReview triggered.
|
✅ Review complete (commit 1d944a8) |
thepastaclaw
left a comment
There was a problem hiding this comment.
Code Review
Small, well-scoped fix-up PR. Most agent findings are either stale (referencing the previous comment text), nitpicky, or second-guessing intentional design choices that the PR explicitly documents. The one finding worth surfacing is the API inconsistency between resolve_dpns_name (now strips .DASH case-insensitively) and is_dpns_name_available (still doesn't), which is a reasonable extension of the same fix.
Reviewed commit: ecccf06
🟡 1 suggestion(s)
1 additional finding
🟡 suggestion: `is_dpns_name_available` does not share the case-insensitive `.dash` parsing now used by `resolve_dpns_name`
packages/rs-sdk/src/platform/dpns_usernames/mod.rs (lines 383-417)
The new extract_dpns_label helper is only consumed by resolve_dpns_name, so is_dpns_name_available("alice.DASH") still feeds "alice.DASH" into convert_to_homograph_safe_chars and queries normalizedLabel == "a11ce.dash", which never matches the indexed "a11ce" and reports the name as available even when resolve_dpns_name("alice.DASH") returns an existing identity. The function's docstring does specify that the argument is the label only (alice), so this is not strictly a bug, but it leaves two adjacent public DPNS APIs with divergent normalization rules for the same input. Routing is_dpns_name_available through extract_dpns_label (or documenting that it intentionally rejects full names) would close that gap and was the spirit of the original review feedback.
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `packages/rs-sdk/src/platform/dpns_usernames/mod.rs`:
- [SUGGESTION] lines 383-417: `is_dpns_name_available` does not share the case-insensitive `.dash` parsing now used by `resolve_dpns_name`
The new `extract_dpns_label` helper is only consumed by `resolve_dpns_name`, so `is_dpns_name_available("alice.DASH")` still feeds `"alice.DASH"` into `convert_to_homograph_safe_chars` and queries `normalizedLabel == "a11ce.dash"`, which never matches the indexed `"a11ce"` and reports the name as available even when `resolve_dpns_name("alice.DASH")` returns an existing identity. The function's docstring does specify that the argument is the label only (`alice`), so this is not strictly a bug, but it leaves two adjacent public DPNS APIs with divergent normalization rules for the same input. Routing `is_dpns_name_available` through `extract_dpns_label` (or documenting that it intentionally rejects full names) would close that gap and was the spirit of the original review feedback.
ecccf06 to
3dfeafcCompare
thepastaclaw
left a comment
There was a problem hiding this comment.
Code Review
Verified at SHA 3dfeafc. The PR is small and focused, and the prior carry-forward concern about case-insensitive .dash handling is genuinely resolved by routing both DPNS APIs through normalize_dpns_label. One real residual inconsistency remains: is_dpns_name_available lacks the empty-normalized-label guard that resolve_dpns_name has, so suffix-only inputs like ".dash" are reported as available. The wallet best-effort registration after a successful broadcast is documented as intentional; the codex-general 'blocking' framing overstates the impact since the network rejects duplicate spends and the trade-off is explicitly noted in code comments.
Reviewed commit: 3dfeafc
🟡 2 suggestion(s)
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `packages/rs-sdk/src/platform/dpns_usernames/mod.rs`:
- [SUGGESTION] lines 404-405: `is_dpns_name_available` should mirror `resolve_dpns_name`'s empty-normalized-label guard
After `let normalized_label = normalize_dpns_label(name);`, this function unconditionally issues a `fetch_many` against `normalizedLabel == ""` for inputs like `""`, `".dash"`, or `".DASH"` (covered by the new unit test at lines 527-530). Since no registered domain has an empty `normalizedLabel`, the function returns `Ok(true)` and reports an unregistrable label as available, which is the opposite of the safe answer. `resolve_dpns_name` at lines 451-454 short-circuits this exact case with `Ok(None)`, and the docstring at lines 390-392 explicitly promises that `is_dpns_name_available` mirrors `Sdk::resolve_dpns_name`. Add the same guard (returning `Ok(false)` for an empty normalized label, or surfacing a typed validation error) so the two adjacent APIs agree end-to-end and the network roundtrip is avoided for clearly malformed input.
In `packages/rs-platform-wallet/src/wallet/core/broadcast.rs`:
- [SUGGESTION] lines 171-190: Post-broadcast bookkeeping failures are silently swallowed; consider surfacing them or documenting expected recovery
After `broadcast_transaction(&tx)` succeeds, this block downgrades two failure modes to `tracing::warn!` and still returns `Ok(tx)`: (a) the wallet is missing from `wallet_manager`, and (b) `check_core_transaction` reports the just-built transaction as not relevant. In both cases the wallet never records the mempool spend or change output, so a subsequent `send_to_addresses` from the same handle can reselect the already-broadcast inputs; the network will then reject the duplicate spend at broadcast time, surfacing as a confusing `TransactionBuild`/broadcast error to the next caller until a later mempool/block sync repairs local state. The design comment at lines 155-170 documents broadcast-first semantics intentionally (returning `Err` after a successful broadcast would itself be misleading), so this is more of a robustness suggestion than a bug: consider either returning a typed warning to the caller, or expanding the comment to explicitly cover the wallet-missing / not-relevant cases and how the next sync is expected to repair state. The wallet-missing branch in particular does not look like a transient condition.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
3dfeafc to
1d944a8Compare
thepastaclaw
left a comment
There was a problem hiding this comment.
Code Review
Small PR with both prior carry-forward findings already addressed. One legitimate cross-language gap remains: the C/Swift FFI for DPNS availability still rejects full .dash names that the Rust SDK (widened in this PR) now accepts. The Rust-quality nitpick about the subset check duplicates a design decision the author already documented.
Reviewed commit: 1d944a8
🟡 1 suggestion(s)
1 additional finding
🟡 suggestion: C/Swift DPNS availability FFI still rejects full `.dash` names that the Rust SDK now accepts
packages/rs-sdk-ffi/src/dpns/queries/availability.rs (lines 59-83)
This PR widens Sdk::is_dpns_name_available to accept either a bare label or a full DPNS name, stripping a case-insensitive .dash suffix via normalize_dpns_label (packages/rs-sdk/src/platform/dpns_usernames/mod.rs:397-411). The C FFI wrapper, however, still validates the inbound string with is_valid_username(label_str) before calling into Rust. Because is_valid_username requires alphanumeric start/end and only [a-zA-Z0-9-] in between, inputs like "alice.dash" or "alice.DASH" short-circuit to valid: false, available: false instead of being normalized and queried like the Rust and WASM paths now do. Swift callers reach the SDK exclusively through this wrapper, so non-Rust consumers do not actually receive the new case-insensitive .dash behavior the PR title advertises. Consider either normalizing the suffix at the FFI boundary before the validity check, or invoking the SDK directly and letting it decide.
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `packages/rs-sdk-ffi/src/dpns/queries/availability.rs`:
- [SUGGESTION] lines 59-83: C/Swift DPNS availability FFI still rejects full `.dash` names that the Rust SDK now accepts
This PR widens `Sdk::is_dpns_name_available` to accept either a bare label or a full DPNS name, stripping a case-insensitive `.dash` suffix via `normalize_dpns_label` (packages/rs-sdk/src/platform/dpns_usernames/mod.rs:397-411). The C FFI wrapper, however, still validates the inbound string with `is_valid_username(label_str)` before calling into Rust. Because `is_valid_username` requires alphanumeric start/end and only `[a-zA-Z0-9-]` in between, inputs like `"alice.dash"` or `"alice.DASH"` short-circuit to `valid: false, available: false` instead of being normalized and queried like the Rust and WASM paths now do. Swift callers reach the SDK exclusively through this wrapper, so non-Rust consumers do not actually receive the new case-insensitive `.dash` behavior the PR title advertises. Consider either normalizing the suffix at the FFI boundary before the validity check, or invoking the SDK directly and letting it decide.
Fresh dispatcher-requested review for this queue item. A same-SHA blank/placeholder review already existed, so this review is posted explicitly rather than skipped by same-SHA dedup.
1bd306a
into
dashpay:fix/dpns-case-and-utxo-race-v3.1-devUh oh!
There was an error while loading. Please reload this page.
Summary
Addresses review feedback from #3585:
send into an error
.dashsuffix unit coverageValidation
git diff --checkcargo test -p dash-sdk test_extract_dpns_label --libcargo check -p platform-walletcargo clippy -p dash-sdk --lib -- -D warningscargo clippy -p platform-wallet --lib -- -D warningswas run and reachedpre-existing clippy failures in
packages/rs-platform-wallet/src/manager/accessors.rsunrelated to this diff(
manual_unwrap_or_default,unnecessary_cast,redundant_closure).cargo fmt --all -- --checkand workspacecargo checksuccessfully during commit.Summary by CodeRabbit