In calc_iter_count(), which is part of the modexp precompile gas calculation, the most-significant bit of the exponent is added to the intermediate result. The MSB is computed using U256::from(exp.bits()) - U256::from(1)) in:
This works only if the exponent is non-zero; subtracting 1 from zero results in an underflow, leading to inaccurate gas requirements for specific inputs.
Geth computes the MSB as follows; notice the condition bitlen > 0:
var msb int
if bitlen := expHead.BitLen(); bitlen > 0 {
msb = bitlen - 1
}
This PR changes the underflowing subtraction into a saturating_sub so that an underflow never occurs.
Performance / NEAR gas cost considerations
Testing
Fuzzing.
How should this be reviewed
A test has been added to modexp.rs which asserts that the required gas for the specified input is 65536; an equivalent Go program which uses Geth to demonstrate this is provided below:
Description
In
calc_iter_count()
, which is part of the modexp precompile gas calculation, the most-significant bit of the exponent is added to the intermediate result. The MSB is computed usingU256::from(exp.bits()) - U256::from(1))
in:This works only if the exponent is non-zero; subtracting
1
from zero results in an underflow, leading to inaccurate gas requirements for specific inputs.Geth computes the MSB as follows; notice the condition
bitlen > 0
:This PR changes the underflowing subtraction into a
saturating_sub
so that an underflow never occurs.Performance / NEAR gas cost considerations
Testing
Fuzzing.
How should this be reviewed
A test has been added to
modexp.rs
which asserts that the required gas for the specified input is65536
; an equivalent Go program which uses Geth to demonstrate this is provided below:Additional information