Skip to content

Conversation

@thephez
Copy link
Collaborator

@thephez thephez commented Oct 28, 2025

Issue being fixed or feature implemented

Developers using the DPNS registration API were encountering a cryptic error message "Invalid public key security level MASTER" when the identity key parameter was not passed. This error only appeared after attempting to sign the state transition, making it difficult to understand what went wrong and how to fix it.

What was done?

Added comprehensive early validation and helpful error messages for DPNS name registration:

  • WASM SDK validation (packages/wasm-sdk/src/dpns.rs): Validate key purpose is AUTHENTICATION, security level is CRITICAL or HIGH (not MASTER), and private key matches the specified public key before attempting cryptographic operations
  • JS SDK validation (packages/js-evo-sdk/src/dpns/facade.ts): Add input validation for publicKeyId parameter with clear error messages and comprehensive JSDoc documentation
  • Test coverage (packages/js-evo-sdk/tests/unit/facades/dpns.spec.mjs): Add 6 test cases covering validation of omitted, undefined, null, negative, non-number, and valid publicKeyId values

Error messages now explain which requirement failed, list all suitable keys available in the identity, and provide specific guidance (e.g., "Use key 1 (CRITICAL) or 2 (HIGH), NOT 0 (MASTER)").

How Has This Been Tested?

  • Unit tests added for all validation scenarios (6 new test cases, all passing)

Breaking Changes

None. This is fully backwards compatible - it only adds validation and improves error messages.

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

Summary by CodeRabbit

  • New Features

    • Added DPNS name registration with input validation for publicKeyId and enhanced cryptographic key checks (purpose, security level, private key match) plus clearer error feedback.
  • Tests

    • Added unit tests covering registerName validation scenarios (missing/invalid publicKeyId and successful registration).

✏️ Tip: You can customize this high-level summary in your review settings.

@thephez
Copy link
Collaborator Author

thephez commented Oct 28, 2025

@coderabbitai review

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 28, 2025

📝 Walkthrough

Walkthrough

Adds a new public registerName method to the JS DPNS facade with TypeScript/JSDoc and runtime validation for publicKeyId. Adds WASM-side identity public key checks: purpose must be AUTHENTICATION, security level CRITICAL or HIGH, and the provided private key must match the public key before proceeding with DPNS registration.

Changes

Cohort / File(s) Summary
JS/TS DPNS facade & tests
packages/js-evo-sdk/src/dpns/facade.ts, packages/js-evo-sdk/tests/unit/facades/dpns.spec.mjs
Adds DpnsFacade.registerName(...) with JSDoc and runtime validation for publicKeyId (defined/non-null, non-negative number). Adds tests for missing/undefined/null/negative/non-numeric publicKeyId and a successful call asserting wasm invocation.
WASM DPNS validation
packages/wasm-sdk/src/dpns.rs
Adds identity public key validation during dpnsRegisterName: require key purpose == AUTHENTICATION; require security level ∈ {CRITICAL, HIGH} (collects guidance keys if not); verify private key matches public key via signer; return descriptive invalid-argument errors if checks fail.

Sequence Diagram

sequenceDiagram
    participant User as User Code
    participant JsFacade as JS Facade
    participant Wasm as WASM SDK
    participant KeyStore as Identity Key Store / Signer

    User->>JsFacade: registerName(label, identityId, publicKeyId, privateKeyWif, onPreorder?)
    activate JsFacade
    JsFacade->>JsFacade: Validate publicKeyId (defined, non-null, >= 0)
    alt publicKeyId invalid
        JsFacade-->>User: Throw validation error
    else publicKeyId valid
        JsFacade->>Wasm: dpnsRegisterName(label, identityId, publicKeyId, privateKeyWif, onPreorder)
        activate Wasm
        Wasm->>KeyStore: Get public key for (identityId, publicKeyId)
        activate KeyStore
        KeyStore-->>Wasm: publicKey (purpose, security_level, data)
        Wasm->>Wasm: Check purpose == AUTHENTICATION
        Wasm->>Wasm: Check security_level ∈ {CRITICAL, HIGH}
        Wasm->>KeyStore: signer.can_sign_with(publicKey, privateKeyWif)
        KeyStore-->>Wasm: can_sign (true/false)
        alt any validation fails
            Wasm-->>JsFacade: Return invalid-argument error (descriptive)
            JsFacade-->>User: Propagate error
        else all validations pass
            Wasm->>Wasm: Store callback & register DPNS name
            Wasm-->>JsFacade: Registration result
            JsFacade-->>User: Registration result
        end
        deactivate KeyStore
        deactivate Wasm
    end
    deactivate JsFacade
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I hop with keys and careful cheer,
I check the purpose, strength, and gear.
AUTH true, levels high and bright,
I sign the name and set it right.
A rabbit's stamp — small, swift delight.

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately describes the main change: adding validation and tests for the registerName publicKeyId parameter across WASM and JS SDKs.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/dpns-key-validation

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.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Oct 28, 2025

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@thephez thephez changed the title test: add validation tests for registerName publicKeyId parameter test: add validation/tests for registerName publicKeyId parameter Oct 28, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a 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/dpns.rs (1)

82-141: Validation logic is correct and provides excellent error messages.

The key validation properly enforces DPNS requirements (AUTHENTICATION purpose, CRITICAL/HIGH security levels) and provides helpful guidance by listing suitable alternative keys.

Consider these minor refinements for more idiomatic Rust:

Lines 107-118: Replace the if-else and string concatenation with a match expression and format! macro:

-                    let level_name = if k.security_level() == SecurityLevel::CRITICAL {
-                        "CRITICAL"
-                    } else {
-                        "HIGH"
-                    };
-                    Some(
-                        String::from("  Key ")
-                            + &key_id.to_string()
-                            + ": "
-                            + level_name
-                            + " security level",
-                    )
+                    let level_name = match k.security_level() {
+                        SecurityLevel::CRITICAL => "CRITICAL",
+                        SecurityLevel::HIGH => "HIGH",
+                        _ => return None,
+                    };
+                    Some(format!("  Key {}: {} security level", key_id, level_name))
packages/js-evo-sdk/src/dpns/facade.ts (1)

60-81: Solid input validation with helpful error messages.

The validation logic correctly handles the common error cases (undefined, null, non-number, negative) and provides clear guidance about which keys are suitable for DPNS registration. This addresses the PR objective of providing early validation before cryptographic operations.

For completeness, you could add validation for NaN and Infinity, though these are unlikely in practice:

-    if (typeof publicKeyId !== 'number' || publicKeyId < 0) {
+    if (typeof publicKeyId !== 'number' || !Number.isFinite(publicKeyId) || publicKeyId < 0) {
       throw new Error(`publicKeyId must be a non-negative number, got: ${publicKeyId}`);
     }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f49390f and 6674a04.

📒 Files selected for processing (3)
  • packages/js-evo-sdk/src/dpns/facade.ts (1 hunks)
  • packages/js-evo-sdk/tests/unit/facades/dpns.spec.mjs (1 hunks)
  • packages/wasm-sdk/src/dpns.rs (2 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
packages/**/tests/**

📄 CodeRabbit inference engine (AGENTS.md)

Place unit and integration tests alongside each package in packages//tests

Files:

  • packages/js-evo-sdk/tests/unit/facades/dpns.spec.mjs
**/*.rs

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.rs: Format Rust code with cargo fmt
Run Clippy linter for Rust code

Files:

  • packages/wasm-sdk/src/dpns.rs
packages/wasm-sdk/**

📄 CodeRabbit inference engine (CLAUDE.md)

Keep WASM SDK docs in sync (run generate_docs.py) when updating the WASM SDK

Files:

  • packages/wasm-sdk/src/dpns.rs
packages/**/**/*.{js,ts,jsx,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

packages/**/**/*.{js,ts,jsx,tsx}: Adhere to ESLint with Airbnb/TypeScript configs for JS/TS code
Use camelCase for JS/TS variables and functions
Use PascalCase for JS/TS classes
Prefer kebab-case filenames within JS packages

Files:

  • packages/js-evo-sdk/src/dpns/facade.ts
🔇 Additional comments (4)
packages/wasm-sdk/src/dpns.rs (2)

5-7: LGTM! Imports support the new validation logic.

The imported traits and enums are necessary for the key validation functionality added below.


143-155: Excellent security validation!

Verifying that the private key matches the public key via signer.can_sign_with before proceeding prevents cryptographic failures and provides clear error messages early in the flow. This directly addresses the PR objective of catching errors before attempting to sign state transitions.

packages/js-evo-sdk/tests/unit/facades/dpns.spec.mjs (1)

58-143: Excellent test coverage for publicKeyId validation!

The test suite comprehensively covers all edge cases:

  • Missing, undefined, and null values
  • Invalid types (string)
  • Invalid ranges (negative numbers)
  • Valid positive case

The error message assertions verify that users receive helpful guidance, directly supporting the PR objective of improving error messages for DPNS registration.

packages/js-evo-sdk/src/dpns/facade.ts (1)

36-59: Outstanding documentation with clear security guidance!

The JSDoc provides comprehensive guidance that will help developers avoid the cryptic error described in the PR objectives. The explicit warning about key security levels and the practical example make the API much more developer-friendly.

@thephez thephez marked this pull request as ready for review October 28, 2025 19:35
@thephez thephez changed the title test: add validation/tests for registerName publicKeyId parameter feat: add validation/tests for registerName publicKeyId parameter Oct 28, 2025
@thephez thephez changed the title feat: add validation/tests for registerName publicKeyId parameter feat(sdk): add validation/tests for registerName publicKeyId parameter Oct 30, 2025
async registerName(args: { label: string; identityId: string; publicKeyId: number; privateKeyWif: string; onPreorder?: Function }): Promise<any> {
const { label, identityId, publicKeyId, privateKeyWif, onPreorder } = args;

// Validate inputs
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How this is possible? Typing is not allow it. Oh, when you use it form JS, not TypeScript?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it was from JS. Just trying to make things easier for people like me that don't know what they're doing 🤪 You can close the PR if it is a bad approach.

@QuantumExplorer QuantumExplorer changed the base branch from master to v3.0-dev December 24, 2025 00:23
@QuantumExplorer
Copy link
Member

@shumkov what should be done here?

…election

Add comprehensive validation before signing DPNS registration state transitions to catch common errors early and provide clear, actionable error messages to developers. Fixes issue where users accidentally use MASTER key (ID 0) which is not allowed for DPNS registration, resulting in cryptic error messages only after signing attempt.
@thephez thephez force-pushed the feat/dpns-key-validation branch from 28f639a to 9e06d0d Compare December 24, 2025 16:05
@thephez
Copy link
Collaborator Author

thephez commented Dec 24, 2025

Rebased on latest v3.0-dev. Defer to @shumkov as to whether or not it makes sense to include.

@github-actions github-actions bot added this to the v3.0.0 milestone Dec 24, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (2)
packages/js-evo-sdk/tests/unit/facades/dpns.spec.mjs (2)

103-130: Consider testing additional edge cases.

The tests cover negative and non-number values, but could also test:

  • publicKeyId: 0 (MASTER key, which per the PR description should be rejected)
  • Float values like 1.5
  • Special values like NaN or Infinity

These would ensure the validation is comprehensive.


132-140: Consider verifying call arguments.

The positive test confirms dpnsRegisterName is called once but doesn't verify the arguments passed. Adding argument verification would strengthen the test.

🔎 Example enhancement
     it('should accept valid publicKeyId', async () => {
       await client.dpns.registerName({
         label: 'test',
         identityId: 'someId',
         publicKeyId: 1,
         privateKeyWif: 'someKey',
       });
       expect(wasmSdk.dpnsRegisterName).to.be.calledOnce();
+      expect(wasmSdk.dpnsRegisterName).to.be.calledWith(
+        'test',
+        'someId',
+        1,
+        'someKey',
+        null
+      );
     });
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6674a04 and 9e06d0d.

📒 Files selected for processing (2)
  • packages/js-evo-sdk/src/dpns/facade.ts
  • packages/js-evo-sdk/tests/unit/facades/dpns.spec.mjs
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/js-evo-sdk/src/dpns/facade.ts
🧰 Additional context used
🧠 Learnings (3)
📓 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.
Learnt from: QuantumExplorer
Repo: dashpay/platform PR: 2711
File: packages/wasm-sdk/docs.html:2359-2383
Timestamp: 2025-07-28T20:00:24.323Z
Learning: In packages/wasm-sdk/docs.html, QuantumExplorer confirmed that placeholder private keys in documentation examples are acceptable as they are not real keys, though field name accuracy for the SDK API should still be maintained.
📚 Learning: 2025-11-25T13:10:47.943Z
Learnt from: CR
Repo: dashpay/platform PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T13:10:47.943Z
Learning: Applies to **/tests/**/*.{js,jsx,ts,tsx,rs} : Name tests descriptively, starting with 'should …'

Applied to files:

  • packages/js-evo-sdk/tests/unit/facades/dpns.spec.mjs
📚 Learning: 2025-07-28T20:00:24.323Z
Learnt from: QuantumExplorer
Repo: dashpay/platform PR: 2711
File: packages/wasm-sdk/docs.html:2359-2383
Timestamp: 2025-07-28T20:00:24.323Z
Learning: In packages/wasm-sdk/docs.html, QuantumExplorer confirmed that placeholder private keys in documentation examples are acceptable as they are not real keys, though field name accuracy for the SDK API should still be maintained.

Applied to files:

  • packages/js-evo-sdk/tests/unit/facades/dpns.spec.mjs
🧬 Code graph analysis (1)
packages/js-evo-sdk/tests/unit/facades/dpns.spec.mjs (6)
packages/wasm-sdk/tests/functional/identities.spec.mjs (1)
  • client (9-9)
packages/js-evo-sdk/tests/unit/facades/group.spec.mjs (2)
  • client (6-6)
  • wasmSdk (5-5)
packages/js-evo-sdk/tests/unit/facades/identities.spec.mjs (5)
  • client (6-6)
  • wasmSdk (5-5)
  • wasmSdk (168-168)
  • wasmSdk (185-185)
  • wasmSdk (201-201)
packages/js-evo-sdk/tests/unit/facades/protocol.spec.mjs (2)
  • client (6-6)
  • wasmSdk (5-5)
packages/wasm-sdk/tests/functional/dpns.spec.mjs (1)
  • client (8-8)
packages/js-evo-sdk/tests/unit/facades/tokens.spec.mjs (2)
  • client (6-6)
  • wasmSdk (5-5)
⏰ 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) / Unused dependencies
  • GitHub Check: Rust packages (wasm-sdk) / Linting
  • GitHub Check: Rust packages (wasm-sdk) / Tests
  • GitHub Check: Build Docker images (RS-DAPI, rs-dapi, rs-dapi) / Build RS-DAPI image
  • GitHub Check: Build Docker images (Drive, drive, drive-abci) / Build Drive image
  • GitHub Check: Build JS packages / Build JS
  • GitHub Check: Rust crates security audit

Copy link
Contributor

@coderabbitai coderabbitai bot left a 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 (1)
packages/js-evo-sdk/tests/unit/facades/dpns.spec.mjs (1)

58-142: Comprehensive test coverage for publicKeyId validation.

The test suite thoroughly covers the JS-layer validation requirements:

  • Presence checks (omitted, undefined, null)
  • Type validation (non-number)
  • Range validation (negative)
  • Happy path (valid publicKeyId)

All test names follow the "should..." convention, error assertions are specific and helpful, and the structure is consistent throughout.

💡 Optional: Consider edge case tests

While the current coverage is solid, you might optionally add tests for:

  • publicKeyId: 0 to document that MASTER keys pass JS validation (and are rejected later by WASM with a better error)
  • Non-integer numbers like 1.5 to verify behavior with floats
  • Special values like NaN or Infinity

These are not critical since the current tests adequately cover the intended validation logic.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9e06d0d and ed2205f.

📒 Files selected for processing (1)
  • packages/js-evo-sdk/tests/unit/facades/dpns.spec.mjs
🧰 Additional context used
🧠 Learnings (5)
📓 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.
Learnt from: QuantumExplorer
Repo: dashpay/platform PR: 2711
File: packages/wasm-sdk/docs.html:2359-2383
Timestamp: 2025-07-28T20:00:24.323Z
Learning: In packages/wasm-sdk/docs.html, QuantumExplorer confirmed that placeholder private keys in documentation examples are acceptable as they are not real keys, though field name accuracy for the SDK API should still be maintained.
📚 Learning: 2024-12-03T05:47:30.524Z
Learnt from: shumkov
Repo: dashpay/platform PR: 2365
File: packages/dashmate/src/listr/tasks/ssl/zerossl/obtainZeroSSLCertificateTaskFactory.js:206-213
Timestamp: 2024-12-03T05:47:30.524Z
Learning: In `obtainZeroSSLCertificateTaskFactory.js`, when handling ZeroSSL API errors during domain verification, the error detail structure is consistent when an error occurs, so additional null checks on `e.details[ctx.externalIp]` may not be necessary.

Applied to files:

  • packages/js-evo-sdk/tests/unit/facades/dpns.spec.mjs
📚 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/js-evo-sdk/tests/unit/facades/dpns.spec.mjs
📚 Learning: 2025-07-28T20:00:24.323Z
Learnt from: QuantumExplorer
Repo: dashpay/platform PR: 2711
File: packages/wasm-sdk/docs.html:2359-2383
Timestamp: 2025-07-28T20:00:24.323Z
Learning: In packages/wasm-sdk/docs.html, QuantumExplorer confirmed that placeholder private keys in documentation examples are acceptable as they are not real keys, though field name accuracy for the SDK API should still be maintained.

Applied to files:

  • packages/js-evo-sdk/tests/unit/facades/dpns.spec.mjs
📚 Learning: 2025-11-25T13:10:47.943Z
Learnt from: CR
Repo: dashpay/platform PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-25T13:10:47.943Z
Learning: Applies to **/tests/**/*.{js,jsx,ts,tsx,rs} : Name tests descriptively, starting with 'should …'

Applied to files:

  • packages/js-evo-sdk/tests/unit/facades/dpns.spec.mjs
⏰ 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) / Unused dependencies
  • GitHub Check: Rust packages (wasm-sdk) / Linting
  • GitHub Check: Rust packages (wasm-sdk) / Tests
  • GitHub Check: Build Docker images (Drive, drive, drive-abci) / 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 (1)
packages/js-evo-sdk/tests/unit/facades/dpns.spec.mjs (1)

89-102: Past review feedback addressed.

The null publicKeyId test now includes both error message assertions ('publicKeyId is required' and 'CRITICAL or HIGH security level'), making it consistent with the omitted and undefined test cases. This resolves the previous review concern.

@dashpay dashpay deleted a comment from reneesweet82-maker Dec 24, 2025
@thephez
Copy link
Collaborator Author

thephez commented Dec 24, 2025

Test failure is unrelated to this PR. Also present on v3.0-dev (e.g. https://github.com/dashpay/platform/actions/runs/20488069314/job/58874775920).

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.

4 participants