Skip to content

feat(crypto): add proposal-gated ECDSA validation - #49

Open
Federico2014 wants to merge 4 commits into
developfrom
feature/strict-ecdsa-validation
Open

feat(crypto): add proposal-gated ECDSA validation#49
Federico2014 wants to merge 4 commits into
developfrom
feature/strict-ecdsa-validation

Conversation

@Federico2014

@Federico2014 Federico2014 commented Aug 5, 2026

Copy link
Copy Markdown
Owner

What does this PR do?

This PR adds proposal 99 (ALLOW_STRICT_ECDSA_VALIDATION), gated by java-tron block version VERSION_4_8_3, to activate strict recoverable secp256k1 ECDSA validation for transaction, block-witness, and TVM recovery paths.

Strict validation:

  • requires exactly 65-byte transaction and block signatures;
  • validates normalized recovery IDs and 1 <= r, s < n before curve work;
  • preserves valid high-S signatures and existing recovery-header conventions;
  • uses Bouncy Castle BigIntegers.modOddInverse for valid inverses;
  • rejects a recovered point at infinity before public-key encoding or address derivation; and
  • rejects null signatures and null r/s components at the public recovery boundary.

Existing public ECKey recovery overloads remain legacy-compatible and delegate with strict validation disabled; new overloads allow strict validation to be selected explicitly.

Fresh RPC and P2P transaction admission requires exactly 65-byte signatures independently of proposal activation. Relay handshake recovery is also always strict. Inbound block sanitization canonicalizes an overlong witness signature to a detached 65-byte copy, preventing the response object from retaining the oversized backing storage. Batch transaction verification validates all signature lengths before submitting any asynchronous verification task.

When proposal 99 becomes active, cached positive transaction-verification results are invalidated across pending, re-push, popped, and pushing queues. Cache reuse requires an explicitly verified capsule with matching signatures, and per-transaction synchronization prevents an in-flight legacy validation from restoring a stale positive result.

Why are these changes required?

Trailing signature bytes create non-canonical encodings and unnecessary network, memory, and storage costs without changing the recovered signer. Malformed components should also be rejected before expensive elliptic-curve work or asynchronous task submission.

A range-valid signature can recover the secp256k1 point at infinity. That value is not a valid public key, but the legacy path can encode it as {0x00} and derive a deterministic address from an empty public-key payload. Strict recovery rejects this result at the common recovery boundary.

Proposal-gated consensus rules preserve historical transaction, block, and VM behavior, while independent admission checks reject malformed fresh input early. Cache invalidation prevents a legacy verification result from bypassing the post-activation rules.

This PR has been tested by:

  • Unit tests:
    • ECKeyTest
    • ManagerSignaturePreValidationTest
    • SanitizeUnknownFieldsTest
    • targeted proposal, transaction, block, VM, relay, cache-transition, and P2P admission tests
  • Checkstyle:
    • ./gradlew :framework:checkstyleMain
    • ./gradlew :framework:checkstyleTest
  • Manual testing: Not performed.

Coverage includes activation boundaries, legacy and strict signature lengths, scalar and recovery-ID bounds, high-S compatibility, modular-inverse conformance, null components, point-at-infinity recovery, witness-signature sanitization, pre-submission length validation, VM behavior, and verification-cache transitions.

Follow up

Confirm the numeric fork version assigned to VERSION_4_8_3, complete the TIP review, and coordinate the release and proposal activation schedule before enabling proposal 99.

Extra details

Related TIP draft: Federico2014/tips#2

Compatibility:

  • The proposal defaults to disabled and requires no database migration.
  • Pre-activation transaction, block, and VM consensus behavior remains unchanged.
  • Existing ECKey public overloads retain legacy defaults.
  • Valid high-S signatures and recovery headers 27..34 remain supported.
  • Fresh transaction admission requires exactly 65 bytes regardless of proposal state.
  • PBFT message-signature validation and SM2 consensus recovery are unchanged.

Consensus upgrade: all block-producing and validating nodes must run a release containing this change before proposal 99 is activated.

Cross-module impact: crypto recovery, VM execution, chainbase state, proposal processing, admission validation, block sanitization, and transaction-cache lifecycle share one activation boundary and must be deployed together.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds fork-gated strict ECDSA validation. It stores activation state through a proposal, enforces 65-byte signatures and recovery bounds, applies strict checks to blocks and transactions, and invalidates cached verification states after activation.

Changes

Strict ECDSA validation

Layer / File(s) Summary
Activation contract and dynamic property
common/src/main/java/org/tron/core/config/Parameter.java, actuator/src/main/java/org/tron/core/utils/ProposalUtil.java, chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java, framework/src/main/java/org/tron/core/consensus/ProposalService.java, framework/src/main/java/org/tron/core/Wallet.java, framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java, framework/src/test/java/org/tron/core/services/ProposalServiceTest.java
Adds fork version VERSION_4_8_3, proposal type 99, proposal validation, dynamic-property storage, proposal processing, chain-parameter exposure, and activation tests.
Strict signature and recovery primitives
common/src/main/java/org/tron/core/Constant.java, crypto/src/main/java/org/tron/common/crypto/ECKey.java, crypto/src/main/java/org/tron/common/crypto/SignUtils.java, framework/src/test/java/org/tron/common/crypto/ECKeyTest.java
Requires exact 65-byte signatures in strict mode and validates recovery IDs, r, s, message hashes, and modular inversion. Existing permissive overloads remain available.
Block and transaction validation
chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java, chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java, framework/src/test/java/org/tron/core/capsule/BlockCapsuleTest.java, framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java, framework/src/test/java/org/tron/core/WalletMockTest.java, framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java
Passes the strict-validation setting through witness and transaction signature validation. Tests update padded-signature handling and invalid component rejection.
Verification cache invalidation
framework/src/main/java/org/tron/core/db/Manager.java, framework/src/test/java/org/tron/core/db/ManagerMockTest.java, framework/src/test/java/org/tron/core/db/ManagerTest.java
Revalidates unverified transactions and clears verification flags across pending, repush, popped, and pushing collections when strict validation activates.

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

Sequence Diagram(s)

sequenceDiagram
  participant ProposalService
  participant DynamicPropertiesStore
  participant Manager
  participant TransactionCapsule
  participant ECKey
  ProposalService->>DynamicPropertiesStore: save strict validation value
  Manager->>DynamicPropertiesStore: detect activation at maintenance boundary
  Manager->>TransactionCapsule: clear verified state
  TransactionCapsule->>ECKey: validate signatures in strict mode
  ECKey-->>TransactionCapsule: accept or reject recovered signature
Loading

Possibly related issues

  • Federico2014/tips#2 — Covers governance-activated strict ECDSA validation, 65-byte enforcement, recovery checks, and modular inverse handling.

Possibly related PRs

Suggested reviewers: halibobo1205

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.54% 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 main change: proposal-gated ECDSA validation.
  • Fix all pre-merge checks with AI
✨ 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/strict-ecdsa-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.

@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: 2

🤖 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 `@framework/src/main/java/org/tron/core/db/Manager.java`:
- Around line 1924-1930: Update the transaction verification cache used by
pushTransaction and validateSignature to bind each cached result to the strict
ECDSA activation state or validation epoch, and revalidate whenever it does not
match the current state. Ensure an in-flight legacy validation cannot restore a
cache entry usable after activation, while preserving normal cache reuse within
the same state. Add an overlap test covering legacy validation blocked until
activation completes.

In `@framework/src/test/java/org/tron/core/WalletMockTest.java`:
- Around line 212-217: Gate strict signature-length validation on the shared
EC-key and dynamic-property activation condition. In
framework/src/test/java/org/tron/core/WalletMockTest.java:212-217, explicitly
test strict validation disabled and enabled, preserving legacy handling before
activation and expecting SIGERROR after activation; update
Wallet.broadcastTransaction accordingly. In
framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java:405-421,
add the same off/on coverage, preserving legacy P2P handling before activation
and expecting BAD_TRX after activation; gate the P2P validation path with the
same condition.
🪄 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: 14f8d709-6824-4aa8-aed3-17684f6258b4

📥 Commits

Reviewing files that changed from the base of the PR and between c2e1eea and 307fb5c.

📒 Files selected for processing (20)
  • actuator/src/main/java/org/tron/core/utils/ProposalUtil.java
  • chainbase/src/main/java/org/tron/core/capsule/BlockCapsule.java
  • chainbase/src/main/java/org/tron/core/capsule/TransactionCapsule.java
  • chainbase/src/main/java/org/tron/core/store/DynamicPropertiesStore.java
  • common/src/main/java/org/tron/core/Constant.java
  • common/src/main/java/org/tron/core/config/Parameter.java
  • crypto/src/main/java/org/tron/common/crypto/ECKey.java
  • crypto/src/main/java/org/tron/common/crypto/SignUtils.java
  • framework/src/main/java/org/tron/core/Wallet.java
  • framework/src/main/java/org/tron/core/consensus/ProposalService.java
  • framework/src/main/java/org/tron/core/db/Manager.java
  • framework/src/test/java/org/tron/common/crypto/ECKeyTest.java
  • framework/src/test/java/org/tron/core/WalletMockTest.java
  • framework/src/test/java/org/tron/core/actuator/utils/ProposalUtilTest.java
  • framework/src/test/java/org/tron/core/capsule/BlockCapsuleTest.java
  • framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java
  • framework/src/test/java/org/tron/core/db/ManagerMockTest.java
  • framework/src/test/java/org/tron/core/db/ManagerTest.java
  • framework/src/test/java/org/tron/core/net/messagehandler/TransactionsMsgHandlerTest.java
  • framework/src/test/java/org/tron/core/services/ProposalServiceTest.java
💤 Files with no reviewable changes (1)
  • common/src/main/java/org/tron/core/Constant.java

Comment thread framework/src/main/java/org/tron/core/db/Manager.java
Comment thread framework/src/test/java/org/tron/core/WalletMockTest.java

@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 20 files

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

Re-trigger cubic

Comment thread framework/src/main/java/org/tron/core/db/Manager.java
Comment thread crypto/src/main/java/org/tron/common/crypto/SignUtils.java
Comment thread framework/src/test/java/org/tron/core/capsule/TransactionCapsuleTest.java Outdated
Comment thread actuator/src/main/java/org/tron/core/utils/ProposalUtil.java
@Federico2014
Federico2014 force-pushed the feature/strict-ecdsa-validation branch from 307fb5c to f0483b0 Compare August 5, 2026 10:07
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@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 8 files (changes from recent commits).

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

Re-trigger cubic

Comment thread common/src/main/java/org/tron/core/vm/config/VMConfig.java
Comment thread crypto/src/main/java/org/tron/common/crypto/SignUtils.java
@Federico2014
Federico2014 force-pushed the feature/strict-ecdsa-validation branch from 4112998 to f2addb0 Compare August 13, 2026 09:56
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.

1 participant