Skip to content

fix(platform-wallet): add TRANSFER key to default identity registration key set#3894

Merged
QuantumExplorer merged 1 commit into
v3.1-devfrom
claude/gracious-matsumoto-0cf48f
Jun 14, 2026
Merged

fix(platform-wallet): add TRANSFER key to default identity registration key set#3894
QuantumExplorer merged 1 commit into
v3.1-devfrom
claude/gracious-matsumoto-0cf48f

Conversation

@QuantumExplorer

Copy link
Copy Markdown
Member

Issue being fixed or feature implemented

Identities created on-device by SwiftExampleApp were provisioned with only AUTHENTICATION keys (MASTER/CRITICAL/HIGH) plus the optional DashPay ENCRYPTION/DECRYPTION pair — but no key with purpose=TRANSFER (purpose 3). Dash Platform requires a purpose=TRANSFER, security_level=CRITICAL key to sign IdentityCreditTransfer (ID-04) and IdentityCreditWithdrawal (ID-10) state transitions, so those broadcasts failed on-chain with Protocol error: missing key: no transfer public key. This blocked the Essential-tier ID-04 / ID-10 flows for every app-created identity, regardless of the (correct) Transfer Credits UI added in #3891.

What was done?

The registration key-set policy is owned by Rust (per packages/swift-sdk/CLAUDE.md), in dash_sdk_derive_and_persist_identity_keys. The fix extends the per-slot policy table so the default registration set includes a TRANSFER key:

keyId key_type purpose security_level
0 ECDSA_SECP256K1 AUTHENTICATION MASTER
1 ECDSA_SECP256K1 AUTHENTICATION CRITICAL
2 ECDSA_SECP256K1 AUTHENTICATION HIGH
3 ECDSA_SECP256K1 TRANSFER CRITICAL
  • packages/rs-platform-wallet-ffi/src/identity_derive_and_persist.rs: add PURPOSE_TRANSFER; change the per-slot match to emit (purpose, security_level) instead of only security_level; slots 0/1/2 keep their previous bytes byte-for-byte (so any caller still passing key_count = 3 is unchanged). TRANSFER keys carry no contract bounds (only ENC/DEC require them). Docs/table updated and a new unit test key_count_four_includes_transfer_critical_key added.
  • packages/swift-sdk/SwiftExampleApp/.../CreateIdentityView.swift: bump defaultKeyCount 3 → 4 and the asset-lock funding floor minIdentityFundingDuffsForDefaultKeys 221_500 → 228_000 duffs. The optional DashPay enc/dec pair auto-shifts to keyId 4/5 via the symbolic firstKeyId: Self.defaultKeyCount (no Swift-side policy added).

How Has This Been Tested?

  • cargo fmt --all; cargo test -p platform-wallet-ffi (incl. the new test) and cargo check -p platform-wallet-ffi --all-targets/--all-features --tests pass. The pre-existing key_count == 3 test is unchanged and still passes (slots 0/1/2 untouched).
  • Built the unified iOS xcframework + SwiftExampleApp and ran on a booted testnet simulator. Created a fresh identity (index 3) via the new build; SwiftData ground-truth shows its keys (keyId,purpose,secLvl) = (0,0,0)(1,0,1)(2,0,2)(3,3,1)(4,1,3)(5,2,3) — the purpose-3 / CRITICAL / ECDSA TRANSFER key is present at keyId 3, with the DashPay enc/dec pair correctly at keyId 4/5. The three pre-existing identities have no purpose-3 key.
  • Drove the Transfer Credits flow with the new identity as sender: the transition now signs with the transfer key and proceeds past the old no transfer public key rejection (build → sign → broadcast → proof verification). The original bug is fixed.

Note: completing the transfer end-to-end in the app is currently blocked by a separate, pre-existing issue — the post-broadcast proof verification (drive::verify::state_transition::verify_state_transition_was_executed_with_proof) overflows the (small) client dispatch-worker stack in the debug build (the known latent recursive Value::Decode). That crash is unrelated to key derivation; this change merely unblocks reaching it. Tracked separately.

Breaking Changes

None. This changes the default key set for newly created identities (SDK/example-app behavior); it is not consensus-breaking and does not alter any existing on-chain data. Pre-release, so no migration concerns.

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

…on key set

App-created identities were provisioned with only AUTHENTICATION
(+ optional DashPay ENCRYPTION/DECRYPTION) keys and no purpose=TRANSFER
key, so IdentityCreditTransfer (ID-04) and IdentityCreditWithdrawal
(ID-10) failed on-chain with "missing key: no transfer public key".

The registration key-set policy lives in Rust in
`dash_sdk_derive_and_persist_identity_keys`. Extend its per-slot table
so keyId 3 = TRANSFER/CRITICAL/ECDSA_SECP256K1 alongside the existing
AUTHENTICATION MASTER/CRITICAL/HIGH keys; slots 0/1/2 keep their bytes
unchanged. TRANSFER keys take no contract bounds (only ENC/DEC do).

Bump SwiftExampleApp's `defaultKeyCount` 3->4 and the funding floor
(`minIdentityFundingDuffsForDefaultKeys` 221_500->228_000 duffs); the
optional DashPay enc/dec pair auto-shifts to keyId 4/5 via the symbolic
`firstKeyId: Self.defaultKeyCount`.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@QuantumExplorer, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 2 minutes and 45 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7d340629-c657-41a0-8974-05741f916946

📥 Commits

Reviewing files that changed from the base of the PR and between b3efe4b and a3a2b80.

📒 Files selected for processing (2)
  • packages/rs-platform-wallet-ffi/src/identity_derive_and_persist.rs
  • packages/swift-sdk/SwiftExampleApp/SwiftExampleApp/Views/CreateIdentityView.swift
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/gracious-matsumoto-0cf48f

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.

@QuantumExplorer
QuantumExplorer merged commit 68faf2c into v3.1-dev Jun 14, 2026
16 of 17 checks passed
@QuantumExplorer
QuantumExplorer deleted the claude/gracious-matsumoto-0cf48f branch June 14, 2026 09:23
@codecov

codecov Bot commented Jun 14, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 71.20%. Comparing base (65042eb) to head (a3a2b80).
⚠️ Report is 20 commits behind head on v3.1-dev.

Additional details and impacted files
@@              Coverage Diff              @@
##           v3.1-dev    #3894       +/-   ##
=============================================
- Coverage     87.22%   71.20%   -16.03%     
=============================================
  Files          2641       20     -2621     
  Lines        328569     2837   -325732     
=============================================
- Hits         286597     2020   -284577     
+ Misses        41972      817    -41155     
Components Coverage Δ
dpp ∅ <ø> (∅)
drive ∅ <ø> (∅)
drive-abci ∅ <ø> (∅)
sdk ∅ <ø> (∅)
dapi-client ∅ <ø> (∅)
platform-version ∅ <ø> (∅)
platform-value ∅ <ø> (∅)
platform-wallet ∅ <ø> (∅)
drive-proof-verifier ∅ <ø> (∅)
🚀 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.

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