diff --git a/CHANGELOG.md b/CHANGELOG.md index 71005da0f30..32b57cdab32 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,8 @@ ## 1.6.0-RC1 ### Additions and Improvements -* Added support for the upcoming YOLOv2 ephemeral testnet and removed the flag for the deprecated YOLOv1 ephemeral testnet. +* Added support for the upcoming YOLOv2 ephemeral testnet and removed the flag for the deprecated YOLOv1 ephemeral testnet. +* Added `debug_standardTraceBlockToFile` JSON-RPC API. This API accepts a block hash and will replay the block. It returns a list of files containing the result of the trace (one file per transaction). [\#1392](https://github.com/hyperledger/besu/pull/1392) ### Bug Fixes diff --git a/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java b/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java index 6d9c8659411..177ebf3a8dd 100644 --- a/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java +++ b/besu/src/main/java/org/hyperledger/besu/RunnerBuilder.java @@ -496,7 +496,8 @@ public Runner build() { webSocketConfiguration, metricsConfiguration, natService, - besuPluginContext.getNamedPlugins()); + besuPluginContext.getNamedPlugins(), + dataDir); jsonRpcHttpService = Optional.of( new JsonRpcHttpService( @@ -560,7 +561,8 @@ public Runner build() { webSocketConfiguration, metricsConfiguration, natService, - besuPluginContext.getNamedPlugins()); + besuPluginContext.getNamedPlugins(), + dataDir); final SubscriptionManager subscriptionManager = createSubscriptionManager(vertx, transactionPool, blockchainQueries); @@ -726,7 +728,8 @@ private Map jsonRpcMethods( final WebSocketConfiguration webSocketConfiguration, final MetricsConfiguration metricsConfiguration, final NatService natService, - final Map namedPlugins) { + final Map namedPlugins, + final Path dataDir) { final Map methods = new JsonRpcMethodsFactory() .methods( @@ -750,7 +753,8 @@ private Map jsonRpcMethods( webSocketConfiguration, metricsConfiguration, natService, - namedPlugins); + namedPlugins, + dataDir); methods.putAll(besuController.getAdditionalJsonRpcMethods(jsonRpcApis)); return methods; } @@ -856,7 +860,6 @@ private WebSocketService createWebsocketService( privateWebSocketMethodsFactory.methods().forEach(websocketMethodsFactory::addMethods); } - final WebSocketRequestHandler websocketRequestHandler = new WebSocketRequestHandler( vertx, diff --git a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java index 6bc30508814..e6f26158e91 100644 --- a/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java +++ b/ethereum/api/src/integration-test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcTestMethodsFactory.java @@ -47,6 +47,7 @@ import org.hyperledger.besu.nat.NatService; import java.math.BigInteger; +import java.nio.file.Path; import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; @@ -113,6 +114,9 @@ public Map methods() { apis.add(RpcApis.WEB3); apis.add(RpcApis.PRIV); apis.add(RpcApis.DEBUG); + + final Path dataDir = mock(Path.class); + return new JsonRpcMethodsFactory() .methods( CLIENT_VERSION, @@ -135,6 +139,7 @@ public Map methods() { webSocketConfiguration, metricsConfiguration, natService, - new HashMap<>()); + new HashMap<>(), + dataDir); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java index aecbcf6e8e1..6a3c68434bb 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/RpcMethod.java @@ -37,6 +37,7 @@ public enum RpcMethod { DEBUG_TRACE_BLOCK("debug_traceBlock"), DEBUG_TRACE_BLOCK_BY_HASH("debug_traceBlockByHash"), DEBUG_TRACE_BLOCK_BY_NUMBER("debug_traceBlockByNumber"), + DEBUG_STANDARD_TRACE_BLOCK_TO_FILE("debug_standardTraceBlockToFile"), DEBUG_TRACE_TRANSACTION("debug_traceTransaction"), DEBUG_BATCH_RAW_TRANSACTION("debug_batchSendRawTransaction"), DEBUG_GET_BAD_BLOCKS("debug_getBadBlocks"), diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugStandardTraceBlockToFile.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugStandardTraceBlockToFile.java new file mode 100644 index 00000000000..c1829fa259b --- /dev/null +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugStandardTraceBlockToFile.java @@ -0,0 +1,95 @@ +/* + * 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.ethereum.api.jsonrpc.internal.methods; + +import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.TransactionTracer.TRACE_PATH; + +import org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.TransactionTraceParams; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.TransactionTracer; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcError; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcResponse; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; +import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; +import org.hyperledger.besu.ethereum.core.Block; +import org.hyperledger.besu.ethereum.core.Hash; + +import java.nio.file.Path; +import java.util.List; +import java.util.Optional; +import java.util.function.Supplier; + +import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.base.Suppliers; + +public class DebugStandardTraceBlockToFile implements JsonRpcMethod { + + private final Supplier transactionTracerSupplier; + private final Supplier blockchainQueries; + private final Path dataDir; + + public DebugStandardTraceBlockToFile( + final Supplier transactionTracerSupplier, + final BlockchainQueries blockchainQueries, + final Path dataDir) { + this.transactionTracerSupplier = transactionTracerSupplier; + this.blockchainQueries = Suppliers.ofInstance(blockchainQueries); + this.dataDir = dataDir; + } + + @Override + public String getName() { + return RpcMethod.DEBUG_STANDARD_TRACE_BLOCK_TO_FILE.getMethodName(); + } + + @Override + public JsonRpcResponse response(final JsonRpcRequestContext requestContext) { + final Hash blockHash = requestContext.getRequiredParameter(0, Hash.class); + final Optional transactionTraceParams = + requestContext.getOptionalParameter(1, TransactionTraceParams.class); + + return blockchainQueries + .get() + .getBlockchain() + .getBlockByHash(blockHash) + .map( + block -> + (JsonRpcResponse) + new JsonRpcSuccessResponse( + requestContext.getRequest().getId(), + traceBlock(block, transactionTraceParams))) + .orElse( + new JsonRpcErrorResponse( + requestContext.getRequest().getId(), JsonRpcError.BLOCK_NOT_FOUND)); + } + + private List traceBlock( + final Block block, final Optional transactionTraceParams) { + return transactionTracerSupplier + .get() + .traceTransactionToFile( + block.getHash(), + block.getBody().getTransactions(), + transactionTraceParams, + dataDir.resolve(TRACE_PATH)); + } + + protected Object emptyResult() { + final ObjectMapper mapper = new ObjectMapper(); + return mapper.createArrayNode(); + } +} diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/TransactionTraceParams.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/TransactionTraceParams.java index 7fb1bb9491d..da7014f5bec 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/TransactionTraceParams.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/parameters/TransactionTraceParams.java @@ -16,28 +16,43 @@ import org.hyperledger.besu.ethereum.debug.TraceOptions; -import com.fasterxml.jackson.annotation.JsonCreator; +import javax.annotation.Nullable; + import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import org.immutables.value.Value; +@Value.Immutable +@JsonSerialize(as = ImmutableTransactionTraceParams.class) +@JsonDeserialize(as = ImmutableTransactionTraceParams.class) @JsonIgnoreProperties(ignoreUnknown = true) -public class TransactionTraceParams { - - private final boolean disableStorage; - private final boolean disableMemory; - private final boolean disableStack; - - @JsonCreator() - public TransactionTraceParams( - @JsonProperty("disableStorage") final boolean disableStorage, - @JsonProperty("disableMemory") final boolean disableMemory, - @JsonProperty("disableStack") final boolean disableStack) { - this.disableStorage = disableStorage; - this.disableMemory = disableMemory; - this.disableStack = disableStack; +public interface TransactionTraceParams { + + @JsonProperty("txHash") + @Nullable + String getTransactionHash(); + + @JsonProperty(value = "disableStorage") + @Value.Default + default boolean disableStorage() { + return false; + } + + @JsonProperty(value = "disableMemory") + @Value.Default + default boolean disableMemory() { + return false; + } + + @JsonProperty(value = "disableStack") + @Value.Default + default boolean disableStack() { + return false; } - public TraceOptions traceOptions() { - return new TraceOptions(!disableStorage, !disableMemory, !disableStack); + default TraceOptions traceOptions() { + return new TraceOptions(!disableStorage(), !disableMemory(), !disableStack()); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockTracer.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockTracer.java index 1552c69df09..c6b53de1816 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockTracer.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/BlockTracer.java @@ -14,7 +14,6 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor; -import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockReplay.TransactionAction; import org.hyperledger.besu.ethereum.core.AbstractWorldUpdater; import org.hyperledger.besu.ethereum.core.AbstractWorldUpdater.StackedUpdater; import org.hyperledger.besu.ethereum.core.Block; @@ -47,7 +46,7 @@ public Optional trace(final Block block, final DebugOperationTracer return blockReplay.block(block, prepareReplayAction(tracer)); } - private TransactionAction prepareReplayAction( + private BlockReplay.TransactionAction prepareReplayAction( final DebugOperationTracer tracer) { return (transaction, header, blockchain, mutableWorldState, transactionProcessor) -> { // if we have no prior updater, it must be the first TX, so use the block's initial state diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTrace.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTrace.java index 94c1eb13fc0..8bac5f1e9fb 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTrace.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTrace.java @@ -19,18 +19,32 @@ import org.hyperledger.besu.ethereum.mainnet.TransactionProcessor.Result; import java.util.List; +import java.util.Optional; public class TransactionTrace { private final Transaction transaction; private final Result result; private final List traceFrames; + private final Optional time; public TransactionTrace( final Transaction transaction, final Result result, final List traceFrames) { this.transaction = transaction; this.result = result; this.traceFrames = traceFrames; + this.time = Optional.empty(); + } + + public TransactionTrace( + final Transaction transaction, + final Result result, + final List traceFrames, + final Long time) { + this.transaction = transaction; + this.result = result; + this.traceFrames = traceFrames; + this.time = Optional.of(time); } public Transaction getTransaction() { @@ -52,4 +66,8 @@ public Result getResult() { public List getTraceFrames() { return traceFrames; } + + public Optional getTime() { + return time; + } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java index 1f37f912575..a8328101ac1 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java @@ -14,16 +14,40 @@ */ package org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor; +import static java.util.function.Predicate.isEqual; + +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.TransactionTraceParams; import org.hyperledger.besu.ethereum.core.Hash; +import org.hyperledger.besu.ethereum.core.Transaction; +import org.hyperledger.besu.ethereum.debug.TraceOptions; import org.hyperledger.besu.ethereum.mainnet.TransactionProcessor.Result; +import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams; import org.hyperledger.besu.ethereum.vm.BlockHashLookup; import org.hyperledger.besu.ethereum.vm.DebugOperationTracer; +import org.hyperledger.besu.ethereum.vm.StandardJsonTracer; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.PrintStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; +import java.util.concurrent.TimeUnit; + +import com.google.common.base.Stopwatch; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; /** Used to produce debug traces of transactions */ public class TransactionTracer { + private static final Logger LOG = LogManager.getLogger(); + + public static final String TRACE_PATH = "traces"; + private final BlockReplay blockReplay; public TransactionTracer(final BlockReplay blockReplay) { @@ -36,6 +60,7 @@ public Optional traceTransaction( blockHash, transactionHash, (transaction, header, blockchain, mutableWorldState, transactionProcessor) -> { + final Stopwatch timer = Stopwatch.createStarted(); final Result result = transactionProcessor.processTransaction( blockchain, @@ -46,7 +71,88 @@ public Optional traceTransaction( tracer, new BlockHashLookup(header, blockchain), false); - return new TransactionTrace(transaction, result, tracer.getTraceFrames()); + timer.stop(); + return new TransactionTrace( + transaction, result, tracer.getTraceFrames(), timer.elapsed(TimeUnit.NANOSECONDS)); }); } + + public Optional traceTransaction( + final Hash blockHash, final Hash transactionHash, final StandardJsonTracer tracer) { + return blockReplay.beforeTransactionInBlock( + blockHash, + transactionHash, + (transaction, header, blockchain, mutableWorldState, transactionProcessor) -> { + final Stopwatch timer = Stopwatch.createStarted(); + final Result result = + transactionProcessor.processTransaction( + blockchain, + mutableWorldState.updater(), + header, + transaction, + header.getCoinbase(), + tracer, + new BlockHashLookup(header, blockchain), + false, + new TransactionValidationParams.Builder().allowFutureNonce(true).build()); + + timer.stop(); + return new TransactionTrace( + transaction, result, new ArrayList<>(), timer.elapsed(TimeUnit.NANOSECONDS)); + }); + } + + public List traceTransactionToFile( + final Hash blockHash, + final List transactions, + final Optional transactionTraceParams, + final Path traceDir) { + final List traces = new ArrayList<>(); + try { + final Optional selectedHash = + transactionTraceParams + .map(TransactionTraceParams::getTransactionHash) + .map(Hash::fromHexString); + final boolean showMemory = + transactionTraceParams + .map(TransactionTraceParams::traceOptions) + .map(TraceOptions::isMemoryEnabled) + .orElse(true); + + if (!Files.isDirectory(traceDir) && !traceDir.toFile().mkdirs()) { + throw new IOException( + String.format("Trace directory '%s' does not exist and could not be made.", traceDir)); + } + for (int i = 0; i < transactions.size(); i++) { + final Transaction transaction = transactions.get(i); + if (selectedHash.isEmpty() + || selectedHash.filter(isEqual(transaction.getHash())).isPresent()) { + final File traceFile = + traceDir + .resolve( + String.format( + "block_%.10s-%d-%.10s-%s", + blockHash.toHexString(), + i, + transaction.getHash().toHexString(), + System.currentTimeMillis())) + .toFile(); + try (PrintStream out = new PrintStream(new FileOutputStream(traceFile))) { + traceTransaction( + blockHash, transaction.getHash(), new StandardJsonTracer(out, showMemory)) + .ifPresent( + trace -> + out.println( + StandardJsonTracer.summaryTrace( + transaction, trace.getTime().orElseThrow(), trace.getResult()))); + traces.add(traceFile.getPath()); + } + } + } + } catch (Exception e) { + LOG.error("Unable to create transaction trace : {}", e.getMessage()); + throw new RuntimeException(e.getMessage(), e); + } + return traces; + } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/JsonRpcError.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/JsonRpcError.java index 00aaafc52ac..8935f861bd1 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/JsonRpcError.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/response/JsonRpcError.java @@ -75,6 +75,7 @@ public enum JsonRpcError { WORLD_STATE_UNAVAILABLE(-32000, "World state unavailable"), // Debug failures + BLOCK_NOT_FOUND(-32000, "Block not found"), PARENT_BLOCK_NOT_FOUND(-32000, "Parent block not found"), // Permissioning/Account allowlist errors diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/DebugJsonRpcMethods.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/DebugJsonRpcMethods.java index 4df32e8ffed..d7e51d78486 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/DebugJsonRpcMethods.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/DebugJsonRpcMethods.java @@ -20,6 +20,7 @@ import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugBatchSendRawTransaction; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugGetBadBlocks; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugMetrics; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugStandardTraceBlockToFile; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugStorageRangeAt; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugTraceBlock; import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugTraceBlockByHash; @@ -36,6 +37,7 @@ import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions; import org.hyperledger.besu.metrics.ObservableMetricsSystem; +import java.nio.file.Path; import java.util.Map; public class DebugJsonRpcMethods extends ApiGroupJsonRpcMethods { @@ -46,16 +48,19 @@ public class DebugJsonRpcMethods extends ApiGroupJsonRpcMethods { private final ProtocolSchedule protocolSchedule; private final ObservableMetricsSystem metricsSystem; private final TransactionPool transactionPool; + private final Path dataDir; DebugJsonRpcMethods( final BlockchainQueries blockchainQueries, final ProtocolSchedule protocolSchedule, final ObservableMetricsSystem metricsSystem, - final TransactionPool transactionPool) { + final TransactionPool transactionPool, + final Path dataDir) { this.blockchainQueries = blockchainQueries; this.protocolSchedule = protocolSchedule; this.metricsSystem = metricsSystem; this.transactionPool = transactionPool; + this.dataDir = dataDir; } @Override @@ -83,6 +88,8 @@ protected Map create() { new DebugTraceBlockByNumber(() -> new BlockTracer(blockReplay), blockchainQueries), new DebugTraceBlockByHash(() -> new BlockTracer(blockReplay)), new DebugBatchSendRawTransaction(transactionPool), - new DebugGetBadBlocks(blockchainQueries, protocolSchedule, blockResult)); + new DebugGetBadBlocks(blockchainQueries, protocolSchedule, blockResult), + new DebugStandardTraceBlockToFile( + () -> new TransactionTracer(blockReplay), blockchainQueries, dataDir)); } } diff --git a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java index 45af5338de0..8b0aa3f54f2 100644 --- a/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java +++ b/ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/methods/JsonRpcMethodsFactory.java @@ -37,6 +37,7 @@ import org.hyperledger.besu.plugin.BesuPlugin; import java.math.BigInteger; +import java.nio.file.Path; import java.util.Collection; import java.util.HashMap; import java.util.List; @@ -67,7 +68,8 @@ public Map methods( final WebSocketConfiguration webSocketConfiguration, final MetricsConfiguration metricsConfiguration, final NatService natService, - final Map namedPlugins) { + final Map namedPlugins, + final Path dataDir) { final Map enabled = new HashMap<>(); if (!rpcApis.isEmpty()) { @@ -85,7 +87,7 @@ public Map methods( namedPlugins, natService), new DebugJsonRpcMethods( - blockchainQueries, protocolSchedule, metricsSystem, transactionPool), + blockchainQueries, protocolSchedule, metricsSystem, transactionPool, dataDir), new EeaJsonRpcMethods( blockchainQueries, protocolSchedule, transactionPool, privacyParameters), new EthJsonRpcMethods( diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java index 6b8e11ee41c..25c8aca3470 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/AbstractJsonRpcHttpServiceTest.java @@ -168,7 +168,8 @@ protected Map getRpcMethods( mock(WebSocketConfiguration.class), mock(MetricsConfiguration.class), natService, - new HashMap<>()); + new HashMap<>(), + folder.getRoot().toPath()); } protected void startService() throws Exception { diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostWhitelistTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostWhitelistTest.java index 87e23d0f1fe..d9457541f55 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostWhitelistTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceHostWhitelistTest.java @@ -118,7 +118,8 @@ public void initServerAndClient() throws Exception { mock(WebSocketConfiguration.class), mock(MetricsConfiguration.class), natService, - new HashMap<>())); + new HashMap<>(), + folder.getRoot().toPath())); service = createJsonRpcHttpService(); service.start().join(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceLoginTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceLoginTest.java index a0ed2caf690..bdc291fb129 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceLoginTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceLoginTest.java @@ -144,7 +144,8 @@ public static void initServerAndClient() throws Exception { mock(WebSocketConfiguration.class), mock(MetricsConfiguration.class), natService, - new HashMap<>())); + new HashMap<>(), + folder.getRoot().toPath())); service = createJsonRpcHttpService(); jwtAuth = service.authenticationService.get().getJwtAuthProvider(); service.start().join(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceRpcApisTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceRpcApisTest.java index 3e405c8f5cf..b2ef0331975 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceRpcApisTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceRpcApisTest.java @@ -211,7 +211,8 @@ private JsonRpcHttpService createJsonRpcHttpServiceWithRpcApis(final JsonRpcConf mock(WebSocketConfiguration.class), mock(MetricsConfiguration.class), natService, - new HashMap<>())); + new HashMap<>(), + folder.getRoot().toPath())); final JsonRpcHttpService jsonRpcHttpService = new JsonRpcHttpService( vertx, @@ -304,7 +305,8 @@ private JsonRpcHttpService createJsonRpcHttpService( webSocketConfiguration, metricsConfiguration, natService, - new HashMap<>())); + new HashMap<>(), + folder.getRoot().toPath())); final JsonRpcHttpService jsonRpcHttpService = new JsonRpcHttpService( vertx, diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTest.java index 144058cadb3..bfbafa05ad3 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTest.java @@ -146,7 +146,8 @@ public static void initServerAndClient() throws Exception { mock(WebSocketConfiguration.class), mock(MetricsConfiguration.class), natService, - new HashMap<>())); + new HashMap<>(), + folder.getRoot().toPath())); service = createJsonRpcHttpService(); service.start().join(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsClientAuthTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsClientAuthTest.java index 2d8595da467..a33ea789094 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsClientAuthTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsClientAuthTest.java @@ -136,7 +136,8 @@ public void initServer() throws Exception { mock(WebSocketConfiguration.class), mock(MetricsConfiguration.class), natService, - Collections.emptyMap())); + Collections.emptyMap(), + folder.getRoot().toPath())); System.setProperty("javax.net.ssl.trustStore", CLIENT_AS_CA_CERT.getKeyStoreFile().toString()); System.setProperty( diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsMisconfigurationTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsMisconfigurationTest.java index 854d363a0ed..3c95e13cf4e 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsMisconfigurationTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsMisconfigurationTest.java @@ -124,7 +124,8 @@ public void beforeEach() throws IOException { mock(WebSocketConfiguration.class), mock(MetricsConfiguration.class), natService, - Collections.emptyMap())); + Collections.emptyMap(), + folder.getRoot().toPath())); } @After diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsTest.java index 81d7973f804..040430c79ec 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/JsonRpcHttpServiceTlsTest.java @@ -127,7 +127,8 @@ public void initServer() throws Exception { mock(WebSocketConfiguration.class), mock(MetricsConfiguration.class), natService, - Collections.emptyMap())); + Collections.emptyMap(), + folder.getRoot().toPath())); service = createJsonRpcHttpService(createJsonRpcConfig()); service.start().join(); baseUrl = service.url(); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugStandardTraceBlockToFileTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugStandardTraceBlockToFileTest.java new file mode 100644 index 00000000000..65943939088 --- /dev/null +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugStandardTraceBlockToFileTest.java @@ -0,0 +1,87 @@ +/* + * 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.ethereum.api.jsonrpc.internal.methods; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequest; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.TransactionTracer; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse; +import org.hyperledger.besu.ethereum.api.query.BlockchainQueries; +import org.hyperledger.besu.ethereum.chain.Blockchain; +import org.hyperledger.besu.ethereum.core.Block; +import org.hyperledger.besu.ethereum.core.BlockDataGenerator; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Optional; + +import org.junit.ClassRule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +public class DebugStandardTraceBlockToFileTest { + + @ClassRule public static final TemporaryFolder folder = new TemporaryFolder(); + + private final BlockchainQueries blockchainQueries = mock(BlockchainQueries.class); + private final Blockchain blockchain = mock(Blockchain.class); + private final TransactionTracer transactionTracer = mock(TransactionTracer.class); + private final DebugStandardTraceBlockToFile debugStandardTraceBlockToFile = + new DebugStandardTraceBlockToFile( + () -> transactionTracer, blockchainQueries, folder.getRoot().toPath()); + + @Test + public void nameShouldBeDebugTraceTransaction() { + assertThat(debugStandardTraceBlockToFile.getName()).isEqualTo("debug_standardTraceBlockToFile"); + } + + @SuppressWarnings("rawtypes") + @Test + public void shouldTraceTheTransactionUsingTheTransactionTracer() { + + final BlockDataGenerator blockGenerator = new BlockDataGenerator(); + final Block genesis = blockGenerator.genesisBlock(); + final Block block = + blockGenerator.block( + new BlockDataGenerator.BlockOptions().setParentHash(genesis.getHeader().getHash())); + + final Object[] params = new Object[] {block.getHash(), new HashMap<>()}; + final JsonRpcRequestContext request = + new JsonRpcRequestContext( + new JsonRpcRequest("2.0", "debug_standardTraceBlockToFile", params)); + + final List paths = new ArrayList<>(); + paths.add("path-1"); + + when(blockchainQueries.getBlockchain()).thenReturn(blockchain); + + when(blockchain.getBlockByHash(block.getHash())).thenReturn(Optional.of(block)); + + when(transactionTracer.traceTransactionToFile(eq(block.getHash()), any(), any(), any())) + .thenReturn(paths); + final JsonRpcSuccessResponse response = + (JsonRpcSuccessResponse) debugStandardTraceBlockToFile.response(request); + final List result = (ArrayList) response.getResult(); + + assertThat(result.size()).isEqualTo(1); + } +} diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceTransactionTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceTransactionTest.java index 025beebb4bd..801dab36e93 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceTransactionTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/methods/DebugTraceTransactionTest.java @@ -36,6 +36,7 @@ import org.hyperledger.besu.ethereum.core.Wei; import org.hyperledger.besu.ethereum.debug.TraceFrame; import org.hyperledger.besu.ethereum.mainnet.TransactionProcessor.Result; +import org.hyperledger.besu.ethereum.vm.DebugOperationTracer; import java.util.Collections; import java.util.HashMap; @@ -121,7 +122,8 @@ public void shouldTraceTheTransactionUsingTheTransactionTracer() { when(blockchain.headBlockNumber()).thenReturn(12L); when(blockchain.transactionByHash(transactionHash)) .thenReturn(Optional.of(transactionWithMetadata)); - when(transactionTracer.traceTransaction(eq(blockHash), eq(transactionHash), any())) + when(transactionTracer.traceTransaction( + eq(blockHash), eq(transactionHash), any(DebugOperationTracer.class))) .thenReturn(Optional.of(transactionTrace)); final JsonRpcSuccessResponse response = (JsonRpcSuccessResponse) debugTraceTransaction.response(request); @@ -184,7 +186,8 @@ public void shouldNotTraceTheTransactionIfNotFound() { when(blockHeader.getNumber()).thenReturn(12L); when(blockchain.headBlockNumber()).thenReturn(12L); when(blockchain.transactionByHash(transactionHash)).thenReturn(Optional.empty()); - when(transactionTracer.traceTransaction(eq(blockHash), eq(transactionHash), any())) + when(transactionTracer.traceTransaction( + eq(blockHash), eq(transactionHash), any(DebugOperationTracer.class))) .thenReturn(Optional.of(transactionTrace)); final JsonRpcSuccessResponse response = (JsonRpcSuccessResponse) debugTraceTransaction.response(request); diff --git a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracerTest.java b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracerTest.java index 6d2bcf77159..865cfc0bc6c 100644 --- a/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracerTest.java +++ b/ethereum/api/src/test/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracerTest.java @@ -20,6 +20,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.ImmutableTransactionTraceParams; import org.hyperledger.besu.ethereum.chain.Blockchain; import org.hyperledger.besu.ethereum.core.Address; import org.hyperledger.besu.ethereum.core.BlockBody; @@ -34,15 +35,23 @@ import org.hyperledger.besu.ethereum.mainnet.TransactionProcessor; import org.hyperledger.besu.ethereum.mainnet.TransactionProcessor.Result; import org.hyperledger.besu.ethereum.vm.DebugOperationTracer; +import org.hyperledger.besu.ethereum.vm.StandardJsonTracer; import org.hyperledger.besu.ethereum.worldstate.WorldStateArchive; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Optional; +import org.apache.tuweni.bytes.Bytes; import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.junit.runner.RunWith; import org.mockito.Mock; import org.mockito.junit.MockitoJUnitRunner; @@ -50,6 +59,8 @@ @RunWith(MockitoJUnitRunner.class) public class TransactionTracerTest { + @Rule public TemporaryFolder traceDir = new TemporaryFolder(); + @Mock private ProtocolSchedule protocolSchedule; @Mock private Blockchain blockchain; @@ -198,4 +209,60 @@ public void traceTransactionShouldReturnEmptyResultWhenBlockIsNotAvailable() { assertThat(transactionTrace).isEmpty(); } + + @Test + public void traceTransactionToFileShouldReturnEmptyListWhenNoTransaction() { + + final List transactions = new ArrayList<>(); + + final List transactionTraces = + transactionTracer.traceTransactionToFile( + blockHash, + transactions, + Optional.of(ImmutableTransactionTraceParams.builder().build()), + traceDir.getRoot().toPath()); + + assertThat(transactionTraces).isEmpty(); + } + + @Test + public void traceTransactionToFileShouldReturnResultFromProcessTransaction() throws IOException { + + List transactions = Collections.singletonList(transaction); + + final Result result = mock(Result.class); + when(result.getOutput()).thenReturn(Bytes.of(0x01, 0x02)); + + when(blockchain.getBlockHeader(blockHash)).thenReturn(Optional.of(blockHeader)); + when(blockchain.getBlockHeader(previousBlockHash)).thenReturn(Optional.of(previousBlockHeader)); + + when(blockBody.getTransactions()).thenReturn(Collections.singletonList(transaction)); + when(blockchain.getBlockBody(blockHash)).thenReturn(Optional.of(blockBody)); + + final WorldUpdater updater = mutableWorldState.updater(); + final Address coinbase = blockHeader.getCoinbase(); + when(transactionProcessor.processTransaction( + eq(blockchain), + eq(updater), + eq(blockHeader), + eq(transaction), + eq(coinbase), + any(StandardJsonTracer.class), + any(), + any(), + any())) + .thenReturn(result); + + final List transactionTraces = + transactionTracer.traceTransactionToFile( + blockHash, + transactions, + Optional.of(ImmutableTransactionTraceParams.builder().build()), + traceDir.getRoot().toPath()); + ; + + assertThat(transactionTraces.size()).isEqualTo(1); + assertThat(Files.readString(Path.of(transactionTraces.get(0)))) + .contains("{\"output\":\"0102\",\"gasUsed\":\"0x0\""); + } } diff --git a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/TransactionValidationParams.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/TransactionValidationParams.java index 97293eaf321..43940c27d65 100644 --- a/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/TransactionValidationParams.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/mainnet/TransactionValidationParams.java @@ -71,7 +71,7 @@ public static TransactionValidationParams blockReplay() { return blockReplayParams; } - static class Builder { + public static class Builder { private boolean allowFutureNonce = false; private boolean checkOnchainPermissions = false; diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EVMToolTracer.java b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/StandardJsonTracer.java similarity index 76% rename from ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EVMToolTracer.java rename to ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/StandardJsonTracer.java index 4d1f8f7bf5d..38f3fd5f73b 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EVMToolTracer.java +++ b/ethereum/core/src/main/java/org/hyperledger/besu/ethereum/vm/StandardJsonTracer.java @@ -14,14 +14,12 @@ * */ -package org.hyperledger.besu.evmtool; +package org.hyperledger.besu.ethereum.vm; import org.hyperledger.besu.ethereum.core.Gas; -import org.hyperledger.besu.ethereum.vm.ExceptionalHaltReason; -import org.hyperledger.besu.ethereum.vm.MessageFrame; -import org.hyperledger.besu.ethereum.vm.Operation; +import org.hyperledger.besu.ethereum.core.Transaction; +import org.hyperledger.besu.ethereum.mainnet.TransactionProcessor; import org.hyperledger.besu.ethereum.vm.Operation.OperationResult; -import org.hyperledger.besu.ethereum.vm.OperationTracer; import org.hyperledger.besu.ethereum.vm.operations.ReturnStack; import java.io.PrintStream; @@ -34,19 +32,19 @@ import org.apache.tuweni.bytes.Bytes; import org.apache.tuweni.units.bigints.UInt256; -class EVMToolTracer implements OperationTracer { +public class StandardJsonTracer implements OperationTracer { - private final ObjectMapper objectMapper = new ObjectMapper(); + private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); private final PrintStream out; private final boolean showMemory; - EVMToolTracer(final PrintStream out, final boolean showMemory) { + public StandardJsonTracer(final PrintStream out, final boolean showMemory) { this.out = out; this.showMemory = showMemory; } - static String shortNumber(final UInt256 number) { + public static String shortNumber(final UInt256 number) { return number.isZero() ? "0x0" : number.toShortHexString(); } @@ -54,10 +52,22 @@ private static String shortBytes(final Bytes bytes) { return bytes.isZero() ? "0x0" : bytes.toShortHexString(); } + public static String summaryTrace( + final Transaction transaction, final long timer, final TransactionProcessor.Result result) { + final ObjectNode summaryLine = OBJECT_MAPPER.createObjectNode(); + summaryLine.put("output", result.getOutput().toUnprefixedHexString()); + summaryLine.put( + "gasUsed", + StandardJsonTracer.shortNumber( + UInt256.valueOf(transaction.getGasLimit() - result.getGasRemaining()))); + summaryLine.put("time", timer); + return summaryLine.toString(); + } + @Override public void traceExecution( final MessageFrame messageFrame, final ExecuteOperation executeOperation) { - final ObjectNode traceLine = objectMapper.createObjectNode(); + final ObjectNode traceLine = OBJECT_MAPPER.createObjectNode(); final Operation currentOp = messageFrame.getCurrentOperation(); traceLine.put("pc", messageFrame.getPC()); @@ -86,7 +96,9 @@ public void traceExecution( if (showMemory) { traceLine.put( "memory", - messageFrame.readMemory(UInt256.ZERO, messageFrame.memoryWordSize()).toHexString()); + messageFrame + .readMemory(UInt256.ZERO, messageFrame.memoryWordSize().multiply(32)) + .toHexString()); } else { traceLine.put("memory", "0x"); } diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java index 1ea8bac5fdb..6d45bfdd0a7 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/EvmToolCommand.java @@ -38,6 +38,7 @@ import org.hyperledger.besu.ethereum.vm.EVM; import org.hyperledger.besu.ethereum.vm.MessageFrame; import org.hyperledger.besu.ethereum.vm.OperationTracer; +import org.hyperledger.besu.ethereum.vm.StandardJsonTracer; import java.io.File; import java.io.IOException; @@ -222,7 +223,7 @@ public void run() { final OperationTracer tracer = // You should have picked Mercy. lastLoop && showJsonResults - ? new EVMToolTracer(System.out, !noMemory) + ? new StandardJsonTracer(System.out, !noMemory) : OperationTracer.NO_TRACING; final Deque messageFrameStack = new ArrayDeque<>(); diff --git a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java index 4b85c55e321..427dca0e035 100644 --- a/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java +++ b/ethereum/evmtool/src/main/java/org/hyperledger/besu/evmtool/StateTestSubCommand.java @@ -36,6 +36,7 @@ import org.hyperledger.besu.ethereum.rlp.RLP; import org.hyperledger.besu.ethereum.vm.BlockHashLookup; import org.hyperledger.besu.ethereum.vm.OperationTracer; +import org.hyperledger.besu.ethereum.vm.StandardJsonTracer; import org.hyperledger.besu.ethereum.worldstate.DefaultMutableWorldState; import java.io.File; @@ -128,7 +129,7 @@ private void executeStateTest(final Map genera private void traceTestSpecs(final String test, final List specs) { final OperationTracer tracer = // You should have picked Mercy. parentCommand.showJsonResults - ? new EVMToolTracer(System.out, !parentCommand.noMemory) + ? new StandardJsonTracer(System.out, !parentCommand.noMemory) : OperationTracer.NO_TRACING; for (final GeneralStateTestCaseEipSpec spec : specs) { @@ -173,7 +174,7 @@ private void traceTestSpecs(final String test, final List