mirror of https://github.com/hyperledger/besu
EvmTool - A CLI for ad hoc performance and fuzz testing (#786)
A standalone CLI that performs EVM execution with provided genesis files and raw EVM bytecodes. Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>pull/812/head
parent
0cf6bd9aad
commit
912d125117
@ -0,0 +1,62 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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 |
||||
* |
||||
*/ |
||||
|
||||
apply plugin: 'java-library' |
||||
apply plugin: 'application' |
||||
apply plugin: 'idea' |
||||
|
||||
jar { |
||||
baseName 'besu-evmtool' |
||||
manifest { |
||||
attributes( |
||||
'Specification-Title': baseName, |
||||
'Specification-Version': project.version, |
||||
'Implementation-Title': baseName, |
||||
'Implementation-Version': calculateVersion() |
||||
) |
||||
} |
||||
} |
||||
|
||||
dependencies { |
||||
implementation project(':besu') |
||||
implementation project(':config') |
||||
implementation project(':crypto') |
||||
implementation project(':consensus:clique') |
||||
implementation project(':consensus:ibft') |
||||
implementation project(':ethereum:core') |
||||
implementation project(':metrics:core') |
||||
implementation project(':services:kvstore') |
||||
implementation project(':util') |
||||
|
||||
implementation 'com.google.dagger:dagger' |
||||
implementation 'com.google.guava:guava' |
||||
implementation 'info.picocli:picocli' |
||||
implementation 'io.vertx:vertx-core' |
||||
implementation 'org.apache.logging.log4j:log4j-api' |
||||
implementation 'org.apache.logging.log4j:log4j-core' |
||||
|
||||
annotationProcessor 'com.google.dagger:dagger-compiler' |
||||
} |
||||
|
||||
mainClassName = 'org.hyperledger.besu.evmtool.EvmTool' |
||||
|
||||
startScripts { |
||||
applicationName = 'evm' |
||||
doLast { |
||||
unixScript.text = unixScript.text.replace('BESU_HOME', '\$APP_HOME') |
||||
windowsScript.text = windowsScript.text.replace('BESU_HOME', '%~dp0..') |
||||
} |
||||
} |
@ -0,0 +1,73 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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.evmtool; |
||||
|
||||
import org.hyperledger.besu.ethereum.chain.Blockchain; |
||||
import org.hyperledger.besu.ethereum.chain.BlockchainStorage; |
||||
import org.hyperledger.besu.ethereum.chain.DefaultBlockchain; |
||||
import org.hyperledger.besu.ethereum.core.Block; |
||||
import org.hyperledger.besu.ethereum.core.MutableWorldView; |
||||
import org.hyperledger.besu.ethereum.core.WorldUpdater; |
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.WorldStateKeyValueStorage; |
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.WorldStatePreimageKeyValueStorage; |
||||
import org.hyperledger.besu.ethereum.worldstate.DefaultMutableWorldState; |
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStatePreimageStorage; |
||||
import org.hyperledger.besu.ethereum.worldstate.WorldStateStorage; |
||||
import org.hyperledger.besu.plugin.services.MetricsSystem; |
||||
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage; |
||||
|
||||
import javax.inject.Named; |
||||
import javax.inject.Singleton; |
||||
|
||||
import dagger.Module; |
||||
import dagger.Provides; |
||||
|
||||
@SuppressWarnings("WeakerAccess") |
||||
@Module(includes = {GenesisFileModule.class, DataStoreModule.class}) |
||||
public class BlockchainModule { |
||||
|
||||
@Singleton |
||||
@Provides |
||||
Blockchain provideBlockchain( |
||||
@Named("GenesisBlock") final Block genesisBlock, |
||||
final BlockchainStorage blockchainStorage, |
||||
final MetricsSystem metricsSystem) { |
||||
return DefaultBlockchain.createMutable(genesisBlock, blockchainStorage, metricsSystem); |
||||
} |
||||
|
||||
@Provides |
||||
MutableWorldView getMutableWorldView( |
||||
final WorldStateStorage worldStateStorage, |
||||
final WorldStatePreimageStorage worldStatePreimageStorage) { |
||||
return new DefaultMutableWorldState(worldStateStorage, worldStatePreimageStorage); |
||||
} |
||||
|
||||
@Provides |
||||
WorldStateStorage provideWorldStateStorage(final KeyValueStorage keyValueStorage) { |
||||
return new WorldStateKeyValueStorage(keyValueStorage); |
||||
} |
||||
|
||||
@Provides |
||||
WorldStatePreimageStorage provideWorldStatePreimageStorage( |
||||
final KeyValueStorage keyValueStorage) { |
||||
return new WorldStatePreimageKeyValueStorage(keyValueStorage); |
||||
} |
||||
|
||||
@Provides |
||||
WorldUpdater provideWorldUpdater(final MutableWorldView mutableWorldView) { |
||||
return mutableWorldView.updater(); |
||||
} |
||||
} |
@ -0,0 +1,44 @@ |
||||
/* |
||||
* Copyright 2018 ConsenSys AG. |
||||
* |
||||
* 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.evmtool; |
||||
|
||||
import org.hyperledger.besu.config.GenesisConfigOptions; |
||||
import org.hyperledger.besu.consensus.clique.CliqueProtocolSchedule; |
||||
import org.hyperledger.besu.consensus.ibft.IbftBlockHeaderFunctions; |
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; |
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; |
||||
|
||||
import javax.inject.Named; |
||||
|
||||
class CliqueGenesisFileModule extends GenesisFileModule { |
||||
|
||||
CliqueGenesisFileModule(final String genesisConfig) { |
||||
super(genesisConfig); |
||||
} |
||||
|
||||
@Override |
||||
ProtocolSchedule<?> provideProtocolSchedule( |
||||
final GenesisConfigOptions configOptions, |
||||
@Named("RevertReasonEnabled") final boolean revertReasonEnabled) { |
||||
// dagger can handle this magic one day
|
||||
return CliqueProtocolSchedule.create(configOptions, null, revertReasonEnabled); |
||||
} |
||||
|
||||
@Override |
||||
BlockHeaderFunctions blockHashFunction() { |
||||
return IbftBlockHeaderFunctions.forOnChainBlock(); |
||||
} |
||||
} |
@ -0,0 +1,41 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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.evmtool; |
||||
|
||||
import org.hyperledger.besu.ethereum.chain.BlockchainStorage; |
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; |
||||
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage; |
||||
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage; |
||||
|
||||
import dagger.Module; |
||||
import dagger.Provides; |
||||
|
||||
@SuppressWarnings("WeakerAccess") |
||||
@Module(includes = GenesisFileModule.class) |
||||
public class DataStoreModule { |
||||
|
||||
@Provides |
||||
@SuppressWarnings("CloseableProvides") |
||||
KeyValueStorage provideKeyValueStorage() { |
||||
throw new RuntimeException("Abstract"); |
||||
} |
||||
|
||||
@Provides |
||||
static BlockchainStorage provideBlockchainStorage( |
||||
final KeyValueStorage keyValueStorage, final BlockHeaderFunctions blockHashFunction) { |
||||
return new KeyValueStoragePrefixedKeyBlockchainStorage(keyValueStorage, blockHashFunction); |
||||
} |
||||
} |
@ -0,0 +1,35 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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.evmtool; |
||||
|
||||
import static picocli.CommandLine.defaultExceptionHandler; |
||||
|
||||
import picocli.CommandLine; |
||||
|
||||
public final class EvmTool { |
||||
private static final int SUCCESS_EXIT_CODE = 0; |
||||
private static final int ERROR_EXIT_CODE = 1; |
||||
|
||||
public static void main(final String... args) { |
||||
|
||||
final EvmToolCommand evmToolCommand = new EvmToolCommand(); |
||||
|
||||
evmToolCommand.parse( |
||||
new CommandLine.RunLast().andExit(SUCCESS_EXIT_CODE), |
||||
defaultExceptionHandler().andExit(ERROR_EXIT_CODE), |
||||
args); |
||||
} |
||||
} |
@ -0,0 +1,285 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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.evmtool; |
||||
|
||||
import org.hyperledger.besu.cli.config.NetworkName; |
||||
import org.hyperledger.besu.ethereum.core.Account; |
||||
import org.hyperledger.besu.ethereum.core.Address; |
||||
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.Gas; |
||||
import org.hyperledger.besu.ethereum.core.Hash; |
||||
import org.hyperledger.besu.ethereum.core.LogsBloomFilter; |
||||
import org.hyperledger.besu.ethereum.core.Wei; |
||||
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; |
||||
import org.hyperledger.besu.ethereum.vm.BlockHashLookup; |
||||
import org.hyperledger.besu.ethereum.vm.Code; |
||||
import org.hyperledger.besu.ethereum.vm.EVM; |
||||
import org.hyperledger.besu.ethereum.vm.ExceptionalHaltReason; |
||||
import org.hyperledger.besu.ethereum.vm.MessageFrame; |
||||
import org.hyperledger.besu.ethereum.vm.ehalt.ExceptionalHaltException; |
||||
|
||||
import java.io.File; |
||||
import java.io.IOException; |
||||
import java.nio.charset.StandardCharsets; |
||||
import java.time.Instant; |
||||
import java.util.ArrayDeque; |
||||
import java.util.List; |
||||
|
||||
import com.google.common.base.Stopwatch; |
||||
import io.vertx.core.json.JsonArray; |
||||
import io.vertx.core.json.JsonObject; |
||||
import org.apache.logging.log4j.Level; |
||||
import org.apache.logging.log4j.LogManager; |
||||
import org.apache.logging.log4j.Logger; |
||||
import org.apache.logging.log4j.core.config.Configurator; |
||||
import org.apache.tuweni.bytes.Bytes; |
||||
import org.apache.tuweni.units.bigints.UInt256; |
||||
import picocli.CommandLine; |
||||
import picocli.CommandLine.Command; |
||||
import picocli.CommandLine.Option; |
||||
|
||||
@Command( |
||||
description = "This command evaluates EVM transactions.", |
||||
abbreviateSynopsis = true, |
||||
name = "evm", |
||||
mixinStandardHelpOptions = true, |
||||
sortOptions = false, |
||||
header = "Usage:", |
||||
synopsisHeading = "%n", |
||||
descriptionHeading = "%nDescription:%n%n", |
||||
optionListHeading = "%nOptions:%n", |
||||
footerHeading = "%n", |
||||
footer = "Hyperledger Besu is licensed under the Apache License 2.0") |
||||
public class EvmToolCommand implements Runnable { |
||||
|
||||
private static final Logger LOG = LogManager.getLogger(); |
||||
|
||||
@Option( |
||||
names = {"--code"}, |
||||
paramLabel = "<code>", |
||||
description = "code to be executed") |
||||
private final Bytes codeHexString = Bytes.EMPTY; |
||||
|
||||
@Option( |
||||
names = {"--gas"}, |
||||
paramLabel = "<int>") |
||||
private final Gas gas = Gas.of(10_000_000_000L); |
||||
|
||||
@Option( |
||||
names = {"--price"}, |
||||
paramLabel = "<int>") |
||||
private final Wei gasPriceGWei = Wei.ZERO; |
||||
|
||||
@Option( |
||||
names = {"--sender"}, |
||||
paramLabel = "<address>", |
||||
description = "address of ORIGIN") |
||||
private final Address sender = Address.fromHexString("0x00"); |
||||
|
||||
@Option( |
||||
names = {"--receiver"}, |
||||
paramLabel = "<address>", |
||||
description = "address of ADDRESS") |
||||
private final Address receiver = Address.fromHexString("0x00"); |
||||
|
||||
@Option( |
||||
names = {"--input"}, |
||||
paramLabel = "<code>", |
||||
description = "CALLDATA") |
||||
private final Bytes callData = Bytes.EMPTY; |
||||
|
||||
@Option( |
||||
names = {"--value"}, |
||||
paramLabel = "<int>") |
||||
private final Wei ethValue = Wei.ZERO; |
||||
|
||||
@Option( |
||||
names = {"--json"}, |
||||
description = "output json output for each opcode") |
||||
private final Boolean showJsonResults = false; |
||||
|
||||
@Option( |
||||
names = {"--nomemory"}, |
||||
description = "disable showing the full memory output for each op") |
||||
private final Boolean showMemory = true; |
||||
|
||||
@Option( |
||||
names = {"--prestate", "--genesis"}, |
||||
description = "a chain specification, the same one that the client normally would use") |
||||
private final File genesisFile = null; |
||||
|
||||
@Option( |
||||
names = {"--chain"}, |
||||
description = "Name of a well know chain") |
||||
private final NetworkName network = null; |
||||
|
||||
@Option( |
||||
names = {"--repeat"}, |
||||
description = "Number of times to repeat before gathering timing") |
||||
private final Integer repeat = 0; |
||||
|
||||
private final EvmToolCommandOptionsModule daggerOptions = new EvmToolCommandOptionsModule(); |
||||
|
||||
void parse( |
||||
final CommandLine.AbstractParseResultHandler<List<Object>> resultHandler, |
||||
final CommandLine.DefaultExceptionHandler<List<Object>> exceptionHandler, |
||||
final String[] args) { |
||||
|
||||
final CommandLine commandLine = new CommandLine(this); |
||||
commandLine.addMixin("Dagger Options", daggerOptions); |
||||
|
||||
// add sub commands here
|
||||
|
||||
commandLine.registerConverter(Address.class, Address::fromHexString); |
||||
commandLine.registerConverter(Bytes.class, Bytes::fromHexString); |
||||
commandLine.registerConverter(Gas.class, (arg) -> Gas.of(Long.parseUnsignedLong(arg))); |
||||
commandLine.registerConverter(Wei.class, (arg) -> Wei.of(Long.parseUnsignedLong(arg))); |
||||
|
||||
commandLine.parseWithHandlers(resultHandler, exceptionHandler, args); |
||||
} |
||||
|
||||
@Override |
||||
public void run() { |
||||
try { |
||||
final EvmToolComponent component = |
||||
DaggerEvmToolComponent.builder() |
||||
.dataStoreModule(new InMemoryDataStoreModule()) |
||||
.genesisFileModule( |
||||
network == null |
||||
? genesisFile == null |
||||
? GenesisFileModule.createGenesisModule(NetworkName.DEV) |
||||
: GenesisFileModule.createGenesisModule(genesisFile) |
||||
: GenesisFileModule.createGenesisModule(network)) |
||||
.evmToolCommandOptionsModule(daggerOptions) |
||||
.metricsSystemModule(new PrometheusMetricsSystemModule()) |
||||
.build(); |
||||
|
||||
final BlockHeader blockHeader = |
||||
BlockHeaderBuilder.create() |
||||
.parentHash(Hash.EMPTY) |
||||
.coinbase(Address.ZERO) |
||||
.difficulty(Difficulty.ONE) |
||||
.number(1) |
||||
.gasLimit(5000) |
||||
.timestamp(Instant.now().toEpochMilli()) |
||||
.ommersHash(Hash.EMPTY_LIST_HASH) |
||||
.stateRoot(Hash.EMPTY_TRIE_HASH) |
||||
.transactionsRoot(Hash.EMPTY) |
||||
.receiptsRoot(Hash.EMPTY) |
||||
.logsBloom(LogsBloomFilter.empty()) |
||||
.gasUsed(0) |
||||
.extraData(Bytes.EMPTY) |
||||
.mixHash(Hash.EMPTY) |
||||
.nonce(0) |
||||
.blockHeaderFunctions(new MainnetBlockHeaderFunctions()) |
||||
.buildBlockHeader(); |
||||
|
||||
Configurator.setAllLevels("", repeat == 0 ? Level.INFO : Level.OFF); |
||||
int repeat = this.repeat; |
||||
do { |
||||
final boolean lastLoop = repeat == 0; |
||||
final MessageFrame messageFrame = |
||||
MessageFrame.builder() |
||||
.type(MessageFrame.Type.MESSAGE_CALL) |
||||
.messageFrameStack(new ArrayDeque<>()) |
||||
.blockchain(component.getBlockchain()) |
||||
.worldState(component.getWorldUpdater()) |
||||
.initialGas(gas) |
||||
.contract(Address.ZERO) |
||||
.address(receiver) |
||||
.originator(sender) |
||||
.gasPrice(gasPriceGWei) |
||||
.inputData(callData) |
||||
.sender(Address.ZERO) |
||||
.value(ethValue) |
||||
.apparentValue(ethValue) |
||||
.code(new Code(codeHexString)) |
||||
.blockHeader(blockHeader) |
||||
.depth(0) |
||||
.completer(c -> {}) |
||||
.miningBeneficiary(blockHeader.getCoinbase()) |
||||
.blockHashLookup(new BlockHashLookup(blockHeader, component.getBlockchain())) |
||||
.contractAccountVersion(Account.DEFAULT_VERSION) |
||||
.build(); |
||||
|
||||
messageFrame.setState(MessageFrame.State.CODE_EXECUTING); |
||||
final EVM evm = component.getEvmAtBlock().apply(0); |
||||
|
||||
final Stopwatch stopwatch = Stopwatch.createStarted(); |
||||
evm.runToHalt( |
||||
messageFrame, |
||||
(frame, currentGasCost, executeOperation) -> { |
||||
if (showJsonResults && lastLoop) { |
||||
System.out.println(createEvmTraceOperation(messageFrame)); |
||||
} |
||||
executeOperation.execute(); |
||||
}); |
||||
stopwatch.stop(); |
||||
|
||||
if (lastLoop) { |
||||
System.out.println( |
||||
new JsonObject() |
||||
.put( |
||||
"gasUser", |
||||
gas.minus(messageFrame.getRemainingGas()).asUInt256().toShortHexString()) |
||||
.put("timens", stopwatch.elapsed().toNanos()) |
||||
.put("time", stopwatch.elapsed().toNanos() / 1000)); |
||||
} |
||||
} while (repeat-- > 0); |
||||
|
||||
} catch (final IOException | ExceptionalHaltException e) { |
||||
LOG.fatal(e); |
||||
} |
||||
} |
||||
|
||||
private JsonObject createEvmTraceOperation(final MessageFrame messageFrame) { |
||||
final JsonArray stack = new JsonArray(); |
||||
for (int i = 0; i < messageFrame.stackSize(); i++) { |
||||
stack.add(messageFrame.getStackItem(i).toShortHexString()); |
||||
} |
||||
final String error = |
||||
messageFrame.getExceptionalHaltReasons().stream() |
||||
.findFirst() |
||||
.map(ExceptionalHaltReason::getDescription) |
||||
.orElse( |
||||
messageFrame |
||||
.getRevertReason() |
||||
.map(bytes -> new String(bytes.toArrayUnsafe(), StandardCharsets.UTF_8)) |
||||
.orElse("")); |
||||
|
||||
final JsonObject results = new JsonObject(); |
||||
results.put("pc", messageFrame.getPC()); |
||||
results.put("op", messageFrame.getCurrentOperation().getOpcode()); |
||||
results.put("gas", messageFrame.getRemainingGas().asUInt256().toShortHexString()); |
||||
|
||||
results.put( |
||||
"gasCost", |
||||
messageFrame.getCurrentOperation().cost(messageFrame).asUInt256().toShortHexString()); |
||||
if (!showMemory) { |
||||
results.put( |
||||
"memory", |
||||
messageFrame.readMemory(UInt256.ZERO, messageFrame.memoryWordSize()).toHexString()); |
||||
} |
||||
results.put("memSize", messageFrame.memoryByteSize()); |
||||
results.put("depth", messageFrame.getMessageStackDepth() + 1); |
||||
results.put("stack", stack); |
||||
results.put("error", error); |
||||
results.put("opName", messageFrame.getCurrentOperation().getName()); |
||||
return results; |
||||
} |
||||
} |
@ -0,0 +1,42 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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.evmtool; |
||||
|
||||
import javax.inject.Named; |
||||
|
||||
import dagger.Module; |
||||
import dagger.Provides; |
||||
import picocli.CommandLine.Option; |
||||
|
||||
@SuppressWarnings("WeakerAccess") |
||||
@Module |
||||
public class EvmToolCommandOptionsModule { |
||||
|
||||
@Option( |
||||
names = {"--revert-reason-enabled"}, |
||||
paramLabel = "<Boolean>", |
||||
description = "Should revert reasons be persisted. (default: ${FALLBACK-VALUE})", |
||||
arity = "0..1", |
||||
fallbackValue = "true") |
||||
final Boolean revertReasonEnabled = true; |
||||
|
||||
@Provides |
||||
@Named("RevertReasonEnabled") |
||||
boolean isRevertReasonEnabled() { |
||||
return revertReasonEnabled; |
||||
} |
||||
} |
@ -0,0 +1,44 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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.evmtool; |
||||
|
||||
import org.hyperledger.besu.ethereum.chain.Blockchain; |
||||
import org.hyperledger.besu.ethereum.core.WorldUpdater; |
||||
import org.hyperledger.besu.ethereum.vm.EVM; |
||||
|
||||
import java.util.function.Function; |
||||
import javax.inject.Singleton; |
||||
|
||||
import dagger.Component; |
||||
|
||||
@Singleton |
||||
@Component( |
||||
modules = { |
||||
ProtocolModule.class, |
||||
GenesisFileModule.class, |
||||
DataStoreModule.class, |
||||
BlockchainModule.class, |
||||
EvmToolCommandOptionsModule.class, |
||||
MetricsSystemModule.class, |
||||
}) |
||||
public interface EvmToolComponent { |
||||
|
||||
Function<Integer, EVM> getEvmAtBlock(); |
||||
|
||||
WorldUpdater getWorldUpdater(); |
||||
|
||||
Blockchain getBlockchain(); |
||||
} |
@ -0,0 +1,114 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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.evmtool; |
||||
|
||||
import org.hyperledger.besu.cli.config.EthNetworkConfig; |
||||
import org.hyperledger.besu.cli.config.NetworkName; |
||||
import org.hyperledger.besu.config.GenesisConfigFile; |
||||
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 java.io.File; |
||||
import java.io.IOException; |
||||
import java.nio.charset.Charset; |
||||
import java.nio.file.Files; |
||||
import javax.inject.Named; |
||||
import javax.inject.Singleton; |
||||
|
||||
import dagger.Module; |
||||
import dagger.Provides; |
||||
import io.vertx.core.json.JsonObject; |
||||
|
||||
@Module |
||||
public class GenesisFileModule { |
||||
|
||||
private final String genesisConfig; |
||||
|
||||
protected GenesisFileModule(final File genesisFile) throws IOException { |
||||
this.genesisConfig = Files.readString(genesisFile.toPath(), Charset.defaultCharset()); |
||||
} |
||||
|
||||
protected GenesisFileModule(final String genesisConfig) { |
||||
this.genesisConfig = genesisConfig; |
||||
} |
||||
|
||||
@Singleton |
||||
@Provides |
||||
GenesisConfigFile providesGenesisConfigFile() { |
||||
return GenesisConfigFile.fromConfig(genesisConfig); |
||||
} |
||||
|
||||
@Singleton |
||||
@Provides |
||||
GenesisConfigOptions provideGenesisConfigOptions(final GenesisConfigFile genesisConfigFile) { |
||||
return genesisConfigFile.getConfigOptions(); |
||||
} |
||||
|
||||
@Singleton |
||||
@Provides |
||||
ProtocolSchedule<?> provideProtocolSchedule( |
||||
final GenesisConfigOptions configOptions, |
||||
@Named("RevertReasonEnabled") final boolean revertReasonEnabled) { |
||||
throw new RuntimeException("Abstract"); |
||||
} |
||||
|
||||
@Singleton |
||||
@Provides |
||||
GenesisState provideGenesisState( |
||||
final GenesisConfigFile genesisConfigFile, final ProtocolSchedule<?> protocolSchedule) { |
||||
return GenesisState.fromConfig(genesisConfigFile, protocolSchedule); |
||||
} |
||||
|
||||
@Singleton |
||||
@Provides |
||||
BlockHeaderFunctions blockHashFunction() { |
||||
throw new RuntimeException("Abstract"); |
||||
} |
||||
|
||||
@Singleton |
||||
@Provides |
||||
@Named("GenesisBlock") |
||||
Block provideGenesisBlock(final GenesisState genesisState) { |
||||
return genesisState.getBlock(); |
||||
} |
||||
|
||||
static GenesisFileModule createGenesisModule(final NetworkName networkName) { |
||||
return createGenesisModule(EthNetworkConfig.jsonConfig(networkName)); |
||||
} |
||||
|
||||
static GenesisFileModule createGenesisModule(final File genesisFile) throws IOException { |
||||
return createGenesisModule(Files.readString(genesisFile.toPath(), Charset.defaultCharset())); |
||||
} |
||||
|
||||
private static GenesisFileModule createGenesisModule(final String genesisConfig) { |
||||
// duplicating work from JsonGenesisConfigOptions, but in a refactoring this goes away.
|
||||
final JsonObject genesis = new JsonObject(genesisConfig); |
||||
final JsonObject config = genesis.getJsonObject("config"); |
||||
if (config.containsKey("ethash")) { |
||||
return new MainnetGenesisFileModule(genesisConfig); |
||||
} else if (config.containsKey("ibft")) { |
||||
return new IBFTGenesisFileModule(genesisConfig); |
||||
} else if (config.containsKey("clique")) { |
||||
return new CliqueGenesisFileModule(genesisConfig); |
||||
} else { |
||||
// default is mainnet
|
||||
return new MainnetGenesisFileModule(genesisConfig); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,43 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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.evmtool; |
||||
|
||||
import org.hyperledger.besu.config.GenesisConfigOptions; |
||||
import org.hyperledger.besu.consensus.ibft.IbftBlockHeaderFunctions; |
||||
import org.hyperledger.besu.consensus.ibft.IbftProtocolSchedule; |
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; |
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; |
||||
|
||||
import javax.inject.Named; |
||||
|
||||
class IBFTGenesisFileModule extends GenesisFileModule { |
||||
|
||||
IBFTGenesisFileModule(final String genesisConfig) { |
||||
super(genesisConfig); |
||||
} |
||||
|
||||
@Override |
||||
ProtocolSchedule<?> provideProtocolSchedule( |
||||
final GenesisConfigOptions configOptions, |
||||
@Named("RevertReasonEnabled") final boolean revertReasonEnabled) { |
||||
return IbftProtocolSchedule.create(configOptions); |
||||
} |
||||
|
||||
@Override |
||||
BlockHeaderFunctions blockHashFunction() { |
||||
return IbftBlockHeaderFunctions.forOnChainBlock(); |
||||
} |
||||
} |
@ -0,0 +1,27 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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.evmtool; |
||||
|
||||
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage; |
||||
import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage; |
||||
|
||||
class InMemoryDataStoreModule extends DataStoreModule { |
||||
|
||||
@Override |
||||
KeyValueStorage provideKeyValueStorage() { |
||||
return new InMemoryKeyValueStorage(); |
||||
} |
||||
} |
@ -0,0 +1,43 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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.evmtool; |
||||
|
||||
import org.hyperledger.besu.config.GenesisConfigOptions; |
||||
import org.hyperledger.besu.ethereum.core.BlockHeaderFunctions; |
||||
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions; |
||||
import org.hyperledger.besu.ethereum.mainnet.MainnetProtocolSchedule; |
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; |
||||
|
||||
import javax.inject.Named; |
||||
|
||||
class MainnetGenesisFileModule extends GenesisFileModule { |
||||
|
||||
MainnetGenesisFileModule(final String genesisConfig) { |
||||
super(genesisConfig); |
||||
} |
||||
|
||||
@Override |
||||
ProtocolSchedule<?> provideProtocolSchedule( |
||||
final GenesisConfigOptions configOptions, |
||||
@Named("RevertReasonEnabled") final boolean revertReasonEnabled) { |
||||
return MainnetProtocolSchedule.fromConfig(configOptions); |
||||
} |
||||
|
||||
@Override |
||||
BlockHeaderFunctions blockHashFunction() { |
||||
return new MainnetBlockHeaderFunctions(); |
||||
} |
||||
} |
@ -0,0 +1,32 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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.evmtool; |
||||
|
||||
import org.hyperledger.besu.plugin.services.MetricsSystem; |
||||
|
||||
import dagger.Module; |
||||
import dagger.Provides; |
||||
|
||||
@SuppressWarnings("WeakerAccess") |
||||
@Module |
||||
public class MetricsSystemModule { |
||||
|
||||
@Provides |
||||
MetricsSystem getMetricsSystem() { |
||||
throw new RuntimeException("Abstract"); |
||||
} |
||||
} |
@ -0,0 +1,29 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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.evmtool; |
||||
|
||||
import org.hyperledger.besu.metrics.prometheus.MetricsConfiguration; |
||||
import org.hyperledger.besu.metrics.prometheus.PrometheusMetricsSystem; |
||||
import org.hyperledger.besu.plugin.services.MetricsSystem; |
||||
|
||||
public class PrometheusMetricsSystemModule extends MetricsSystemModule { |
||||
|
||||
@Override |
||||
public MetricsSystem getMetricsSystem() { |
||||
return PrometheusMetricsSystem.init(MetricsConfiguration.builder().build()); |
||||
} |
||||
} |
@ -0,0 +1,34 @@ |
||||
/* |
||||
* Copyright ConsenSys AG. |
||||
* |
||||
* 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.evmtool; |
||||
|
||||
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule; |
||||
import org.hyperledger.besu.ethereum.vm.EVM; |
||||
|
||||
import java.util.function.Function; |
||||
|
||||
import dagger.Module; |
||||
import dagger.Provides; |
||||
|
||||
@SuppressWarnings("WeakerAccess") |
||||
@Module(includes = GenesisFileModule.class) |
||||
public class ProtocolModule { |
||||
|
||||
@Provides |
||||
Function<Integer, EVM> provideEvmAtBlock(final ProtocolSchedule<?> protocolSchedule) { |
||||
return blockNum -> protocolSchedule.getByBlockNumber(blockNum).getEvm(); |
||||
} |
||||
} |
Loading…
Reference in new issue