Skip to content

Commit

Permalink
Add '--fork=' to EvmTool (#4913)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
shemnon committed Jan 13, 2023
1 parent 80bebf2 commit 1cd15a8
Show file tree
Hide file tree
Showing 14 changed files with 178 additions and 37 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -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
Expand Down
7 changes: 6 additions & 1 deletion config/src/main/resources/experimental.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,12 @@
"experimentalEipsTime": 0,
"contractSizeLimit": 2147483647,
"ethash": {
"fixeddifficulty": 100
},
"terminalTotalDifficulty": 0,
"checkpoint": {
"hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"number": 0,
"totalDifficulty": "0x0"
}
},
"nonce": "0x42",
Expand Down
7 changes: 6 additions & 1 deletion config/src/main/resources/future.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@
"chainId": 2022,
"futureEipsTime": 0,
"ethash": {
"fixeddifficulty": 100
},
"terminalTotalDifficulty": 0,
"checkpoint": {
"hash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"number": 0,
"totalDifficulty": "0x0"
}
},
"nonce": "0x42",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<GenesisAccount> genesisAccounts =
parseAllocations(config).collect(Collectors.toList());
final Block block =
Expand Down Expand Up @@ -135,7 +136,7 @@ private static Hash calculateGenesisStateHash(final List<GenesisAccount> genesis
private static BlockHeader buildHeader(
final GenesisConfigFile genesis,
final Hash genesisRootHash,
final ProtocolSchedule protocolSchedule) {
final HeaderBasedProtocolSchedule protocolSchedule) {

return BlockHeaderBuilder.create()
.parentHash(parseParentHash(genesis))
Expand Down Expand Up @@ -263,16 +264,13 @@ private Wei parseBalance(final String balance) {

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;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -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();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -50,6 +51,18 @@ boolean provideRevertReasonEnabled() {
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"},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -37,7 +38,7 @@
})
public interface EvmToolComponent {

Function<Integer, ProtocolSpec> getProtocolSpec();
Function<BlockHeader, ProtocolSpec> getProtocolSpec();

WorldUpdater getWorldUpdater();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -62,16 +63,18 @@ GenesisConfigOptions provideGenesisConfigOptions(final GenesisConfigFile genesis

@Singleton
@Provides
ProtocolSchedule provideProtocolSchedule(
HeaderBasedProtocolSchedule provideProtocolSchedule(
final GenesisConfigOptions configOptions,
@Named("Fork") final Optional<String> fork,
@Named("RevertReasonEnabled") final boolean revertReasonEnabled) {
throw new RuntimeException("Abstract");
}

@Singleton
@Provides
GenesisState provideGenesisState(
final GenesisConfigFile genesisConfigFile, final ProtocolSchedule protocolSchedule) {
final GenesisConfigFile genesisConfigFile,
final HeaderBasedProtocolSchedule protocolSchedule) {
return GenesisState.fromConfig(genesisConfigFile, protocolSchedule);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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();
}
}

0 comments on commit 1cd15a8

Please sign in to comment.