diff --git a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java index 4262ff9644..7e1be15fb6 100644 --- a/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java +++ b/besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java @@ -1514,6 +1514,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable { } if (genesisConfigOptionsSupplier.get().getCancunTime().isPresent() + || genesisConfigOptionsSupplier.get().getCancunEOFTime().isPresent() || genesisConfigOptionsSupplier.get().getPragueTime().isPresent() || genesisConfigOptionsSupplier.get().getPragueEOFTime().isPresent()) { if (kzgTrustedSetupFile != null) { diff --git a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java index 8e47af3b75..849b121186 100644 --- a/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/GenesisConfigOptions.java @@ -242,6 +242,13 @@ public interface GenesisConfigOptions { */ OptionalLong getCancunTime(); + /** + * Gets cancun EOF time. + * + * @return the cancun EOF time + */ + OptionalLong getCancunEOFTime(); + /** * Gets prague time. * diff --git a/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java index d5635d9ae3..b418a67851 100644 --- a/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/JsonGenesisConfigOptions.java @@ -288,6 +288,11 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions { return getOptionalLong("shanghaitime"); } + @Override + public OptionalLong getCancunEOFTime() { + return getOptionalLong("cancuneoftime"); + } + @Override public OptionalLong getCancunTime() { return getOptionalLong("cancuntime"); @@ -461,6 +466,7 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions { getMergeNetSplitBlockNumber().ifPresent(l -> builder.put("mergeNetSplitBlock", l)); getShanghaiTime().ifPresent(l -> builder.put("shanghaiTime", l)); getCancunTime().ifPresent(l -> builder.put("cancunTime", l)); + getCancunEOFTime().ifPresent(l -> builder.put("cancunEOFTime", l)); getPragueTime().ifPresent(l -> builder.put("pragueTime", l)); getPragueEOFTime().ifPresent(l -> builder.put("pragueEOFTime", l)); getTerminalBlockNumber().ifPresent(l -> builder.put("terminalBlockNumber", l)); @@ -610,6 +616,7 @@ public class JsonGenesisConfigOptions implements GenesisConfigOptions { Stream.of( getShanghaiTime(), getCancunTime(), + getCancunEOFTime(), getPragueTime(), getPragueEOFTime(), getFutureEipsTime(), diff --git a/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java b/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java index 32800f58a1..24f3331029 100644 --- a/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java +++ b/config/src/main/java/org/hyperledger/besu/config/StubGenesisConfigOptions.java @@ -48,6 +48,7 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions, Cloneable private OptionalLong mergeNetSplitBlockNumber = OptionalLong.empty(); private OptionalLong shanghaiTime = OptionalLong.empty(); private OptionalLong cancunTime = OptionalLong.empty(); + private OptionalLong cancunEOFTime = OptionalLong.empty(); private OptionalLong pragueTime = OptionalLong.empty(); private OptionalLong pragueEOFTime = OptionalLong.empty(); private OptionalLong futureEipsTime = OptionalLong.empty(); @@ -82,7 +83,9 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions, Cloneable private boolean fixedBaseFee = false; /** Default constructor. */ - public StubGenesisConfigOptions() {} + public StubGenesisConfigOptions() { + // Explicit default constructor because of JavaDoc linting + } @Override public StubGenesisConfigOptions clone() { @@ -238,6 +241,11 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions, Cloneable return cancunTime; } + @Override + public OptionalLong getCancunEOFTime() { + return cancunEOFTime; + } + @Override public OptionalLong getPragueTime() { return pragueTime; @@ -630,6 +638,17 @@ public class StubGenesisConfigOptions implements GenesisConfigOptions, Cloneable return this; } + /** + * Cancun EOF time. + * + * @param timestamp the timestamp + * @return the stub genesis config options + */ + public StubGenesisConfigOptions cancunEOFTime(final long timestamp) { + cancunEOFTime = OptionalLong.of(timestamp); + return this; + } + /** * Prague time. * diff --git a/config/src/test/java/org/hyperledger/besu/config/GenesisConfigOptionsTest.java b/config/src/test/java/org/hyperledger/besu/config/GenesisConfigOptionsTest.java index 0e8138e1bc..ed313ad6cf 100644 --- a/config/src/test/java/org/hyperledger/besu/config/GenesisConfigOptionsTest.java +++ b/config/src/test/java/org/hyperledger/besu/config/GenesisConfigOptionsTest.java @@ -193,6 +193,13 @@ class GenesisConfigOptionsTest { assertThat(config.getCancunTime()).hasValue(1670470142); } + @Test + void shouldGetCancunEOFTime() { + final GenesisConfigOptions config = + fromConfigOptions(singletonMap("cancunEOFTime", 1670470142)); + assertThat(config.getCancunEOFTime()).hasValue(1670470142); + } + @Test void shouldGetPragueTime() { final GenesisConfigOptions config = fromConfigOptions(singletonMap("pragueTime", 1670470143)); @@ -238,6 +245,7 @@ class GenesisConfigOptionsTest { assertThat(config.getMergeNetSplitBlockNumber()).isEmpty(); assertThat(config.getShanghaiTime()).isEmpty(); assertThat(config.getCancunTime()).isEmpty(); + assertThat(config.getCancunEOFTime()).isEmpty(); assertThat(config.getPragueTime()).isEmpty(); assertThat(config.getPragueEOFTime()).isEmpty(); assertThat(config.getFutureEipsTime()).isEmpty(); diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java index e975a01f8f..00b20a0170 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java @@ -304,7 +304,15 @@ public final class GenesisState { if (cancunTimestamp.isPresent()) { return genesis.getTimestamp() >= cancunTimestamp.getAsLong(); } - return isPragueAtGenesis(genesis); + return isPragueAtGenesis(genesis) || isCancunEOFAtGenesis(genesis); + } + + private static boolean isCancunEOFAtGenesis(final GenesisConfigFile genesis) { + final OptionalLong cancunEOFTimestamp = genesis.getConfigOptions().getCancunEOFTime(); + if (cancunEOFTimestamp.isPresent()) { + return genesis.getTimestamp() >= cancunEOFTimestamp.getAsLong(); + } + return isPragueEOFAtGenesis(genesis); } private static boolean isPragueAtGenesis(final GenesisConfigFile genesis) { diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecFactory.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecFactory.java index a902d9faa7..aa9bae6c7e 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecFactory.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/MainnetProtocolSpecFactory.java @@ -128,6 +128,11 @@ public class MainnetProtocolSpecFactory { chainId, isRevertReasonEnabled, genesisConfigOptions, evmConfiguration, miningParameters); } + public ProtocolSpecBuilder cancunEOFDefinition(final GenesisConfigOptions genesisConfigOptions) { + return MainnetProtocolSpecs.cancunEOFDefinition( + chainId, isRevertReasonEnabled, genesisConfigOptions, evmConfiguration, miningParameters); + } + public ProtocolSpecBuilder pragueDefinition(final GenesisConfigOptions genesisConfigOptions) { return MainnetProtocolSpecs.pragueDefinition( chainId, isRevertReasonEnabled, genesisConfigOptions, evmConfiguration, miningParameters); 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 763c751e4f..b4a75c49c2 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 @@ -617,6 +617,19 @@ public abstract class MainnetProtocolSpecs { .name("Cancun"); } + static ProtocolSpecBuilder cancunEOFDefinition( + final Optional chainId, + final boolean enableRevertReason, + final GenesisConfigOptions genesisConfigOptions, + final EvmConfiguration evmConfiguration, + final MiningParameters miningParameters) { + + ProtocolSpecBuilder protocolSpecBuilder = + cancunDefinition( + chainId, enableRevertReason, genesisConfigOptions, evmConfiguration, miningParameters); + return addEOF(chainId, evmConfiguration, protocolSpecBuilder).name("CancunEOF"); + } + static ProtocolSpecBuilder pragueDefinition( final Optional chainId, final boolean enableRevertReason, @@ -657,8 +670,17 @@ public abstract class MainnetProtocolSpecs { final EvmConfiguration evmConfiguration, final MiningParameters miningParameters) { - return pragueDefinition( - chainId, enableRevertReason, genesisConfigOptions, evmConfiguration, miningParameters) + ProtocolSpecBuilder protocolSpecBuilder = + pragueDefinition( + chainId, enableRevertReason, genesisConfigOptions, evmConfiguration, miningParameters); + return addEOF(chainId, evmConfiguration, protocolSpecBuilder).name("PragueEOF"); + } + + private static ProtocolSpecBuilder addEOF( + final Optional chainId, + final EvmConfiguration evmConfiguration, + final ProtocolSpecBuilder protocolSpecBuilder) { + return protocolSpecBuilder // EIP-7692 EOF v1 Gas calculator .gasCalculator(PragueEOFGasCalculator::new) // EIP-7692 EOF v1 EVM and opcodes @@ -674,8 +696,7 @@ public abstract class MainnetProtocolSpecs { true, List.of(MaxCodeSizeRule.from(evm), EOFValidationCodeRule.from(evm)), 1, - SPURIOUS_DRAGON_FORCE_DELETE_WHEN_EMPTY_ADDRESSES)) - .name("PragueEOF"); + SPURIOUS_DRAGON_FORCE_DELETE_WHEN_EMPTY_ADDRESSES)); } static ProtocolSpecBuilder futureEipsDefinition( diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java index 100a4425cd..649442f88c 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ProtocolScheduleBuilder.java @@ -246,6 +246,7 @@ public class ProtocolScheduleBuilder { // Begin timestamp forks lastForkBlock = validateForkOrder("Shanghai", config.getShanghaiTime(), lastForkBlock); lastForkBlock = validateForkOrder("Cancun", config.getCancunTime(), lastForkBlock); + lastForkBlock = validateForkOrder("CancunEOF", config.getCancunEOFTime(), lastForkBlock); lastForkBlock = validateForkOrder("Prague", config.getPragueTime(), lastForkBlock); lastForkBlock = validateForkOrder("PragueEOF", config.getPragueEOFTime(), lastForkBlock); lastForkBlock = validateForkOrder("FutureEips", config.getFutureEipsTime(), lastForkBlock); @@ -326,6 +327,7 @@ public class ProtocolScheduleBuilder { // Timestamp Forks timestampMilestone(config.getShanghaiTime(), specFactory.shanghaiDefinition(config)), timestampMilestone(config.getCancunTime(), specFactory.cancunDefinition(config)), + timestampMilestone(config.getCancunEOFTime(), specFactory.cancunEOFDefinition(config)), timestampMilestone(config.getPragueTime(), specFactory.pragueDefinition(config)), timestampMilestone(config.getPragueEOFTime(), specFactory.pragueEOFDefinition(config)), timestampMilestone(config.getFutureEipsTime(), specFactory.futureEipsDefinition(config)), diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/MainnetGenesisFileModule.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/MainnetGenesisFileModule.java index dc6b6dce00..db70ccf41f 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/MainnetGenesisFileModule.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/MainnetGenesisFileModule.java @@ -117,6 +117,9 @@ class MainnetGenesisFileModule extends GenesisFileModule { Map.entry( "cancun", createSchedule(new StubGenesisConfigOptions().cancunTime(0).baseFeePerGas(0x0a))), + Map.entry( + "cancuneof", + createSchedule(new StubGenesisConfigOptions().cancunEOFTime(0).baseFeePerGas(0x0a))), Map.entry( "prague", createSchedule(new StubGenesisConfigOptions().pragueTime(0).baseFeePerGas(0x0a))), diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/benchmarks/BenchmarkExecutor.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/benchmarks/BenchmarkExecutor.java index 50a6df67d4..082fae7f69 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/benchmarks/BenchmarkExecutor.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/benchmarks/BenchmarkExecutor.java @@ -113,12 +113,12 @@ public abstract class BenchmarkExecutor { } timer.stop(); - if (executions < 1) { + if (executions > 0) { + final double elapsed = timer.elapsed(TimeUnit.NANOSECONDS) / 1.0e9D; + return elapsed / executions; + } else { return Double.NaN; } - - final double elapsed = timer.elapsed(TimeUnit.NANOSECONDS) / 1.0e9D; - return elapsed / executions; } /** @@ -143,7 +143,15 @@ public abstract class BenchmarkExecutor { case SHANGHAI -> new ShanghaiGasCalculator(); case CANCUN -> new CancunGasCalculator(); case PRAGUE -> new PragueGasCalculator(); - case PRAGUE_EOF, OSAKA, AMSTERDAM, BOGOTA, POLIS, BANGKOK, FUTURE_EIPS, EXPERIMENTAL_EIPS -> + case CANCUN_EOF, + PRAGUE_EOF, + OSAKA, + AMSTERDAM, + BOGOTA, + POLIS, + BANGKOK, + FUTURE_EIPS, + EXPERIMENTAL_EIPS -> new PragueEOFGasCalculator(); }; } diff --git a/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/state-test/create-eof.json b/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/state-test/create-eof.json index 4e8529872d..e924043042 100644 --- a/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/state-test/create-eof.json +++ b/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/state-test/create-eof.json @@ -45,7 +45,7 @@ }, "out": "0x", "post": { - "Prague": [ + "CancunEOF": [ { "hash": "0x1a8642a04dae90535f00f53d3a30284c4db051d508a653db89eb100ba9aecbf3", "logs": "0xf48b954a6a6f4ce6b28e4950b7027413f4bdc8f459df6003b6e8d7a1567c8940", @@ -79,7 +79,7 @@ {"pc":5,"section":0,"op":95,"gas":"0x793d71","gasCost":"0x2","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"PUSH0"}, {"pc":6,"section":0,"op":95,"gas":"0x793d6f","gasCost":"0x2","memSize":0,"stack":["0x0"],"depth":1,"refund":0,"opName":"PUSH0"}, {"pc":7,"section":0,"op":238,"immediate":"0x00","gas":"0x793d6d","gasCost":"0x0","memSize":0,"stack":["0x0","0x0"],"depth":1,"refund":0,"opName":"RETURNCONTRACT"}, - {"output":"","gasUsed":"0xe433","test":"create-eof","fork":"Prague","d":0,"g":0,"v":0,"postHash":"0x1a8642a04dae90535f00f53d3a30284c4db051d508a653db89eb100ba9aecbf3","postLogsHash":"0xf48b954a6a6f4ce6b28e4950b7027413f4bdc8f459df6003b6e8d7a1567c8940","pass":true}, + {"output":"","gasUsed":"0xe433","test":"create-eof","fork":"CancunEOF","d":0,"g":0,"v":0,"postHash":"0x1a8642a04dae90535f00f53d3a30284c4db051d508a653db89eb100ba9aecbf3","postLogsHash":"0xf48b954a6a6f4ce6b28e4950b7027413f4bdc8f459df6003b6e8d7a1567c8940","pass":true}, {"pc":0,"op":239,"gas":"0x794068","gasCost":"0x0","memSize":0,"stack":[],"depth":1,"refund":0,"opName":"INVALID","error":"Bad instruction"}, {"output":"","gasUsed":"0x7a1200","test":"create-eof","fork":"Cancun","d":0,"g":0,"v":0,"postHash":"0xaa80d89bc89f58da8de41d3894bd1a241896ff91f7a5964edaefb39e8e3a4a98","postLogsHash":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","pass":true,"error":"INVALID_OPERATION"} ] diff --git a/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/trace/create-eof.json b/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/trace/create-eof.json index bba2c85103..b0699f1b3c 100644 --- a/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/trace/create-eof.json +++ b/ethereum/evmtool/src/test/resources/org/hyperledger/besu/evmtool/trace/create-eof.json @@ -8,7 +8,7 @@ "--coinbase", "4444588443C3A91288C5002483449ABA1054192B", "--fork", - "pragueeof" + "CancunEOF" ], "stdin": "", "stdout": [ diff --git a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestProtocolSchedules.java b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestProtocolSchedules.java index 0976b92421..4d62c314ae 100644 --- a/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestProtocolSchedules.java +++ b/ethereum/referencetests/src/main/java/org/hyperledger/besu/ethereum/referencetests/ReferenceTestProtocolSchedules.java @@ -84,6 +84,7 @@ public class ReferenceTestProtocolSchedules { "ShanghaiToCancunAtTime15k", createSchedule(genesisStub.clone().shanghaiTime(0).cancunTime(15000))); builder.put("Cancun", createSchedule(genesisStub.clone().cancunTime(0))); + builder.put("CancunEOF", createSchedule(genesisStub.clone().cancunEOFTime(0))); // also load KZG file for mainnet KZGPointEvalPrecompiledContract.init(); builder.put( 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 9bf370d031..8dc536c7bf 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/EvmSpecVersion.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/EvmSpecVersion.java @@ -55,6 +55,8 @@ public enum EvmSpecVersion { SHANGHAI(0x6000, 0xc000, 0, true, "Shanghai", "Finalized"), /** Cancun evm spec version. */ CANCUN(0x6000, 0xc000, 0, true, "Cancun", "Finalized"), + /** Cancun evm spec version. */ + CANCUN_EOF(0x6000, 0xc000, 1, false, "CancunEOF", "For Testing"), /** Prague evm spec version. */ PRAGUE(0x6000, 0xc000, 0, false, "Prague", "In Development"), /** PragueEOF evm spec version. */ @@ -201,6 +203,10 @@ public enum EvmSpecVersion { if ("prague".equalsIgnoreCase(name)) { return EvmSpecVersion.PRAGUE_EOF; } + // TODO remove once PragueEOF settles + if ("cancuneof".equalsIgnoreCase(name)) { + return EvmSpecVersion.CANCUN_EOF; + } for (var version : EvmSpecVersion.values()) { if (version.name().equalsIgnoreCase(name)) { return 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 11ce3546a8..2d9be8d312 100644 --- a/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java +++ b/evm/src/main/java/org/hyperledger/besu/evm/MainnetEVMs.java @@ -897,6 +897,76 @@ public class MainnetEVMs { registry.put(new BlobBaseFeeOperation(gasCalculator)); } + /** + * CancunEOF evm. + * + * @param evmConfiguration the evm configuration + * @return the evm + */ + public static EVM cancunEOF(final EvmConfiguration evmConfiguration) { + return cancunEOF(DEV_NET_CHAIN_ID, evmConfiguration); + } + + /** + * CancunEOF evm. + * + * @param chainId the chain id + * @param evmConfiguration the evm configuration + * @return the evm + */ + public static EVM cancunEOF(final BigInteger chainId, final EvmConfiguration evmConfiguration) { + return cancunEOF(new CancunGasCalculator(), chainId, evmConfiguration); + } + + /** + * CancunEOF evm. + * + * @param gasCalculator the gas calculator + * @param chainId the chain id + * @param evmConfiguration the evm configuration + * @return the evm + */ + public static EVM cancunEOF( + final GasCalculator gasCalculator, + final BigInteger chainId, + final EvmConfiguration evmConfiguration) { + return new EVM( + cancunEOFOperations(gasCalculator, chainId), + gasCalculator, + evmConfiguration, + EvmSpecVersion.CANCUN_EOF); + } + + /** + * Operation registry for PragueEOF's operations. + * + * @param gasCalculator the gas calculator + * @param chainId the chain id + * @return the operation registry + */ + public static OperationRegistry cancunEOFOperations( + final GasCalculator gasCalculator, final BigInteger chainId) { + OperationRegistry operationRegistry = new OperationRegistry(); + registerCancunEOFOperations(operationRegistry, gasCalculator, chainId); + return operationRegistry; + } + + /** + * Register CancunEOF's operations. + * + * @param registry the registry + * @param gasCalculator the gas calculator + * @param chainID the chain id + */ + public static void registerCancunEOFOperations( + final OperationRegistry registry, + final GasCalculator gasCalculator, + final BigInteger chainID) { + registerCancunOperations(registry, gasCalculator, chainID); + + registerEOFOperations(registry, gasCalculator); + } + /** * Prague evm. * @@ -1034,6 +1104,11 @@ public class MainnetEVMs { final BigInteger chainID) { registerPragueOperations(registry, gasCalculator, chainID); + registerEOFOperations(registry, gasCalculator); + } + + private static void registerEOFOperations( + final OperationRegistry registry, final GasCalculator gasCalculator) { // EIP-663 Unlimited Swap and Dup registry.put(new DupNOperation(gasCalculator)); registry.put(new SwapNOperation(gasCalculator)); 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 a65bd034d5..08b7a067a1 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 @@ -160,6 +160,7 @@ public class EVMExecutor { case PARIS -> paris(chainId, evmConfiguration); case SHANGHAI -> shanghai(chainId, evmConfiguration); case CANCUN -> cancun(chainId, evmConfiguration); + case CANCUN_EOF -> cancunEOF(chainId, evmConfiguration); case PRAGUE -> prague(chainId, evmConfiguration); case PRAGUE_EOF -> pragueEOF(chainId, evmConfiguration); case OSAKA -> osaka(chainId, evmConfiguration); @@ -493,6 +494,21 @@ public class EVMExecutor { return executor; } + /** + * Instantiate Cancun EOF evm executor. + * + * @param chainId the chain ID + * @param evmConfiguration the evm configuration + * @return the evm executor + */ + public static EVMExecutor cancunEOF( + final BigInteger chainId, final EvmConfiguration evmConfiguration) { + final EVMExecutor executor = new EVMExecutor(MainnetEVMs.cancunEOF(chainId, evmConfiguration)); + executor.precompileContractRegistry = + MainnetPrecompiledContracts.cancun(executor.evm.getGasCalculator()); + return executor; + } + /** * Instantiate Prague evm executor. * 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 index a080f649c9..aa9dcdb23f 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/fluent/EVMExecutorTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/fluent/EVMExecutorTest.java @@ -126,6 +126,10 @@ class EVMExecutorTest { EVMExecutor cancunEVM = EVMExecutor.cancun(EvmConfiguration.DEFAULT); assertThat(cancunEVM.getChainId()).contains(defaultChainId); + EVMExecutor cancunEOFEVM = + EVMExecutor.cancunEOF(defaultChainId.toBigInteger(), EvmConfiguration.DEFAULT); + assertThat(cancunEOFEVM.getChainId()).contains(defaultChainId); + EVMExecutor pragueEVM = EVMExecutor.pragueEOF(defaultChainId.toBigInteger(), EvmConfiguration.DEFAULT); assertThat(pragueEVM.getChainId()).contains(defaultChainId); diff --git a/evm/src/test/java/org/hyperledger/besu/evm/operations/EofCreateOperationTest.java b/evm/src/test/java/org/hyperledger/besu/evm/operations/EofCreateOperationTest.java index c0a7f2bcc4..86a0f8cce1 100644 --- a/evm/src/test/java/org/hyperledger/besu/evm/operations/EofCreateOperationTest.java +++ b/evm/src/test/java/org/hyperledger/besu/evm/operations/EofCreateOperationTest.java @@ -62,7 +62,7 @@ class EofCreateOperationTest { @Test void innerContractIsCorrect() { - final EVM evm = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT); + final EVM evm = MainnetEVMs.cancunEOF(EvmConfiguration.DEFAULT); Code code = evm.getCodeUncached(INNER_CONTRACT); assertThat(code.isValid()).isTrue(); @@ -92,7 +92,7 @@ class EofCreateOperationTest { @Test void eofCreatePassesInCallData() { Bytes outerContract = EOF_CREATE_CONTRACT; - final EVM evm = MainnetEVMs.pragueEOF(EvmConfiguration.DEFAULT); + final EVM evm = MainnetEVMs.cancunEOF(EvmConfiguration.DEFAULT); Code code = evm.getCodeUncached(outerContract); if (!code.isValid()) {