Skip to content

fix(net): restrict admission signature length#6782

Merged
kuny0707 merged 2 commits into
tronprotocol:release_v4.8.2from
Federico2014:fix/limit_sig_length_65
May 26, 2026
Merged

fix(net): restrict admission signature length#6782
kuny0707 merged 2 commits into
tronprotocol:release_v4.8.2from
Federico2014:fix/limit_sig_length_65

Conversation

@Federico2014
Copy link
Copy Markdown
Collaborator

@Federico2014 Federico2014 commented May 19, 2026

What does this PR do?

Adds a signature-length range check at broadcast / P2P admission entrypoints, before any signature recovery work is done. Accepted sizes are [PER_SIGN_LENGTH, MAX_PER_SIGN_LENGTH] = [65, 68]:

  • Wallet.broadcastTransaction rejects the transaction with SIGERROR when any signature in the list falls outside [65, 68].
  • TransactionsMsgHandler.check throws P2pException(BAD_TRX) when any signature in a TransactionsMessage falls outside [65, 68], causing the peer to be disconnected with BAD_TX.
  • RelayService.checkHelloMessage returns false when the HelloMessage signature from a fast-forward peer falls outside [65, 68].

The predicate is centralized in SignUtils.isValidLength(int size); all three call sites now share that helper. The bounds live in Constant.PER_SIGN_LENGTH (= 65) and Constant.MAX_PER_SIGN_LENGTH (= 68).

Why are these changes required?

A canonical TRON ECDSA signature is encoded as 65 bytes (r 32 + s 32 + v 1). The affected entrypoints currently pass malformed admission payloads into SignUtils.signatureToAddress / signature recovery first, which wastes CPU before the request is rejected or fails later.

This PR adds a cheap length check at the network and broadcast boundaries so invalid admission payloads fail before crypto recovery is attempted. This is intentionally scoped to admission handling only.

Why [65, 68] instead of strict == 65?

A canonical signature is 65 bytes. Historical on-chain data, however, contains transactions with a small amount of trailing padding (up to 3 bytes) that ECDSA recovery silently ignores. Using MAX_PER_SIGN_LENGTH = 68 closes the previously unbounded encoding window at admission while remaining tolerant of clients that may still produce the legacy padded form.

The long-term goal is to tighten the rule once the compatibility window is no longer needed. Because the bounds are centralized in Constant and the predicate is centralized in SignUtils.isValidLength, that tightening is a one-line change.

Consensus compatibility

This PR does not change transaction validation for blocks or any shared consensus validation path.

In particular, TransactionCapsule.checkWeight keeps the looser sig.size() < 65 check so historical signatures with trailing padding remain valid; longer signatures continue to be parsed by the existing Rsv.fromSignature behavior using the first 65 bytes. Tightening that shared validation path would be a consensus-impacting behavior change and is intentionally not part of this PR.

To keep this rule visible to future readers, SignUtils.isValidLength carries a javadoc that names the admission-vs-consensus split and points at TransactionCapsule.checkWeight so the next reviewer who greps either operator lands on the explanation.

The observable behavior change is limited to local broadcast / P2P admission:

  • Clients broadcasting transactions with signatures outside [65, 68] now receive SIGERROR before downstream checks.
  • Peers sending transaction messages with signatures outside [65, 68] are rejected at message admission with BAD_TX.
  • Fast-forward hello messages with signatures outside [65, 68] are rejected before signature recovery.

This PR has been tested by:

  • Unit Tests
    • WalletMockTest#testBroadcastTxInvalidSigLength: 64 / 69 / empty signatures return SIGERROR; 65-byte and 68-byte (upper bound) signatures fall through.
    • TransactionsMsgHandlerTest#testInvalidSigLength: 64 / 69 signatures raise P2pException(BAD_TRX) via assertThrows; 65-byte and 68-byte signatures pass the new length check.
    • RelayServiceTest#testCheckHelloMessage: extended to assert that 64 / 69 / empty HelloMessage signatures return false; the existing 65-byte case still returns true.
  • Manual Testing
    • ./gradlew :framework:checkstyleMain :framework:checkstyleTest
    • ./gradlew :framework:test --tests "org.tron.core.WalletMockTest.testBroadcastTxInvalidSigLength" --tests "org.tron.core.net.messagehandler.TransactionsMsgHandlerTest.testInvalidSigLength" --tests "org.tron.core.net.services.RelayServiceTest.testCheckHelloMessage"

Follow up

None.

@Sunny6889

This comment was marked as resolved.

bladehan1

This comment was marked as off-topic.

@Federico2014 Federico2014 changed the title fix(net): enforce 65-byte signature length fix(net): restrict admission signature length to [65, 68] May 20, 2026
@Federico2014 Federico2014 changed the title fix(net): restrict admission signature length to [65, 68] fix(net): restrict admission signature length May 20, 2026
@Federico2014 Federico2014 reopened this May 25, 2026
@Federico2014 Federico2014 requested a review from bladehan1 May 26, 2026 03:33
Comment thread framework/src/main/java/org/tron/core/Wallet.java
Comment thread common/src/main/java/org/tron/core/Constant.java Outdated
@Federico2014 Federico2014 force-pushed the fix/limit_sig_length_65 branch from 6ac1c2c to 3eceacc Compare May 26, 2026 05:01
@kuny0707 kuny0707 merged commit 01441dc into tronprotocol:release_v4.8.2 May 26, 2026
10 checks passed
@halibobo1205 halibobo1205 added the topic:net p2p net work, synchronization label May 26, 2026
@halibobo1205 halibobo1205 added this to the GreatVoyage-v4.8.2 milestone May 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

topic:net p2p net work, synchronization

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants