From 1cd15a86f6cd92290f98333fe0955a09ffd0f949 Mon Sep 17 00:00:00 2001 From: Danno Ferrin Date: Fri, 13 Jan 2023 14:37:02 -0700 Subject: [PATCH] Add '--fork=' to EvmTool (#4913) * Add '--fork=' to EvmTool Add a CLI '--fork' option to allow code to be evaluated in specific forks. Signed-off-by: Danno Ferrin --- CHANGELOG.md | 9 ++ config/src/main/resources/experimental.json | 7 +- config/src/main/resources/future.json | 7 +- .../besu/ethereum/chain/GenesisState.java | 22 ++-- .../ScheduleBasedBlockHeaderFunctions.java | 14 ++- .../besu/evmtool/CliqueGenesisFileModule.java | 6 +- .../besu/evmtool/EvmToolCommand.java | 3 +- .../evmtool/EvmToolCommandOptionsModule.java | 13 +++ .../besu/evmtool/EvmToolComponent.java | 3 +- .../besu/evmtool/GenesisFileModule.java | 9 +- .../besu/evmtool/IBFTGenesisFileModule.java | 6 +- .../evmtool/MainnetGenesisFileModule.java | 102 +++++++++++++++++- .../besu/evmtool/ProtocolModule.java | 8 +- .../besu/evmtool/QBFTGenesisFileModule.java | 6 +- 14 files changed, 178 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1d573ec902c..3699a671c33 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## 23.1.1 + +### Breaking Changes + +### Additions and Improvements +- Added option to evm CLI tool to allow code execution at specific forks [#4913](https://github.com/hyperledger/besu/pull/4913) + +### Bug Fixes + ## 23.1.0 ### Breaking Changes diff --git a/config/src/main/resources/experimental.json b/config/src/main/resources/experimental.json index d5dba12d4a1..f73b46d84ee 100644 --- a/config/src/main/resources/experimental.json +++ b/config/src/main/resources/experimental.json @@ -4,7 +4,12 @@ "experimentalEipsTime": 0, "contractSizeLimit": 2147483647, "ethash": { - "fixeddifficulty": 100 + }, + "terminalTotalDifficulty": 0, + "checkpoint": { + "hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "number": 0, + "totalDifficulty": "0x0" } }, "nonce": "0x42", diff --git a/config/src/main/resources/future.json b/config/src/main/resources/future.json index 38a5ca10fcb..0d375369834 100644 --- a/config/src/main/resources/future.json +++ b/config/src/main/resources/future.json @@ -3,7 +3,12 @@ "chainId": 2022, "futureEipsTime": 0, "ethash": { - "fixeddifficulty": 100 + }, + "terminalTotalDifficulty": 0, + "checkpoint": { + "hash": "0x0000000000000000000000000000000000000000000000000000000000000000", + "number": 0, + "totalDifficulty": "0x0" } }, "nonce": "0x42", 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 4c32d7a4fe2..bd77eafaef7 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 @@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder; import org.hyperledger.besu.ethereum.core.Difficulty; import org.hyperledger.besu.ethereum.core.MutableWorldState; +import org.hyperledger.besu.ethereum.mainnet.HeaderBasedProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions; import org.hyperledger.besu.ethereum.storage.keyvalue.WorldStateKeyValueStorage; @@ -81,7 +82,7 @@ public static GenesisState fromJson(final String json, final ProtocolSchedule pr * @return A new {@link GenesisState}. */ public static GenesisState fromConfig( - final GenesisConfigFile config, final ProtocolSchedule protocolSchedule) { + final GenesisConfigFile config, final HeaderBasedProtocolSchedule protocolSchedule) { final List genesisAccounts = parseAllocations(config).collect(Collectors.toList()); final Block block = @@ -135,7 +136,7 @@ private static Hash calculateGenesisStateHash(final List genesis private static BlockHeader buildHeader( final GenesisConfigFile genesis, final Hash genesisRootHash, - final ProtocolSchedule protocolSchedule) { + final HeaderBasedProtocolSchedule protocolSchedule) { return BlockHeaderBuilder.create() .parentHash(parseParentHash(genesis)) @@ -263,16 +264,13 @@ private Wei parseBalance(final String balance) { private Map parseStorage(final Map storage) { final Map parsedStorage = new HashMap<>(); - storage - .entrySet() - .forEach( - entry -> { - final UInt256 key = - withNiceErrorMessage("storage key", entry.getKey(), UInt256::fromHexString); - final UInt256 value = - withNiceErrorMessage("storage value", entry.getValue(), UInt256::fromHexString); - parsedStorage.put(key, value); - }); + storage.forEach( + (key1, value1) -> { + final UInt256 key = withNiceErrorMessage("storage key", key1, UInt256::fromHexString); + final UInt256 value = + withNiceErrorMessage("storage value", value1, UInt256::fromHexString); + parsedStorage.put(key, value); + }); return parsedStorage; } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ScheduleBasedBlockHeaderFunctions.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ScheduleBasedBlockHeaderFunctions.java index 43a521123a4..651a93dc983 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ScheduleBasedBlockHeaderFunctions.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ScheduleBasedBlockHeaderFunctions.java @@ -26,13 +26,13 @@ */ public class ScheduleBasedBlockHeaderFunctions implements BlockHeaderFunctions { - private final ProtocolSchedule protocolSchedule; + private final HeaderBasedProtocolSchedule protocolSchedule; - private ScheduleBasedBlockHeaderFunctions(final ProtocolSchedule protocolSchedule) { + private ScheduleBasedBlockHeaderFunctions(final HeaderBasedProtocolSchedule protocolSchedule) { this.protocolSchedule = protocolSchedule; } - public static BlockHeaderFunctions create(final ProtocolSchedule protocolSchedule) { + public static BlockHeaderFunctions create(final HeaderBasedProtocolSchedule protocolSchedule) { return new ScheduleBasedBlockHeaderFunctions(protocolSchedule); } @@ -47,6 +47,12 @@ public ParsedExtraData parseExtraData(final BlockHeader header) { } private BlockHeaderFunctions getBlockHeaderFunctions(final SealableBlockHeader header) { - return protocolSchedule.getByBlockNumber(header.getNumber()).getBlockHeaderFunctions(); + if (protocolSchedule instanceof ProtocolSchedule) { + return ((ProtocolSchedule) protocolSchedule) + .getByBlockNumber(header.getNumber()) + .getBlockHeaderFunctions(); + } else { + return protocolSchedule.getByBlockHeader(header).getBlockHeaderFunctions(); + } } } diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/CliqueGenesisFileModule.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/CliqueGenesisFileModule.java index 30dfed3100e..890de053616 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/CliqueGenesisFileModule.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/CliqueGenesisFileModule.java @@ -22,9 +22,10 @@ import org.hyperledger.besu.crypto.NodeKey; import org.hyperledger.besu.crypto.SignatureAlgorithmFactory; import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; -import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +import org.hyperledger.besu.ethereum.mainnet.HeaderBasedProtocolSchedule; import org.hyperledger.besu.evm.internal.EvmConfiguration; +import java.util.Optional; import javax.inject.Named; class CliqueGenesisFileModule extends GenesisFileModule { @@ -38,8 +39,9 @@ class CliqueGenesisFileModule extends GenesisFileModule { } @Override - ProtocolSchedule provideProtocolSchedule( + HeaderBasedProtocolSchedule provideProtocolSchedule( final GenesisConfigOptions configOptions, + @Named("Fork") final Optional fork, @Named("RevertReasonEnabled") final boolean revertReasonEnabled) { // dagger can handle this magic one day return CliqueProtocolSchedule.create( diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java index b8bf244dc1d..ed140c01369 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java @@ -222,7 +222,8 @@ public void run() { int remainingIters = this.repeat; Log4j2ConfiguratorUtil.setLevel( "org.hyperledger.besu.ethereum.mainnet.AbstractProtocolScheduleBuilder", Level.OFF); - final ProtocolSpec protocolSpec = component.getProtocolSpec().apply(0); + final ProtocolSpec protocolSpec = + component.getProtocolSpec().apply(BlockHeaderBuilder.createDefault().buildBlockHeader()); Log4j2ConfiguratorUtil.setLevel( "org.hyperledger.besu.ethereum.mainnet.AbstractProtocolScheduleBuilder", null); final Transaction tx = diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommandOptionsModule.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommandOptionsModule.java index 7296a0e86de..9c97c8d36f8 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommandOptionsModule.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommandOptionsModule.java @@ -24,6 +24,7 @@ import org.hyperledger.besu.services.BesuConfigurationImpl; import java.nio.file.Path; +import java.util.Optional; import javax.inject.Named; import javax.inject.Singleton; @@ -50,6 +51,18 @@ boolean provideRevertReasonEnabled() { return revertReasonEnabled; } + @Option( + names = {"--fork"}, + paramLabel = "", + description = "Fork to evaluate, overriding network setting.") + String fork = null; + + @Provides + @Named("Fork") + Optional provideFork() { + return Optional.ofNullable(fork); + } + @SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings. @Option( names = {"--key-value-storage"}, diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolComponent.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolComponent.java index f54bc2a93f2..b5c4fc4d6f8 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolComponent.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolComponent.java @@ -16,6 +16,7 @@ package org.hyperledger.besu.evmtool; import org.hyperledger.besu.ethereum.chain.Blockchain; +import org.hyperledger.besu.ethereum.core.BlockHeader; import org.hyperledger.besu.ethereum.core.MutableWorldState; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; import org.hyperledger.besu.evm.worldstate.WorldUpdater; @@ -37,7 +38,7 @@ }) public interface EvmToolComponent { - Function getProtocolSpec(); + Function getProtocolSpec(); WorldUpdater getWorldUpdater(); diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/GenesisFileModule.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/GenesisFileModule.java index 2746d2e4332..55b4e7e8392 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/GenesisFileModule.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/GenesisFileModule.java @@ -22,12 +22,13 @@ import org.hyperledger.besu.ethereum.chain.GenesisState; import org.hyperledger.besu.ethereum.core.Block; import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; -import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +import org.hyperledger.besu.ethereum.mainnet.HeaderBasedProtocolSchedule; import java.io.File; import java.io.IOException; import java.nio.charset.Charset; import java.nio.file.Files; +import java.util.Optional; import javax.inject.Named; import javax.inject.Singleton; @@ -62,8 +63,9 @@ GenesisConfigOptions provideGenesisConfigOptions(final GenesisConfigFile genesis @Singleton @Provides - ProtocolSchedule provideProtocolSchedule( + HeaderBasedProtocolSchedule provideProtocolSchedule( final GenesisConfigOptions configOptions, + @Named("Fork") final Optional fork, @Named("RevertReasonEnabled") final boolean revertReasonEnabled) { throw new RuntimeException("Abstract"); } @@ -71,7 +73,8 @@ ProtocolSchedule provideProtocolSchedule( @Singleton @Provides GenesisState provideGenesisState( - final GenesisConfigFile genesisConfigFile, final ProtocolSchedule protocolSchedule) { + final GenesisConfigFile genesisConfigFile, + final HeaderBasedProtocolSchedule protocolSchedule) { return GenesisState.fromConfig(genesisConfigFile, protocolSchedule); } diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/IBFTGenesisFileModule.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/IBFTGenesisFileModule.java index 9000a6f96b3..53c8fadd9f2 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/IBFTGenesisFileModule.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/IBFTGenesisFileModule.java @@ -23,9 +23,10 @@ import org.hyperledger.besu.consensus.ibft.IbftForksSchedulesFactory; import org.hyperledger.besu.consensus.ibft.IbftProtocolSchedule; import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; -import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +import org.hyperledger.besu.ethereum.mainnet.HeaderBasedProtocolSchedule; import org.hyperledger.besu.evm.internal.EvmConfiguration; +import java.util.Optional; import javax.inject.Named; class IBFTGenesisFileModule extends GenesisFileModule { @@ -36,8 +37,9 @@ class IBFTGenesisFileModule extends GenesisFileModule { } @Override - ProtocolSchedule provideProtocolSchedule( + HeaderBasedProtocolSchedule provideProtocolSchedule( final GenesisConfigOptions configOptions, + @Named("Fork") final Optional fork, @Named("RevertReasonEnabled") final boolean revertReasonEnabled) { final ForksSchedule forksSchedule = IbftForksSchedulesFactory.create(configOptions); 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 c60c48b4371..8c5827e1e90 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 @@ -16,12 +16,22 @@ package org.hyperledger.besu.evmtool; import org.hyperledger.besu.config.GenesisConfigOptions; +import org.hyperledger.besu.config.StubGenesisConfigOptions; import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; +import org.hyperledger.besu.ethereum.core.PrivacyParameters; +import org.hyperledger.besu.ethereum.mainnet.HeaderBasedProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule; -import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +import org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder; +import org.hyperledger.besu.ethereum.mainnet.ProtocolSpecAdapters; +import org.hyperledger.besu.ethereum.mainnet.TimestampScheduleBuilder; import org.hyperledger.besu.evm.internal.EvmConfiguration; +import java.math.BigInteger; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.function.Supplier; import javax.inject.Named; class MainnetGenesisFileModule extends GenesisFileModule { @@ -31,14 +41,96 @@ class MainnetGenesisFileModule extends GenesisFileModule { } @Override - ProtocolSchedule provideProtocolSchedule( + BlockHeaderFunctions blockHashFunction() { + return new MainnetBlockHeaderFunctions(); + } + + @Override + HeaderBasedProtocolSchedule provideProtocolSchedule( final GenesisConfigOptions configOptions, + @Named("Fork") final Optional fork, @Named("RevertReasonEnabled") final boolean revertReasonEnabled) { + if (fork.isPresent()) { + var schedules = createSchedules(); + var schedule = schedules.get(fork.map(String::toLowerCase).get()); + if (schedule != null) { + return schedule.get(); + } + } return MainnetProtocolSchedule.fromConfig(configOptions, EvmConfiguration.DEFAULT); } - @Override - BlockHeaderFunctions blockHashFunction() { - return new MainnetBlockHeaderFunctions(); + public static Map> createSchedules() { + return Map.ofEntries( + Map.entry("frontier", createSchedule(new StubGenesisConfigOptions())), + Map.entry("homestead", createSchedule(new StubGenesisConfigOptions().homesteadBlock(0))), + Map.entry("eip150", createSchedule(new StubGenesisConfigOptions().eip150Block(0))), + Map.entry("eip158", createSchedule(new StubGenesisConfigOptions().eip158Block(0))), + Map.entry("byzantium", createSchedule(new StubGenesisConfigOptions().byzantiumBlock(0))), + Map.entry( + "constantinople", + createSchedule(new StubGenesisConfigOptions().constantinopleBlock(0))), + Map.entry( + "constantinoplefix", createSchedule(new StubGenesisConfigOptions().petersburgBlock(0))), + Map.entry("petersburg", createSchedule(new StubGenesisConfigOptions().petersburgBlock(0))), + Map.entry("istanbul", createSchedule(new StubGenesisConfigOptions().istanbulBlock(0))), + Map.entry( + "muirglacier", createSchedule(new StubGenesisConfigOptions().muirGlacierBlock(0))), + Map.entry("berlin", createSchedule(new StubGenesisConfigOptions().berlinBlock(0))), + Map.entry( + "london", + createSchedule(new StubGenesisConfigOptions().londonBlock(0).baseFeePerGas(0x0a))), + Map.entry( + "arrowglacier", createSchedule(new StubGenesisConfigOptions().arrowGlacierBlock(0))), + Map.entry( + "grayglacier", createSchedule(new StubGenesisConfigOptions().grayGlacierBlock(0))), + Map.entry( + "merge", + createSchedule( + new StubGenesisConfigOptions().mergeNetSplitBlock(0).baseFeePerGas(0x0a))), + Map.entry( + "shanghai", + createTimestampSchedule( + new StubGenesisConfigOptions().shanghaiTime(0).baseFeePerGas(0x0a))), + Map.entry( + "cancun", + createTimestampSchedule( + new StubGenesisConfigOptions().cancunTime(0).baseFeePerGas(0x0a))), + Map.entry( + "futureeips", + createTimestampSchedule( + new StubGenesisConfigOptions().futureEipsTime(0).baseFeePerGas(0x0a))), + Map.entry( + "experimentaleips", + createTimestampSchedule( + new StubGenesisConfigOptions().experimentalEipsTime(0).baseFeePerGas(0x0a)))); + } + + private static Supplier createSchedule( + final GenesisConfigOptions options) { + return () -> + new ProtocolScheduleBuilder( + options, + options.getChainId().orElse(BigInteger.ONE), + ProtocolSpecAdapters.create(0, Function.identity()), + PrivacyParameters.DEFAULT, + false, + options.isQuorum(), + EvmConfiguration.DEFAULT) + .createProtocolSchedule(); + } + + private static Supplier createTimestampSchedule( + final GenesisConfigOptions options) { + return () -> + new TimestampScheduleBuilder( + options, + options.getChainId().orElse(BigInteger.ONE), + ProtocolSpecAdapters.create(0, Function.identity()), + PrivacyParameters.DEFAULT, + false, + options.isQuorum(), + EvmConfiguration.DEFAULT) + .createTimestampSchedule(); } } diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/ProtocolModule.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/ProtocolModule.java index 218e8e02ffb..9564d73d6a4 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/ProtocolModule.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/ProtocolModule.java @@ -15,7 +15,8 @@ */ package org.hyperledger.besu.evmtool; -import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +import org.hyperledger.besu.ethereum.core.BlockHeader; +import org.hyperledger.besu.ethereum.mainnet.HeaderBasedProtocolSchedule; import org.hyperledger.besu.ethereum.mainnet.ProtocolSpec; import java.util.function.Function; @@ -30,7 +31,8 @@ public class ProtocolModule { @Provides @Singleton - Function getProtocolSpec(final ProtocolSchedule protocolSchedule) { - return protocolSchedule::getByBlockNumber; + Function getProtocolSpec( + final HeaderBasedProtocolSchedule protocolSchedule) { + return protocolSchedule::getByBlockHeader; } } diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/QBFTGenesisFileModule.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/QBFTGenesisFileModule.java index 7afb621ada7..bfd226ea244 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/QBFTGenesisFileModule.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/QBFTGenesisFileModule.java @@ -22,8 +22,9 @@ import org.hyperledger.besu.consensus.qbft.QbftForksSchedulesFactory; import org.hyperledger.besu.consensus.qbft.QbftProtocolSchedule; import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; -import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; +import org.hyperledger.besu.ethereum.mainnet.HeaderBasedProtocolSchedule; +import java.util.Optional; import javax.inject.Named; class QBFTGenesisFileModule extends GenesisFileModule { @@ -35,8 +36,9 @@ class QBFTGenesisFileModule extends GenesisFileModule { } @Override - ProtocolSchedule provideProtocolSchedule( + HeaderBasedProtocolSchedule provideProtocolSchedule( final GenesisConfigOptions configOptions, + @Named("Fork") final Optional fork, @Named("RevertReasonEnabled") final boolean revertReasonEnabled) { final ForksSchedule forksSchedule = QbftForksSchedulesFactory.create(configOptions);