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 tightens fresh RPC and P2P ECDSA signature admission to exactly 65 bytes and introduces proposal-gated strict consensus validation for transaction and block-witness signatures. Strict mode validates the encoded length, normalized recovery ID, and r/s scalar bounds before elliptic-curve recovery, preserves high-S signatures, and uses BigIntegers.modOddInverse for valid modular inverses.

Strict public-key recovery now rejects point-at-infinity results instead of encoding them as {0x00} and deriving an address from an empty public-key payload. It also rejects null signatures and null r/s components with a predictable IllegalArgumentException. Legacy recovery behavior remains unchanged before activation.

It adds proposal 99 (ALLOW_STRICT_ECDSA_VALIDATION) and block version 4.8.3 support for one-way activation. The same activation state is loaded into the VM configuration snapshot so ECRecover and signature-recovery precompiles use strict recovery after activation while preserving historical VM behavior before activation. Relay hello-message verification is a non-consensus admission path and therefore always uses strict ECDSA recovery.

PBFT message-signature validation is explicitly outside the scope of this PR and retains its existing legacy behavior.

When the proposal becomes active during maintenance processing, cached transaction verification results are invalidated across the pending, re-push, popped, and pushing queues. Block verification reuses a pending result only when the cached capsule is explicitly verified and its signatures match.

Transaction signature validation and cache invalidation are synchronized per TransactionCapsule, with isVerified published through a volatile field. This prevents an in-flight legacy validation from restoring isVerified=true after activation invalidation, without serializing validation of different transactions on a global lock.

Why are these changes required?

Padded and malformed ECDSA signatures create non-canonical encodings and may reach expensive or failure-prone elliptic-curve operations. A specially constructed, range-valid signature can also recover the secp256k1 point at infinity, which is not a valid public key but was historically encoded as {0x00} and converted into a deterministic address.

Proposal-gated consensus activation preserves transaction, block, and VM historical compatibility while allowing the network to enforce strict validation for post-activation processing. Non-consensus admission paths can reject these invalid signatures immediately.

A successful verification cache entry is valid only for the rule set under which it was computed. Invalidating and coordinating cached results at the activation boundary ensures that a transaction accepted under legacy rules cannot bypass strict validation when it is later considered for block inclusion.

This PR has been tested by:

  • Unit Tests:
    • ./gradlew :framework:test --tests 'org.tron.common.crypto.ECKeyTest'
    • ./gradlew :framework:test --tests 'org.tron.common.crypto.ECKeyTest' --tests 'org.tron.common.runtime.vm.PrecompiledContractsTest.testECRecoverPointAtInfinityStrictValidation'
    • ./gradlew :framework:test --tests 'org.tron.core.net.services.RelayServiceTest'
    • Targeted tests for WalletMockTest, ProposalUtilTest, BlockCapsuleTest, TransactionCapsuleTest, ManagerMockTest, ManagerTest, TransactionsMsgHandlerTest, and ProposalServiceTest
    • Coverage includes activation/validation overlap, signature lengths, null signature components, r/s values 0, n, and n+1, invalid wire recovery values, invalid compact headers and recovery IDs, valid high-S signatures, point-at-infinity recovery, and VM behavior before and after activation.
  • Checkstyle:
    • ./gradlew :framework:checkstyleMain
    • ./gradlew :framework:checkstyleTest
  • Manual Testing: Not performed.

Follow up

Coordinate the final TIP review, release version, and proposal activation schedule before enabling proposal 99.

Extra details

Related TIP draft: Federico2014/tips#2

Compatibility:

  • Fresh RPC, P2P, and relay admission requires exactly 65-byte signatures independently of proposal activation; relay signature recovery is also always strict.
  • Transaction and block consensus validation retains legacy behavior before activation and applies strict validation after activation.
  • VM ECRecover and signature-recovery precompiles retain legacy point-at-infinity behavior before activation and reject it after activation.
  • PBFT message-signature validation is not modified by this PR and remains legacy-compatible.
  • Historical padded signatures remain verifiable, and read-only signature-weight and approved-list APIs remain legacy-compatible.
  • The new dynamic property defaults to disabled; no database migration is required.

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

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

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Federico2014, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 104 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 352a2a74-cf9c-44ec-b990-8b5452c35100

📥 Commits

Reviewing files that changed from the base of the PR and between f0483b0 and f2addb0.

📒 Files selected for processing (9)
  • actuator/src/main/java/org/tron/core/vm/PrecompiledContracts.java
  • actuator/src/main/java/org/tron/core/vm/config/ConfigLoader.java
  • common/src/main/java/org/tron/core/vm/config/VMConfig.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/net/service/relay/RelayService.java
  • framework/src/test/java/org/tron/common/crypto/ECKeyTest.java
  • framework/src/test/java/org/tron/common/runtime/vm/PrecompiledContractsTest.java
  • framework/src/test/java/org/tron/common/runtime/vm/VMConfigIsolationTest.java
📝 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 summarizes the main change: proposal-gated strict ECDSA validation.
✨ 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