Skip to content

feat(platform-wallet)!: persist engine spent claims and restore them across backends - #5306

Draft
lklimek wants to merge 2 commits into
fix/pr-5126from
feat/wallet-spent-claim-deltas
Draft

lklimek wants to merge 2 commits into
fix/pr-5126from
feat/wallet-spent-claim-deltas

Conversation

@lklimek

@lklimek lklimek commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

Basic explanation

TL;DR: Save the Core wallet engine's own reports of spent coins and restore them after restart.

Value: SQLite, iOS and Android persistence use the same source of truth for spent coins while preserving transaction history and accounting.

Risks: Existing development wallet stores require recreation and rescan, and native bindings must be rebuilt together. Mobile runtime validation remains outstanding. No consensus behavior changes.

User story

As a wallet user, I want restarting the wallet to preserve which coins are spent and the history of my pending payments.

Scenario

A wallet receives funds, sends a payment, saves its state and restarts.

Actual behavior: Storage reconstructs spending state from transaction history and sweep stamps, which can name a conflict winner rather than the actual spender.

Expected behavior: Storage saves the engine's spending decisions directly. Restoring them protects spent coins and retains pending-payment history, including sends with no change output.

Detailed discussion

Stacked on #5150: this PR targets fix/pr-5126 to isolate the follow-up. After #5150 lands, retarget to v5.1-dev. Uses dashpay/rust-dashcore#1113 at 6d5a7ba5337aa2fab92f6ac3320e7cef456867f0; merge that dependency and move the pin to a merged revision before landing.

Issue being fixed or feature implemented

Consume the engine's authoritative spent-outpoint changes instead of treating historical TXO/sweep stamps as claimant provenance. Related #5220 handles shared history replay; this change retains the history/proof reconstruction still needed for accounting.

What was done?

  • Pin all rust-dashcore workspace dependencies to chore(release): update changelog and bump version to 0.24.5 #1113. The lockfile changes only its 13 package source references; registry versions are unchanged.
  • Share normalized Core restoration between SQLite and FFI. Preserve ordered engine batches in CoreChangeSet: upsert claims, then delete releases within each batch. Unknown claimants remain present claims.
  • Persist claims atomically with their events in dedicated SQLite V020, SwiftData V4 and Room 15 tables. A completeness marker certifies only new wallet registrations; old stores fail explicitly rather than infer claims from history.
  • Add an appended, size-gated FFI persistence callback and JNI transport; restore claim arrays through WalletRestoreEntryFFI.
  • Restore claims before funding replay. SQLite commits engine-derived repair deltas with history repairs and rolls both back in recovery mode. Temporarily stage validated guarded inputs for pending-send accounting, removing leftovers before exposing the wallet.

The upstream late-InstantSend sweep-event gap remains (dashpay/rust-dashcore#976; #1106 touches that path). Existing reservation-only abandonment is unchanged; a first-class removal API and retirement of remaining host history reconstruction are separate work.

How Has This Been Tested?

  • 253 targeted Rust tests passed: 108 SQLite restart/reconstruction/conflict tests; 44 storage unit tests; 17 wallet load/claim/restore tests; 77 FFI persistence/layout tests; 7 JNI tests.
  • Event-driven restart tests compare persisted claims with the engine map. Coverage includes unknown and recordless claims, ordering, wallet isolation, rollback, legacy-store refusal, and pending sends without change.
  • Scoped formatting and strict Clippy passed for wallet, storage, wallet FFI, unified FFI and JNI using --all-targets --all-features --locked -- --no-deps -D warnings.
  • Android SQL probes passed for migration, nullable claims, ordering, rollback and deletion cascade; the Room schema identity was checked against the compiler algorithm.
  • Not run: Swift/iOS and Android builds/runtime tests, full workspace tests, or WASM runtime tests. Mobile regression tests are included, but Apple/Java/Android toolchains are unavailable on this Linux host.

Breaking Changes

  • Requires a fresh authoritative-claim wallet store and rescan; no legacy provenance backfill.
  • Appends fields to the restore FFI struct, whose layout is not size-gated. Rebuild native libraries, generated headers and host wrappers together. The persistence extension callback itself is size-gated.
  • Public Rust startup/changeset types gain fields; storage errors gain the typed incomplete-claims failure.

In-place changes to shipped generations

None. This change does not modify versioned consensus behavior.

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
  • If I added or changed GroveDB structure, I described it in the area's structure.rs, regenerated grovedb-structure.json, and checked the structure viewer link posted on this pull request

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

🤖 Co-authored by Claudius the Magnificent AI Agent

…ed claims

Share normalized Core metadata and UTXO restoration between SQLite and FFI. Append an authoritative spent-claim input to the FFI restore entry; hosts and native bindings must rebuild together.

Preserve existing SQLite final-claim restoration and all history/proof replay. Swift/JNI claim producers stay empty pending engine deltas: legacy sweep stamps do not reliably identify the actual spending transaction.

Validated with 238 targeted tests, formatting, and strict Clippy for wallet, storage, FFI and JNI. Apple builds were unavailable on Linux.

<sub>🤖 Co-authored by [Claudius the Magnificent](https://github.com/lklimek/claudius) AI Agent</sub>
Pin rust-dashcore PR #1113 at 6d5a7ba5 and persist engine claim batches atomically through SQLite, SwiftData and Room. Restore authoritative claims before history replay and preserve guarded inputs temporarily for pending-send record reconstruction.

Require a fresh authoritative-claim store and rebuild native bindings together. Retain history/proof reconstruction and document the upstream late-InstantSend event gap.

Validated with 253 targeted Rust tests, scoped formatting and strict CI Clippy. Swift and Android runtime tests require unavailable platform toolchains.

<sub>🤖 Co-authored by [Claudius the Magnificent](https://github.com/lklimek/claudius) AI Agent</sub>
@coderabbitai

coderabbitai Bot commented Oct 6, 2026

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@thepastaclaw

Copy link
Copy Markdown
Collaborator

🕓 Review not started yet because this PR is a draft.

  • Request normal review — click when the PR is ready for review.
  • Request priority review — click to move this review to the front of the queue.

Commit a4b1a88. Normal review starts when eligible; priority review starts as soon as a slot is available.

This branch has not been deployed

No deployments
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.

2 participants