-
Notifications
You must be signed in to change notification settings - Fork 45
fix(wasm-sdk): enable identity_update to add ECDSA_SECP256K1 and BLS12_381 keys #2947
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix(wasm-sdk): enable identity_update to add ECDSA_SECP256K1 and BLS12_381 keys #2947
Conversation
📝 WalkthroughWalkthroughIntroduces helper parser functions for key type, purpose, and security level, along with a comprehensive Changes
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested reviewers
Poem
Pre-merge checks and finishing touches✅ Passed checks (3 passed)
✨ Finishing touches
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. Comment |
…2_381 keys Previously, identity_update failed when adding ECDSA_SECP256K1 or BLS12_381 keys with signature verification errors. The root cause was that these key types require self-signing (is_unique_key_type() == true), but identity_update used SingleKeySigner which only held the master key. Changes: - Switch from SingleKeySigner to SimpleSigner in identity_update - Add master key to signer for state transition signing - Extract parse_keys_for_identity_update helper function for key parsing - Accept privateKeyHex/privateKeyWif for signing key types (ECDSA_SECP256K1, BLS12_381) and derive public keys from private keys - Add new signing keys to SimpleSigner so they can sign for themselves - Maintain backward compatibility: ECDSA_HASH160 still accepts data field API changes for add_public_keys parameter: - ECDSA_SECP256K1: requires privateKeyHex or privateKeyWif (was: data) - BLS12_381: requires privateKeyHex (was: data) - ECDSA_HASH160: accepts privateKeyHex or data (backward compatible) - BIP13_SCRIPT_HASH, EDDSA_25519_HASH160: unchanged (data field) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
5debb12 to
c455ee6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 0
🧹 Nitpick comments (2)
packages/wasm-sdk/src/state_transitions/identity/mod.rs (2)
54-64: Consider error handling for invalid security level values.Unlike
parse_key_typeandparse_purposewhich error on unknown values,parse_security_levelsilently defaults toHIGHfor any unrecognized string. While the docstring documents this behavior, a typo like"HGIH"would silently be accepted asHIGH, potentially masking configuration errors.Consider returning a
Resultlike the other parsers, or at least logging a warning for non-Noneunrecognized values:🔎 Potential alternative approach
-fn parse_security_level(s: Option<&str>) -> SecurityLevel { +fn parse_security_level(s: Option<&str>) -> Result<SecurityLevel, WasmSdkError> { match s { - Some("MASTER") => SecurityLevel::MASTER, - Some("CRITICAL") => SecurityLevel::CRITICAL, - Some("HIGH") => SecurityLevel::HIGH, - Some("MEDIUM") => SecurityLevel::MEDIUM, - _ => SecurityLevel::HIGH, + Some("MASTER") => Ok(SecurityLevel::MASTER), + Some("CRITICAL") => Ok(SecurityLevel::CRITICAL), + Some("HIGH") => Ok(SecurityLevel::HIGH), + Some("MEDIUM") => Ok(SecurityLevel::MEDIUM), + None => Ok(SecurityLevel::HIGH), // Default when not specified + Some(s) => Err(WasmSdkError::invalid_argument(format!( + "Unknown security level: {}", + s + ))), } }
396-561: Consider reusingparse_keys_for_identity_updateto reduce duplication.The key parsing logic in
identity_create(lines 396-561) largely duplicates what's now inparse_keys_for_identity_update. While there are minor differences (e.g.,BTreeMapvsVec, different unsupported key type handling), consolidating this logic could improve maintainability.If the behaviors need to differ, consider extracting a lower-level helper that both functions can call with configuration flags.
📜 Review details
Configuration used: defaults
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
packages/wasm-sdk/src/state_transitions/identity/mod.rs
🧰 Additional context used
📓 Path-based instructions (1)
**/*.rs
📄 CodeRabbit inference engine (CLAUDE.md)
**/*.rs: Rust code must passcargo clippy --workspacelinter checks
Rust code must be formatted usingcargo fmt --all
**/*.rs: Use 4-space indent for Rust files
Follow rustfmt defaults and keep code clippy-clean for Rust modules
Use snake_case for Rust module names
Use PascalCase for Rust type names
Use SCREAMING_SNAKE_CASE for Rust constants
Files:
packages/wasm-sdk/src/state_transitions/identity/mod.rs
🧠 Learnings (10)
📓 Common learnings
Learnt from: QuantumExplorer
Repo: dashpay/platform PR: 2673
File: packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_update/mod.rs:1164-1197
Timestamp: 2025-06-18T03:44:14.385Z
Learning: QuantumExplorer determined that a CodeRabbit suggestion about fixing signable_bytes calculation in identity update tests with contract-bound keys was incorrect - the code flow is working as intended without the suggested changes.
📚 Learning: 2025-08-05T13:55:39.147Z
Learnt from: thephez
Repo: dashpay/platform PR: 2718
File: packages/wasm-sdk/index.html:0-0
Timestamp: 2025-08-05T13:55:39.147Z
Learning: The get_identity_keys_with_proof_info function in the Rust WASM bindings does not support the "search" key request type and lacks the searchPurposeMap parameter. When proof mode is enabled with keyRequestType === 'search', the implementation falls back to the non-proof version (get_identity_keys) to maintain functionality.
Applied to files:
packages/wasm-sdk/src/state_transitions/identity/mod.rs
📚 Learning: 2024-10-09T00:22:57.778Z
Learnt from: QuantumExplorer
Repo: dashpay/platform PR: 2215
File: packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/create_owner_identity/v1/mod.rs:19-30
Timestamp: 2024-10-09T00:22:57.778Z
Learning: In the Rust file `packages/rs-drive-abci/src/execution/platform_events/core_based_updates/update_masternode_identities/create_owner_identity/v1/mod.rs`, within the `create_owner_identity_v1` function, the `add_public_keys` method of the `Identity` struct cannot fail and does not require explicit error handling.
Applied to files:
packages/wasm-sdk/src/state_transitions/identity/mod.rs
📚 Learning: 2025-07-28T20:00:08.502Z
Learnt from: QuantumExplorer
Repo: dashpay/platform PR: 2711
File: packages/wasm-sdk/AI_REFERENCE.md:771-783
Timestamp: 2025-07-28T20:00:08.502Z
Learning: In packages/wasm-sdk/AI_REFERENCE.md, the documentation correctly shows the actual SDK method signatures (including identityCreate and identityTopUp with their full parameter lists), which may differ from the UI inputs shown in fixed_definitions.json. The UI may collect fewer parameters from users while handling additional requirements internally.
Applied to files:
packages/wasm-sdk/src/state_transitions/identity/mod.rs
📚 Learning: 2024-11-20T20:43:41.185Z
Learnt from: QuantumExplorer
Repo: dashpay/platform PR: 2257
File: packages/rs-drive-abci/tests/strategy_tests/masternodes.rs:212-220
Timestamp: 2024-11-20T20:43:41.185Z
Learning: In `packages/rs-drive-abci/tests/strategy_tests/masternodes.rs`, the pattern of generating a `PrivateKey`, converting it to bytes, and reconstructing a `BlsPrivateKey` from those bytes is intentional. Avoid suggesting to simplify this code in future reviews.
Applied to files:
packages/wasm-sdk/src/state_transitions/identity/mod.rs
📚 Learning: 2025-11-25T13:10:38.019Z
Learnt from: CR
Repo: dashpay/platform PR: 0
File: packages/swift-sdk/SwiftExampleApp/CLAUDE.md:0-0
Timestamp: 2025-11-25T13:10:38.019Z
Learning: Applies to packages/swift-sdk/SwiftExampleApp/**/{KeychainManager,*Key,*Identity}.swift : Store private keys separately from identities using iOS Keychain for secure storage; private keys belong to public keys, not identities
Applied to files:
packages/wasm-sdk/src/state_transitions/identity/mod.rs
📚 Learning: 2025-06-18T03:44:14.385Z
Learnt from: QuantumExplorer
Repo: dashpay/platform PR: 2673
File: packages/rs-drive-abci/src/execution/validation/state_transition/state_transitions/identity_update/mod.rs:1164-1197
Timestamp: 2025-06-18T03:44:14.385Z
Learning: QuantumExplorer determined that a CodeRabbit suggestion about fixing signable_bytes calculation in identity update tests with contract-bound keys was incorrect - the code flow is working as intended without the suggested changes.
Applied to files:
packages/wasm-sdk/src/state_transitions/identity/mod.rs
📚 Learning: 2024-10-21T01:03:42.458Z
Learnt from: QuantumExplorer
Repo: dashpay/platform PR: 2227
File: packages/rs-dpp/src/core_types/validator_set/v0/mod.rs:299-299
Timestamp: 2024-10-21T01:03:42.458Z
Learning: In the `test_serialize_deserialize_validator_set_v0` test within `packages/rs-dpp/src/core_types/validator_set/v0/mod.rs`, deterministic BLS keys cannot be easily used; therefore, using `BlsPublicKey::generate()` is acceptable.
Applied to files:
packages/wasm-sdk/src/state_transitions/identity/mod.rs
📚 Learning: 2024-11-20T16:05:40.200Z
Learnt from: QuantumExplorer
Repo: dashpay/platform PR: 2257
File: packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/for_saving.rs:148-151
Timestamp: 2024-11-20T16:05:40.200Z
Learning: In `packages/rs-drive-abci/src/platform_types/signature_verification_quorum_set/v0/for_saving.rs`, when converting public keys from `QuorumForSavingV0` to `VerificationQuorum`, it's acceptable to use `.expect()` for public key conversion, as the conversion has been verified and panics are acceptable in this context.
Applied to files:
packages/wasm-sdk/src/state_transitions/identity/mod.rs
📚 Learning: 2024-10-30T11:19:59.163Z
Learnt from: lklimek
Repo: dashpay/platform PR: 2277
File: packages/rs-sdk/tests/fetch/config.rs:233-233
Timestamp: 2024-10-30T11:19:59.163Z
Learning: In the Rust SDK's `rs-sdk/tests` integration tests (e.g., in `packages/rs-sdk/tests/fetch/config.rs`), we cannot create objects during tests because there is no support for object creation in this context. Therefore, hardcoded values for test identities must be used.
Applied to files:
packages/wasm-sdk/src/state_transitions/identity/mod.rs
🧬 Code graph analysis (1)
packages/wasm-sdk/src/state_transitions/identity/mod.rs (3)
packages/wasm-sdk/src/error.rs (2)
invalid_argument(75-77)generic(71-73)packages/wasm-sdk/src/queries/identity.rs (3)
new(94-96)new(125-127)keys(107-113)packages/simple-signer/src/signer.rs (1)
private_keys(39-43)
🪛 Gitleaks (8.30.0)
packages/wasm-sdk/src/state_transitions/identity/mod.rs
[high] 1936-1936: Detected a Generic API Key, potentially exposing access to various services and sensitive operations.
(generic-api-key)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (7)
- GitHub Check: Rust packages (wasm-sdk) / Linting
- GitHub Check: Rust packages (wasm-sdk) / Tests
- GitHub Check: Build Docker images (Dashmate helper, dashmate-helper, dashmate-helper) / Build Dashmate helper image
- GitHub Check: Build Docker images (Drive, drive, drive-abci, SDK_TEST_DATA=true
) / Build Drive image - GitHub Check: Build Docker images (RS-DAPI, rs-dapi, rs-dapi) / Build RS-DAPI image
- GitHub Check: Build JS packages / Build JS
- GitHub Check: Rust crates security audit
🔇 Additional comments (3)
packages/wasm-sdk/src/state_transitions/identity/mod.rs (3)
89-288: LGTM!The
parse_keys_for_identity_updatefunction is well-structured with comprehensive key type handling. The approach of usingOption<[u8; 32]>to track whether keys need signing (matchingis_unique_key_type()semantics) is clean, and error messages are specific and helpful for debugging.
1248-1263: LGTM - Core fix for identity_update with non-HASH160 keys.The switch from
SingleKeySignertoSimpleSignerwith both the master key and new signing keys correctly addresses the root cause. NewECDSA_SECP256K1andBLS12_381keys can now self-sign as required by DPP validation (is_unique_key_type() == true).
1817-2092: Excellent test coverage for the new parser.The tests comprehensively cover the key parsing scenarios including:
- Both
privateKeyHexandprivateKeyWifformats for ECDSA_SECP256K1- WIF rejection for BLS12_381
- Signer population verification (signing keys added, non-signing keys not added)
- Error cases (missing keys, invalid formats, wrong lengths)
- Mixed key sets and edge cases
The static analysis hint on line 1936 is a false positive - the WIF
cNurmMT7bXe3S92JijPi2V5wSHvWzrk4vKJ7fgLPNo5Ajv2YAP3zis an intentional test key used to verify BLS12_381 correctly rejects WIF format.
Issue being fixed or feature implemented
Previously, identity_update failed when adding non HASH_160 keys with signature verification errors. The root cause was that these key types require self-signing (is_unique_key_type() == true), but identity_update used SingleKeySigner which only held the master key.
What was done?
Changes:
API changes for add_public_keys parameter:
How Has This Been Tested?
Added 12 unit tests for the parse_keys_for_identity_update helper function:
Tests cover:
Tests verify both the returned keys and that the SimpleSigner is correctly populated (signing keys added, non-signing keys excluded).
Breaking Changes
None. The previous behavior for adding ECDSA_SECP256K1 and BLS12_381 keys via identity_update was non-functional (always failed signature verification). This fix makes these key types work by requiring private keys for signing.
Checklist:
For repository code-owners and collaborators only
Summary by CodeRabbit
New Features
Refactor
Tests
✏️ Tip: You can customize this high-level summary in your review settings.