feat(vm): implement TIP-7883 ModExp gas cost increase#6654
feat(vm): implement TIP-7883 ModExp gas cost increase#6654yanghang8612 wants to merge 1 commit intotronprotocol:developfrom
Conversation
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
be82ead to
f13e430
Compare
| BigInteger energy = BigInteger.valueOf(multComplexity) | ||
| .multiply(BigInteger.valueOf(iterCount)); | ||
|
|
||
| BigInteger minEnergy = BigInteger.valueOf(500); | ||
| if (isLessThan(energy, minEnergy)) { | ||
| return 500L; | ||
| } | ||
|
|
||
| return isLessThan(energy, BigInteger.valueOf(Long.MAX_VALUE)) ? energy.longValueExact() | ||
| : Long.MAX_VALUE; |
There was a problem hiding this comment.
Good defensive coding — using BigInteger for the intermediate multiplication avoids any potential overflow with large baseLen/modLen values (up to 1024 bytes), and the Long.MAX_VALUE cap ensures the result is always safe to return as a long. Well handled.
| */ | ||
| private long getMultComplexityTIP7883(int baseLen, int modLen) { | ||
| long maxLength = max(baseLen, modLen, VMConfig.disableJavaLangMath()); | ||
| long words = (maxLength + 7) / 8; // ceil(maxLength / 8) |
There was a problem hiding this comment.
The inline comment // ceil(maxLength / 8) is a nice touch — it makes the intent of (maxLength + 7) / 8 immediately clear without needing to mentally decode the arithmetic. The structure also maps 1:1 to the spec's pseudocode, which makes auditing straightforward.
| if (maxLength <= 32) { | ||
| return 16; | ||
| } | ||
| return 2 * words * words; |
There was a problem hiding this comment.
[P1] Suggestion: use overflow-safe arithmetic for long-term review burden reduction
2 * words * words uses plain long multiplication. Proving it won't overflow requires tracing the full input chain: parseLen() → intValueSafe() returns int → max words = 268,435,456 → 2 * words² = 1.44×10¹⁷ < Long.MAX_VALUE. This reasoning is correct today, but not self-evident — if parseLen() return type or UPPER_BOUND ever changes, the safety assumption silently breaks.
Using overflow-safe arithmetic makes the code self-evidently safe with zero external reasoning required, reducing the review burden for future readers:
return Math.multiplyExact(2, Math.multiplyExact(words, words));This is a long-term maintainability suggestion, not a current correctness issue.
| * Minimal complexity of 16; doubled complexity for base/modulus > 32 bytes. | ||
| */ | ||
| private long getMultComplexityTIP7883(int baseLen, int modLen) { | ||
| long maxLength = max(baseLen, modLen, VMConfig.disableJavaLangMath()); |
There was a problem hiding this comment.
[SHOULD]getMultComplexityTIP7883 and getIterationCountTIP7883 are new methods with no legacy constraints. They should use StrictMathWrapper directly instead of the deprecated Maths.max(a, b, boolean) pattern.
Suggested changes:
// getMultComplexityTIP7883
- long maxLength = max(baseLen, modLen, VMConfig.disableJavaLangMath());
+ long maxLength = StrictMathWrapper.max(baseLen, modLen);
// avoid silent overflow on 2 * words * words
- return 2 * words * words;
+ return StrictMathWrapper.multiplyExact(2L, StrictMathWrapper.multiplyExact(words, words));
// getIterationCountTIP7883
- return max(iterCount, 1, VMConfig.disableJavaLangMath());
+ return StrictMathWrapper.max(iterCount, 1L);Reasons:
Mathsis@Deprecated— new code should not add more callers.2 * words * wordsrelies on manual reasoning about value ranges for overflow safety. UsingmultiplyExactmakes this explicit and fail-fast.
Summary
Implement TIP-7883 ModExp precompile repricing, gated behind the existing
allowTvmOsakaflag.Changes from the current pricing formula:
GQUAD_DIVISOR, tripling general cost2 * ceil(maxLen/8)²for >32 bytesRelated: tronprotocol/tips#837