From 65240fdf4697a81824048d453a0d9818c37c2c3d Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Mon, 2 Sep 2024 16:06:19 -0600 Subject: [PATCH] Plumb maxCode overriddes into EVM (#7557) * Plumb maxCode overriddes into EVM Restore lost functionality: the maxcodesize and maxinitcodesize should be plumed into the operations and validation rules when set. Signed-off-by: Danno Ferrin --------- Signed-off-by: Danno Ferrin Co-authored-by: Sally MacFarlane --- CHANGELOG.md | 1 + .../ethereum/mainnet/MainnetProtocolSpecs.java | 6 +++--- .../ethereum/eof/EOFReferenceTestTools.java | 2 +- .../java/org/hyperledger/besu/evm/EVM.java | 18 ++++++++++++++++++ .../contractvalidation/MaxCodeSizeRule.java | 10 +++++++--- .../besu/evm/fluent/EVMExecutor.java | 17 +++++++++-------- .../evm/operation/AbstractCreateOperation.java | 2 +- .../evm/operation/ReturnContractOperation.java | 2 +- .../ContractCreationProcessorTest.java | 6 ++++-- 9 files changed, 45 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 798e5345717..edaa0502681 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Include current chain head block when computing `eth_maxPriorityFeePerGas` [#7485](https://github.com/hyperledger/besu/pull/7485) ### Bug fixes +- The genesis config override `contractSizeLimit` was not wired into code size limits [#7557](https://github.com/hyperledger/besu/issues/7557) ## 24.9.0 diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java index a96ca58fddb..ddc8b49b4f6 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecs.java @@ -650,7 +650,7 @@ static ProtocolSpecBuilder shanghaiDefinition( TransactionType.FRONTIER, TransactionType.ACCESS_LIST, TransactionType.EIP1559), - evm.getEvmVersion().getMaxInitcodeSize())) + evm.getMaxInitcodeSize())) .withdrawalsProcessor(new WithdrawalsProcessor()) .withdrawalsValidator(new WithdrawalsValidator.AllowedWithdrawals()) .name("Shanghai"); @@ -730,7 +730,7 @@ static ProtocolSpecBuilder cancunDefinition( TransactionType.ACCESS_LIST, TransactionType.EIP1559, TransactionType.BLOB), - evm.getEvmVersion().getMaxInitcodeSize())) + evm.getMaxInitcodeSize())) .precompileContractRegistryBuilder(MainnetPrecompiledContractRegistries::cancun) .blockHeaderValidatorBuilder(MainnetBlockHeaderValidator::cancunBlockHeaderValidator) .blockHashProcessor(new CancunBlockHashProcessor()) @@ -814,7 +814,7 @@ static ProtocolSpecBuilder pragueDefinition( TransactionType.EIP1559, TransactionType.BLOB, TransactionType.SET_CODE), - evm.getEvmVersion().getMaxInitcodeSize())) + evm.getMaxInitcodeSize())) // EIP-2935 Blockhash processor .blockHashProcessor(new PragueBlockHashProcessor()) diff --git a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/eof/EOFReferenceTestTools.java b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/eof/EOFReferenceTestTools.java index 3c0c2dbbb2f..b5def9556d4 100644 --- a/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/eof/EOFReferenceTestTools.java +++ b/ethereum/referencetests/src/reference-test/java/org/hyperledger/besu/ethereum/eof/EOFReferenceTestTools.java @@ -124,7 +124,7 @@ public static void executeTest( // hardwire in the magic byte transaction checks if (evm.getMaxEOFVersion() < 1) { assertThat(expected.exception()).isEqualTo("EOF_InvalidCode"); - } else if (code.size() > evm.getEvmVersion().getMaxInitcodeSize()) { + } else if (code.size() > evm.getMaxInitcodeSize()) { // this check is in EOFCREATE and Transaction validator, but unit tests sniff it out. assertThat(false) .withFailMessage( diff --git a/evm/src/main/java/org/hyperledger/besu/evm/EVM.java b/evm/src/main/java/org/hyperledger/besu/evm/EVM.java index f2eb7cf29df..69575143923 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/EVM.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/EVM.java @@ -142,6 +142,24 @@ public int getMaxEOFVersion() { return evmSpecVersion.maxEofVersion; } + /** + * Gets the max code size, taking configuration and version into account + * + * @return The max code size override, if not set the max code size for the EVM version. + */ + public int getMaxCodeSize() { + return evmConfiguration.maxCodeSizeOverride().orElse(evmSpecVersion.maxCodeSize); + } + + /** + * Gets the max initcode Size, taking configuration and version into account + * + * @return The max initcode size override, if not set the max initcode size for the EVM version. + */ + public int getMaxInitcodeSize() { + return evmConfiguration.maxInitcodeSizeOverride().orElse(evmSpecVersion.maxInitcodeSize); + } + /** * Returns the non-fork related configuration parameters of the EVM. * diff --git a/evm/src/main/java/org/hyperledger/besu/evm/contractvalidation/MaxCodeSizeRule.java b/evm/src/main/java/org/hyperledger/besu/evm/contractvalidation/MaxCodeSizeRule.java index 794650a1390..9fd7cb801da 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/contractvalidation/MaxCodeSizeRule.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/contractvalidation/MaxCodeSizeRule.java @@ -18,6 +18,7 @@ import org.hyperledger.besu.evm.EvmSpecVersion; import org.hyperledger.besu.evm.frame.ExceptionalHaltReason; import org.hyperledger.besu.evm.frame.MessageFrame; +import org.hyperledger.besu.evm.internal.EvmConfiguration; import java.util.Optional; @@ -75,16 +76,19 @@ public static ContractValidationRule of(final int maxCodeSize) { * @return the contract validation rule */ public static ContractValidationRule from(final EVM evm) { - return from(evm.getEvmVersion()); + return from(evm.getEvmVersion(), evm.getEvmConfiguration()); } /** * Fluent MaxCodeSizeRule from the EVM it is working with. * * @param evmspec The evm spec version to get the size rules from. + * @param evmConfiguration The evm configuration, including overrides * @return the contract validation rule */ - public static ContractValidationRule from(final EvmSpecVersion evmspec) { - return new MaxCodeSizeRule(evmspec.getMaxCodeSize()); + public static ContractValidationRule from( + final EvmSpecVersion evmspec, final EvmConfiguration evmConfiguration) { + return new MaxCodeSizeRule( + evmConfiguration.maxCodeSizeOverride().orElse(evmspec.getMaxCodeSize())); } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java b/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java index a0461980432..a182ae9454d 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/fluent/EVMExecutor.java @@ -77,7 +77,9 @@ public class EVMExecutor { private OperationTracer tracer = OperationTracer.NO_TRACING; private boolean requireDeposit = true; private List contractValidationRules = - List.of(MaxCodeSizeRule.from(EvmSpecVersion.SPURIOUS_DRAGON), PrefixCodeRule.of()); + List.of( + MaxCodeSizeRule.from(EvmSpecVersion.SPURIOUS_DRAGON, EvmConfiguration.DEFAULT), + PrefixCodeRule.of()); private long initialNonce = 1; private Collection
forceCommitAddresses = List.of(Address.fromHexString("0x03")); private Set
accessListWarmAddresses = new BytesTrieSet<>(Address.SIZE); @@ -241,8 +243,7 @@ public static EVMExecutor spuriousDragon(final EvmConfiguration evmConfiguration final EVMExecutor executor = new EVMExecutor(MainnetEVMs.spuriousDragon(evmConfiguration)); executor.precompileContractRegistry = MainnetPrecompiledContracts.frontier(executor.evm.getGasCalculator()); - executor.contractValidationRules = - List.of(MaxCodeSizeRule.from(EvmSpecVersion.SPURIOUS_DRAGON)); + executor.contractValidationRules = List.of(MaxCodeSizeRule.from(executor.evm)); return executor; } @@ -256,7 +257,7 @@ public static EVMExecutor byzantium(final EvmConfiguration evmConfiguration) { final EVMExecutor executor = new EVMExecutor(MainnetEVMs.byzantium(evmConfiguration)); executor.precompileContractRegistry = MainnetPrecompiledContracts.byzantium(executor.evm.getGasCalculator()); - executor.contractValidationRules = List.of(MaxCodeSizeRule.from(EvmSpecVersion.BYZANTIUM)); + executor.contractValidationRules = List.of(MaxCodeSizeRule.from(executor.evm)); return executor; } @@ -270,7 +271,7 @@ public static EVMExecutor constantinople(final EvmConfiguration evmConfiguration final EVMExecutor executor = new EVMExecutor(MainnetEVMs.constantinople(evmConfiguration)); executor.precompileContractRegistry = MainnetPrecompiledContracts.byzantium(executor.evm.getGasCalculator()); - executor.contractValidationRules = List.of(MaxCodeSizeRule.from(EvmSpecVersion.CONSTANTINOPLE)); + executor.contractValidationRules = List.of(MaxCodeSizeRule.from(executor.evm)); return executor; } @@ -284,7 +285,7 @@ public static EVMExecutor petersburg(final EvmConfiguration evmConfiguration) { final EVMExecutor executor = new EVMExecutor(MainnetEVMs.petersburg(evmConfiguration)); executor.precompileContractRegistry = MainnetPrecompiledContracts.byzantium(executor.evm.getGasCalculator()); - executor.contractValidationRules = List.of(MaxCodeSizeRule.from(EvmSpecVersion.PETERSBURG)); + executor.contractValidationRules = List.of(MaxCodeSizeRule.from(executor.evm)); return executor; } @@ -319,7 +320,7 @@ public static EVMExecutor istanbul( final EVMExecutor executor = new EVMExecutor(MainnetEVMs.istanbul(chainId, evmConfiguration)); executor.precompileContractRegistry = MainnetPrecompiledContracts.istanbul(executor.evm.getGasCalculator()); - executor.contractValidationRules = List.of(MaxCodeSizeRule.from(EvmSpecVersion.ISTANBUL)); + executor.contractValidationRules = List.of(MaxCodeSizeRule.from(executor.evm)); return executor; } @@ -354,7 +355,7 @@ public static EVMExecutor berlin( final EVMExecutor executor = new EVMExecutor(MainnetEVMs.berlin(chainId, evmConfiguration)); executor.precompileContractRegistry = MainnetPrecompiledContracts.istanbul(executor.evm.getGasCalculator()); - executor.contractValidationRules = List.of(MaxCodeSizeRule.from(EvmSpecVersion.BERLIN)); + executor.contractValidationRules = List.of(MaxCodeSizeRule.from(executor.evm)); return executor; } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java index 3a78016f2de..5d9bea61ce0 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/AbstractCreateOperation.java @@ -97,7 +97,7 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) { Code code = codeSupplier.get(); - if (code != null && code.getSize() > evm.getEvmVersion().getMaxInitcodeSize()) { + if (code != null && code.getSize() > evm.getMaxInitcodeSize()) { frame.popStackItems(getStackItemsConsumed()); return new OperationResult(cost, ExceptionalHaltReason.CODE_TOO_LARGE); } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/ReturnContractOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/ReturnContractOperation.java index 97895800765..2860c93795e 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/ReturnContractOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/ReturnContractOperation.java @@ -64,7 +64,7 @@ public OperationResult execute(final MessageFrame frame, final EVM evm) { } Bytes auxData = frame.readMemory(from, length); - if (code.getDataSize() + auxData.size() > evm.getEvmVersion().getMaxCodeSize()) { + if (code.getDataSize() + auxData.size() > evm.getMaxCodeSize()) { return new OperationResult(cost, ExceptionalHaltReason.CODE_TOO_LARGE); } if (code.getDataSize() + auxData.size() < code.getDeclaredDataSize()) { diff --git a/evm/src/test/java/org/hyperledger/besu/evm/processor/ContractCreationProcessorTest.java b/evm/src/test/java/org/hyperledger/besu/evm/processor/ContractCreationProcessorTest.java index 40ef063db15..3420df88dcd 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/processor/ContractCreationProcessorTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/processor/ContractCreationProcessorTest.java @@ -206,7 +206,8 @@ void shouldThrowAnExceptionWhenCodeContractTooLarge() { new ContractCreationProcessor( evm, true, - Collections.singletonList(MaxCodeSizeRule.from(EvmSpecVersion.SPURIOUS_DRAGON)), + Collections.singletonList( + MaxCodeSizeRule.from(EvmSpecVersion.SPURIOUS_DRAGON, EvmConfiguration.DEFAULT)), 1, Collections.emptyList()); final Bytes contractCode = @@ -227,7 +228,8 @@ void shouldNotThrowAnExceptionWhenCodeContractTooLarge() { new ContractCreationProcessor( evm, true, - Collections.singletonList(MaxCodeSizeRule.from(EvmSpecVersion.SPURIOUS_DRAGON)), + Collections.singletonList( + MaxCodeSizeRule.from(EvmSpecVersion.SPURIOUS_DRAGON, EvmConfiguration.DEFAULT)), 1, Collections.emptyList()); final Bytes contractCode =