Skip to content

Tracer option for debug trace RPC calls #8509

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

Draft
wants to merge 67 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
67 commits
Select commit Hold shift + click to select a range
63808c6
wip
usmansaleem Mar 31, 2025
bc3c51c
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem Mar 31, 2025
01760cc
Debug Trace Block By Hash - tracer option
usmansaleem Apr 2, 2025
23127b0
TraceOption with TracerConfig
usmansaleem Apr 2, 2025
c64bc2a
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem Apr 2, 2025
12f59e2
Introduce TransactionStepFactory. Stub implementation for DebugCallTr…
usmansaleem Apr 3, 2025
d53f27d
Rename OpcodeTracerConfig to StructLogTracerConfig
usmansaleem Apr 3, 2025
26747a7
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem Apr 3, 2025
8799b45
stub
usmansaleem Apr 3, 2025
802b241
Fix TraceOptions usage
usmansaleem Apr 3, 2025
c2b8a44
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem Apr 3, 2025
e7563af
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem Apr 7, 2025
a32c885
WIP - DebugCallTracerResult
usmansaleem Apr 7, 2025
7b4d2ab
WIP - DebugCallTracerResult
usmansaleem Apr 7, 2025
cf253ce
rearrange json fields to match geth output
usmansaleem Apr 8, 2025
73f0056
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem Apr 8, 2025
20d22df
fix DebugOperationTracerTest
usmansaleem Apr 8, 2025
cce2b5a
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem Apr 13, 2025
5fb88a2
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem Apr 16, 2025
d17bb00
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem Apr 22, 2025
d92a7e7
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem Apr 22, 2025
87c751b
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem Apr 23, 2025
a35c7e3
set input and from for CREATE in calltracer
usmansaleem Apr 24, 2025
8f552a6
set value
usmansaleem Apr 28, 2025
4535dbb
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem Apr 28, 2025
9a4d904
remove extra ;
usmansaleem Apr 30, 2025
f31c7be
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem Apr 30, 2025
0475a9d
naive implementation for handing call stacks
usmansaleem May 1, 2025
29e4622
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem May 2, 2025
b079cfd
fix json ignore annotation
usmansaleem May 5, 2025
29942e5
review suggestion - use ArrayDeque
usmansaleem May 5, 2025
a971afa
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem May 7, 2025
b8f4f5e
json property order
usmansaleem May 8, 2025
f651137
shorted value hex
usmansaleem May 8, 2025
668d8c9
fix output and error
usmansaleem May 8, 2025
5f185e4
map revert reason if not empty
usmansaleem May 8, 2025
616b9db
Updated logic to calculate gas and gasCost
usmansaleem May 8, 2025
016eca2
remove unused code
usmansaleem May 8, 2025
207964b
code fix
usmansaleem May 8, 2025
e6516b4
Use BigInteger for gas and gasUsed
usmansaleem May 8, 2025
1151f15
Some more BigInteger
usmansaleem May 8, 2025
acf1d9a
Reimplement processTraceFrames handleCall, handleCreate, selfDestruct
usmansaleem May 8, 2025
a3f1413
call data load
usmansaleem May 8, 2025
cb50915
return and revert
usmansaleem May 8, 2025
3a1465b
add missing methods and cleanup Result class
usmansaleem May 8, 2025
b850421
toAddress
usmansaleem May 8, 2025
7b1105b
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem May 9, 2025
402c413
big refactoring of DebugCallTracerResult
usmansaleem May 9, 2025
26a37e1
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem May 12, 2025
20cb03b
hirerchal call stack
usmansaleem May 12, 2025
18e9f9f
Add some debug info
usmansaleem May 12, 2025
e6e891b
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem May 13, 2025
4c8667c
Modify DebugTraceTransactionStepFactory to be used by DebugTraceTrans…
usmansaleem May 14, 2025
48618be
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem May 15, 2025
a9bf98e
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem May 18, 2025
15143f0
Rename StructLogTracerConfig to DefaultTracerConfig
usmansaleem May 19, 2025
6d067e4
Simplify TracerOptions
usmansaleem May 19, 2025
a303f7f
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem May 19, 2025
fb8f921
Fix DebugTraceTransactionTest and enhance DebugTraceTransactionStepFa…
usmansaleem May 19, 2025
5478a4a
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem May 19, 2025
54e7472
DebugTraceCall to return appropriate tracer result
usmansaleem May 19, 2025
8c92f29
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem May 19, 2025
7b6c287
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem May 19, 2025
8533272
DebugCallTracerResult fix calls
usmansaleem May 20, 2025
d67ebdf
attempt address calculation logic
usmansaleem May 20, 2025
88f37bd
simplify extract to address
usmansaleem May 20, 2025
583fae6
Merge remote-tracking branch 'upstream/main' into debug_trace
usmansaleem May 21, 2025
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
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
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.jsonrpc.internal.results.DebugTraceTransactionDetails;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.DebugStructLoggerTracerResult;
import org.hyperledger.besu.plugin.services.rpc.RpcResponseType;
import org.hyperledger.besu.testutil.BlockTestUtil;

Expand Down Expand Up @@ -68,8 +68,8 @@ public void debugTraceTransactionSuccessTest() {

final JsonRpcResponse response = method.response(request);
assertThat(response.getType()).isEqualTo(RpcResponseType.SUCCESS);
DebugTraceTransactionDetails debugTraceTransactionDetails =
(DebugTraceTransactionDetails) ((JsonRpcSuccessResponse) response).getResult();
DebugStructLoggerTracerResult debugTraceTransactionDetails =
(DebugStructLoggerTracerResult) ((JsonRpcSuccessResponse) response).getResult();
assertThat(debugTraceTransactionDetails.getGas()).isEqualTo(23705L);
assertThat(debugTraceTransactionDetails.getReturnValue()).isEmpty();
assertThat(debugTraceTransactionDetails.failed()).isFalse();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ protected Collection<DebugTraceTransactionResult> getTraces(

TransactionSource transactionSource = new TransactionSource(block);
DebugOperationTracer debugOperationTracer =
new DebugOperationTracer(traceOptions, true);
new DebugOperationTracer(traceOptions.defaultTracerConfig(), true);
ExecuteTransactionStep executeTransactionStep =
new ExecuteTransactionStep(
chainUpdater,
Expand All @@ -124,8 +124,7 @@ protected Collection<DebugTraceTransactionResult> getTraces(
debugOperationTracer,
protocolSpec,
block);
DebugTraceTransactionStep debugTraceTransactionStep =
new DebugTraceTransactionStep();

Pipeline<TransactionTrace> traceBlockPipeline =
createPipelineFrom(
"getTransactions",
Expand All @@ -136,7 +135,10 @@ protected Collection<DebugTraceTransactionResult> getTraces(
"debug_trace_block")
.thenProcess("executeTransaction", executeTransactionStep)
.thenProcessAsyncOrdered(
"debugTraceTransactionStep", debugTraceTransactionStep, 4)
"debugTraceTransactionStep",
DebugTraceTransactionStepFactory.createAsync(
traceOptions.tracerType()),
4)
.andFinishWith("collect_results", tracesList::add);

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,14 @@
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.tracing.vm.VmTraceGenerator;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.debug.DefaultTracerConfig;
import org.hyperledger.besu.ethereum.debug.TraceOptions;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.TransactionValidationParams;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulatorResult;

import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;
Expand Down Expand Up @@ -121,8 +123,11 @@ protected TransactionValidationParams buildTransactionValidationParams() {

protected TraceOptions buildTraceOptions(final Set<TraceTypeParameter.TraceType> traceTypes) {
return new TraceOptions(
traceTypes.contains(TraceType.STATE_DIFF),
false,
traceTypes.contains(TraceType.TRACE) || traceTypes.contains(TraceType.VM_TRACE));
"",
new DefaultTracerConfig(
traceTypes.contains(TraceType.STATE_DIFF),
false,
traceTypes.contains(TraceType.TRACE) || traceTypes.contains(TraceType.VM_TRACE)),
Map.of());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.debug.TraceOptions;
import org.hyperledger.besu.ethereum.debug.DefaultTracerConfig;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.vm.DebugOperationTracer;

Expand Down Expand Up @@ -84,7 +84,8 @@ private TransactionTrace getTransactionTrace(final Block block, final Hash trans
.trace(
mutableWorldState,
block,
new DebugOperationTracer(new TraceOptions(false, false, true), false))
new DebugOperationTracer(
new DefaultTracerConfig(false, false, true), false))
.map(BlockTrace::getTransactionTraces)
.orElse(Collections.emptyList())
.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ protected Object resultByBlockNumber(
return new JsonRpcErrorResponse(requestContext.getRequest().getId(), BLOCK_NOT_FOUND);
}

final DebugOperationTracer tracer = new DebugOperationTracer(traceOptions, recordChildCallGas);
final DebugOperationTracer tracer =
new DebugOperationTracer(traceOptions.defaultTracerConfig(), recordChildCallGas);
return transactionSimulator
.process(
callParams,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import org.hyperledger.besu.ethereum.api.query.BlockWithMetadata;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata;
import org.hyperledger.besu.ethereum.debug.TraceOptions;
import org.hyperledger.besu.ethereum.debug.DefaultTracerConfig;
import org.hyperledger.besu.ethereum.vm.DebugOperationTracer;
import org.hyperledger.besu.evm.account.Account;

Expand Down Expand Up @@ -119,7 +119,8 @@ protected Object resultByBlockHash(
.trace(
mutableWorldState,
blockHash,
new DebugOperationTracer(new TraceOptions(false, true, true), false))
new DebugOperationTracer(
new DefaultTracerConfig(false, true, true), false))
.map(BlockTrace::getTransactionTraces)
.orElse(Collections.emptyList())
.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ protected Object resultByBlockNumber(

TransactionSource transactionSource = new TransactionSource(block);
DebugOperationTracer debugOperationTracer =
new DebugOperationTracer(traceOptions, true);
new DebugOperationTracer(traceOptions.defaultTracerConfig(), true);
ExecuteTransactionStep executeTransactionStep =
new ExecuteTransactionStep(
chainUpdater,
Expand All @@ -131,8 +131,7 @@ protected Object resultByBlockNumber(
debugOperationTracer,
protocolSpec,
block);
DebugTraceTransactionStep debugTraceTransactionStep =
new DebugTraceTransactionStep();

Pipeline<TransactionTrace> traceBlockPipeline =
createPipelineFrom(
"getTransactions",
Expand All @@ -143,7 +142,10 @@ protected Object resultByBlockNumber(
"debug_trace_block_by_number")
.thenProcess("executeTransaction", executeTransactionStep)
.thenProcessAsyncOrdered(
"debugTraceTransactionStep", debugTraceTransactionStep, 4)
"debugTraceTransactionStep",
DebugTraceTransactionStepFactory.createAsync(
traceOptions.tracerType()),
4)
.andFinishWith("collect_results", tracesList::add);

try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
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.RpcErrorType;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.DebugTraceTransactionDetails;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.debug.TraceOptions;
import org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams;
Expand Down Expand Up @@ -103,8 +102,11 @@ protected PreCloseStateHandler<Object> getSimulatorResultHandler(
final TransactionTrace transactionTrace =
new TransactionTrace(
result.transaction(), result.result(), tracer.getTraceFrames());

return new DebugTraceTransactionDetails(transactionTrace);
return DebugTraceTransactionStepFactory.create(
getTraceOptions(requestContext).tracerType())
.apply(transactionTrace)
.getResult();
// return new DebugStructLoggerTracerResult(transactionTrace);
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
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.jsonrpc.internal.response.RpcErrorType;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.DebugTraceTransactionDetails;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.DebugTraceTransactionResult;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata;
import org.hyperledger.besu.ethereum.debug.TraceOptions;
Expand Down Expand Up @@ -76,31 +76,32 @@ public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
RpcErrorType.INVALID_TRANSACTION_TRACE_PARAMS,
e);
}
final DebugTraceTransactionDetails debugTraceTransactionResult =
final DebugTraceTransactionResult debugResult =
debugTraceTransactionResult(hash, transactionWithMetadata.get(), traceOptions);

return new JsonRpcSuccessResponse(
requestContext.getRequest().getId(), debugTraceTransactionResult);
requestContext.getRequest().getId(), debugResult.getResult());
} else {
return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), null);
}
}

private DebugTraceTransactionDetails debugTraceTransactionResult(
private DebugTraceTransactionResult debugTraceTransactionResult(
final Hash hash,
final TransactionWithMetadata transactionWithMetadata,
final TraceOptions traceOptions) {
final Hash blockHash = transactionWithMetadata.getBlockHash().get();

final DebugOperationTracer execTracer = new DebugOperationTracer(traceOptions, true);
final DebugOperationTracer execTracer =
new DebugOperationTracer(traceOptions.defaultTracerConfig(), true);

return Tracer.processTracing(
blockchain,
blockHash,
mutableWorldState ->
transactionTracer
.traceTransaction(mutableWorldState, blockHash, hash, execTracer)
.map(DebugTraceTransactionDetails::new))
.map(DebugTraceTransactionStepFactory.create(traceOptions.tracerType())))
.orElse(null);
}
}

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Copyright contributors to Besu.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods;

import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.TransactionTrace;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.DebugCallTracerResult;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.DebugStructLoggerTracerResult;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.DebugTraceTransactionResult;

import java.util.concurrent.CompletableFuture;
import java.util.function.Function;

import com.fasterxml.jackson.annotation.JsonGetter;

/**
* Factory for creating transaction steps for various tracers.
*
* <p>This factory provides methods to create functions that process a {@link TransactionTrace} and
* return a {@link DebugTraceTransactionResult} with the appropriate tracer result based on the
* specified tracer type. Both synchronous and asynchronous processing options are available through
* the {@code create} and {@code createAsync} methods respectively.
*/
public class DebugTraceTransactionStepFactory {

/**
* Creates a function that processes a {@link TransactionTrace} and returns a {@link
* DebugTraceTransactionResult} with the appropriate tracer result based on the specified tracer
* type.
*
* @param tracerType the type of tracer to use for processing the transaction trace
* @return a function that processes a {@link TransactionTrace} and returns a {@link
* DebugTraceTransactionResult} with the appropriate tracer result
*/
public static Function<TransactionTrace, DebugTraceTransactionResult> create(
final String tracerType) {
// Normalize null values to empty string
final String normalizedTracerType = tracerType == null ? "" : tracerType;
return switch (normalizedTracerType) {
case "" ->
transactionTrace -> {
var result = new DebugStructLoggerTracerResult(transactionTrace);
return new DebugTraceTransactionResult(transactionTrace, result);
};
case "callTracer" ->
transactionTrace -> {
var result = new DebugCallTracerResult(transactionTrace);
return new DebugTraceTransactionResult(transactionTrace, result);
};
// TODO: Load via "plugin" system, and then raise an error if not found
default ->
transactionTrace ->
new DebugTraceTransactionResult(transactionTrace, new NotYetImplemented());
};
}

/**
* Creates an asynchronous function that processes a {@link TransactionTrace} and returns a {@link
* DebugTraceTransactionResult} with the appropriate tracer result based on the specified tracer
* type.
*
* @param tracerType the type of tracer to use for processing the transaction trace
* @return an asynchronous function that processes a {@link TransactionTrace} and returns a {@link
* DebugTraceTransactionResult} with the appropriate tracer result
*/
public static Function<TransactionTrace, CompletableFuture<DebugTraceTransactionResult>>
createAsync(final String tracerType) {
return transactionTrace ->
CompletableFuture.supplyAsync(() -> create(tracerType).apply(transactionTrace));
}

static class NotYetImplemented {
@JsonGetter("error")
public String getError() {
return "Not Yet Implemented";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.core.MutableWorldState;
import org.hyperledger.besu.ethereum.debug.TraceOptions;
import org.hyperledger.besu.ethereum.debug.DefaultTracerConfig;
import org.hyperledger.besu.ethereum.eth.manager.EthScheduler;
import org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
Expand Down Expand Up @@ -127,7 +127,7 @@ protected ArrayNodeWrapper traceBlock(

TransactionSource transactionSource = new TransactionSource(block);
DebugOperationTracer debugOperationTracer =
new DebugOperationTracer(new TraceOptions(false, false, true), false);
new DebugOperationTracer(new DefaultTracerConfig(false, false, true), false);
ExecuteTransactionStep executeTransactionStep =
new ExecuteTransactionStep(
chainUpdater,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ private JsonNode getSingleCallResult(
final WorldUpdater worldUpdater) {
final Set<TraceTypeParameter.TraceType> traceTypes = traceTypeParameter.getTraceTypes();
final DebugOperationTracer tracer =
new DebugOperationTracer(buildTraceOptions(traceTypes), false);
new DebugOperationTracer(buildTraceOptions(traceTypes).defaultTracerConfig(), false);
final var miningBeneficiary =
protocolSchedule
.getByBlockHeader(header)
Expand Down
Loading
Loading