Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Evmtool graalvm support #5192

Merged
merged 19 commits into from
Mar 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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;
atoulme marked this conversation as resolved.
Show resolved Hide resolved

/** 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");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this related to this PR?

Copy link
Contributor Author

@shemnon shemnon Mar 11, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This unused feature (the ability to calculate the fork from an arbitrary genesis file and world state) has a long cascading requirement that ultimately brings in all the RocksDB classes, and requires significantly more reflection config. Nobody uses the feature because it is fragile and buggy.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In short, these need to be removed to use GraalVM for evmtool. I assert that no one will miss them.

}
return new MainnetGenesisFileModule(genesisConfig);
}
}

This file was deleted.

Loading