Skip to content

feat(kotlin-sdk)!: reset an outbound contact account's pool and keep its request digest on Android - #5590

Draft
romchornyi wants to merge 1 commit into
fix/contact-rebuild-ffi-swiftfrom
fix/contact-rebuild-kotlin
Draft

romchornyi wants to merge 1 commit into
fix/contact-rebuild-ffi-swiftfrom
fix/contact-rebuild-kotlin

Conversation

@romchornyi

@romchornyi romchornyi commented Oct 26, 2026 •

Copy link
Copy Markdown
Contributor

Basic explanation

What this does: This does the same for the Android host that #5589 does for iOS:

  • Kotlin stores the reset that drops a replaced contact account's old addresses;
  • Kotlin stores the digest of the contact request the account was built from;
  • the JNI bridge connects the new callbacks.

Value: On Android, a contact who sends a new key gets a clean account, and a restart knows whether the account is current.

Risks: Low to medium.

Stack (review and merge in order):

  1. fix(platform-wallet)!: keep a contact's payment account across relaunches and replace it cleanly on rotation #5587: the rule, in Rust, plus SQLite .
  2. feat(platform-wallet-ffi)!: let hosts reset an outbound contact account's pool and keep its request digest #5589: the FFI slots plus Swift storage.
  3. feat(kotlin-sdk)!: reset an outbound contact account's pool and keep its request digest on Android #5590: JNI plus Kotlin storage (Room v16) and the parity entry (this PR). Merge it together with feat(platform-wallet-ffi)!: let hosts reset an outbound contact account's pool and keep its request digest #5589, or right after it: once feat(platform-wallet-ffi)!: let hosts reset an outbound contact account's pool and keep its request digest #5589 is in, the FFI fails a replacement on any host that keeps pools without the reset slot, and the Android host gets that slot only in feat(kotlin-sdk)!: reset an outbound contact account's pool and keep its request digest on Android #5590.

Issue being fixed or feature implemented

Part 3 of the stack started in #5587.

What was done?

rs-unified-sdk-jni

  • Trampolines for the three slots, with descriptors added to the FfiSmokeTest verification table.
  • Each slot is wired only when the bridge overrides it. The digest pair is wired only as a pair.
  • A null digest crosses as an empty array. A wrong-length read becomes an error.

kotlin-sdk

  • NativePersistenceBridge gets three new methods: onResetAccountAddressPool, onPersistAccountXpubDigest and onLoadAccountXpubDigest.
  • The handler implements them:
    • reset unlinks TXOs (the FK cascades) and then calls deleteByAccount;
    • an empty digest clears the stored one;
    • a missing account row throws, except for a wallet removed mid-round.
  • AccountEntity.encryptedXpubDigest, Room v16 with MIGRATION_15_16, and the exported 16.json.

docs: parity manifest entry dashpay.outbound_account_rotation, with a regenerated PARITY_SUMMARY.md.

How Has This Been Tested?

  • cargo test -p rs-unified-sdk-jni --all-features (53), including slot wiring by overrides. Clippy is clean.
  • ./gradlew :sdk:testDebugUnitTest: PlatformWalletPersistenceHandlerTest. The reset keeps TXOs and requires the account row; the digest survives a restart and can be cleared.
  • DashDatabaseMigrationTest.migrate15To16AddsOutboundAccountDigestColumn, with the 4→latest and 1→latest chains extended to v16. These compile (:sdk:compileDebugAndroidTestKotlin) but were not run here, because they need a device.
  • python3 scripts/check_sdk_parity_manifest.py passes.

Breaking Changes

  • Room: schema v16.
  • Custom NativePersistenceBridge subclasses that persist pools must override onResetAccountAddressPool, or replacement rounds fail.

Checklist:

  • I have performed a self-review of my own code
  • My Rust, FFI, WASM, Swift or Kotlin changes follow the coding conventions
  • 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
  • If I added or changed a system contract's document schemas, I checked the contract viewer link posted on this pull request

For repository code-owners and collaborators only

  • I have assigned this pull request to a milestone

🤖 Generated with Claude Code

…est digest on Android

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WYhtAUUCkvoBmp19LA8Z31
@coderabbitai

coderabbitai Bot commented Oct 26, 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
  • Autofix · 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 55dc3dd. 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.

3 participants