diff --git a/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/trace/coinbase-cold.json b/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/trace/coinbase-cold.json new file mode 100644 index 00000000000..406c2684e26 --- /dev/null +++ b/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/trace/coinbase-cold.json @@ -0,0 +1,57 @@ +{ + "cli": [ + "--notime", + "--json", + "--code", + "4131ff", + "--coinbase", + "4444588443C3A91288C5002483449ABA1054192B", + "--fork", + "paris" + ], + "stdin": "", + "stdout": [ + { + "pc": 0, + "op": 65, + "gas": "0x2540b91f8", + "gasCost": "0x2", + "memSize": 0, + "stack": [], + "depth": 1, + "refund": 0, + "opName": "COINBASE" + }, + { + "pc": 1, + "op": 49, + "gas": "0x2540b91f6", + "gasCost": "0xa28", + "memSize": 0, + "stack": [ + "0x4444588443c3a91288c5002483449aba1054192b" + ], + "depth": 1, + "refund": 0, + "opName": "BALANCE" + }, + { + "pc": 2, + "op": 255, + "gas": "0x2540b87ce", + "gasCost": "0x1388", + "memSize": 0, + "stack": [ + "0x0" + ], + "depth": 1, + "refund": 0, + "opName": "SELFDESTRUCT" + }, + { + "gasUser": "0x1db2", + "gasTotal": "0x1db2", + "output": "0x" + } + ] +} \ No newline at end of file diff --git a/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/trace/coinbase-warm.json b/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/trace/coinbase-warm.json new file mode 100644 index 00000000000..9140a0268c8 --- /dev/null +++ b/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/trace/coinbase-warm.json @@ -0,0 +1,57 @@ +{ + "cli": [ + "--notime", + "--json", + "--code", + "4131ff", + "--coinbase", + "4444588443C3A91288C5002483449ABA1054192B", + "--fork", + "shanghai" + ], + "stdin": "", + "stdout": [ + { + "pc": 0, + "op": 65, + "gas": "0x2540b91f8", + "gasCost": "0x2", + "memSize": 0, + "stack": [], + "depth": 1, + "refund": 0, + "opName": "COINBASE" + }, + { + "pc": 1, + "op": 49, + "gas": "0x2540b91f6", + "gasCost": "0x64", + "memSize": 0, + "stack": [ + "0x4444588443c3a91288c5002483449aba1054192b" + ], + "depth": 1, + "refund": 0, + "opName": "BALANCE" + }, + { + "pc": 2, + "op": 255, + "gas": "0x2540b9192", + "gasCost": "0x1388", + "memSize": 0, + "stack": [ + "0x0" + ], + "depth": 1, + "refund": 0, + "opName": "SELFDESTRUCT" + }, + { + "gasUser": "0x13ee", + "gasTotal": "0x13ee", + "output": "0x" + } + ] +} \ No newline at end of file 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 5903588fa32..f31cec13f09 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/EVM.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/EVM.java @@ -31,6 +31,7 @@ import org.hyperledger.besu.evm.operation.AddOperation; import org.hyperledger.besu.evm.operation.AndOperation; import org.hyperledger.besu.evm.operation.ByteOperation; +import org.hyperledger.besu.evm.operation.ChainIdOperation; import org.hyperledger.besu.evm.operation.DivOperation; import org.hyperledger.besu.evm.operation.DupOperation; import org.hyperledger.besu.evm.operation.ExpOperation; @@ -139,6 +140,21 @@ public EvmSpecVersion getEvmVersion() { return evmSpecVersion; } + /** + * Return the ChainId this Executor is using, or empty if the EVM version does not expose chain + * ID. + * + * @return the ChainId, or empty if not exposed. + */ + public Optional getChainId() { + Operation op = operations.get(ChainIdOperation.OPCODE); + if (op instanceof ChainIdOperation chainIdOperation) { + return Optional.of(chainIdOperation.getChainId()); + } else { + return Optional.empty(); + } + } + /** * Run to halt. * diff --git a/evm/src/main/java/org/hyperledger/besu/evm/EvmSpecVersion.java b/evm/src/main/java/org/hyperledger/besu/evm/EvmSpecVersion.java index da44cc17c8c..9025670b8d6 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/EvmSpecVersion.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/EvmSpecVersion.java @@ -27,6 +27,10 @@ public enum EvmSpecVersion { FRONTIER(0, true, "Frontier", "Finalized"), /** Homestead evm spec version. */ HOMESTEAD(0, true, "Homestead", "Finalized"), + /** Tangerine Whistle evm spec version. */ + TANGERINE_WHISTLE(0, true, "Tangerine Whistle", "Finalized"), + /** Spurious Dragon evm spec version. */ + SPURIOUS_DRAGON(0, true, "Spuruous Dragon", "Finalized"), /** Byzantium evm spec version. */ BYZANTIUM(0, true, "Byzantium", "Finalized"), /** Constantinople evm spec version. */ diff --git a/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java b/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java index 7884816ecf0..e1398c0dbcf 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java @@ -328,7 +328,12 @@ public static void registerHomesteadOperations( * @return the evm */ public static EVM spuriousDragon(final EvmConfiguration evmConfiguration) { - return homestead(new SpuriousDragonGasCalculator(), evmConfiguration); + GasCalculator gasCalculator = new SpuriousDragonGasCalculator(); + return new EVM( + homesteadOperations(gasCalculator), + gasCalculator, + evmConfiguration, + EvmSpecVersion.SPURIOUS_DRAGON); } /** @@ -338,7 +343,12 @@ public static EVM spuriousDragon(final EvmConfiguration evmConfiguration) { * @return the evm */ public static EVM tangerineWhistle(final EvmConfiguration evmConfiguration) { - return homestead(new TangerineWhistleGasCalculator(), evmConfiguration); + GasCalculator gasCalculator = new TangerineWhistleGasCalculator(); + return new EVM( + homesteadOperations(gasCalculator), + gasCalculator, + evmConfiguration, + EvmSpecVersion.TANGERINE_WHISTLE); } /** @@ -413,11 +423,16 @@ public static EVM constantinople(final EvmConfiguration evmConfiguration) { */ public static EVM constantinople( final GasCalculator gasCalculator, final EvmConfiguration evmConfiguration) { + var version = EvmSpecVersion.CONSTANTINOPLE; + return constantiNOPEl(gasCalculator, evmConfiguration, version); + } + + private static EVM constantiNOPEl( + final GasCalculator gasCalculator, + final EvmConfiguration evmConfiguration, + final EvmSpecVersion version) { return new EVM( - constantinopleOperations(gasCalculator), - gasCalculator, - evmConfiguration, - EvmSpecVersion.CONSTANTINOPLE); + constantinopleOperations(gasCalculator), gasCalculator, evmConfiguration, version); } /** @@ -455,7 +470,8 @@ public static void registerConstantinopleOperations( * @return the evm */ public static EVM petersburg(final EvmConfiguration evmConfiguration) { - return constantinople(new PetersburgGasCalculator(), evmConfiguration); + return constantiNOPEl( + new PetersburgGasCalculator(), evmConfiguration, EvmSpecVersion.PETERSBURG); } /** @@ -1145,7 +1161,7 @@ public static void registerFutureEipsOperations( * @return the evm */ public static EVM experimentalEips(final EvmConfiguration evmConfiguration) { - return futureEips(DEV_NET_CHAIN_ID, evmConfiguration); + return experimentalEips(DEV_NET_CHAIN_ID, evmConfiguration); } /** @@ -1157,7 +1173,7 @@ public static EVM experimentalEips(final EvmConfiguration evmConfiguration) { */ public static EVM experimentalEips( final BigInteger chainId, final EvmConfiguration evmConfiguration) { - return futureEips(chainId, evmConfiguration); + return experimentalEips(new CancunGasCalculator(), chainId, evmConfiguration); } /** @@ -1176,7 +1192,7 @@ public static EVM experimentalEips( experimentalEipsOperations(gasCalculator, chainId), gasCalculator, evmConfiguration, - EvmSpecVersion.FUTURE_EIPS); + EvmSpecVersion.EXPERIMENTAL_EIPS); } /** 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 32e477a2cf4..8df1d1907f6 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 @@ -50,6 +50,7 @@ import com.google.common.collect.HashMultimap; import com.google.common.collect.Multimap; +import com.google.errorprone.annotations.InlineMe; import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; @@ -83,6 +84,7 @@ public class EVMExecutor { private Multimap accessListWarmStorage = HashMultimap.create(); private MessageCallProcessor messageCallProcessor = null; private ContractCreationProcessor contractCreationProcessor = null; + private MessageFrame.Type messageFrameType = MessageFrame.Type.MESSAGE_CALL; private EVMExecutor(final EVM evm) { checkNotNull(evm, "evm must not be null"); @@ -147,6 +149,8 @@ public static EVMExecutor evm( return switch (fork) { case FRONTIER -> frontier(evmConfiguration); case HOMESTEAD -> homestead(evmConfiguration); + case TANGERINE_WHISTLE -> tangerineWhistle(evmConfiguration); + case SPURIOUS_DRAGON -> spuriousDragon(evmConfiguration); case BYZANTIUM -> byzantium(evmConfiguration); case CONSTANTINOPLE -> constantinople(evmConfiguration); case PETERSBURG -> petersburg(evmConfiguration); @@ -283,9 +287,18 @@ public static EVMExecutor petersburg(final EvmConfiguration evmConfiguration) { * * @param evmConfiguration the evm configuration * @return the evm executor - */ + * @deprecated Migrate to use {@link EVMExecutor#evm(EvmSpecVersion)}. + */ + @InlineMe( + replacement = "EVMExecutor.evm(EvmSpecVersion.ISTANBUL, BigInteger.ONE, evmConfiguration)", + imports = { + "java.math.BigInteger", + "org.hyperledger.besu.evm.EvmSpecVersion", + "org.hyperledger.besu.evm.fluent.EVMExecutor" + }) + @Deprecated(forRemoval = true) public static EVMExecutor istanbul(final EvmConfiguration evmConfiguration) { - return istanbul(BigInteger.ONE, evmConfiguration); + return evm(EvmSpecVersion.ISTANBUL, BigInteger.ONE, evmConfiguration); } /** @@ -309,9 +322,18 @@ public static EVMExecutor istanbul( * * @param evmConfiguration the evm configuration * @return the evm executor - */ + * @deprecated Migrate to use {@link EVMExecutor#evm(EvmSpecVersion)}. + */ + @InlineMe( + replacement = "EVMExecutor.evm(EvmSpecVersion.BERLIN, BigInteger.ONE, evmConfiguration)", + imports = { + "java.math.BigInteger", + "org.hyperledger.besu.evm.EvmSpecVersion", + "org.hyperledger.besu.evm.fluent.EVMExecutor" + }) + @Deprecated(forRemoval = true) public static EVMExecutor berlin(final EvmConfiguration evmConfiguration) { - return berlin(BigInteger.ONE, evmConfiguration); + return evm(EvmSpecVersion.BERLIN, BigInteger.ONE, evmConfiguration); } /** @@ -335,9 +357,18 @@ public static EVMExecutor berlin( * * @param evmConfiguration the evm configuration * @return the evm executor - */ + * @deprecated Migrate to use {@link EVMExecutor#evm(EvmSpecVersion)}. + */ + @InlineMe( + replacement = "EVMExecutor.evm(EvmSpecVersion.LONDON, BigInteger.ONE, evmConfiguration)", + imports = { + "java.math.BigInteger", + "org.hyperledger.besu.evm.EvmSpecVersion", + "org.hyperledger.besu.evm.fluent.EVMExecutor" + }) + @Deprecated(forRemoval = true) public static EVMExecutor london(final EvmConfiguration evmConfiguration) { - return london(BigInteger.ONE, evmConfiguration); + return evm(EvmSpecVersion.LONDON, BigInteger.ONE, evmConfiguration); } /** @@ -360,9 +391,18 @@ public static EVMExecutor london( * * @param evmConfiguration the evm configuration * @return the evm executor - */ + * @deprecated Migrate to use {@link EVMExecutor#evm(EvmSpecVersion)}. + */ + @InlineMe( + replacement = "EVMExecutor.evm(EvmSpecVersion.PARIS, BigInteger.ONE, evmConfiguration)", + imports = { + "java.math.BigInteger", + "org.hyperledger.besu.evm.EvmSpecVersion", + "org.hyperledger.besu.evm.fluent.EVMExecutor" + }) + @Deprecated(forRemoval = true) public static EVMExecutor paris(final EvmConfiguration evmConfiguration) { - return paris(BigInteger.ONE, evmConfiguration); + return evm(EvmSpecVersion.PARIS, BigInteger.ONE, evmConfiguration); } /** @@ -385,9 +425,18 @@ public static EVMExecutor paris( * * @param evmConfiguration the evm configuration * @return the evm executor - */ + * @deprecated Migrate to use {@link EVMExecutor#evm(EvmSpecVersion)}. + */ + @InlineMe( + replacement = "EVMExecutor.evm(EvmSpecVersion.SHANGHAI, BigInteger.ONE, evmConfiguration)", + imports = { + "java.math.BigInteger", + "org.hyperledger.besu.evm.EvmSpecVersion", + "org.hyperledger.besu.evm.fluent.EVMExecutor" + }) + @Deprecated(forRemoval = true) public static EVMExecutor shanghai(final EvmConfiguration evmConfiguration) { - return shanghai(BigInteger.ONE, evmConfiguration); + return evm(EvmSpecVersion.SHANGHAI, BigInteger.ONE, evmConfiguration); } /** @@ -410,9 +459,18 @@ public static EVMExecutor shanghai( * * @param evmConfiguration the evm configuration * @return the evm executor - */ + * @deprecated Migrate to use {@link EVMExecutor#evm(EvmSpecVersion)}. + */ + @InlineMe( + replacement = "EVMExecutor.evm(EvmSpecVersion.CANCUN, BigInteger.ONE, evmConfiguration)", + imports = { + "java.math.BigInteger", + "org.hyperledger.besu.evm.EvmSpecVersion", + "org.hyperledger.besu.evm.fluent.EVMExecutor" + }) + @Deprecated(forRemoval = true) public static EVMExecutor cancun(final EvmConfiguration evmConfiguration) { - return cancun(BigInteger.ONE, evmConfiguration); + return evm(EvmSpecVersion.CANCUN, BigInteger.ONE, evmConfiguration); } /** @@ -480,9 +538,18 @@ public static EVMExecutor bogota( * * @param evmConfiguration the evm configuration * @return the evm executor - */ + * @deprecated Migrate to use {@link EVMExecutor#evm(EvmSpecVersion)}. + */ + @InlineMe( + replacement = "EVMExecutor.evm(EvmSpecVersion.FUTURE_EIPS, BigInteger.ONE, evmConfiguration)", + imports = { + "java.math.BigInteger", + "org.hyperledger.besu.evm.EvmSpecVersion", + "org.hyperledger.besu.evm.fluent.EVMExecutor" + }) + @Deprecated(forRemoval = true) public static EVMExecutor futureEips(final EvmConfiguration evmConfiguration) { - return futureEips(BigInteger.ONE, evmConfiguration); + return evm(EvmSpecVersion.FUTURE_EIPS, BigInteger.ONE, evmConfiguration); } /** @@ -580,7 +647,7 @@ public Bytes execute() { final ContractCreationProcessor ccp = thisContractCreationProcessor(); final MessageFrame initialMessageFrame = MessageFrame.builder() - .type(MessageFrame.Type.MESSAGE_CALL) + .type(messageFrameType) .worldUpdater(worldUpdater.updater()) .initialGas(gas) .contract(contract) @@ -623,8 +690,7 @@ public Bytes execute() { * @return the evm executor */ public EVMExecutor commitWorldState() { - this.commitWorldState = true; - return this; + return commitWorldState(true); } /** @@ -763,6 +829,16 @@ public EVMExecutor code(final Code code) { return this; } + /** + * Sets Code. + * + * @param codeBytes the code bytes + * @return the evm executor + */ + public EVMExecutor code(final Bytes codeBytes) { + return code(codeBytes, Hash.hash(codeBytes)); + } + /** * Sets Code. * @@ -834,8 +910,7 @@ public EVMExecutor prevRandao(final Bytes32 prevRandao) { * SimpleBlockValues} */ public EVMExecutor baseFee(final Wei baseFee) { - ((SimpleBlockValues) this.blockValues).setBaseFee(Optional.ofNullable(baseFee)); - return this; + return baseFee(Optional.ofNullable(baseFee)); } /** @@ -1050,4 +1125,32 @@ public EVMExecutor contractCallProcessor( this.contractCreationProcessor = contractCreationProcessor; return this; } + + /** + * Sets the message frame type + * + * @param messageFrameType message frame type + */ + public EVMExecutor messageFrameType(final MessageFrame.Type messageFrameType) { + this.messageFrameType = messageFrameType; + return this; + } + + /** + * Returns the EVM version this executor is using + * + * @return the current EVM version + */ + public EvmSpecVersion getEVMVersion() { + return evm.getEvmVersion(); + } + + /** + * Returns the ChaindD this executor is using + * + * @return the current chain ID + */ + public Optional getChainId() { + return evm.getChainId(); + } } diff --git a/evm/src/main/java/org/hyperledger/besu/evm/operation/ChainIdOperation.java b/evm/src/main/java/org/hyperledger/besu/evm/operation/ChainIdOperation.java index 66918298fa9..9eec2ef83ba 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/operation/ChainIdOperation.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/operation/ChainIdOperation.java @@ -18,11 +18,13 @@ import org.hyperledger.besu.evm.frame.MessageFrame; import org.hyperledger.besu.evm.gascalculator.GasCalculator; +import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.bytes.Bytes32; /** The Chain id operation. */ public class ChainIdOperation extends AbstractFixedCostOperation { + public static final int OPCODE = 0x46; private final Bytes32 chainId; /** @@ -32,10 +34,19 @@ public class ChainIdOperation extends AbstractFixedCostOperation { * @param chainId the chain id */ public ChainIdOperation(final GasCalculator gasCalculator, final Bytes32 chainId) { - super(0x46, "CHAINID", 0, 1, gasCalculator, gasCalculator.getBaseTierGasCost()); + super(OPCODE, "CHAINID", 0, 1, gasCalculator, gasCalculator.getBaseTierGasCost()); this.chainId = chainId; } + /** + * Returns the chain ID this operation uses + * + * @return then chainID; + */ + public Bytes getChainId() { + return chainId; + } + @Override public Operation.OperationResult executeFixedCostOperation( final MessageFrame frame, final EVM evm) { diff --git a/evm/src/test/java/org/hyperledger/besu/evm/StandardJsonTracerTest.java b/evm/src/test/java/org/hyperledger/besu/evm/StandardJsonTracerTest.java index 9ba9ebf96ae..95772986814 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/StandardJsonTracerTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/StandardJsonTracerTest.java @@ -21,7 +21,6 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; import org.hyperledger.besu.evm.fluent.EVMExecutor; -import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.tracing.StandardJsonTracer; import java.io.ByteArrayOutputStream; @@ -37,7 +36,7 @@ void eip3155ModifiedTestCase() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream out = new PrintStream(baos); - var executor = EVMExecutor.istanbul(EvmConfiguration.DEFAULT); + var executor = EVMExecutor.evm(EvmSpecVersion.ISTANBUL); StandardJsonTracer tracer = new StandardJsonTracer(out, true, true, true, false); executor.tracer(tracer); executor.gas(10_000_000_000L); @@ -82,7 +81,7 @@ void updatedStorageTestCase() { ByteArrayOutputStream baos = new ByteArrayOutputStream(); PrintStream out = new PrintStream(baos); - var executor = EVMExecutor.istanbul(EvmConfiguration.DEFAULT); + var executor = EVMExecutor.evm(EvmSpecVersion.ISTANBUL); StandardJsonTracer tracer = new StandardJsonTracer(out, false, false, false, true); executor.tracer(tracer); executor.gas(10_000_000_000L); diff --git a/evm/src/test/java/org/hyperledger/besu/evm/fluent/EVMExecutorTest.java b/evm/src/test/java/org/hyperledger/besu/evm/fluent/EVMExecutorTest.java new file mode 100644 index 00000000000..176f0070980 --- /dev/null +++ b/evm/src/test/java/org/hyperledger/besu/evm/fluent/EVMExecutorTest.java @@ -0,0 +1,229 @@ +/* + * Copyright contributors to Hyperledger Besu + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on + * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + */ +package org.hyperledger.besu.evm.fluent; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import org.hyperledger.besu.datatypes.Address; +import org.hyperledger.besu.datatypes.Hash; +import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.evm.EVM; +import org.hyperledger.besu.evm.EvmSpecVersion; +import org.hyperledger.besu.evm.code.CodeFactory; +import org.hyperledger.besu.evm.frame.MessageFrame; +import org.hyperledger.besu.evm.gascalculator.FrontierGasCalculator; +import org.hyperledger.besu.evm.internal.EvmConfiguration; +import org.hyperledger.besu.evm.operation.OperationRegistry; +import org.hyperledger.besu.evm.precompile.PrecompileContractRegistry; +import org.hyperledger.besu.evm.processor.ContractCreationProcessor; +import org.hyperledger.besu.evm.processor.MessageCallProcessor; +import org.hyperledger.besu.evm.tracing.StandardJsonTracer; + +import java.math.BigInteger; +import java.util.List; +import java.util.Optional; +import java.util.Set; + +import com.google.common.collect.MultimapBuilder; +import org.apache.tuweni.bytes.Bytes; +import org.apache.tuweni.bytes.Bytes32; +import org.jetbrains.annotations.NotNull; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +class EVMExecutorTest { + + @Test + void currentEVM() { + var subject = EVMExecutor.evm(); + assertThat(subject.getEVMVersion()).isEqualTo(EvmSpecVersion.SHANGHAI); + } + + @ParameterizedTest + @EnumSource(EvmSpecVersion.class) + void evmByRequest(final EvmSpecVersion version) { + var subject = EVMExecutor.evm(version); + assertThat(subject.getEVMVersion()).isEqualTo(version); + } + + @ParameterizedTest + @EnumSource(EvmSpecVersion.class) + void evmWithChainIDByRequest(final EvmSpecVersion version) { + var subject = EVMExecutor.evm(version, BigInteger.TEN); + assertThat(subject.getEVMVersion()).isEqualTo(version); + if (EvmSpecVersion.ISTANBUL.compareTo(version) <= 0) { + assertThat(subject.getChainId()).map(Bytes::trimLeadingZeros).map(Bytes::toInt).contains(10); + } else { + assertThat(subject.getChainId()).isEmpty(); + } + } + + @ParameterizedTest + @EnumSource(EvmSpecVersion.class) + void evmWithChainIDByBytes(final EvmSpecVersion version) { + var subject = EVMExecutor.evm(version, Bytes.fromHexString("0xc4a1201d")); + assertThat(subject.getEVMVersion()).isEqualTo(version); + if (EvmSpecVersion.ISTANBUL.compareTo(version) <= 0) { + assertThat(subject.getChainId()) + .map(Bytes::trimLeadingZeros) + .map(Bytes::toInt) + .contains(0xc4a1201d); + } else { + assertThat(subject.getChainId()).isEmpty(); + } + } + + @Test + void customEVM() { + var subject = + EVMExecutor.evm( + new EVM( + new OperationRegistry(), + new FrontierGasCalculator(), + EvmConfiguration.DEFAULT, + EvmSpecVersion.EXPERIMENTAL_EIPS)); + assertThat(subject).isNotNull(); + } + + @Test + void nullEVM() { + assertThrows(NullPointerException.class, () -> EVMExecutor.evm((EVM) null)); + } + + @SuppressWarnings({"removal", "InlineMeInliner"}) + @Test + void defaultChainIdAPIs() { + Bytes32 defaultChainId = Bytes32.leftPad(Bytes.of(1)); + + EVMExecutor istanbulEVM = EVMExecutor.istanbul(EvmConfiguration.DEFAULT); + assertThat(istanbulEVM.getChainId()).contains(defaultChainId); + + EVMExecutor berlinEVM = EVMExecutor.berlin(EvmConfiguration.DEFAULT); + assertThat(berlinEVM.getChainId()).contains(defaultChainId); + + EVMExecutor londonEVM = EVMExecutor.london(EvmConfiguration.DEFAULT); + assertThat(londonEVM.getChainId()).contains(defaultChainId); + + EVMExecutor parisEVM = EVMExecutor.paris(EvmConfiguration.DEFAULT); + assertThat(parisEVM.getChainId()).contains(defaultChainId); + + EVMExecutor shanghaiEVM = EVMExecutor.shanghai(EvmConfiguration.DEFAULT); + assertThat(shanghaiEVM.getChainId()).contains(defaultChainId); + + EVMExecutor cancunEVM = EVMExecutor.cancun(EvmConfiguration.DEFAULT); + assertThat(cancunEVM.getChainId()).contains(defaultChainId); + + EVMExecutor futureEipsVM = EVMExecutor.futureEips(EvmConfiguration.DEFAULT); + assertThat(futureEipsVM.getChainId()).contains(defaultChainId); + } + + @Test + void executeCode() { + var result = + EVMExecutor.evm(EvmSpecVersion.SHANGHAI) + .worldUpdater(createSimpleWorld().updater()) + .execute( + CodeFactory.createCode(Bytes.fromHexString("0x6001600255"), 1, false), + Bytes.EMPTY, + Wei.ZERO, + Address.ZERO); + assertThat(result).isNotNull(); + } + + @Test + void executeBytes() { + var result = + EVMExecutor.evm(EvmSpecVersion.SHANGHAI) + .worldUpdater(createSimpleWorld().updater()) + .execute(Bytes.fromHexString("0x6001600255"), Bytes.EMPTY, Wei.ZERO, Address.ZERO); + assertThat(result).isNotNull(); + } + + @Test + void giantExecuteStack() { + SimpleWorld simpleWorld = createSimpleWorld(); + + var tracer = new StandardJsonTracer(System.out, false, true, true, false); + var result = + EVMExecutor.evm(EvmSpecVersion.SHANGHAI) + .messageFrameType(MessageFrame.Type.CONTRACT_CREATION) + .worldUpdater(simpleWorld.updater()) + .tracer(tracer) + .contract(Address.fromHexString("0x100")) + .gas(15_000_000L) + .sender(Address.fromHexString("0x200")) + .receiver(Address.fromHexString("0x300")) + .coinbase(Address.fromHexString("0x400")) + .number(1) + .timestamp(9999) + .gasLimit(15_000_000) + .commitWorldState() + .gasPriceGWei(Wei.ONE) + .blobGasPrice(Wei.ONE) + .callData(Bytes.fromHexString("0x12345678")) + .ethValue(Wei.fromEth(1)) + .code(CodeFactory.createCode(Bytes.fromHexString("0x6001600255"), 0, false)) + .blockValues(new SimpleBlockValues()) + .difficulty(Bytes.ofUnsignedLong(1L)) + .mixHash(Bytes32.ZERO) + .baseFee(Wei.ONE) + .number(1) + .timestamp(100L) + .gasLimit(15_000_000L) + .blockHashLookup(number -> Hash.ZERO) + .versionedHashes(Optional.empty()) + .precompileContractRegistry(new PrecompileContractRegistry()) + .requireDeposit(false) + .initialNonce(42) + .contractValidationRules(List.of()) + .forceCommitAddresses(List.of()) + .warmAddress(Address.ZERO) + .accessListWarmStorage( + Address.ZERO, Bytes32.ZERO, Bytes32.leftPad(Bytes.ofUnsignedLong(2L))) + .messageCallProcessor(new MessageCallProcessor(null, null)) + .contractCallProcessor(new ContractCreationProcessor(null, null, true, null, 1L)) + .execute(); + assertThat(result).isNotNull(); + } + + @Test + void anternateExecStack() { + SimpleWorld simpleWorld = createSimpleWorld(); + var result = + EVMExecutor.evm(EvmSpecVersion.SHANGHAI) + .worldUpdater(simpleWorld.updater()) + .messageFrameType(MessageFrame.Type.MESSAGE_CALL) + .code(Bytes.fromHexString("0x6001600255")) + .prevRandao(Bytes32.ZERO) + .accessListWarmAddresses(Set.of()) + .accessListWarmStorage(MultimapBuilder.linkedHashKeys().arrayListValues().build()) + .execute(); + assertThat(result).isNotNull(); + } + + @NotNull + private static SimpleWorld createSimpleWorld() { + SimpleWorld simpleWorld = new SimpleWorld(); + + simpleWorld.createAccount(Address.fromHexString("0x0"), 1, Wei.fromEth(100)); + simpleWorld.createAccount(Address.fromHexString("0x100"), 1, Wei.fromEth(100)); + simpleWorld.createAccount(Address.fromHexString("0x200"), 1, Wei.fromEth(100)); + simpleWorld.createAccount(Address.fromHexString("0x300"), 1, Wei.fromEth(100)); + simpleWorld.createAccount(Address.fromHexString("0x400"), 1, Wei.fromEth(100)); + return simpleWorld; + } +} diff --git a/evm/src/test/java/org/hyperledger/besu/evm/processor/AbstractMessageProcessorTest.java b/evm/src/test/java/org/hyperledger/besu/evm/processor/AbstractMessageProcessorTest.java index 7932741b3d7..598758fb752 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/processor/AbstractMessageProcessorTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/processor/AbstractMessageProcessorTest.java @@ -26,9 +26,9 @@ import org.hyperledger.besu.datatypes.Address; import org.hyperledger.besu.datatypes.Wei; +import org.hyperledger.besu.evm.EvmSpecVersion; import org.hyperledger.besu.evm.fluent.EVMExecutor; import org.hyperledger.besu.evm.frame.MessageFrame; -import org.hyperledger.besu.evm.internal.EvmConfiguration; import org.hyperledger.besu.evm.operation.Operation; import org.hyperledger.besu.evm.tracing.OperationTracer; import org.hyperledger.besu.evm.worldstate.WorldUpdater; @@ -99,7 +99,7 @@ void shouldTraceContextIfStackSizeIsGreaterZeroAndFailure(final int stackSize) { @Test void shouldTraceContextEnterExitForEip3155Test() { - final EVMExecutor executor = EVMExecutor.shanghai(EvmConfiguration.DEFAULT); + final EVMExecutor executor = EVMExecutor.evm(EvmSpecVersion.SHANGHAI); final ContextTracer contextTracer = new ContextTracer(); executor.tracer(contextTracer);