/* * Copyright contributors to Hyperledger Besu. * * 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: 'application' apply plugin: 'java-library' apply plugin: 'jacoco' jar { archiveBaseName = 'besu-test-fuzz' manifest { attributes( 'Specification-Title': archiveBaseName, 'Specification-Version': project.version, 'Implementation-Title': archiveBaseName, 'Implementation-Version': calculateVersion(), 'Commit-Hash': getGitCommitDetails(40).hash ) } } dependencies { implementation project(':besu') implementation project(':crypto:algorithms') implementation project(':datatypes') implementation project(':ethereum:referencetests') implementation project(':evm') implementation project(':util') implementation 'com.fasterxml.jackson.core:jackson-databind' implementation 'com.google.guava:guava' implementation 'info.picocli:picocli' implementation 'io.tmio:tuweni-bytes' implementation 'org.jacoco:org.jacoco.agent' implementation 'org.jacoco:org.jacoco.core' } application { applicationName = 'BesuFuzz' mainClass = 'org.hyperledger.besu.testfuzz.BesuFuzz' applicationDefaultJvmArgs = [ '-javaagent:$APP_HOME/lib/jacocoagent.jar' ] } def corpusDir = "${buildDir}/generated/corpus" tasks.register("runFuzzer", JavaExec) { doNotTrackState("Produces no artifacts") classpath = sourceSets.main.runtimeClasspath mainClass = 'org.hyperledger.besu.testfuzz.BesuFuzz' args = [ "eof-container", "--tests-dir=${projectDir}/../ethereum/referencetests/src/reference-test/external-resources/EOFTests", "--corpus-dir=${corpusDir}" ] doFirst { mkdir corpusDir } } // Adds guidance to the fuzzer but with a 90% performance drop. tasks.register("fuzzGuided") { doLast { runFuzzer.args += "--guidance-regexp=org/(hyperledger/besu|apache/tuweni)" runFuzzer.args += "--new-corpus-dir=${corpusDir}/.." } finalizedBy("runFuzzer") } // This fuzzes besu as an external client. Besu fuzzing as a local client is enabled by default. tasks.register("fuzzBesu") { dependsOn(":installDist") doLast { runFuzzer.args += "--client=besu=../build/install/besu/bin/evmtool code-validate" } finalizedBy("runFuzzer") } tasks.register("fuzzEvmone") { doLast { runFuzzer.args += "--client=evm1=evmone-eofparse" } finalizedBy("runFuzzer") } tasks.register("fuzzEthereumJS") { doLast { runFuzzer.args += "--client=etjs=tsx ../../../ethereumjs/ethereumjs-monorepo/packages/evm/scripts/eofContainerValidator.ts" } finalizedBy("runFuzzer") } tasks.register("fuzzGeth") { doLast { runFuzzer.args += "--client=geth=eofdump eofparser" } finalizedBy("runFuzzer") } tasks.register("fuzzNethermind") { doLast { runFuzzer.args += "--client=neth=netheofparse -x" } finalizedBy("runFuzzer") } tasks.register("fuzzReth") { doLast { runFuzzer.args += "--client=revm=revme bytecode --eof-runtime" } finalizedBy("runFuzzer") } tasks.register("fuzzAll") { dependsOn fuzzEvmone, fuzzEthereumJS, fuzzGeth, fuzzNethermind, fuzzReth } jacoco { applyTo run applyTo runFuzzer } // Copies jacoco into the lib directory tasks.register("copyJacoco", Copy) { // The jacocoagent.jar is embedded within the jar from zipTree(configurations.jacocoAgent.singleFile).filter { it.name == 'jacocoagent.jar' }.singleFile into layout.buildDirectory.dir("install/${application.applicationName}/lib") } installDist.finalizedBy copyJacoco startScripts { defaultJvmOpts = [ "-Dsecp256k1.randomize=false" ] unixStartScriptGenerator.template = resources.text.fromFile("${projectDir}/src/main/scripts/unixStartScript.txt") windowsStartScriptGenerator.template = resources.text.fromFile("${projectDir}/src/main/scripts/windowsStartScript.txt") doLast { tweakStartScript(startScripts) } } static def tweakStartScript(createScriptTask) { def shortenWindowsClasspath = { line -> line.replaceAll(/^set CLASSPATH=.*$/, "set CLASSPATH=%APP_HOME%/lib/*") } createScriptTask.unixScript.text = createScriptTask.unixScript.text.replace('BESU_HOME', '\$APP_HOME') createScriptTask.windowsScript.text = createScriptTask.windowsScript.text.replace('BESU_HOME', '%~dp0..') // Prevent the error originating from the 8191 chars limit on Windows createScriptTask.windowsScript.text = createScriptTask.windowsScript .readLines() .collect(shortenWindowsClasspath) .join('\r\n') }