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 <danno.ferrin@swirldslabs.com>
pull/4928/head
Danno Ferrin 2 years ago committed by GitHub
parent 80bebf2b73
commit 1cd15a86f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 9
      CHANGELOG.md
  2. 7
      config/src/main/resources/experimental.json
  3. 7
      config/src/main/resources/future.json
  4. 22
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/chain/GenesisState.java
  5. 14
      ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/ScheduleBasedBlockHeaderFunctions.java
  6. 6
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/CliqueGenesisFileModule.java
  7. 3
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java
  8. 13
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommandOptionsModule.java
  9. 3
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolComponent.java
  10. 9
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/GenesisFileModule.java
  11. 6
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/IBFTGenesisFileModule.java
  12. 102
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/MainnetGenesisFileModule.java
  13. 8
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/ProtocolModule.java
  14. 6
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/QBFTGenesisFileModule.java

@ -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

@ -4,7 +4,12 @@
"experimentalEipsTime": 0,
"contractSizeLimit": 2147483647,
"ethash": {
"fixeddifficulty": 100
},
"terminalTotalDifficulty": 0,
"checkpoint": {
"hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"number": 0,
"totalDifficulty": "0x0"
}
},
"nonce": "0x42",

@ -3,7 +3,12 @@
"chainId": 2022,
"futureEipsTime": 0,
"ethash": {
"fixeddifficulty": 100
},
"terminalTotalDifficulty": 0,
"checkpoint": {
"hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"number": 0,
"totalDifficulty": "0x0"
}
},
"nonce": "0x42",

@ -25,6 +25,7 @@ import org.hyperledger.besu.ethereum.core.BlockHeader;
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 final class GenesisState {
* @return A new {@link GenesisState}.
*/
public static GenesisState fromConfig(
final GenesisConfigFile config, final ProtocolSchedule protocolSchedule) {
final GenesisConfigFile config, final HeaderBasedProtocolSchedule protocolSchedule) {
final List<GenesisAccount> genesisAccounts =
parseAllocations(config).collect(Collectors.toList());
final Block block =
@ -135,7 +136,7 @@ public final class GenesisState {
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 @@ public final class GenesisState {
private Map<UInt256, UInt256> parseStorage(final Map<String, String> storage) {
final Map<UInt256, UInt256> 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;
}

@ -26,13 +26,13 @@ import org.hyperledger.besu.ethereum.core.SealableBlockHeader;
*/
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 class ScheduleBasedBlockHeaderFunctions implements BlockHeaderFunctions {
}
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();
}
}
}

@ -22,9 +22,10 @@ import org.hyperledger.besu.crypto.KeyPairSecurityModule;
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<String> fork,
@Named("RevertReasonEnabled") final boolean revertReasonEnabled) {
// dagger can handle this magic one day
return CliqueProtocolSchedule.create(

@ -222,7 +222,8 @@ public class EvmToolCommand implements Runnable {
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 =

@ -24,6 +24,7 @@ import org.hyperledger.besu.plugin.services.BesuConfiguration;
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 @@ public class EvmToolCommandOptionsModule {
return revertReasonEnabled;
}
@Option(
names = {"--fork"},
paramLabel = "<String>",
description = "Fork to evaluate, overriding network setting.")
String fork = null;
@Provides
@Named("Fork")
Optional<String> provideFork() {
return Optional.ofNullable(fork);
}
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings.
@Option(
names = {"--key-value-storage"},

@ -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 @@ import dagger.Component;
})
public interface EvmToolComponent {
Function<Integer, ProtocolSpec> getProtocolSpec();
Function<BlockHeader, ProtocolSpec> getProtocolSpec();
WorldUpdater getWorldUpdater();

@ -22,12 +22,13 @@ import org.hyperledger.besu.config.GenesisConfigOptions;
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 @@ public class GenesisFileModule {
@Singleton
@Provides
ProtocolSchedule provideProtocolSchedule(
HeaderBasedProtocolSchedule provideProtocolSchedule(
final GenesisConfigOptions configOptions,
@Named("Fork") final Optional<String> fork,
@Named("RevertReasonEnabled") final boolean revertReasonEnabled) {
throw new RuntimeException("Abstract");
}
@ -71,7 +73,8 @@ public class GenesisFileModule {
@Singleton
@Provides
GenesisState provideGenesisState(
final GenesisConfigFile genesisConfigFile, final ProtocolSchedule protocolSchedule) {
final GenesisConfigFile genesisConfigFile,
final HeaderBasedProtocolSchedule protocolSchedule) {
return GenesisState.fromConfig(genesisConfigFile, protocolSchedule);
}

@ -23,9 +23,10 @@ import org.hyperledger.besu.consensus.ibft.IbftExtraDataCodec;
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<String> fork,
@Named("RevertReasonEnabled") final boolean revertReasonEnabled) {
final ForksSchedule<BftConfigOptions> forksSchedule =
IbftForksSchedulesFactory.create(configOptions);

@ -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<String> 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<String, Supplier<HeaderBasedProtocolSchedule>> 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<HeaderBasedProtocolSchedule> 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<HeaderBasedProtocolSchedule> 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();
}
}

@ -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<Integer, ProtocolSpec> getProtocolSpec(final ProtocolSchedule protocolSchedule) {
return protocolSchedule::getByBlockNumber;
Function<BlockHeader, ProtocolSpec> getProtocolSpec(
final HeaderBasedProtocolSchedule protocolSchedule) {
return protocolSchedule::getByBlockHeader;
}
}

@ -22,8 +22,9 @@ import org.hyperledger.besu.consensus.qbft.QbftExtraDataCodec;
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<String> fork,
@Named("RevertReasonEnabled") final boolean revertReasonEnabled) {
final ForksSchedule<QbftConfigOptions> forksSchedule =
QbftForksSchedulesFactory.create(configOptions);

Loading…
Cancel
Save