Uh oh!
There was an error while loading. Please reload this page.
chore(swift-sdk): remove Account.derivePrivateKeyWIF - #4339
Conversation
Warning Review limit reached
Next review available in:25 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (1)
📝 WalkthroughWalkthroughThe Swift ChangesAccount API cleanup
Estimated code review effort: 1 (Trivial) | ~5 minutes Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
🕓 Ready for review — 2 ahead in queue (commit 0556874) |
There was a problem hiding this comment.
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/swift-sdk/Sources/SwiftDashSDK/KeyWallet/Account.swift`:
- Around line 6-8: Update the documentation comment for Account to describe that
it deliberately exposes no account-specific public operations, while retaining
the explanation of getAccount(type:) and handle cleanup. Do not state that
Account has no members, since it stores private state such as the FFI handle and
wallet.
🪄 Autofix
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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 143ef858-41f0-4534-ae6b-a6232143d9be
📒 Files selected for processing (1)
packages/swift-sdk/Sources/SwiftDashSDK/KeyWallet/Account.swift
Uh oh!
There was an error while loading. Please reload this page.
Unused after #4338 moved the secp256k1 provider families onto `providerKeyAtIndex`: no caller remains in platform (including the example app) or in dashwallet-ios. Removed rather than fixed. It applied the account derivation path twice — it asked callers for the account root while the FFI applies the account's own path itself — so every owner/voting key came from `m/9'/5'/3'/1'/9'/5'/3'/1'/index`. Nothing failed locally, because the keys were well-formed and deterministic; it surfaced only as Platform rejecting masternode votes as having no voter identity. Correcting it would have left the last of the parallel derivation path #4338 exists to consolidate, and kept the variant WITHOUT the seed-vs-xpub cross-check, watch-only support, or address that `providerKeyAtIndex` provides. Its ambiguity was the bug — called on an account, taking a wallet, the relationship between the account's own path and the passed key implicit — so even corrected, the next reader has to re-derive why "m" is right. Deleting removes the question. Callers wanting key material use `providerKeyAtIndex` (provider families, DIP-3 path resolved Rust-side and cross-checked) or `Wallet.derivePrivateKey(path:)` (explicit full path, no implicit path to apply twice). `Account`'s doc now says this, and describes what the type actually is: a handle whose lifetime `Wallet.getAccount(type:)` uses to report that an account exists. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
0556874 to
ae0c34fCompareUh oh!
There was an error while loading. Please reload this page.
Replaces #4334, which fixed this function. Deleting it is better now that nothing calls it.
Why it's unused
#4338 moves the secp256k1 provider families (masternode owner / voting keys) onto
providerKeyAtIndex. After it,Account.derivePrivateKeyWIFhas zero callers — in platform (including the example app) and in dashwallet-ios.Why delete rather than fix
It applied the account derivation path twice: it asked callers for the account root path, while
account_derive_private_key_as_wif_at→derive_xpriv_from_master_xprivresolvesAccount::derivation_path()itself. So every owner/voting key came fromNothing failed locally — the keys were well-formed and deterministic, and round-tripped through WIF parsing and signing without complaint. It surfaced only as Platform rejecting masternode votes as having no voter identity, because the voter identity is derived from the signing key's own hash160.
Fixing it (#4334) would have kept the last of the parallel derivation path #4338 exists to consolidate — and kept the variant without the seed-vs-xpub cross-check, watch-only support, or address that
providerKeyAtIndexprovides. The ambiguity was the bug: called on an account, taking a wallet, with the relationship between the account's own path and the passed key implicit. Even corrected, the next reader has to re-derive why"m"is right. Deleting removes the question instead of documenting the answer.Replacements
ManagedPlatformWallet.providerKeyAtIndex(kind:index:includePrivate:)— DIP-3 path resolved Rust-side, seed cross-checked against the account xpub, works for watch-onlyWallet.derivePrivateKey(path:)— full path in, key out; no implicit path to apply twiceAccount's doc now points at both, and describes what the type actually is: a handle whose lifetimeWallet.getAccount(type:)uses to report that an account exists (and create it as a side effect). That is its one remaining caller.Coverage
No regression. #4334's Swift tests pinned the DIP-3 paths, but #4338's Rust tests pin the same paths at the layer that derives them — plus the watch-only case the Swift tests never reached, which is what the app actually runs.
Testing
derivePrivateKeyWIFdefinition or call site remains in either repoDepends on #4338 landing first, since that removes the last caller.
🤖 Generated with Claude Code
Summary by CodeRabbit