-
Notifications
You must be signed in to change notification settings - Fork 1.5k
core: avoid big.Int in modexp required gas computation #16396
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
0ff8a01 to
ded9d74
Compare
| if !allZero(header[0:28]) || !allZero(header[32:32+28]) || !allZero(header[64:64+28]) { | ||
| // Except for the case where both base and mod are zeros. | ||
| if allZero(header[0:32]) && allZero(header[64:96]) { | ||
| return minGas |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This isn't right for Fusaka because MultComplexity won't be 0 even when both base and mod are zeros.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The issue is hidden (i.e. not testable) because of the EIP-7823 (modexp length limits) applied later in the Run() function. In other words: we compute incorrect (by EIP-7883) gas cost here, but it does not matter because the execution ends with an error (by EIP-7823).
This is an argument to move EIP-7823 implementation from Run() to RequiredGas().
For now, I'm correcting the implementation.
Optimize the gas calculation for the modexp precompile by avoiding big.Int. The implementation is ported from evmone: https://github.com/ipsilon/evmone/blob/2cbfad3d5eda9bd920f1174088fe48d41f9edcd7/test/state/precompiles.cpp#L102 This has been additionally tested by executing all tests from the precompiles fuzzing corpus. However, this implementation has not been directly fuzzed.
ded9d74 to
1131587
Compare
| for i := 0; i < len(expHeadExplicitBytes); i++ { | ||
| expByte := expHeadExplicitBytes[i] | ||
| if expByte != 0 { | ||
| expTopByteBitWidth := 8 - uint32(bits.LeadingZeros8(expByte)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm wondering whether it is more performant to pad the input to 32 bytes and use uint256.BitLen instead of going byte by byte
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In this case this made it slower so I'm not going to change it now. However, I used uint256 for initial lengths and the performance has improved by up to 4% in the full benchmarks.
|
Final benchmarks: |
Optimize the gas calculation for the modexp precompile by avoiding big.Int. The implementation is ported from evmone: https://github.com/ipsilon/evmone/blob/2cbfad3d5eda9bd920f1174088fe48d41f9edcd7/test/state/precompiles.cpp#L102 This has been additionally tested but executing all tests from the precompiles fuzzing corpus. However, this implementation has not been directly fuzzed.
Optimize the gas calculation for the modexp precompile by avoiding big.Int. The implementation is ported from evmone: https://github.com/ipsilon/evmone/blob/2cbfad3d5eda9bd920f1174088fe48d41f9edcd7/test/state/precompiles.cpp#L102
This has been additionally tested but executing all tests from the precompiles fuzzing corpus. However, this implementation has not been directly fuzzed.