feat(vm): implement TIP-854 canonicalize sign-precompile calldata#6715
Open
yanghang8612 wants to merge 2 commits intotronprotocol:developfrom
Open
feat(vm): implement TIP-854 canonicalize sign-precompile calldata#6715yanghang8612 wants to merge 2 commits intotronprotocol:developfrom
yanghang8612 wants to merge 2 commits intotronprotocol:developfrom
Conversation
3d45f40 to
b59683f
Compare
…alidateSign under Osaka Reject calldata that doesn't fit the (words - H) / I shape (H=5, I=5/6) inside execute(); rejected inputs return Pair.of(false, EMPTY_BYTE_ARRAY). getEnergyForData unchanged.
… precompiles Add Osaka-gated rejection cases (mis-aligned, short head, bad tail, null) and a Program#callToPrecompiledAddress integration test pinning outer-frame containment.
b59683f to
8ad2227
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Implements TIP-854 (Canonicalize calldata for signature-verification precompiles) for java-tron, gated behind the existing
ALLOW_TVM_OSAKAhardfork.ValidateMultiSign.executeandBatchValidateSign.doExecute. The guard rejects when, withW = 32, any of the following holds:data == null,data.length % W != 0,data.length < H*W, or(data.length - H*W) % (I*W) != 0.(H, I)are the same constants the per-call energy formula(words - H) / Ialready bakes in:(5, 5)forvalidateMultiSign,(5, 6)forbatchValidateSign.executereturns(false, empty)without invoking the decoder and without performing anyecrecover. The invoking call frame — reachable through any ofCALL/CALLTOKEN/STATICCALL/DELEGATECALL/CALLCODE— consumes its pre-allocated energy, the stack receives0, memory receives no return data, and the outer transaction continues with its remaining budget intact.length == H*W + I*W*Nfor someN >= 0), the new rule is a no-op. Pre-activation behaviour, including the per-call energy cost, is byte-for-byte unchanged.committee.*key /CommonParameter/Argsplumbing — reuses the already-wired Osaka gate.Why are these changes required?
The two precompiles charge energy under a fixed shape assumption — the pricing formula treats calldata as a static head followed by exactly
Nequally-sized tail items — but the existing execute path does not enforce the same shape before decoding. The decoder follows whatever offsets calldata supplies and silently zero-pads any missing bytes throughArrays.copyOfRange. As a result, the set of byte strings accepted is a strict superset of the shapes pricing has ever been evaluated for: non-word-aligned trailing bytes are dropped, inputs shorter than the static head are zero-padded out, and tails that don't decompose into an integer number of items still flow through. This makes the precompiles harder to reason about for wallets, SDKs, indexers, audits, and formal specifications. This PR closes the gap by collapsing the accepted set to exactly the shapes pricing already assumes.This PR has been tested by:
ValidateMultiSignContractTest(3 new cases): rejects malformed calldata across three buckets (non-32-aligned tail, fewer thanHwords, aligned-but-bad-tail) plusnull; canonical-input behaviour identical pre- vs post-activation; pre-activation does not take the new reject path.BatchValidateSignContractTest(3 new cases): same three shapes, parameterised for(H, I) = (5, 6); the canonical-input case uses real 65-byte signatures so eachbyteselement encodes in exactly four words.OperationsTest.testTip854OuterFrameContainment: drives both precompiles throughProgram.callToPrecompiledAddresswith malformed calldata underOp.CALLand asserts (a) no exception propagates to the outer frame, (b) the inner CALL pushes0, (c) the outer frame keeps executing afterwards../gradlew :actuator:compileJava :framework:compileTestJava— OK../gradlew :framework:test --tests "*ValidateMultiSignContractTest" --tests "*BatchValidateSignContractTest" --tests "*OperationsTest.testTip854*"— all pass.Follow up
abi.encodeconformance) is intentionally out of scope per the TIP and can be addressed in a follow-up if desired.