Update evmtool graalvm build (#5639)

* add new class to reflection config
* move CLI output to be system-err oriented
* make logger in evmtool nop
* exclude some problematic jars from compilation
  - mixed versions of bouncy castle
  - netty initializations of log4j
* Standardize JSON ObjectMapper Construction
* Add some manual mappings
* Directly instantiate crypto algorithms where appropriate

Signed-off-by: Danno Ferrin <danno.ferrin@swirldslabs.com>
This commit is contained in:
Danno Ferrin
2023-06-27 23:46:15 -06:00
committed by GitHub
parent a9a11fa985
commit fcdb20296a
18 changed files with 285 additions and 93 deletions

View File

@@ -5,6 +5,7 @@
### Breaking Changes
### Additions and Improvements
- EvmTool now executes the `execution-spec-tests` via the `t8n` and `b11r`. See the [README](ethereum/evmtool/README.md) in EvmTool for more instructions.
### Bug Fixes
- Use the node's configuration to determine if DNS enode URLs are allowed in calls to `admin_addPeer` and `admin_removePeer` [#5584](https://github.com/hyperledger/besu/pull/5584)

View File

@@ -1021,7 +1021,6 @@ tasks.register("verifyDistributions") {
dependencies {
implementation project(':besu')
implementation project(':ethereum:evmtool')
errorprone 'com.google.errorprone:error_prone_core'
}

View File

@@ -14,6 +14,11 @@
*/
package org.hyperledger.besu.crypto;
import static org.hyperledger.besu.crypto.MessageDigestFactory.BLAKE2BF_ALG;
import static org.hyperledger.besu.crypto.MessageDigestFactory.KECCAK256_ALG;
import static org.hyperledger.besu.crypto.MessageDigestFactory.RIPEMD160_ALG;
import static org.hyperledger.besu.crypto.MessageDigestFactory.SHA256_ALG;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.function.Supplier;
@@ -26,13 +31,6 @@ import org.apache.tuweni.bytes.Bytes32;
public abstract class Hash {
private Hash() {}
/** The constant KECCAK256_ALG. */
public static final String KECCAK256_ALG = "KECCAK-256";
private static final String SHA256_ALG = "SHA-256";
private static final String RIPEMD160_ALG = "RIPEMD160";
private static final String BLAKE2BF_ALG = "BLAKE2BF";
private static final Supplier<MessageDigest> KECCAK256_SUPPLIER =
Suppliers.memoize(() -> messageDigest(KECCAK256_ALG));
private static final Supplier<MessageDigest> SHA256_SUPPLIER =

View File

@@ -18,11 +18,25 @@ import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import org.bouncycastle.jcajce.provider.digest.Keccak;
import org.bouncycastle.jcajce.provider.digest.RIPEMD160;
import org.bouncycastle.jcajce.provider.digest.SHA256;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
/** The Message digest factory. */
public class MessageDigestFactory {
private MessageDigestFactory() {}
/** Keccak-256 */
public static final String KECCAK256_ALG = "KECCAK-256";
/** SHA-256 */
public static final String SHA256_ALG = "SHA-256";
/** RipeMD-160 */
public static final String RIPEMD160_ALG = "RIPEMD160";
/** Blake2b F Function */
public static final String BLAKE2BF_ALG = "BLAKE2BF";
static {
Security.addProvider(new BesuProvider());
Security.addProvider(new BouncyCastleProvider());
@@ -37,6 +51,12 @@ public class MessageDigestFactory {
*/
@SuppressWarnings("DoNotInvokeMessageDigestDirectly")
public static MessageDigest create(final String algorithm) throws NoSuchAlgorithmException {
return MessageDigest.getInstance(algorithm);
return switch (algorithm) {
case KECCAK256_ALG -> new Keccak.Digest256();
case SHA256_ALG -> new SHA256.Digest();
case RIPEMD160_ALG -> new RIPEMD160.Digest();
case BLAKE2BF_ALG -> new Blake2bfMessageDigest();
default -> MessageDigest.getInstance(algorithm);
};
}
}

View File

@@ -39,6 +39,8 @@ import com.google.common.collect.Lists;
public class TlsHelpers {
private TlsHelpers() {}
private static KeyStore loadP12KeyStore(final File pkcsFile, final String password)
throws KeyStoreException, NoSuchAlgorithmException, CertificateException {
final KeyStore store = KeyStore.getInstance("pkcs12");
@@ -82,7 +84,7 @@ public class TlsHelpers {
private static String generateFingerprint(final X509Certificate cert)
throws NoSuchAlgorithmException, CertificateEncodingException {
final MessageDigest md = MessageDigestFactory.create("SHA-256");
final MessageDigest md = MessageDigestFactory.create(MessageDigestFactory.SHA256_ALG);
md.update(cert.getEncoded());
final byte[] digest = md.digest();

View File

@@ -14,9 +14,9 @@
*/
package org.hyperledger.besu.ethereum.mainnet;
import static org.hyperledger.besu.crypto.MessageDigestFactory.KECCAK256_ALG;
import static org.hyperledger.besu.ethereum.mainnet.EthHash.EPOCH_LENGTH;
import org.hyperledger.besu.crypto.Hash;
import org.hyperledger.besu.crypto.MessageDigestFactory;
import java.security.DigestException;
@@ -25,11 +25,13 @@ import java.security.NoSuchAlgorithmException;
public class DirectAcyclicGraphSeed {
private DirectAcyclicGraphSeed() {}
public static final ThreadLocal<MessageDigest> KECCAK_256 =
ThreadLocal.withInitial(
() -> {
try {
return MessageDigestFactory.create(Hash.KECCAK256_ALG);
return MessageDigestFactory.create(KECCAK256_ALG);
} catch (final NoSuchAlgorithmException ex) {
throw new IllegalStateException(ex);
}

127
ethereum/evmtool/README.md Normal file
View File

@@ -0,0 +1,127 @@
EVM Tool
========
EVM Tool is a stand alone EVM executor and test execution tool. The
principal purpose of the tool is for testing and validation of the EVM
and enclosing data structures.
Using EVM Tool in execution-specification-tests
-----------------------------------------------
To use EVM Tool in Execution Spec tests it is recommended that you use
the GraalVM build, as the framework incurs significant startup penalties
for each invocation when run via the Java runtime.
### Building Execution Tests on macOS
Current as of 24 Jun 2023.
MacOS users will typically encounter two problems,one relating to the
version of Python used and one relating to zsh.
Homebrew will only install the most recent version of Python
as `python3`, and that is 3.11. The execution tests require 3.10. The
solution is to use a 3.10 version of python to set up the virtual
environment.
```zsh
python3.10 -m venv ./venv/
```
Zsh requires braces to be escaped in the command line, so the step to
install python packages needs to escape the brackets
```zsh
pip install -e .\[docs,lint,test\]
```
An all-in-one script, including homebrew, would look like
```zsh
brew install ethereum solidity
git clone https://github.com/ethereum/execution-spec-tests
cd execution-spec-tests
python3 -m venv ./venv/
source ./venv/bin/activate
pip install -e .[docs,lint,test]
```
### Building EvmTool with GraalVM on macOS
First you need a GraalVM JDK installed, if not already installed.
It is recommended you install [SDKMAN](https://sdkman.io/install) to
manage the graalVM install, homebrew has issues with native attributes
and code signing.
```zsh
sdk install java 22.3.r17-grl
sdk use java 22.3.r17-grl
```
You can also manually install GraalVM from
the [GraalVM website](https://www.graalvm.org/downloads)..
Once GraalVM is installed you use the `nativeCompile` target.
```zsh
./gradlew nativeCompile
```
The resulting binary
is `./ethereum/evmtool/build/native/nativeCompile/evmtool`
If the testing repository and besu are installed in the same parent
directory, the command to run the execution tests is
```zsh
fill -v tests --evm-bin ../besu/ethereum/evmtool/build/install/evmtool/bin/evm
```
Assuming homebrew and SDKMan are both installed, the complete script is
```zsh
sdk install java 22.3.r17-grl
sdk use java 22.3.r17-grl
git clone https://github.com/hyperledger/besu
cd besu
./gradlew nativeCompile
cd ..
brew install ethereum solidity
git clone https://github.com/ethereum/execution-spec-tests
cd execution-spec-tests
python3 -m venv ./venv/
source ./venv/bin/activate
pip install -e .[docs,lint,test]
fill -v tests --evm-bin ../besu/ethereum/evmtool/build/install/evmtool/bin/evm
```
If you don't want to use the GraalVM tool the binary that is compatible
is generated by the `ethereum:evmtool:installdist` target and is located
at `./ethereum/evmtool/build/install/evmtool/bin/evm`
Why not GraalVM for everything?
-------------------------------
Using GraalVM in execution-spec-tests results in over 20x performance
increase in execution. It will be faster to build GraalVM from scratch
and run the execution-spec-tests than to run just the Java version.
It is demonstrably faster to run the Java version for a node.
All the test execution gains are the result of reduced startup
penalties. Larger benchmarks will show that performance intensive EVM
code will be slower in GraalVM than the Java version due to the adaptive
compiler.
For contracts that execute 30 million gas in small operations it is
often faster to run the Java EVMTool than the GraalVM EVMTool, including
startup penalty. The execution tests focus on smaller VM tests that
demonstrate specification conformance.
We would also need to reconsider some library choices. GraalVM does not
work with Log4J, and we would have to ban that library across Besu and
all dependents. Libraries such as Netty also have some problematic entry
points that interact poorly with how SLF4J needs to initialize.

View File

@@ -56,6 +56,8 @@ dependencies {
implementation 'info.picocli:picocli'
implementation 'io.vertx:vertx-core'
runtimeOnly 'org.slf4j:slf4j-nop'
annotationProcessor 'com.google.dagger:dagger-compiler'
annotationProcessor 'info.picocli:picocli-codegen'
@@ -65,9 +67,6 @@ dependencies {
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'
@@ -160,7 +159,7 @@ graalvmNative {
// 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", [".*"])
excludeConfig.put("io.netty:netty-buffer", [".*"])
}
}
}
@@ -169,10 +168,12 @@ graalvmNative {
configurations.nativeImageClasspath {
// netty statically allocates some problematic classes
exclude group: 'io.netty', module: 'netty-buffer'
exclude group: 'io.netty', module: 'netty-common'
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"
exclude group: 'org.bouncycastle', module: 'bcprov-jdk18on'
}

View File

@@ -64,41 +64,57 @@
},
{
"name": "org.hyperledger.besu.ethereum.referencetests.ReferenceTestEnv",
"queryAllPublicConstructors" : true,
"queryAllPublicMethods" : true,
"queryAllPublicConstructors": true,
"queryAllPublicMethods": true,
"allDeclaredConstructors": true,
"allPublicMethods": true
},
{
"name": "org.hyperledger.besu.ethereum.referencetests.ReferenceTestEnv$EnvWithdrawal",
"queryAllPublicConstructors" : true,
"queryAllPublicMethods" : true,
"queryAllPublicConstructors": true,
"queryAllPublicMethods": true,
"allDeclaredConstructors": true,
"allPublicMethods": true
},
{
"name": "org.hyperledger.besu.ethereum.referencetests.ReferenceTestWorldState",
"queryAllPublicConstructors" : true,
"queryAllPublicMethods" : true,
"queryAllPublicConstructors": true,
"queryAllPublicMethods": true,
"allDeclaredConstructors": true,
"allPublicMethods": true
},
{
"name": "org.hyperledger.besu.ethereum.referencetests.ReferenceTestWorldState$AccountMock",
"queryAllPublicConstructors" : true,
"queryAllPublicMethods" : true,
"queryAllPublicConstructors": true,
"queryAllPublicMethods": true,
"allDeclaredConstructors": true,
"allPublicMethods": true
},
{
"name": "org.hyperledger.besu.ethereum.referencetests.BlockchainReferenceTestCaseSpec$ReferenceTestBlockHeader",
"queryAllPublicConstructors" : true,
"queryAllPublicMethods" : true,
"queryAllPublicConstructors": true,
"queryAllPublicMethods": true,
"allDeclaredConstructors": true,
"allPublicMethods": true
},
{
"name": "org.hyperledger.besu.evm.internal.ReturnStack$ReturnStackItem[]",
"unsafeAllocated": true
},
{
"name": "org.hyperledger.besu.evmtool.T8nSubCommand$RejectedTransaction",
"queryAllPublicConstructors": true,
"queryAllPublicMethods": true,
"allDeclaredConstructors": true,
"allPublicMethods": true
},
{
"name": "org.hyperledger.besu.evm.log.Log",
"allDeclaredConstructors": true,
"allPublicConstructors": true,
"allDeclaredMethods": true,
"allPublicMethods": true,
"allDeclaredFields": true,
"allPublicFields": true
}
]

View File

@@ -23,7 +23,6 @@ import org.hyperledger.besu.ethereum.core.BlockHeaderBuilder;
import org.hyperledger.besu.ethereum.mainnet.MainnetBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.referencetests.BlockchainReferenceTestCaseSpec.ReferenceTestBlockHeader;
import org.hyperledger.besu.ethereum.rlp.BytesValueRLPOutput;
import org.hyperledger.besu.util.LogConfigurator;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
@@ -37,17 +36,12 @@ import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.util.DefaultIndenter;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.tuweni.bytes.Bytes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.IParameterConsumer;
@@ -64,8 +58,6 @@ import picocli.CommandLine.ParentCommand;
mixinStandardHelpOptions = true,
versionProvider = VersionProvider.class)
public class B11rSubCommand implements Runnable {
private static final Logger LOG = LoggerFactory.getLogger(B11rSubCommand.class);
static final String COMMAND_NAME = "block-builder";
static final String COMMAND_ALIAS = "b11r";
private static final Path stdoutPath = Path.of("stdout");
@@ -126,8 +118,6 @@ public class B11rSubCommand implements Runnable {
description = "The account state after the transition")
private final Path outBlock = Path.of("block.json");
private static final ObjectMapper objectMapper = new ObjectMapper();
@ParentCommand private final EvmToolCommand parentCommand;
@Parameters(parameterConsumer = OnlyEmptyParams.class)
@@ -162,14 +152,8 @@ public class B11rSubCommand implements Runnable {
@Override
public void run() {
LogConfigurator.setLevel("", "OFF");
objectMapper.setDefaultPrettyPrinter(
(new DefaultPrettyPrinter())
.withSpacesInObjectEntries()
.withObjectIndenter(DefaultIndenter.SYSTEM_LINEFEED_INSTANCE.withIndent(" "))
.withArrayIndenter(DefaultIndenter.SYSTEM_LINEFEED_INSTANCE.withIndent(" ")));
ObjectMapper objectMapper = JsonUtils.createObjectMapper();
final ObjectReader b11rReader = objectMapper.reader();
objectMapper.disable(Feature.AUTO_CLOSE_SOURCE);
ObjectNode config;
try {
@@ -216,11 +200,12 @@ public class B11rSubCommand implements Runnable {
jpe.printStackTrace();
return;
} catch (final IOException e) {
LOG.error("Unable to read state file", e);
System.err.println("Unable to read state file");
e.printStackTrace(System.err);
return;
}
var testHeader = this.readHeader(config.get("header"));
var testHeader = this.readHeader(config.get("header"), objectMapper);
Bytes txsBytes = null;
if (config.has("txs")) {
@@ -277,7 +262,8 @@ public class B11rSubCommand implements Runnable {
}
}
private ReferenceTestBlockHeader readHeader(final JsonNode jsonObject) {
private ReferenceTestBlockHeader readHeader(
final JsonNode jsonObject, final ObjectMapper objectMapper) {
ObjectNode objectNode = (ObjectNode) jsonObject;
maybeMoveField(objectNode, "sha3Uncles", "uncleHash");
maybeMoveField(objectNode, "miner", "coinbase");

View File

@@ -38,14 +38,11 @@ import javax.inject.Singleton;
import com.google.common.base.Suppliers;
import dagger.Module;
import dagger.Provides;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@SuppressWarnings({"CloseableProvides"})
@Module(includes = GenesisFileModule.class)
public class DataStoreModule {
private static final Logger LOG = LoggerFactory.getLogger(DataStoreModule.class);
private final Supplier<RocksDBKeyValueStorageFactory> rocksDBFactory =
Suppliers.memoize(
() ->
@@ -131,7 +128,7 @@ public class DataStoreModule {
case "rocksdb":
return rocksDBFactory.get().create(segment, commonConfiguration, metricsSystem);
default:
LOG.error("Unknown key, continuing as though 'memory' was specified");
System.err.println("Unknown key, continuing as though 'memory' was specified");
// fall through
case "memory":
return new InMemoryKeyValueStorage();

View File

@@ -43,7 +43,6 @@ import org.hyperledger.besu.evm.tracing.StandardJsonTracer;
import org.hyperledger.besu.evm.worldstate.WorldState;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.metrics.MetricsSystemModule;
import org.hyperledger.besu.util.LogConfigurator;
import java.io.BufferedWriter;
import java.io.ByteArrayInputStream;
@@ -70,8 +69,6 @@ import io.vertx.core.json.JsonObject;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.apache.tuweni.units.bigints.UInt256;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import picocli.CommandLine;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
@@ -98,8 +95,6 @@ import picocli.CommandLine.Option;
})
public class EvmToolCommand implements Runnable {
private static final Logger LOG = LoggerFactory.getLogger(EvmToolCommand.class);
@Option(
names = {"--code"},
paramLabel = "<code>",
@@ -288,7 +283,6 @@ public class EvmToolCommand implements Runnable {
@Override
public void run() {
LogConfigurator.setLevel("", "OFF");
try {
final EvmToolComponent component =
DaggerEvmToolComponent.builder()
@@ -438,7 +432,8 @@ public class EvmToolCommand implements Runnable {
} while (remainingIters-- > 0);
} catch (final IOException e) {
LOG.error("Unable to create Genesis module", e);
System.err.println("Unable to create Genesis module");
e.printStackTrace(System.out);
}
}

View File

@@ -0,0 +1,59 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* 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.datatypes.Address;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.core.util.DefaultIndenter;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import org.apache.tuweni.bytes.Bytes;
public class JsonUtils {
private JsonUtils() {}
/**
* Create an object mapper with all the standard bells and whistles needed for evmtool
*
* @return a properly constructed ObjectMapper
*/
public static ObjectMapper createObjectMapper() {
final ObjectMapper objectMapper = new ObjectMapper();
// Attempting to get byte-perfect to go's standard json output
objectMapper.setDefaultPrettyPrinter(
(new DefaultPrettyPrinter())
.withSpacesInObjectEntries()
.withObjectIndenter(DefaultIndenter.SYSTEM_LINEFEED_INSTANCE.withIndent(" "))
.withArrayIndenter(DefaultIndenter.SYSTEM_LINEFEED_INSTANCE.withIndent(" ")));
// When we stream stdin we cannot close the stream
objectMapper.disable(Feature.AUTO_CLOSE_SOURCE);
// GraalVM has a hard time reflecting these classes for serialization
SimpleModule serializers = new SimpleModule("Serializers");
serializers.addSerializer(Address.class, ToStringSerializer.instance);
serializers.addSerializer(Bytes.class, ToStringSerializer.instance);
objectMapper.registerModule(serializers);
return objectMapper;
}
}

View File

@@ -44,7 +44,6 @@ import org.hyperledger.besu.evm.tracing.StandardJsonTracer;
import org.hyperledger.besu.evm.worldstate.WorldState;
import org.hyperledger.besu.evm.worldstate.WorldUpdater;
import org.hyperledger.besu.evmtool.exception.UnsupportedForkException;
import org.hyperledger.besu.util.LogConfigurator;
import java.io.BufferedReader;
import java.io.File;
@@ -56,15 +55,12 @@ import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.base.Stopwatch;
import org.apache.tuweni.bytes.Bytes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import picocli.CommandLine.Parameters;
@@ -76,8 +72,6 @@ import picocli.CommandLine.ParentCommand;
mixinStandardHelpOptions = true,
versionProvider = VersionProvider.class)
public class StateTestSubCommand implements Runnable {
private static final Logger LOG = LoggerFactory.getLogger(StateTestSubCommand.class);
public static final String COMMAND_NAME = "state-test";
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"})
@@ -92,8 +86,6 @@ public class StateTestSubCommand implements Runnable {
@Parameters
private final List<Path> stateTestFiles = new ArrayList<>();
private final ObjectMapper objectMapper = new ObjectMapper();
@SuppressWarnings("unused")
public StateTestSubCommand() {
// PicoCLI requires this
@@ -106,9 +98,8 @@ public class StateTestSubCommand implements Runnable {
@Override
public void run() {
LogConfigurator.setLevel("", "OFF");
final ObjectMapper stateTestMapper = new ObjectMapper();
stateTestMapper.disable(Feature.AUTO_CLOSE_SOURCE);
final ObjectMapper stateTestMapper = JsonUtils.createObjectMapper();
final JavaType javaType =
stateTestMapper
.getTypeFactory()
@@ -147,7 +138,8 @@ public class StateTestSubCommand implements Runnable {
} catch (final JsonProcessingException jpe) {
parentCommand.out.println("File content error: " + jpe);
} catch (final IOException e) {
LOG.error("Unable to read state file", e);
System.err.println("Unable to read state file");
e.printStackTrace(System.err);
}
}
@@ -173,6 +165,7 @@ public class StateTestSubCommand implements Runnable {
parentCommand.showReturnData)
: OperationTracer.NO_TRACING;
final ObjectMapper objectMapper = JsonUtils.createObjectMapper();
for (final GeneralStateTestCaseEipSpec spec : specs) {
final BlockHeader blockHeader = spec.getBlockHeader();

View File

@@ -40,7 +40,6 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
import io.vertx.core.Vertx;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
import io.vertx.core.json.jackson.DatabindCodec;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import picocli.CommandLine;
@@ -93,7 +92,7 @@ public class T8nServerSubCommand implements Runnable {
}
}
ObjectMapper objectMapper = DatabindCodec.mapper();
ObjectMapper objectMapper = JsonUtils.createObjectMapper();
final T8nExecutor.T8nResult result =
T8nExecutor.runTest(
chainId,
@@ -111,7 +110,9 @@ public class T8nServerSubCommand implements Runnable {
}
@Override
public void disposeTracer(final OperationTracer tracer) {}
public void disposeTracer(final OperationTracer tracer) {
// No output streams to dispose of
}
});
ObjectNode outputObject = objectMapper.createObjectNode();

View File

@@ -34,7 +34,6 @@ import org.hyperledger.besu.evm.AccessListEntry;
import org.hyperledger.besu.evm.tracing.OperationTracer;
import org.hyperledger.besu.evm.tracing.StandardJsonTracer;
import org.hyperledger.besu.plugin.data.TransactionType;
import org.hyperledger.besu.util.LogConfigurator;
import java.io.FileOutputStream;
import java.io.FileReader;
@@ -55,10 +54,7 @@ import java.util.Spliterators;
import java.util.Stack;
import java.util.stream.StreamSupport;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.util.DefaultIndenter;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectReader;
@@ -66,8 +62,6 @@ import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.tuweni.bytes.Bytes;
import org.apache.tuweni.bytes.Bytes32;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import picocli.CommandLine.Command;
import picocli.CommandLine.IParameterConsumer;
import picocli.CommandLine.Model.ArgSpec;
@@ -84,7 +78,6 @@ import picocli.CommandLine.ParentCommand;
mixinStandardHelpOptions = true,
versionProvider = VersionProvider.class)
public class T8nSubCommand implements Runnable {
private static final Logger LOG = LoggerFactory.getLogger(T8nSubCommand.class);
record RejectedTransaction(int index, String error) {}
@@ -189,15 +182,8 @@ public class T8nSubCommand implements Runnable {
@Override
public void run() {
LogConfigurator.setLevel("", "OFF");
final ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setDefaultPrettyPrinter(
(new DefaultPrettyPrinter())
.withSpacesInObjectEntries()
.withObjectIndenter(DefaultIndenter.SYSTEM_LINEFEED_INSTANCE.withIndent(" "))
.withArrayIndenter(DefaultIndenter.SYSTEM_LINEFEED_INSTANCE.withIndent(" ")));
final ObjectMapper objectMapper = JsonUtils.createObjectMapper();
final ObjectReader t8nReader = objectMapper.reader();
objectMapper.disable(Feature.AUTO_CLOSE_SOURCE);
MutableWorldState initialWorldState;
ReferenceTestEnv referenceTestEnv;
@@ -252,7 +238,8 @@ public class T8nSubCommand implements Runnable {
jpe.printStackTrace();
return;
} catch (final IOException e) {
LOG.error("Unable to read state file", e);
System.err.println("Unable to read state file");
e.printStackTrace(System.err);
return;
}
@@ -349,7 +336,8 @@ public class T8nSubCommand implements Runnable {
parentCommand.out.println(writer.writeValueAsString(outputObject));
}
} catch (IOException ioe) {
LOG.error("Could not write results", ioe);
System.err.println("Could not write results");
ioe.printStackTrace(System.err);
}
}

View File

@@ -1 +0,0 @@
"0xf90620f860800a8307a12094000000000000000000000000000000000000010080801ca0f73b923883495dc2174285c8fa4176de3d45accfb11cc8034ea1dd09831a4ddfa01c6bccbcd655b4022bcc27de4b9d5cee9ce999cdb8459b0afec4f5054ea02243f860010a8307a12094000000000000000000000000000000000000010180801ba0bffca3f433f61c957d822af37f2b49c57700ff338588d51ea82dc9f720c91d9da0168bb65cc72d586384383f8ceef3a6a60e54b7f4aaa978a6dad271ced54b2ebff860020a8307a12094000000000000000000000000000000000000010280801ba03d9f110bcf0c44be552d4d0ec8387b705604f7d3bb3794dcef4004c38963103ea013bda734f3b5987b8c855f6aab046754506266ff32352ba0898c4eba4acaec8bf860030a8307a12094000000000000000000000000000000000000010380801ba0ecb276d2486664ea779813e599b6f07b7b0df746626d7fdddf60ea425efcb324a0739841682e79a8302dc2e146dfd1eecbdc611d386d42287bcdd94a39bf536020f860040a8307a12094000000000000000000000000000000000000010480801ba002866b5c5fa5dbfa3d88b71a49b82a779c2d508cda631893176782dbcd7435aaa003c380a9af9bfdb3503abcfd5037d3c66f39bb7a19011a3291712d22292c5236f860050a8307a12094000000000000000000000000000000000000010580801ca0c70d2e000e503933d0f1a9a923dc647924811a912adf77692ff7d8f6808d5617a04ad82c92b980580a4a67e4c405e83d560a14201c3fd4b3a42d34dcc19336479af860060a8307a12094000000000000000000000000000000000000010680801ca07f2527f8cbe14e021d270dd214a1820355c7af128001889f57b7f9bba46a6c5da03033308de0d39b9d1b47d28f81df39ceaff330349298c65deb836efe8bce273ff860070a8307a12094000000000000000000000000000000000000010780801ba0ecb720a8764f8967b95dc66e961c6261fceb392c0e90461d7d66113d3c8bbd12a02655e28b751cc2e03a835aa817d884b540765dba12968bc53f53737b4234ee21f860080a8307a12094000000000000000000000000000000000000010880801ba095a2e27c0b296679141c0ad61be112f689b134c04d1773814ddae67fefb2dfbda02955f126d57d8b9777f47c520ffe4285890ca2dd1189e67b3407d6369997e7ecf860090a8307a12094000000000000000000000000000000000000010980801ca02468a120d0ee8c57caac354f56842a1db10813169a328f9f852279668b573907a03971f4c2e6bc0aa666812712719199df6fe37c0e1e122131cdb47d6c0c77b371f8600a0a8307a12094000000000000000000000000000000000000010a80801ba0a3a2018ab0bc2695b94bb85d710f4d07132a94f8c3e0f385824da5fee11899a5a00d2dfe430ea5aaff3de8bbb9339e7485474c8e4e34636f787124a7a91e4d6d6af8600b0a8307a12094000000000000000000000000000000000000010b80801ba0b91968fdb3aecea26094ec30649daa4de81a875bcb1a123e732b8f3f112ce232a02ef8cd85969d8bcef5f4ee1f5d20783b8d9b7466726c15ebf911565825187665f8600c0a8307a12094000000000000000000000000000000000000010c80801ca0dd27e75aa990793205805c22265b04be8299b208fad4f37a7f652ecf32b67390a05aa8cda18521548ff8f95e88f49f309d05cab32de28a0942b8a7a824c50df459f8600d0a8307a12094000000000000000000000000000000000000010d80801ba0fad07ce7139dd4e00266194e6a51c048f74eaba3c0a1b03ece378a810abfaa63a04fec880dafaa5382797b4f88b16138b1f0c4e084817072c77ff9bf17ddd4ac26f8600e0a8307a12094000000000000000000000000000000000000010e80801ca0208b22ab245221bdc5cae6586d2ef019a2c37be41166e04b8abe354c41a8f5b6a032d5d6ef07731cd1684531c775c1727ef6ba75de18cda96d998aaa0c1db0bd68f8600f0a8307a12094000000000000000000000000000000000000010f80801ba0055225ffd3d8b2d19c32aa68cb46e7b52c1d99844fb8b7a53b922ea1649e9c5ba06ae2a1e3b9712354b706d0f4da6ea76ed2f8f75277a51a14a3e0ccf25b85c626"

View File

@@ -21,6 +21,8 @@ import org.hyperledger.besu.ethereum.rlp.RLPOutput;
import java.util.List;
import java.util.Objects;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;
import org.apache.tuweni.bytes.Bytes;
@@ -42,7 +44,11 @@ public class Log {
* @param data Data associated with this log.
* @param topics Indexable topics associated with this log.
*/
public Log(final Address logger, final Bytes data, final List<LogTopic> topics) {
@JsonCreator
public Log(
@JsonProperty("logger") final Address logger,
@JsonProperty("data") final Bytes data,
@JsonProperty("topics") final List<LogTopic> topics) {
this.logger = logger;
this.data = data;
this.topics = ImmutableList.copyOf(topics);
@@ -81,6 +87,7 @@ public class Log {
*
* @return the logger
*/
@JsonProperty("logger")
public Address getLogger() {
return logger;
}
@@ -90,6 +97,7 @@ public class Log {
*
* @return the data
*/
@JsonProperty("data")
public Bytes getData() {
return data;
}
@@ -99,16 +107,16 @@ public class Log {
*
* @return the topics
*/
@JsonProperty("topics")
public List<LogTopic> getTopics() {
return topics;
}
@Override
public boolean equals(final Object other) {
if (!(other instanceof Log)) return false;
if (!(other instanceof Log that)) return false;
// Compare data
final Log that = (Log) other;
return this.data.equals(that.data)
&& this.logger.equals(that.logger)
&& this.topics.equals(that.topics);