Skip to content

feat(platform-wallet): SPV cancel_background/identity_ids accessors + FFI no-selectable-inputs error mapping#3651

Open
lklimek wants to merge 3 commits into
v3.1-devfrom
feat/platform-wallet-spv-accessors-and-ffi-errors
Open

feat(platform-wallet): SPV cancel_background/identity_ids accessors + FFI no-selectable-inputs error mapping#3651
lklimek wants to merge 3 commits into
v3.1-devfrom
feat/platform-wallet-spv-accessors-and-ffi-errors

Conversation

@lklimek
Copy link
Copy Markdown
Contributor

@lklimek lklimek commented May 15, 2026

Issue being fixed or feature implemented

Independent carve-out of three small production clusters (D, E, K) extracted from #3549 (the e2e-framework PR), so they can land on v3.1-dev without waiting for the large e2e suite to be ready. No companion issue — this PR is the unit of work tracking.

D — SPV runtime + identity accessors (spv/runtime.rs, wallet/identity/state/manager/accessors.rs)

  • SpvRuntime::cancel_background() — synchronously fires the background run() task's cancellation token so a sync context (e.g. a std::panic::set_hook callback) can release the dash-spv data-dir lock before the next init attempt without blocking the panicking thread. Idempotent.
  • IdentityManager::identity_ids() — snapshot of every managed identity's Identifier across both buckets (order unspecified).
  • Note: the SpvRuntime::event_manager() accessor originally part of this cluster has been removed (commit 66a1a64abd) — it is superseded by its deletion in test(rs-platform-wallet): e2e suite, Found-025 fix + triage pins #3549 and is no longer needed here.

E — FFI error mapping (rs-platform-wallet-ffi/src/error.rs)

  • New result codes ErrorArithmeticOverflow = 13 (reserved, ABI placeholder — currently unused) and ErrorNoSelectableInputs = 14.
  • NoSpendableInputs / OnlyOutputAddressesFunded / OnlyDustInputs now map to the dedicated ErrorNoSelectableInputs code instead of flattening to ErrorUnknown; the typed Display rendering survives in the result message so callers can distinguish the underlying cause. Catch-all ErrorUnknown retained for unmapped variants.
  • Two unit tests pin the mapping (no_selectable_inputs_maps_to_dedicated_code) and the catch-all fall-through (unmapped_variants_fall_through_to_unknown).

E (supporting) — copied error variants (rs-platform-wallet/src/error.rs)

K — DAPI dispatch trace log (rs-dapi-client/src/dapi_client.rs)

  • One tracing::trace! emitting the resolved DAPI endpoint/method/request type. Pure observability, no behavior change.

What was done?

Carved clusters D, E, K out of #3549 as an independent production change targeting v3.1-dev.

Removed scope vs. the original carve-out: SpvRuntime::event_manager() was dropped (commit 66a1a64abd) because #3549 deletes that accessor outright — keeping it here would be dead/superseded surface. The retained D accessors are cancel_background() and identity_ids().

This PR is intentionally independent on v3.1-dev (not stacked on #3554/#3585) per an explicit operator directive given during the carve-out session — "Create an independent PR on top of v3.1-dev and copy these new errors there. We'll handle conflicts during merge." The commit-message wording "Per maintainer decision this PR is independent on v3.1-dev" is inaccurate and is corrected here at the PR-narrative level: there was no dashpay/platform maintainer decision; the true provenance is the in-session operator directive quoted above. History was deliberately not rewritten so the immutable commit record stays intact.

The error-enum variants NoSpendableInputs (from #3585), OnlyOutputAddressesFunded and OnlyDustInputs (from #3554) are copied verbatim and deliberately duplicated so D+E+K compiles standalone. These definitions WILL collide with #3554/#3585 at merge time — this is expected and accepted; the conflicts are resolved at merge (the definitions are identical, so resolution is mechanical). A human maintainer should explicitly ratify this deliberate-duplication strategy before this PR is merged.

How Has This Been Tested?

  • cargo build -p platform-wallet-ffi -p platform-wallet -p rs-dapi-client — clean.
  • cargo clippy -p platform-wallet-ffi -p platform-wallet -p rs-dapi-client — zero diagnostics on changed code (only pre-existing workspace Cargo.toml profile warnings, present on untouched base).
  • cargo test -p platform-wallet-ffi --lib error — all passed (incl. no_selectable_inputs_maps_to_dedicated_code, unmapped_variants_fall_through_to_unknown).
  • Single-file rustfmt --edition 2021 on each touched file.

Breaking Changes

None. Additive: new error variants, new FFI result codes (existing codes unchanged, new codes 13/14), new public accessors, one trace log. The event_manager() accessor removal has no external effect — the accessor never shipped on v3.1-dev.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have added or updated relevant unit/integration/functional/e2e tests
  • I have added "!" to the title and described breaking changes in the corresponding section if my code contains any
  • I have made corresponding changes to the documentation if needed

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

🤖 Generated with Claude Code

🤖 Co-authored by Claudius the Magnificent AI Agent

Carve-out of clusters D, E, K from #3549 (e2e framework PR) as an
independent production change on v3.1-dev.

D — SPV runtime accessors: SpvRuntime::cancel_background() (sync
cancellation-token fire for panic-hook data-dir-lock release) and
SpvRuntime::event_manager(); IdentityManager::identity_ids() snapshot.

E — FFI error mapping: dedicated ErrorNoSelectableInputs=14 (and
reserved ErrorArithmeticOverflow=13); NoSpendableInputs /
OnlyOutputAddressesFunded / OnlyDustInputs now map to the dedicated
FFI code instead of flattening to ErrorUnknown.

K — DAPI dispatch trace log: one tracing::trace! emitting the
resolved endpoint/method. Pure observability.

E's match arm consumes three PlatformWalletError variants that live
in the still-open #3554 (OnlyOutputAddressesFunded, OnlyDustInputs)
and #3585 (NoSpendableInputs). Per maintainer decision this PR is
independent on v3.1-dev and copies those variant definitions verbatim
so it compiles standalone; duplicate definitions are expected and
resolved at merge.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 15, 2026

📝 Walkthrough

Walkthrough

This PR extends wallet error handling with three new input selection failure types, maps them through FFI bindings with dedicated error codes, adds a background task cancellation method to SpvRuntime, provides an identity identifier accessor, and enhances DAPI request dispatch tracing.

Changes

Wallet Infrastructure Enhancements

Layer / File(s) Summary
Input selection error types and contracts
packages/rs-platform-wallet/src/error.rs
Adds three new PlatformWalletError variants (NoSpendableInputs, OnlyOutputAddressesFunded, OnlyDustInputs) with structured fields for account metadata, funded outputs, and input constraints; imports expanded to include StandardAccountType, PlatformAddress, and Credits.
FFI error code mapping and validation
packages/rs-platform-wallet-ffi/src/error.rs
Extends PlatformWalletFFIResultCode with ErrorArithmeticOverflow and ErrorNoSelectableInputs codes; updates From<PlatformWalletError> conversion to explicitly map the three input-selection variants to ErrorNoSelectableInputs while preserving typed error messages; includes unit tests verifying both dedicated mapping and fallback-to-ErrorUnknown behavior.
SpvRuntime background cancellation API
packages/rs-platform-wallet/src/spv/runtime.rs
Adds cancel_background() method to synchronously fire and remove stored cancellation tokens for background tasks without affecting the running client itself.
Identity state accessor
packages/rs-platform-wallet/src/wallet/identity/state/manager/accessors.rs
Adds identity_ids() method to IdentityManager that snapshots all managed identity identifiers across both in-wallet and out-of-wallet buckets into an owned Vec.
DAPI request dispatch tracing
packages/rs-dapi-client/src/dapi_client.rs
Adds explicit tracing::trace! event under dapi_client::dispatch target logging the resolved DAPI endpoint address and request metadata before transport execution.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Suggested reviewers

  • shumkov
  • QuantumExplorer

🐰 Five new tools hop in stride,

Errors mapped, runtimes guide,

Trackers log, accessors peek,

Wallet's reach now strong and sleek! 🎯

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: SPV runtime accessors (cancel_background, identity_ids), FFI error mapping for input selection, and observational logging improvements.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/platform-wallet-spv-accessors-and-ffi-errors

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.

@github-actions github-actions Bot added this to the v3.1.0 milestone May 15, 2026
@lklimek lklimek changed the title feat(rs-platform-wallet): SPV runtime accessors + FFI error mapping feat(platform-wallet): SPV runtime accessors + FFI error mapping May 18, 2026
@lklimek lklimek marked this pull request as ready for review May 18, 2026 06:53
@lklimek lklimek requested a review from QuantumExplorer as a code owner May 18, 2026 06:53
@thepastaclaw
Copy link
Copy Markdown
Collaborator

thepastaclaw commented May 18, 2026

✅ Review complete (commit 66a1a64)

@lklimek lklimek added the ready for final review Ready for the final review. If AI was involved in producing this PR, it has already had a reviewer. label May 18, 2026
@lklimek lklimek changed the title feat(platform-wallet): SPV runtime accessors + FFI error mapping feat(platform-wallet): spv runtime accessors + FFI error mapping May 18, 2026
Copy link
Copy Markdown
Collaborator

@thepastaclaw thepastaclaw left a comment

Choose a reason for hiding this comment

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

Code Review

I verified the flagged changes against b8ccad8d277fb46882466adecd958af0ccd126c2. The FFI error remapping is real and the added tests are directionally correct, but the new SpvRuntime::cancel_background() API does not satisfy the restart-after-panic contract described in its own docs and is not safe as a panic-hook escape hatch. One additional test-coverage gap remains in the new FFI error-code contract.

Reviewed commit: b8ccad8

🔴 1 blocking | 🟡 1 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-platform-wallet/src/spv/runtime.rs`:
- [BLOCKING] lines 182-200: `cancel_background()` is not a reliable panic-hook recovery path
  This method is documented as the synchronous escape hatch for panic-hook contexts that need the dash-spv data-dir lock released before the next init attempt, but the implementation only removes the stored token and calls `token.cancel()`. The actual teardown still happens later on the spawned task's async path after `run()` leaves the `select!` and reaches `self.stop().await`, so a caller can return from `cancel_background()` and race straight into a new `start()` while the old client still owns the lock. On top of that, this panic-path API acquires `background_cancel` with `.expect("background_cancel poisoned")`, which will panic again if the mutex was poisoned by an earlier unwind. As written, the method neither guarantees lock release before re-init nor stays usable in the failure mode it was added to handle.

In `packages/rs-platform-wallet-ffi/src/error.rs`:
- [SUGGESTION] lines 405-444: The new FFI test does not cover all three variants mapped to `ErrorNoSelectableInputs`
  The production mapping at lines 176-180 explicitly groups `NoSpendableInputs`, `OnlyOutputAddressesFunded`, and `OnlyDustInputs` under `ErrorNoSelectableInputs`, and the enum docs say callers distinguish the cause from the preserved message text. The new test only constructs `NoSpendableInputs`, so the two payload-heavy variants with their own `Display` output are still unpinned. A future edit could break one of those user-visible messages or accidentally remap one variant while this test still passes.

Comment thread packages/rs-platform-wallet/src/spv/runtime.rs
Comment thread packages/rs-platform-wallet-ffi/src/error.rs
@lklimek lklimek removed the ready for final review Ready for the final review. If AI was involved in producing this PR, it has already had a reviewer. label May 18, 2026
…(superseded by #3549)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/rs-platform-wallet-ffi/src/error.rs`:
- Around line 82-90: The doc comment for ErrorNoSelectableInputs has the
parentheticals for NoSpendableInputs and OnlyOutputAddressesFunded reversed;
update the parentheses so NoSpendableInputs reads "(account has nothing
spendable)" and OnlyOutputAddressesFunded reads "(every funded address is also a
destination)" while leaving OnlyDustInputs and the rest of the description
unchanged (refer to ErrorNoSelectableInputs, NoSpendableInputs,
OnlyOutputAddressesFunded, OnlyDustInputs to locate the text).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 3ed43d77-2176-4f5c-b362-9473fbb82092

📥 Commits

Reviewing files that changed from the base of the PR and between cd93b2f and 66a1a64.

📒 Files selected for processing (5)
  • packages/rs-dapi-client/src/dapi_client.rs
  • packages/rs-platform-wallet-ffi/src/error.rs
  • packages/rs-platform-wallet/src/error.rs
  • packages/rs-platform-wallet/src/spv/runtime.rs
  • packages/rs-platform-wallet/src/wallet/identity/state/manager/accessors.rs

Comment thread packages/rs-platform-wallet-ffi/src/error.rs
@codecov
Copy link
Copy Markdown

codecov Bot commented May 18, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.05%. Comparing base (cd93b2f) to head (66a1a64).

Additional details and impacted files
@@             Coverage Diff              @@
##           v3.1-dev    #3651      +/-   ##
============================================
- Coverage     88.06%   88.05%   -0.01%     
============================================
  Files          2521     2521              
  Lines        308995   308781     -214     
============================================
- Hits         272122   271908     -214     
  Misses        36873    36873              
Components Coverage Δ
dpp 88.01% <ø> (ø)
drive 87.03% <ø> (-0.03%) ⬇️
drive-abci 90.05% <ø> (ø)
sdk ∅ <ø> (∅)
dapi-client ∅ <ø> (∅)
platform-version ∅ <ø> (∅)
platform-value 92.17% <ø> (ø)
platform-wallet ∅ <ø> (∅)
drive-proof-verifier 53.13% <ø> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Copy link
Copy Markdown
Collaborator

@thepastaclaw thepastaclaw left a comment

Choose a reason for hiding this comment

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

Code Review

I verified the reported issues against 66a1a64abd500691d97b49a5197b9eccd41acc0c. Three findings hold: the new SPV panic-path cancellation API does not provide the synchronous recovery its docs promise, the new Rust-side FFI code is not mirrored through Swift, and the added Rust test does not cover all three variants that now share the dedicated FFI code.

Reviewed commit: 66a1a64

🔴 1 blocking | 🟡 2 suggestion(s)

1 additional finding

🟡 suggestion: Swift no longer mirrors the Rust FFI result-code enum, so `ErrorNoSelectableInputs` is downgraded to `.errorUnknown`

packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletResult.swift (lines 7-58)

Rust now exports ErrorArithmeticOverflow = 13 and ErrorNoSelectableInputs = 14, and the FFI conversion returns ErrorNoSelectableInputs for NoSpendableInputs, OnlyOutputAddressesFunded, and OnlyDustInputs. The Swift mirror still stops at errorUtf8Conversion = 12 and falls through to default for any newer value, so code 14 is converted to .errorUnknown before PlatformWalletError(result:) builds the thrown error. The message string still survives, but the dedicated ABI code added in this PR does not survive the Rust-to-Swift boundary.

🤖 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-platform-wallet/src/spv/runtime.rs`:
- [BLOCKING] lines 182-201: `cancel_background()` cannot guarantee the lock-release behavior its panic-hook docs promise
  This method only takes the stored token and calls `cancel()`. It does not wait for the spawned `run()` task to leave the `select!`, reach `self.stop().await`, and release the underlying SPV client and storage lock. That means a panic-hook caller can return from `cancel_background()` and immediately race into a new `start()` while the old task still owns the data-dir lock, which is the exact scenario the doc comment says this API handles. The same panic-path API also uses `.lock().expect("background_cancel poisoned")`, so if the mutex was poisoned by the unwind that triggered the hook, the recovery path panics again instead of cancelling anything.

In `packages/swift-sdk/Sources/SwiftDashSDK/PlatformWallet/PlatformWalletResult.swift`:
- [SUGGESTION] lines 7-58: Swift no longer mirrors the Rust FFI result-code enum, so `ErrorNoSelectableInputs` is downgraded to `.errorUnknown`
  Rust now exports `ErrorArithmeticOverflow = 13` and `ErrorNoSelectableInputs = 14`, and the FFI conversion returns `ErrorNoSelectableInputs` for `NoSpendableInputs`, `OnlyOutputAddressesFunded`, and `OnlyDustInputs`. The Swift mirror still stops at `errorUtf8Conversion = 12` and falls through to `default` for any newer value, so code 14 is converted to `.errorUnknown` before `PlatformWalletError(result:)` builds the thrown error. The message string still survives, but the dedicated ABI code added in this PR does not survive the Rust-to-Swift boundary.

In `packages/rs-platform-wallet-ffi/src/error.rs`:
- [SUGGESTION] lines 405-434: The new FFI test covers only one of the three variants mapped to `ErrorNoSelectableInputs`
  `From<PlatformWalletError>` maps `NoSpendableInputs`, `OnlyOutputAddressesFunded`, and `OnlyDustInputs` to the same FFI code, but `no_selectable_inputs_maps_to_dedicated_code()` exercises only `NoSpendableInputs`. The other two variants carry different payloads and different `Display` text, so a later refactor could break one of those mappings or its user-visible message while this test still passes. The dedicated-code contract added in this PR should be pinned for all three variants.

Comment thread packages/rs-platform-wallet/src/spv/runtime.rs
Comment thread packages/rs-platform-wallet-ffi/src/error.rs
@lklimek lklimek added the ready for final review Ready for the final review. If AI was involved in producing this PR, it has already had a reviewer. label May 18, 2026
@lklimek lklimek changed the title feat(platform-wallet): spv runtime accessors + FFI error mapping feat(platform-wallet): SPV cancel_background/identity_ids accessors + FFI no-selectable-inputs error mapping May 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready for final review Ready for the final review. If AI was involved in producing this PR, it has already had a reviewer.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants