Skip to content

Conversation

distractedm1nd
Copy link
Contributor

@distractedm1nd distractedm1nd commented Feb 17, 2025

This PR dramatically reduces cycle count and enables k256 for wasm architecture

Before (without p256 precompile):
telegram-cloud-photo-size-2-5287551452790778282-y

After adding p256 precompile:
telegram-cloud-photo-size-2-5305516923032824986-y

After moving to k256:
image

Summary by CodeRabbit

  • Chores

    • Updated cryptographic dependencies, replacing secp256k1 with k256 for enhanced security and maintainability.
  • Refactor

    • Streamlined key management and signature processing, ensuring uniform behavior in signing, verification, and serialization across all environments.

These improvements bolster the reliability and consistency of the cryptographic operations, providing a more robust security framework for users.

Copy link

vercel bot commented Feb 17, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

1 Skipped Deployment
Name Status Preview Comments Updated (UTC)
prism ⬜️ Ignored (Inspect) Visit Preview Feb 18, 2025 1:06pm

Copy link
Contributor

coderabbitai bot commented Feb 17, 2025

Walkthrough

This pull request replaces the use of the secp256k1 crate with the k256 crate for handling elliptic curve cryptography. The change spans multiple Cargo manifest files and source files to remove conditional compilation and update key generation, signing, and verification processes. In each affected module, dependency declarations, patches, and associated methods have been updated to align with the new cryptographic library.

Changes

File(s) Change Summary
Cargo.toml Removed secp256k1 dependency and patch; added k256 with version "0.13.4" and features ecdsa, serde; patch updated accordingly.
crates/keys/Cargo.toml Removed secp256k1 (including its feature) from dependencies for non-WASM targets; added k256 dependency.
crates/keys/src/algorithm.rs Removed the Secp256k1 enum variant and its parsing logic from the CryptoAlgorithm enum.
crates/keys/src/signatures.rs Eliminated conditional compilation for Secp256k1; updated serialization methods (to_bytes, to_der) and modified methods to use from_slice instead of from_compact.
crates/keys/src/signing_keys.rs Updated the Secp256k1 signing key to use k256’s implementation; changed instantiation from new to random and simplified the signing process.
crates/keys/src/tests.rs Replaced the import from secp256k1 with k256::ecdsa::SigningKey and updated the test key generation to use the random method.
crates/keys/src/verifying_keys.rs Modified the Secp256k1 verifying key to use k256::ecdsa::VerifyingKey; updated methods for byte and DER conversion, key construction from bytes/DER, and signature verification.

Sequence Diagram(s)

sequenceDiagram
    participant Client
    participant KeyManager as SigningKey Manager
    participant K256Signer as k256::ecdsa::SigningKey
    participant K256Verifier as k256::ecdsa::VerifyingKey

    Client->>KeyManager: Request new secp256k1 key
    KeyManager->>K256Signer: Generate key using random method
    K256Signer-->>KeyManager: Return generated key
    Client->>KeyManager: Submit message for signing
    KeyManager->>K256Signer: Call sign_digest(message)
    K256Signer-->>KeyManager: Return signature
    Client->>K256Verifier: Provide message and signature for verification
    K256Verifier->>Client: Execute verify_digest and return result
Loading

Possibly related PRs

Suggested reviewers

  • jns-ps
  • smuu

Poem

Oh, what a hop in our code today,
The old secp256k1 has hopped away.
Now, k256 leads with a sparkling byte,
Cryptography shines in the neon light.
I’m a rabbit, leaping through each line—coding magic divine! 🐇💻


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b5e5f36 and 51094a1.

📒 Files selected for processing (2)
  • crates/keys/src/tests.rs (1 hunks)
  • crates/keys/src/verifying_keys.rs (7 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • crates/keys/src/tests.rs
  • crates/keys/src/verifying_keys.rs
⏰ Context from checks skipped due to timeout of 90000ms (5)
  • GitHub Check: unused dependencies
  • GitHub Check: clippy
  • GitHub Check: unit-test
  • GitHub Check: build-and-push-image
  • GitHub Check: integration-test

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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)
crates/keys/src/signing_keys.rs (1)

3-5: Consider renaming the alias for clarity.
Renaming DigestSigner as P256DigestSigner might help avoid confusion, as "P256" typically refers to the secp256r1 (p256) curve rather than the secp256k1 (k256) curve.

Proposed rename:

-use k256::ecdsa::{
-    signature::DigestSigner as P256DigestSigner, Signature as Secp256k1Signature,
-    SigningKey as Secp256k1SigningKey,
+use k256::ecdsa::{
+    signature::DigestSigner as K256DigestSigner, Signature as Secp256k1Signature,
+    SigningKey as Secp256k1SigningKey,
crates/keys/src/verifying_keys.rs (1)

93-97: DER-based parsing for secp256k1.
Consistently using from_public_key_der() for secp256k1 ensures standard DER support. Validate that any older secp256k1 keys in non-DER form are migrated if necessary.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 2b38313 and acea240.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (8)
  • Cargo.toml (2 hunks)
  • crates/keys/Cargo.toml (1 hunks)
  • crates/keys/src/algorithm.rs (0 hunks)
  • crates/keys/src/signatures.rs (3 hunks)
  • crates/keys/src/signing_keys.rs (4 hunks)
  • crates/keys/src/tests.rs (2 hunks)
  • crates/keys/src/verifying_keys.rs (7 hunks)
  • crates/zk/sp1-script/Cargo.toml (1 hunks)
💤 Files with no reviewable changes (1)
  • crates/keys/src/algorithm.rs
🧰 Additional context used
🧠 Learnings (1)
crates/keys/src/verifying_keys.rs (1)
Learnt from: distractedm1nd
PR: deltadevsde/prism#150
File: crates/common/src/keys.rs:27-31
Timestamp: 2024-11-12T11:47:59.930Z
Learning: In the Rust codebase of `prism`, within the `VerifyingKey::as_bytes` method in `crates/common/src/keys.rs`, returning a `Vec<u8>` is necessary because the underlying key types (`Secp256k1VerifyingKey` and `Ed25519VerifyingKey`) provide their byte representations by value. Returning a `&[u8]` would involve borrowing from a temporary value, which is not feasible.
⏰ Context from checks skipped due to timeout of 90000ms (6)
  • GitHub Check: unused dependencies
  • GitHub Check: integration-test
  • GitHub Check: clippy
  • GitHub Check: unit-test
  • GitHub Check: build-and-push-image
  • GitHub Check: Analyze (javascript-typescript)
🔇 Additional comments (21)
crates/keys/src/signing_keys.rs (3)

7-7: LGTM for the p256 import.
The addition or modification to import p256 references for secp256r1 usage is consistent with the rest of the file.


40-40: Good switch to the random constructor.
Using Secp256k1SigningKey::random is the correct approach for k256-based key generation. Ensure integration tests cover this path for stable key generation.


93-95: Digest-based signing approach is valid.
Using sign_digest aligns well with the new library’s API. Just confirm all sign/verify codepaths consistently use a hashed message.

crates/keys/src/verifying_keys.rs (7)

11-11: Adoption of k256 verifying key.
Switching to Secp256k1VerifyingKey from the k256 crate is consistent with the new secp256k1 logic.


64-64: Confirm compression settings.
to_sec1_bytes() can yield either compressed or uncompressed format depending on the library’s defaults. Confirm that usage here is consistent with your overall format choice (compressed vs. uncompressed).


72-72: DER output for secp256k1 key.
Generating DER with to_public_key_der() is valid. Ensure all consumers can handle the resulting ASN.1 structure properly.

[approve]


83-83: Use of from_sec1_bytes.
This is correct for p256/k256 style SEC1-encoded public keys. Confirm the function is robust to both compressed and uncompressed forms if needed.


127-129: Digest verification for secp256k1.
Using verify_digest aligns well with the sign_digest approach. This symmetry avoids confusion in hashing steps.


190-190: Cloning verifying key.
Invoking sk.verifying_key() followed by .to_owned() is reasonable to decouple lifetimes. No issues here.


241-242: Fallback to k256 if p256 decoding fails.
Because a 33/65-byte key could theoretically parse as either p256 or k256, ensure that collisions are unlikely or handled. In rare edge cases, a valid point on both curves could pass here.

crates/keys/src/signatures.rs (4)

5-5: Switched to k256::ecdsa::Signature.
Adopting Secp256k1Signature from the k256 crate is proper, matching your key changes.


28-28: Check raw signature format.
sig.to_vec() returns the raw 64-byte R||S form. Verify this is the intended format for storage or transmission, as it differs from DER encoding.


36-36: DER serialization for secp256k1.
Confirm that sig.to_der() produces a valid ASN.1 structure recognized across the ecosystem.


47-47: Switched to from_slice for raw signature loading.
from_slice expects a 64-byte R||S signature. Ensure your external callers provide that format to avoid parsing errors.

crates/keys/src/tests.rs (2)

5-5: LGTM! Import updated to use k256.

The change from secp256k1 to k256 is correctly implemented.


143-143: LGTM! Key generation method updated.

The change from new() to random() aligns with k256's API.

crates/keys/Cargo.toml (1)

19-19: LGTM! Dependency updated to k256.

The change correctly adds k256 as a workspace dependency, ensuring consistent versioning across the crate.

crates/zk/sp1-script/Cargo.toml (1)

33-33:

❓ Verification inconclusive

Verify if secp256k1 patch is still needed.

Despite transitioning to k256, the secp256k1 patch is retained. This might be necessary for transitive dependencies, but it's worth verifying.


🏁 Script executed:

#!/bin/bash
# Check for remaining secp256k1 dependencies
cargo tree | grep secp256k1

Length of output: 125


Manual Verification Required: secp256k1 Patch Necessity

The previous automated check couldn’t verify the secp256k1 dependency due to the unavailability of the cargo command in the sandbox environment. Please use the above shell script (or a manual search) to check for any references to "secp256k1" in the repository. This will confirm whether the patch retained in crates/zk/sp1-script/Cargo.toml (line 33) is still needed for transitive dependency support despite transitioning to k256.

  • File to check: crates/zk/sp1-script/Cargo.toml (line 33)
  • Action Required: Verify that no transitive dependencies require secp256k1. If unused, consider removing the patch; otherwise, document why it remains necessary.

🏁 Script executed:

[run_scripts]
#!/bin/bash
# Search for all references to "secp256k1" across the repository to determine its usage.
rg "secp256k1"

Length of output: 2631


Attention: Verify if the secp256k1 Patch Remains Necessary

The repository still contains several references to secp256k1 (e.g., in tests and key verification logic). Although there's been a transition toward k256, the custom secp256k1 patch in crates/zk/sp1-script/Cargo.toml (line 33) might still be required to satisfy transitive dependencies or support legacy tests.

  • Files to Review:
    • crates/zk/sp1-script/Cargo.toml (line 33): Confirm if the patched secp256k1 is still referenced downstream.
    • crates/keys/src/verifying_keys.rs and crates/keys/src/signing_keys.rs: Check usage of secp256k1 functions.
    • Test files in crates/keys/src/tests.rs and crates/tree/src/tests.rs: Verify that secp256k1-related tests are still valid.
    • Other references (e.g., in justfile and crates/node_types/prover/src/prover/tests.rs): Ensure consistency with the current cryptographic strategy.

Please manually verify whether the secp256k1 patch is essential for supporting transitive dependencies or if the remaining usages can transition entirely to k256. If it’s no longer required, consider removing the patch along with any redundant tests; otherwise, document its necessity for future maintainability.

Cargo.toml (3)

107-107: LGTM! k256 dependency correctly configured.

The k256 dependency is added with the necessary features (ecdsa, serde) for the codebase.


158-158: LGTM! k256 patch consistently versioned.

The k256 patch is correctly configured and version-aligned with other elliptic curve patches.


1-1:

❓ Verification inconclusive

Verify performance improvements.

The PR claims significant performance improvements, particularly for WebAssembly. Consider adding benchmarks to quantify the improvements.


🌐 Web query:

What are the performance differences between secp256k1 and k256 implementations, particularly for WebAssembly?

💡 Result:

The performance differences between secp256k1 (C-based implementations) and k256 (pure Rust) in WebAssembly (WASM) contexts depend on several factors:

Key Performance Insights

  1. Native vs. WASM Performance

    • C-based libsecp256k1 (compiled to WASM):
      • Achieves ~10x faster performance compared to JavaScript implementations[2][5].
      • Remains ~3x slower than native Node.js bindings (e.g., secp256k1-node)[2].
    • Pure Rust k256 (compiled to WASM):
      • Benchmarks show it is significantly slower than C-based WASM implementations[9]. For example:
        • k256 signature verification is ~3x slower than libsecp256k1[4].
  2. WebAssembly Optimization Challenges

    • Compiler optimizations for WASM (e.g., via LLVM) are less effective compared to native builds[3].
    • Memory usage for WASM is ~2–5x higher than equivalent JavaScript code[3], impacting resource-constrained environments.

Practical Considerations

Factor secp256k1 (C/WASM) k256 (Rust/WASM)
Speed Faster due to optimized C code Slower due to pure Rust implementation[9]
Memory Usage Higher memory footprint[3][5] Lower overhead in Rust-native projects
Portability Requires WASM toolchain (Emscripten/LLVM)[5] No external dependencies; no_std support[6]
Security Audited C code Not independently audited[8]

Use-Case Recommendations

  • High-Performance Needs: Use C-based libsecp256k1 compiled to WASM for tasks like blockchain signing or encryption[2][5].
  • Rust Integration: Opt for k256 if portability and ease of integration in Rust projects outweigh raw speed[6][9].
  • Browser Environments: Both benefit from faster WASM parse/compile times compared to JavaScript[2][3], but performance varies across browsers (Firefox > Chrome > Edge)[3].

For example:

// Example: Using secp256k1-wasm in browsers
import { sign } from 'secp256k1-wasm';
const signature = sign(privateKey, message);

Future Outlook

  • WASM Performance Gains: As browser engines optimize WASM execution (e.g., JIT improvements), both implementations will see speedups[2][3].
  • Rust Tooling: Ongoing optimizations in k256 may narrow the gap with C-based solutions[9].

In summary, choose libsecp256k1 for speed-critical WASM applications and k256 for Rust-centric projects prioritizing simplicity over maximum performance[2][6][9].

Citations:


Performance Improvement Verification and Benchmarking Required

The PR claims significant performance improvements for WebAssembly. However, the current changes (e.g., in Cargo.toml with [workspace.package]) do not include quantitative data. Benchmarks are needed to substantiate the performance claims.

Based on recent findings:

  • C-based libsecp256k1 compiled to WASM shows notable speedups (up to a ~10x improvement over JavaScript, though still about 3x slower than native bindings) compared to the pure Rust k256, which is approximately 3x slower in signature verification.
  • Memory usage and compiler optimizations can also differ substantially between these implementations.

Action Items:

  • Add comprehensive benchmarks: Include tests, ideally using a benchmarking suite (e.g., criterion.rs), to measure and compare the actual performance improvements in your WASM environment.
  • Document observed metrics: Provide quantitative numbers to clearly demonstrate the claimed performance benefits over previous implementations.

@jns-ps jns-ps changed the title deps: moving from secp256k1 to k256 build: moving from secp256k1 to k256 Feb 18, 2025
@distractedm1nd distractedm1nd merged commit d064197 into main Feb 19, 2025
9 of 10 checks passed
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.

2 participants