Skip to content

feat(crypto): add native secp256k1 support - #52

Open
Federico2014 wants to merge 4 commits into
developfrom
feature/configurable_secp256k1_jna
Open

feat(crypto): add native secp256k1 support#52
Federico2014 wants to merge 4 commits into
developfrom
feature/configurable_secp256k1_jna

Conversation

@Federico2014

@Federico2014 Federico2014 commented Aug 6, 2026

Copy link
Copy Markdown
Owner

What does this PR do?

Add an optional JNA-backed NativeSecp256k1 implementation for secp256k1 key construction, deterministic signing, public-key recovery, and address recovery.

Native signing accepts unsigned private-key encodings from 1 to 32 bytes, as well as valid 33-byte Java BigInteger encodings with a leading sign byte. Private keys are validated against the secp256k1 range [1, n - 1] and normalized to the native API's required 32-byte big-endian representation. Temporary private-key buffers are cleared after use without modifying caller-owned input arrays.

Add the crypto.useNativeSecp256k1 configuration option and route ECKey public-key/address recovery used during signature verification through the native implementation when explicitly enabled. PBFT signature recovery now uses the shared SignUtils routing path.

Preserve ECKey recovery compatibility when native verification is enabled:

  • Accept and normalize the legacy recovery-header range v = 27..34.
  • Use native recovery only when 1 <= r, s < n; route other legacy scalar combinations directly to ECKey.
  • Fall back to ECKey when native signature parsing or public-key recovery fails, preserving legacy recovery behavior, including historical point-at-infinity outcomes.
  • Reject invalid recovery headers and oversized signature components without truncation.
  • Continue accepting Base64 signatures with trailing bytes, matching existing ECKey behavior.

If native secp256k1 is requested but unavailable, startup now falls back to ECKey instead of terminating. A WARN records the fallback, and startup INFO reports engine, nativeRequested, nativeActive, and the effective implementation. The runtime useNativeSecp256k1 value reflects the implementation that is actually active.

Add native/ECKey cross-compatibility tests, scalar and recovery-header boundary tests, configuration and logging tests, dependency verification metadata, and an opt-in signing and recovery benchmark.

Why are these changes required?

The existing pure-Java ECKey implementation has significantly higher signing and signature-recovery overhead. Native libsecp256k1 provides a faster implementation while preserving the existing signature format, recovery-ID handling, canonical low-S behavior, recovered TRON addresses, and historical recovery outcomes.

Native acceleration is optional. A missing or unsupported native library should reduce performance rather than prevent a node from starting. Explicit fallback logging and effective-state reporting make this behavior observable to operators.

The feature is disabled by default, so existing nodes retain the original Java implementation unless explicitly configured otherwise.

This PR has been tested by:

  • NativeSecp256k1Test
  • ArgsTest
  • :framework:checkstyleMain
  • :framework:checkstyleTest
  • Manual benchmark

The native and Java implementations were cross-tested with deterministic signatures, bidirectional signature recovery, constructor compatibility, high-S signatures, malformed input, scalar boundaries 0, 1, n - 1, n, and n + 1, recovery headers 27..34, point-at-infinity compatibility, unavailable-native fallback, and configuration routing.

The native signing tests also cover short private-key encodings, 33-byte Java BigInteger sign-padded encodings, invalid private-key ranges, and preservation of caller-owned private-key arrays.

A local 10,000-iteration benchmark measured approximately 36.11x faster signing and 17.45x faster signature-address recovery on an x86_64 Java 8 environment (ECKey: 1,404,666 vs NativeSecp256k1: 38,895 ns/op for signing; 894,673 vs 51,259 ns/op for recovery).

CI validation covers x86_64/JDK 8 and aarch64/JDK 17 build environments.

Follow up

None.

Extra details

The new configuration defaults to false and is effective only when crypto.engine = "eckey". SM2 behavior is unchanged. If the native library is unavailable, configured signature recovery and verification remain on ECKey.

This change adds JNA 5.12.1 and io.github.federico2014:secp256k1:1.3.12, including Gradle dependency verification metadata.

Summary by CodeRabbit

  • New Features

    • Added optional native secp256k1 support for faster cryptographic signing and signature verification.
    • Added configuration to enable native processing, while retaining the existing implementation by default.
    • Native support automatically falls back when unavailable and applies only to compatible elliptic-curve operations.
    • Improved signature recovery compatibility for PBFT validation.
  • Tests

    • Added coverage for configuration, fallback behavior, signing, recovery, edge cases, and performance comparisons.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: b3a3bc93-c551-4491-9e24-3c4448b1c31b

📥 Commits

Reviewing files that changed from the base of the PR and between efb3768 and de4c91a.

📒 Files selected for processing (3)
  • crypto/src/main/java/org/tron/common/crypto/NativeSecp256k1.java
  • framework/src/test/java/org/tron/common/crypto/ECKeyTest.java
  • framework/src/test/java/org/tron/common/crypto/NativeSecp256k1Test.java
🚧 Files skipped from review as they are similar to previous changes (2)
  • framework/src/test/java/org/tron/common/crypto/NativeSecp256k1Test.java
  • crypto/src/main/java/org/tron/common/crypto/NativeSecp256k1.java

📝 Walkthrough

Walkthrough

The PR adds configurable JNA-backed secp256k1 signing and recovery. It routes EC-key verification through the selected backend, updates PBFT signature handling, and adds configuration, compatibility, validation, and benchmark tests.

Changes

Native secp256k1 integration

Layer / File(s) Summary
Configuration contract
common/src/main/java/org/tron/common/parameter/CommonParameter.java, common/src/main/java/org/tron/core/config/args/MiscConfig.java, common/src/main/resources/reference.conf, framework/src/main/resources/config.conf, common/src/test/java/org/tron/core/config/args/MiscConfigTest.java, framework/src/test/java/org/tron/common/ParameterTest.java
Adds crypto.useNativeSecp256k1, disabled by default, with parsing and accessor tests.
Native secp256k1 backend
crypto/src/main/java/org/tron/common/crypto/NativeSecp256k1.java, crypto/build.gradle, gradle/verification-metadata.xml
Adds native key generation, signing, recovery, address derivation, validation, availability detection, and dependency verification metadata.
Runtime routing and PBFT use
crypto/src/main/java/org/tron/common/crypto/SignUtils.java, framework/src/main/java/org/tron/core/config/args/Args.java, consensus/src/main/java/org/tron/consensus/pbft/message/PbftBaseMessage.java, framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java
Configures native verification for the EC-key engine, resets the mode during cleanup, and routes PBFT recovery through SignUtils.
Cryptographic validation and benchmarking
framework/src/test/java/org/tron/common/crypto/NativeSecp256k1Test.java, framework/src/test/java/org/tron/common/crypto/NativeSecp256k1BenchmarkTest.java, framework/src/test/java/org/tron/core/config/args/ArgsTest.java, framework/src/test/java/org/tron/common/crypto/ECKeyTest.java
Tests Java/native parity, invalid inputs, recovery boundaries, fallback behavior, engine selection, logging, formatting, and opt-in performance measurements.

Estimated code review effort: 4 (Complex) | ~45 minutes

Mergeability Score: ⚪ Minimal · up to de4c9

This PR adds opt-in native secp256k1 support with fallback behavior while preserving existing defaults; no actionable merge-blocking risk remains in the supplied evidence.

Possibly related issues

Possibly related PRs

  • Federico2014/java-tron#46 — Modifies ECKey-based secp256k1 key handling and validation used by the native implementation.

Sequence Diagram(s)

sequenceDiagram
  participant PBFTHandler
  participant SignUtils
  participant NativeSecp256k1
  participant ECKey
  PBFTHandler->>SignUtils: Recover signer address
  alt Native EC-key verification enabled
    SignUtils->>NativeSecp256k1: Recover public key and address
    NativeSecp256k1-->>SignUtils: Return address
  else Native verification disabled
    SignUtils->>ECKey: Recover public key and address
    ECKey-->>SignUtils: Return address
  end
  SignUtils-->>PBFTHandler: Return signer address
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 13.16% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the pull request's primary change: adding optional native secp256k1 support.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/configurable_secp256k1_jna

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 (1)
consensus/src/main/java/org/tron/consensus/pbft/message/PbftBaseMessage.java (1)

99-100: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Document the hardcoded engine flag.

The literal true selects the EC-key crypto engine. It preserves the previous ECKey.signatureToAddress behavior, so PBFT recovery stays on EC-key even when the node runs the SM2 engine. That intent is not visible at the call site.

Add a short comment, or extract a named constant such as PBFT_USES_ECKEY_ENGINE. The same literal appears in framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java at lines 176 to 177.

🤖 Prompt for 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.

In `@consensus/src/main/java/org/tron/consensus/pbft/message/PbftBaseMessage.java`
around lines 99 - 100, The hardcoded crypto-engine flag in PbftBaseMessage
signature recovery is undocumented. Add a short comment or reuse a clearly named
constant such as PBFT_USES_ECKEY_ENGINE at the SignUtils.signatureToAddress
call, and apply the same documentation or constant usage to the corresponding
call in PbftDataSyncHandler so the intentional EC-key behavior remains explicit.
🤖 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 `@crypto/build.gradle`:
- Line 16: Update the secp256k1 dependency declaration in the crypto Gradle
configuration: either replace
com.github.federico2014.besu-native:secp256k1:1.3.11 with the official upstream
coordinate, or document the fork’s necessity and build provenance, including who
reviewed it, while preserving the verification metadata alignment.

---

Nitpick comments:
In
`@consensus/src/main/java/org/tron/consensus/pbft/message/PbftBaseMessage.java`:
- Around line 99-100: The hardcoded crypto-engine flag in PbftBaseMessage
signature recovery is undocumented. Add a short comment or reuse a clearly named
constant such as PBFT_USES_ECKEY_ENGINE at the SignUtils.signatureToAddress
call, and apply the same documentation or constant usage to the corresponding
call in PbftDataSyncHandler so the intentional EC-key behavior remains explicit.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 26652c53-d3cf-4f18-b34a-210fb360adea

📥 Commits

Reviewing files that changed from the base of the PR and between f87081b and 780fcc6.

📒 Files selected for processing (16)
  • common/src/main/java/org/tron/common/parameter/CommonParameter.java
  • common/src/main/java/org/tron/core/config/args/MiscConfig.java
  • common/src/main/resources/reference.conf
  • common/src/test/java/org/tron/core/config/args/MiscConfigTest.java
  • consensus/src/main/java/org/tron/consensus/pbft/message/PbftBaseMessage.java
  • crypto/build.gradle
  • crypto/src/main/java/org/tron/common/crypto/NativeSecp256k1.java
  • crypto/src/main/java/org/tron/common/crypto/SignUtils.java
  • framework/src/main/java/org/tron/core/config/args/Args.java
  • framework/src/main/java/org/tron/core/net/messagehandler/PbftDataSyncHandler.java
  • framework/src/main/resources/config.conf
  • framework/src/test/java/org/tron/common/ParameterTest.java
  • framework/src/test/java/org/tron/common/crypto/NativeSecp256k1BenchmarkTest.java
  • framework/src/test/java/org/tron/common/crypto/NativeSecp256k1Test.java
  • framework/src/test/java/org/tron/core/config/args/ArgsTest.java
  • gradle/verification-metadata.xml

Comment thread crypto/build.gradle Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All reported issues were addressed across 16 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread framework/src/test/java/org/tron/core/config/args/ArgsTest.java Outdated
Comment thread crypto/src/main/java/org/tron/common/crypto/NativeSecp256k1.java
Comment thread framework/src/main/java/org/tron/core/config/args/Args.java Outdated
Comment thread crypto/build.gradle Outdated
Comment thread framework/src/test/java/org/tron/common/crypto/NativeSecp256k1BenchmarkTest.java Outdated
@Federico2014 Federico2014 linked an issue Aug 7, 2026 that may be closed by this pull request
@Federico2014
Federico2014 force-pushed the feature/configurable_secp256k1_jna branch from 780fcc6 to f9bd0f3 Compare August 7, 2026 08:31
@Federico2014
Federico2014 force-pushed the feature/configurable_secp256k1_jna branch from b2bfe99 to 174b6a0 Compare August 7, 2026 09:25
coderabbitai[bot]

This comment was marked as resolved.

@Federico2014
Federico2014 force-pushed the feature/configurable_secp256k1_jna branch from 9e4363e to efb3768 Compare August 11, 2026 10:36
coderabbitai[bot]

This comment was marked as resolved.

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.

[Feature] Optimize secp256k1 signature performance

1 participant