Support rocks DBs in EVMTool (#933)

Allows the DB of a stopped node to be used for benchmarking.

Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>
pull/940/head
Danno Ferrin 5 years ago committed by GitHub
parent b0f4b415e7
commit 57b9e4f3f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      ethereum/evmtool/build.gradle
  2. 41
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/BlockchainModule.java
  3. 101
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/DataStoreModule.java
  4. 2
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java
  5. 49
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommandOptionsModule.java
  6. 27
      ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/InMemoryDataStoreModule.java

@ -36,8 +36,10 @@ dependencies {
implementation project(':crypto')
implementation project(':consensus:clique')
implementation project(':consensus:ibft')
implementation project(':ethereum:api')
implementation project(':ethereum:core')
implementation project(':metrics:core')
implementation project(':plugins:rocksdb')
implementation project(':services:kvstore')
implementation project(':util')

@ -15,11 +15,13 @@
*/
package org.hyperledger.besu.evmtool;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.BlockParameter;
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.chain.GenesisState;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.Hash;
import org.hyperledger.besu.ethereum.core.MutableWorldView;
import org.hyperledger.besu.ethereum.core.WorldUpdater;
import org.hyperledger.besu.ethereum.storage.keyvalue.WorldStateKeyValueStorage;
@ -35,6 +37,7 @@ import javax.inject.Singleton;
import dagger.Module;
import dagger.Provides;
import org.apache.tuweni.bytes.Bytes32;
@SuppressWarnings("WeakerAccess")
@Module(includes = {GenesisFileModule.class, DataStoreModule.class})
@ -51,23 +54,30 @@ public class BlockchainModule {
@Provides
MutableWorldView getMutableWorldView(
@Named("StateRoot") final Bytes32 stateRoot,
final WorldStateStorage worldStateStorage,
final WorldStatePreimageStorage worldStatePreimageStorage,
final GenesisState genesisState) {
final DefaultMutableWorldState mutableWorldState =
new DefaultMutableWorldState(worldStateStorage, worldStatePreimageStorage);
genesisState.writeStateTo(mutableWorldState);
return mutableWorldState;
final GenesisState genesisState,
@Named("KeyValueStorageName") final String keyValueStorageName) {
if ("memory".equals(keyValueStorageName)) {
final DefaultMutableWorldState mutableWorldState =
new DefaultMutableWorldState(worldStateStorage, worldStatePreimageStorage);
genesisState.writeStateTo(mutableWorldState);
return mutableWorldState;
} else {
return new DefaultMutableWorldState(stateRoot, worldStateStorage, worldStatePreimageStorage);
}
}
@Provides
WorldStateStorage provideWorldStateStorage(final KeyValueStorage keyValueStorage) {
WorldStateStorage provideWorldStateStorage(
@Named("worldState") final KeyValueStorage keyValueStorage) {
return new WorldStateKeyValueStorage(keyValueStorage);
}
@Provides
WorldStatePreimageStorage provideWorldStatePreimageStorage(
final KeyValueStorage keyValueStorage) {
@Named("worldStatePreimage") final KeyValueStorage keyValueStorage) {
return new WorldStatePreimageKeyValueStorage(keyValueStorage);
}
@ -75,4 +85,21 @@ public class BlockchainModule {
WorldUpdater provideWorldUpdater(final MutableWorldView mutableWorldView) {
return mutableWorldView.updater();
}
@Provides
@Named("StateRoot")
Bytes32 provideStateRoot(final BlockParameter blockParameter, final Blockchain blockchain) {
if (blockParameter.isEarliest()) {
return blockchain.getBlockHeader(0).orElseThrow().getStateRoot();
} else if (blockParameter.isLatest() || blockParameter.isPending()) {
return blockchain.getChainHeadHeader().getStateRoot();
} else if (blockParameter.isNumeric()) {
return blockchain
.getBlockHeader(blockParameter.getNumber().orElseThrow())
.orElseThrow()
.getStateRoot();
} else {
return Hash.EMPTY_TRIE_HASH;
}
}
}

@ -17,25 +17,116 @@ 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.KeyValueSegmentIdentifier;
import org.hyperledger.besu.ethereum.storage.keyvalue.KeyValueStoragePrefixedKeyBlockchainStorage;
import org.hyperledger.besu.plugin.services.BesuConfiguration;
import org.hyperledger.besu.plugin.services.MetricsSystem;
import org.hyperledger.besu.plugin.services.storage.KeyValueStorage;
import org.hyperledger.besu.plugin.services.storage.SegmentIdentifier;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBKeyValueStorageFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.RocksDBMetricsFactory;
import org.hyperledger.besu.plugin.services.storage.rocksdb.configuration.RocksDBCLIOptions;
import org.hyperledger.besu.services.kvstore.InMemoryKeyValueStorage;
import org.hyperledger.besu.services.kvstore.LimitedInMemoryKeyValueStorage;
import java.util.List;
import java.util.function.Supplier;
import javax.inject.Named;
import javax.inject.Singleton;
import com.google.common.base.Suppliers;
import dagger.Module;
import dagger.Provides;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@SuppressWarnings("WeakerAccess")
@SuppressWarnings({"CloseableProvides"})
@Module(includes = GenesisFileModule.class)
public class DataStoreModule {
private static final Logger LOG = LogManager.getLogger();
private final Supplier<RocksDBKeyValueStorageFactory> rocksDBFactory =
Suppliers.memoize(
() ->
new RocksDBKeyValueStorageFactory(
RocksDBCLIOptions.create()::toDomainObject,
List.of(KeyValueSegmentIdentifier.values()),
RocksDBMetricsFactory.PUBLIC_ROCKS_DB_METRICS));
@Provides
@Singleton
@Named("blockchain")
KeyValueStorage provideBlockchainKeyValueStorage(
@Named("KeyValueStorageName") final String keyValueStorageName,
final BesuConfiguration commonConfiguration,
final MetricsSystem metricsSystem) {
return constructKeyValueStorage(
keyValueStorageName,
commonConfiguration,
metricsSystem,
KeyValueSegmentIdentifier.BLOCKCHAIN);
}
@Provides
@Singleton
@Named("worldState")
KeyValueStorage provideWorldStateKeyValueStorage(
@Named("KeyValueStorageName") final String keyValueStorageName,
final BesuConfiguration commonConfiguration,
final MetricsSystem metricsSystem) {
return constructKeyValueStorage(
keyValueStorageName,
commonConfiguration,
metricsSystem,
KeyValueSegmentIdentifier.WORLD_STATE);
}
@Provides
@Singleton
@Named("worldStatePreimage")
KeyValueStorage provideWorldStatePreimageKeyValueStorage(
@Named("KeyValueStorageName") final String keyValueStorageName,
final BesuConfiguration commonConfiguration,
final MetricsSystem metricsSystem) {
return new LimitedInMemoryKeyValueStorage(5000);
}
@Provides
@SuppressWarnings("CloseableProvides")
KeyValueStorage provideKeyValueStorage() {
throw new RuntimeException("Abstract");
@Singleton
@Named("pruning")
KeyValueStorage providePruningKeyValueStorage(
@Named("KeyValueStorageName") final String keyValueStorageName,
final BesuConfiguration commonConfiguration,
final MetricsSystem metricsSystem) {
return constructKeyValueStorage(
keyValueStorageName,
commonConfiguration,
metricsSystem,
KeyValueSegmentIdentifier.PRUNING_STATE);
}
private KeyValueStorage constructKeyValueStorage(
@Named("KeyValueStorageName") final String keyValueStorageName,
final BesuConfiguration commonConfiguration,
final MetricsSystem metricsSystem,
final SegmentIdentifier segment) {
switch (keyValueStorageName) {
case "rocksdb":
return rocksDBFactory.get().create(segment, commonConfiguration, metricsSystem);
default:
LOG.error("Unknown key, continuing as though 'memory' was specified");
// fall through
case "memory":
return new InMemoryKeyValueStorage();
}
}
@Provides
@Singleton
static BlockchainStorage provideBlockchainStorage(
final KeyValueStorage keyValueStorage, final BlockHeaderFunctions blockHashFunction) {
@Named("blockchain") final KeyValueStorage keyValueStorage,
final BlockHeaderFunctions blockHashFunction) {
return new KeyValueStoragePrefixedKeyBlockchainStorage(keyValueStorage, blockHashFunction);
}
}

@ -170,7 +170,7 @@ public class EvmToolCommand implements Runnable {
try {
final EvmToolComponent component =
DaggerEvmToolComponent.builder()
.dataStoreModule(new InMemoryDataStoreModule())
.dataStoreModule(new DataStoreModule())
.genesisFileModule(
network == null
? genesisFile == null

@ -16,10 +16,19 @@
package org.hyperledger.besu.evmtool;
import static org.hyperledger.besu.cli.DefaultCommandValues.getDefaultBesuDataPath;
import org.hyperledger.besu.controller.BesuController;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.BlockParameter;
import org.hyperledger.besu.plugin.services.BesuConfiguration;
import org.hyperledger.besu.services.BesuConfigurationImpl;
import java.nio.file.Path;
import javax.inject.Named;
import dagger.Module;
import dagger.Provides;
import picocli.CommandLine;
import picocli.CommandLine.Option;
@SuppressWarnings("WeakerAccess")
@ -36,7 +45,45 @@ public class EvmToolCommandOptionsModule {
@Provides
@Named("RevertReasonEnabled")
boolean isRevertReasonEnabled() {
boolean provideRevertReasonEnabled() {
return revertReasonEnabled;
}
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings.
@Option(
names = {"--key-value-storage"},
description =
"Identity for the key-value storage to be used (default: 'memory' alternate: 'rocksdb')",
arity = "1")
private String keyValueStorageName = "memory";
@Provides
@Named("KeyValueStorageName")
String provideKeyValueStorageName() {
return keyValueStorageName;
}
@CommandLine.Option(
names = {"--data-path"},
paramLabel = "<PATH>",
description =
"If using RocksDB storage, the path to Besu data directory (default: ${DEFAULT-VALUE})")
final Path dataPath = getDefaultBesuDataPath(this);
@Provides
BesuConfiguration provideBesuConfiguration() {
return new BesuConfigurationImpl(dataPath, dataPath.resolve(BesuController.DATABASE_PATH));
}
@Option(
names = {"--block-number"},
description =
"Block number to evaluate against (default: 'PENDING', or 'EARLIEST', 'LATEST', or a number)",
arity = "1")
private final BlockParameter blockParameter = BlockParameter.PENDING;
@Provides
BlockParameter provideBlockParameter() {
return blockParameter;
}
}

@ -1,27 +0,0 @@
/*
* 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();
}
}
Loading…
Cancel
Save