-
Notifications
You must be signed in to change notification settings - Fork 954
EIP-7823 - Modexp upper bounds #8632
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
Signed-off-by: Simon Dudley <simon.dudley@consensys.net>
Signed-off-by: Simon Dudley <simon.dudley@consensys.net>
Signed-off-by: Simon Dudley <simon.dudley@consensys.net>
*/ | ||
public static BigIntegerModularExponentiationPrecompiledContract osaka( | ||
final GasCalculator gasCalculator) { | ||
return new BigIntegerModularExponentiationPrecompiledContract(gasCalculator, OSAKA_UPPER_BOUND); |
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 looks like an usual design, not consistent with our code - IMO this static logic does not belong here but can be accessed through MainnetPrecompiledContracts::byzantium
and MainnetPrecompiledContracts::osaka
. The duty to configure these things should be on the caller (configuration) not the instance itself.
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.
Let me know what you think 9b34bf9
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.
Do you mean static factory pattern is an unusual design or something specific to this?
The usage of static factory follows the design already in place for some precompiles e.g AltBN128AddPrecompiledContract.byzantium
I think it's pretty conventional for the static factory to live with the class it's constructing and be responsible for configuring the "osaka" version of it.
If you look through MainnetProtocolSpecs, a lot of fork configuration is done by wiring in a fork-specific version of a class, which extends the previous one, e.g. GasCalculator.
The difference here is we wire in a static factory instead of a whole new version of the class, since it's only one value that is changed.
However, if there is a performance issue with the extra check for prague though, wiring in e.g. OsakaBigIntegerModularExponentiationPrecompiledContract is more code but might be easier to JIT compile (we can check profiling to confirm).
Let me know what you think 9b34bf9
No objections in general, but I think my approach is more conventional, at least in Besu.
No configuration currently exists in MainnetPrecompiledContracts, it's just wiring. That's mostly the case for MainnetProtocolSpecs too, with some exceptions. Most config happens in the fork-specific classes I believe.
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.
Do you mean static factory pattern is an unusual design or something specific to this?
Not that it's unusual but it looks a bit weird like this IMO. So you have 2 places you have to modify if you want to add a new fork even if such fork only lowers the limits, MainnetPrecompiledContracts
and BigIntegerModularExponentiationPrecompiledContract
with a corresponding static method.
The usage of static factory follows the design already in place for some precompiles e.g AltBN128AddPrecompiledContract.byzantium
Right... I missed this case. I only looked at populateForPrague
and they are all using constructors. I think the one of the problems is not being consistent, as there are 2 different approaches in parallel.
If you look through MainnetProtocolSpecs, a lot of fork configuration is done by wiring in a fork-specific version of a class, which extends the previous one, e.g. GasCalculator.
Not sure I understand the example - that actually seems to prove my point. So you have all of the different parts constructed in MainnetProtocolSpecs
and MainnetEVMs
not in ProtocolSpec
neither in EVM
- these simply provide the constructor, not the specific static constructor for the fork, and MainnetProtocolSpecs
and MainnetEVMs
instantiate with the right parameters. If we had static factories for every fork in every class it would be a lot of boiler plate.
However, if there is a performance issue with the extra check for prague though, wiring in e.g. OsakaBigIntegerModularExponentiationPrecompiledContract is more code but might be easier to JIT compile (we can check profiling to confirm).
Yes, I think you are referring to the size of the method. It impacts JIT compilation for sure. Though these are configutation methods - they are not hot - so performance is not really a concern here.
I also think that the statics here degrade the testability of BigIntegerModularExponentiationPrecompiledContract
because now there's no way to inject dependencies into the class for testing since all constructors are private. The first temptation would be to package-private the constructor for testing which makes it even worse.
On a separate segway, not sure why MainnetPrecompiledContracts
is an interface since it's clearly a factory class 😆
|| length_of_EXPONENT > upperBound | ||
|| length_of_MODULUS > upperBound) { | ||
return PrecompileContractResult.halt( | ||
null, Optional.of(ExceptionalHaltReason.PRECOMPILE_ERROR)); |
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.
Need to have a unit test for this
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.
yep, this was first draft for the devnet, planning to productionise next. Good reminder 👍
final Bytes input, | ||
final long length_of_BASE, | ||
final long length_of_EXPONENT, | ||
final long length_of_MODULUS) { |
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.
nit: why using underscores in variable names
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 is to match the spec - controversial in java conventions perhaps, but I find it's really useful if the spec and code values match for future reference.
final int modulusLength = clampedToInt(modulusLength(input)); | ||
private PrecompileContractResult computeNative( | ||
final @Nonnull Bytes input, final long length_of_MODULUS) { | ||
final int modulusLength = clampedToInt(length_of_MODULUS); |
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.
Signed-off-by: Simon Dudley <simon.dudley@consensys.net>
8bf2d0c
to
5b6f3b8
Compare
Signed-off-by: Simon Dudley <simon.dudley@consensys.net>
Signed-off-by: Simon Dudley <simon.dudley@consensys.net>
It might just be noise at these levels, but I measure a small impact with profiling, 2% performance impact in the worst case. I think it's negligible and we will be on Fusaka soon enough anyway. |
No performance difference spotted on mainnet, profiling for 10 minutes didn't show modexp at all, so must be rarely used. |
Signed-off-by: Simon Dudley <simon.dudley@consensys.net>
* EIP-7825: Transaction gas limit cap (#8700) * EIP-7825: Transaction gas limit cap Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net> * Support transaction gas limit cap when simulating a tx Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net> * Do not allow isAllowExceedingGasLimit for when block simulation is strict Signed-off-by: Gabriel-Trintinalia <gabriel.trintinalia@consensys.net> --------- Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net> Signed-off-by: Gabriel-Trintinalia <gabriel.trintinalia@consensys.net> Co-authored-by: Gabriel-Trintinalia <gabriel.trintinalia@consensys.net> * EIP-7823 - Modexp upper bounds (#8632) Signed-off-by: Simon Dudley <simon.dudley@consensys.net> * Change Maven artifactIds to avoid possible collisions with other libs (#8589) * Improve Maven artifacts naming to avoid possible collisions with other libs Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net> * Rename besu subproject to app (#8746) * Rename `besu` module to `app` Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net> * Implement percentiles array size limit for eth_feeHistory (#8748) * implement percentiles array size limit for eth_feeHistory Signed-off-by: garyschulte <garyschulte@gmail.com> * Revert "feat: remove chain head check if peer supports eth/69 (#8725)" (#8753) This reverts commit ed1086d. Signed-off-by: Gabriel-Trintinalia <gabriel.trintinalia@consensys.net> --------- Signed-off-by: Fabio Di Fabio <fabio.difabio@consensys.net> Signed-off-by: Gabriel-Trintinalia <gabriel.trintinalia@consensys.net> Signed-off-by: Simon Dudley <simon.dudley@consensys.net> Signed-off-by: garyschulte <garyschulte@gmail.com> Co-authored-by: Fabio Di Fabio <fabio.difabio@consensys.net> Co-authored-by: Simon Dudley <simon.dudley@consensys.net> Co-authored-by: garyschulte <garyschulte@gmail.com>
PR description
TODO
Separate issue: update EEST versionUpdate EEST to v4.5.0 #8641Fixed Issue(s)
Fixes #8602
Thanks for sending a pull request! Have you done the following?
doc-change-required
label to this PR if updates are required.Locally, you can run these tests to catch failures early:
./gradlew spotlessApply
./gradlew build
./gradlew acceptanceTest
./gradlew integrationTest
./gradlew ethereum:referenceTests:referenceTests