Skip to content

Commit

Permalink
Evmtool graalvm support (hyperledger#5192)
Browse files Browse the repository at this point in the history
Changes and config to support using GraalVM AOT to compile and
execute evmTool as an alternate configuration. 

While not as long-term performant the startup time
makes filling reference tests with Besu reasonable.

Signed-off-by: Danno Ferrin <danno.ferrin@swirldslabs.com>
  • Loading branch information
shemnon authored and eum602 committed Nov 3, 2023
1 parent abfc17f commit 0aa5f94
Show file tree
Hide file tree
Showing 13 changed files with 287 additions and 196 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,13 @@

### Breaking Changes

- In `evmtool` (an offline EVM executor tool principally used for reference tests), the `--prestate` and `--genesis` options no longer parse genesis files containing IBFT, QBFT, and Clique network definitions. The same genesis files will work with those json entries removed. [#5192](https://github.com/hyperledger/besu/pull/5192)

### Additions and Improvements

- An alternate build target for the EVM using GraalVM AOT compilaiton was added. [#5192](https://github.com/hyperledger/besu/pull/5192)
- To generate the binary install and use GraalVM 23.3.r17 or higher and run `./gradlew naticeCompile`. The binary will be located in `ethereum/evmtool/build/native/nativeCompile`

### Bug Fixes

### Download Links
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,20 +37,14 @@
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.signers.DSAKCalculator;
import org.bouncycastle.crypto.signers.ECDSASigner;
import org.bouncycastle.jcajce.provider.asymmetric.ec.KeyPairGeneratorSpi;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.math.ec.ECAlgorithms;
import org.bouncycastle.math.ec.ECPoint;

/** The Abstract secp256. */
public abstract class AbstractSECP256 implements SignatureAlgorithm {

/** The constant PRIVATE_KEY_BYTE_LENGTH. */
protected static final int PRIVATE_KEY_BYTE_LENGTH = 32;
/** The constant PUBLIC_KEY_BYTE_LENGTH. */
protected static final int PUBLIC_KEY_BYTE_LENGTH = 64;
/** The constant SIGNATURE_BYTE_LENGTH. */
protected static final int SIGNATURE_BYTE_LENGTH = 65;

/** The constant PROVIDER. */
public static final String PROVIDER = "BC";

Expand Down Expand Up @@ -82,7 +76,7 @@ protected AbstractSECP256(final String curveName, final BigInteger prime) {
curveOrder = curve.getN();
halfCurveOrder = curveOrder.shiftRight(1);
try {
keyPairGenerator = KeyPairGenerator.getInstance(ALGORITHM, PROVIDER);
keyPairGenerator = new KeyPairGeneratorSpi.ECDSA();
} catch (final Exception e) {
throw new RuntimeException(e);
}
Expand Down
41 changes: 37 additions & 4 deletions ethereum/evmtool/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
*
*/

plugins {
id 'org.graalvm.buildtools.native' version '0.9.17'
}

apply plugin: 'java-library'
apply plugin: 'application'
apply plugin: 'idea'
Expand All @@ -36,10 +40,6 @@ dependencies {
implementation project(':config')
implementation project(':crypto')
implementation project(':datatypes')
implementation project(':consensus:clique')
implementation project(':consensus:common')
implementation project(':consensus:ibft')
implementation project(':consensus:qbft')
implementation project(':ethereum:api')
implementation project(':ethereum:core')
implementation project(':ethereum:referencetests')
Expand All @@ -57,13 +57,17 @@ dependencies {
implementation 'io.vertx:vertx-core'

annotationProcessor 'com.google.dagger:dagger-compiler'
annotationProcessor 'info.picocli:picocli-codegen'

testImplementation 'junit:junit'
testImplementation 'org.assertj:assertj-core'
testImplementation 'org.junit.jupiter:junit-jupiter'
testImplementation 'org.mockito:mockito-core'

testRuntimeOnly 'org.junit.vintage:junit-vintage-engine'

// No logging in grallvm EvmTool
nativeImageClasspath 'org.slf4j:slf4j-nop'
}

mainClassName = 'org.hyperledger.besu.evmtool.EvmTool'
Expand Down Expand Up @@ -143,3 +147,32 @@ task dockerUpload(type: Exec) {
executable "sh"
args "-c", cmd
}

graalvmNative {
binaries {
main {
sharedLibrary = false
buildArgs.addAll(
"-H:ReflectionConfigurationFiles=${projectDir}/src/main/graal/reflection-config.json",
"-H:AdditionalSecurityProviders=org.bouncycastle.jce.provider.BouncyCastleProvider",
'-H:+TraceSecurityServices'
)


// Netty drags in older versions of bouncy castle, exclude it so there are no conflicts
excludeConfig.put("io.netty:netty-buffer:4.1.74.Final", [".*"])
}
}
}


configurations.nativeImageClasspath {
// netty statically allocates some problematic classes
exclude group: 'io.netty', module: 'netty-buffer'
exclude group: 'io.netty', module: 'netty-transport'

// keep log4j from sneaking in. GraalVM has an aleric reaction if it sees even one class
exclude group: 'org.slf4j', module: 'log4j-over-slf4j:1.7.36'
exclude group: "log4j", module: "log4j"
exclude group: "org.apache.logging.log4j"
}
104 changes: 104 additions & 0 deletions ethereum/evmtool/src/main/graal/reflection-config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
[
{
"name": "com.github.benmanes.caffeine.cache.PSMW",
"allDeclaredConstructors": true
},
{
"name": "com.github.benmanes.caffeine.cache.PSW",
"allDeclaredConstructors": true
},
{
"name": "com.github.benmanes.caffeine.cache.PSWMS",
"allDeclaredConstructors": true
},
{
"name": "com.github.benmanes.caffeine.cache.SSLA",
"allDeclaredConstructors": true
},
{
"name": "com.github.benmanes.caffeine.cache.SSLMSW",
"allDeclaredConstructors": true
},
{
"name": "com.github.benmanes.caffeine.cache.SSMSW",
"allDeclaredConstructors": true
},
{
"name": "com.github.benmanes.caffeine.cache.SSMW",
"allDeclaredConstructors": true
},
{
"name": "org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi",
"allDeclaredConstructors": true,
"allPublicMethods": true
},
{
"name": "org.bouncycastle.jcajce.provider.asymmetric.ec.KeyFactorySpi$ECDSA",
"allDeclaredConstructors": true,
"allPublicMethods": true
},
{
"name": "org.bouncycastle.jcajce.provider.asymmetric.ec.KeyPairGeneratorSpi",
"allDeclaredConstructors": true,
"allPublicMethods": true
},
{
"name": "org.bouncycastle.jcajce.provider.asymmetric.ec.KeyPairGeneratorSpi$ECDSA",
"allDeclaredConstructors": true,
"allPublicMethods": true
},
{
"name": "org.bouncycastle.jcajce.provider.digest.Keccak$Mappings",
"allDeclaredConstructors": true,
"allPublicMethods": true
},
{
"name": "org.bouncycastle.jcajce.provider.digest.Keccak$Digest256",
"allDeclaredConstructors": true,
"allPublicMethods": true
},
{
"name": "org.bouncycastle.jcajce.provider.digest.Keccak",
"allDeclaredConstructors": true,
"allPublicMethods": true
},
{
"name": "org.hyperledger.besu.ethereum.referencetests.ReferenceTestEnv",
"queryAllPublicConstructors" : true,
"queryAllPublicMethods" : true,
"allDeclaredConstructors": true,
"allPublicMethods": true
},
{
"name": "org.hyperledger.besu.ethereum.referencetests.ReferenceTestEnv$EnvWithdrawal",
"queryAllPublicConstructors" : true,
"queryAllPublicMethods" : true,
"allDeclaredConstructors": true,
"allPublicMethods": true
},
{
"name": "org.hyperledger.besu.ethereum.referencetests.ReferenceTestWorldState",
"queryAllPublicConstructors" : true,
"queryAllPublicMethods" : true,
"allDeclaredConstructors": true,
"allPublicMethods": true
},
{
"name": "org.hyperledger.besu.ethereum.referencetests.ReferenceTestWorldState$AccountMock",
"queryAllPublicConstructors" : true,
"queryAllPublicMethods" : true,
"allDeclaredConstructors": true,
"allPublicMethods": true
},
{
"name": "org.hyperledger.besu.ethereum.referencetests.BlockchainReferenceTestCaseSpec$ReferenceTestBlockHeader",
"queryAllPublicConstructors" : true,
"queryAllPublicMethods" : true,
"allDeclaredConstructors": true,
"allPublicMethods": true
},
{
"name": "org.hyperledger.besu.evm.internal.ReturnStack$ReturnStackItem[]",
"unsafeAllocated": true
}
]
Original file line number Diff line number Diff line change
Expand Up @@ -240,9 +240,11 @@ void maybeMoveField(final ObjectNode jsonObject, final String oldField, final St

private ReferenceTestBlockHeader readHeader(final JsonNode jsonObject) {
ObjectNode objectNode = (ObjectNode) jsonObject;
maybeMoveField(objectNode, "logsBloom", "bloom");
maybeMoveField(objectNode, "sha3Uncles", "uncleHash");
maybeMoveField(objectNode, "miner", "coinbase");
maybeMoveField(objectNode, "transactionsRoot", "transactionsTrie");
maybeMoveField(objectNode, "receiptsRoot", "receiptTrie");
maybeMoveField(objectNode, "logsBloom", "bloom");
return objectMapper.convertValue(jsonObject, ReferenceTestBlockHeader.class);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,9 @@
*/
package org.hyperledger.besu.evmtool;

import org.hyperledger.besu.crypto.SignatureAlgorithmFactory;

public final class EvmTool {

public static void main(final String... args) {
SignatureAlgorithmFactory.setDefaultInstance();

final EvmToolCommand evmToolCommand = new EvmToolCommand();

evmToolCommand.execute(args);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,6 @@ 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;
}
Expand Down Expand Up @@ -101,20 +97,11 @@ static GenesisFileModule createGenesisModule(final File genesisFile) throws IOEx
}

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 if (config.containsKey("qbft")) {
return new QBFTGenesisFileModule(genesisConfig);
} else {
// default is mainnet
return new MainnetGenesisFileModule(genesisConfig);
if (config.containsKey("ibft") || config.containsKey("clique") || config.containsKey("qbft")) {
throw new RuntimeException("Only Ethash and Merge configs accepted as genesis files");
}
return new MainnetGenesisFileModule(genesisConfig);
}
}

This file was deleted.

Loading

0 comments on commit 0aa5f94

Please sign in to comment.