Skip to content

Commit

Permalink
EvmTool - A CLI for ad hoc performance and fuzz testing (#786)
Browse files Browse the repository at this point in the history
A standalone CLI that performs EVM execution with provided genesis
files and raw EVM bytecodes.

Signed-off-by: Danno Ferrin <danno.ferrin@gmail.com>
  • Loading branch information
shemnon authored Apr 29, 2020
1 parent 0cf6bd9 commit 912d125
Show file tree
Hide file tree
Showing 22 changed files with 1,020 additions and 48 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,4 @@ out/
site/
/kubernetes/reports/
/kubernetes/besu-*.tar.gz
**/src/*/generated
103 changes: 62 additions & 41 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -294,30 +294,62 @@ check.dependsOn('checkPluginAPIChanges', 'checkMavenCoordinateCollisions')

subprojects {

sourceSets {
// test-support can be consumed as a library by other projects in their tests
testSupport {
java {
compileClasspath += main.output
runtimeClasspath += main.output
srcDir file('src/test-support/java')
if (file('src/test-support').directory) {
sourceSets {
// test-support can be consumed as a library by other projects in their tests
testSupport {
java {
compileClasspath += main.output
runtimeClasspath += main.output
srcDir file('src/test-support/java')
}
resources.srcDir file('src/test-support/resources')
}
resources.srcDir file('src/test-support/resources')
}
integrationTest {
java {
compileClasspath += main.output
runtimeClasspath += main.output
srcDir file('src/integration-test/java')
}
resources.srcDir file('src/integration-test/resources')

dependencies {
testImplementation sourceSets.testSupport.output
}

task testSupportJar(type: Jar) {
archiveBaseName = "${project.name}-support-test"
classifier = 'test-support'
from sourceSets.testSupport.output
}
}

task testSupportJar(type: Jar) {
archiveBaseName = "${project.name}-support-test"
classifier = 'test-support'
from sourceSets.testSupport.output
if (file('src/integration-test').directory) {
sourceSets {
integrationTest {
java {
compileClasspath += main.output
runtimeClasspath += main.output
srcDir file('src/integration-test/java')
}
resources.srcDir file('src/integration-test/resources')
}
}

if (file('src/test-support').directory) {
dependencies {
integrationTestImplementation sourceSets.testSupport.output
}
}

task integrationTest(type: Test, dependsOn: ["compileTestJava"]) {
group = "verification"
description = "Runs the Besu integration tests"

jvmArgs = [
'--add-opens',
'java.base/java.util=ALL-UNNAMED',
'--add-opens',
'java.base/java.util.concurrent=ALL-UNNAMED'
]
testClassesDirs = sourceSets.integrationTest.output.classesDirs
classpath = sourceSets.integrationTest.runtimeClasspath
outputs.upToDateWhen { false }
}
}

def sourceSetIsPopulated = { sourceSetName ->
Expand Down Expand Up @@ -397,27 +429,6 @@ subprojects {
testSupportArtifacts
}


dependencies {
testImplementation sourceSets.testSupport.output
integrationTestImplementation sourceSets.testSupport.output
}

task integrationTest(type: Test, dependsOn: ["compileTestJava"]) {
group = "verification"
description = "Runs the Besu integration tests"

jvmArgs = [
'--add-opens',
'java.base/java.util=ALL-UNNAMED',
'--add-opens',
'java.base/java.util.concurrent=ALL-UNNAMED'
]
testClassesDirs = sourceSets.integrationTest.output.classesDirs
classpath = sourceSets.integrationTest.runtimeClasspath
outputs.upToDateWhen { false }
}

if (file('src/jmh').directory) {
apply plugin: 'me.champeau.gradle.jmh'

Expand Down Expand Up @@ -605,7 +616,17 @@ task checkSpdxHeader(type: CheckSpdxHeader) {
rootPath = "${projectDir}"
spdxHeader = "* SPDX-License-Identifier: Apache-2.0"
filesRegex = "(.*.java)|(.*.groovy)"
excludeRegex = "(.*generalstate/GeneralStateRegressionReferenceTest.*)|(.*generalstate/GeneralStateReferenceTest.*)|(.*blockchain/BlockchainReferenceTest.*)|(.*.gradle/.*)|(.*.idea/.*)"
excludeRegex = [
"(.*/generalstate/GeneralStateRegressionReferenceTest.*)",
"(.*/generalstate/GeneralStateReferenceTest.*)",
"(.*/blockchain/BlockchainReferenceTest.*)",
"(.*/.gradle/.*)",
"(.*/.idea/.*)",
"(.*/out/.*)",
"(.*/build/.*)",
"(.*/src/main/generated/.*)",
].join("|")

}

task jacocoRootReport(type: org.gradle.testing.jacoco.tasks.JacocoReport) {
Expand Down
1 change: 0 additions & 1 deletion config/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,3 @@ dependencies {
}

configurations { testArtifacts }
artifacts { testSupportArtifacts testSupportJar }
1 change: 0 additions & 1 deletion consensus/common/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,4 @@ task testJar (type: Jar) {

artifacts {
testArtifacts testJar
testSupportArtifacts testSupportJar
}
62 changes: 62 additions & 0 deletions ethereum/evmtool/build.gradle
Original file line number Diff line number Diff line change
@@ -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..')
}
}
Original file line number Diff line number Diff line change
@@ -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();
}
}
Original file line number Diff line number Diff line change
@@ -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();
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Loading

0 comments on commit 912d125

Please sign in to comment.