Skip to content

Commit

Permalink
Merge branch 'main' into no-sdr-grouping
Browse files Browse the repository at this point in the history
  • Loading branch information
fab-10 authored Nov 13, 2023
2 parents 42f9fcb + d6a9633 commit 2d5b16f
Show file tree
Hide file tree
Showing 35 changed files with 1,818 additions and 61 deletions.
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# Changelog

## 23.10.3

### Breaking Changes

### Deprecations

### Additions and Improvements
- Implement debug_traceCall [#5885](https://github.com/hyperledger/besu/pull/5885)

## 23.10.2

### Breaking Changes
Expand Down
2 changes: 1 addition & 1 deletion build.gradle
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright ConsenSys AG.
* 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public enum RpcMethod {
DEBUG_STANDARD_TRACE_BLOCK_TO_FILE("debug_standardTraceBlockToFile"),
DEBUG_STANDARD_TRACE_BAD_BLOCK_TO_FILE("debug_standardTraceBadBlockToFile"),
DEBUG_TRACE_TRANSACTION("debug_traceTransaction"),
DEBUG_TRACE_CALL("debug_traceCall"),
DEBUG_BATCH_RAW_TRANSACTION("debug_batchSendRawTransaction"),
DEBUG_GET_BAD_BLOCKS("debug_getBadBlocks"),
DEBUG_GET_RAW_HEADER("debug_getRawHeader"),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
/*
* Copyright Hyperledger 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 static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType.BLOCK_NOT_FOUND;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType.INTERNAL_ERROR;

import org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.JsonCallParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.debug.TraceOptions;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.transaction.PreCloseStateHandler;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.ethereum.vm.DebugOperationTracer;

import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public abstract class AbstractTraceCall extends AbstractTraceByBlock {
private static final Logger LOG = LoggerFactory.getLogger(AbstractTraceCall.class);

public AbstractTraceCall(
final BlockchainQueries blockchainQueries,
final ProtocolSchedule protocolSchedule,
final TransactionSimulator transactionSimulator) {
super(blockchainQueries, protocolSchedule, transactionSimulator);
}

@Override
protected Object resultByBlockNumber(
final JsonRpcRequestContext requestContext, final long blockNumber) {
final JsonCallParameter callParams =
JsonCallParameterUtil.validateAndGetCallParams(requestContext);
final TraceOptions traceOptions = getTraceOptions(requestContext);
final String blockNumberString = String.valueOf(blockNumber);
LOG.atTrace()
.setMessage("Received RPC rpcName={} callParams={} block={} traceTypes={}")
.addArgument(this::getName)
.addArgument(callParams)
.addArgument(blockNumberString)
.addArgument(traceOptions)
.log();

final Optional<BlockHeader> maybeBlockHeader =
blockchainQueriesSupplier.get().getBlockHeaderByNumber(blockNumber);

if (maybeBlockHeader.isEmpty()) {
return new JsonRpcErrorResponse(requestContext.getRequest().getId(), BLOCK_NOT_FOUND);
}

final DebugOperationTracer tracer = new DebugOperationTracer(traceOptions);
return transactionSimulator
.process(
callParams,
buildTransactionValidationParams(),
tracer,
getSimulatorResultHandler(requestContext, tracer),
maybeBlockHeader.get())
.orElseGet(
() -> new JsonRpcErrorResponse(requestContext.getRequest().getId(), INTERNAL_ERROR));
}

protected abstract TraceOptions getTraceOptions(final JsonRpcRequestContext requestContext);

protected abstract PreCloseStateHandler<Object> getSimulatorResultHandler(
final JsonRpcRequestContext requestContext, final DebugOperationTracer tracer);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* Copyright Hyperledger 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 static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType.INTERNAL_ERROR;

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.BlockParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.TransactionTraceParams;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.TransactionTrace;
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.results.DebugTraceTransactionResult;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.debug.TraceOptions;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.transaction.PreCloseStateHandler;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.ethereum.vm.DebugOperationTracer;

import java.util.Optional;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DebugTraceCall extends AbstractTraceCall {
private static final Logger LOG = LoggerFactory.getLogger(DebugTraceCall.class);

public DebugTraceCall(
final BlockchainQueries blockchainQueries,
final ProtocolSchedule protocolSchedule,
final TransactionSimulator transactionSimulator) {
super(blockchainQueries, protocolSchedule, transactionSimulator);
}

@Override
public String getName() {
return RpcMethod.DEBUG_TRACE_CALL.getMethodName();
}

@Override
protected TraceOptions getTraceOptions(final JsonRpcRequestContext requestContext) {
return requestContext
.getOptionalParameter(2, TransactionTraceParams.class)
.map(TransactionTraceParams::traceOptions)
.orElse(TraceOptions.DEFAULT);
}

@Override
protected BlockParameter blockParameter(final JsonRpcRequestContext request) {
final Optional<BlockParameter> maybeBlockParameter =
request.getOptionalParameter(1, BlockParameter.class);

return maybeBlockParameter.orElse(BlockParameter.LATEST);
}

@Override
protected PreCloseStateHandler<Object> getSimulatorResultHandler(
final JsonRpcRequestContext requestContext, final DebugOperationTracer tracer) {
return (mutableWorldState, maybeSimulatorResult) ->
maybeSimulatorResult.map(
result -> {
if (result.isInvalid()) {
LOG.error("Invalid simulator result {}", result);
final JsonRpcError error =
new JsonRpcError(
INTERNAL_ERROR, result.getValidationResult().getErrorMessage());
return new JsonRpcErrorResponse(requestContext.getRequest().getId(), error);
}

final TransactionTrace transactionTrace =
new TransactionTrace(
result.getTransaction(), result.getResult(), tracer.getTraceFrames());

return new DebugTraceTransactionResult(transactionTrace);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,29 +14,27 @@
*/
package org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods;

import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType.BLOCK_NOT_FOUND;
import static org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.RpcErrorType.INTERNAL_ERROR;

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.JsonCallParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.TraceTypeParameter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.TransactionTrace;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcErrorResponse;
import org.hyperledger.besu.ethereum.api.query.BlockchainQueries;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.BlockHeader;
import org.hyperledger.besu.ethereum.debug.TraceOptions;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.transaction.PreCloseStateHandler;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.ethereum.vm.DebugOperationTracer;

import java.util.Optional;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class TraceCall extends AbstractTraceByBlock implements JsonRpcMethod {
public class TraceCall extends AbstractTraceCall {
private static final Logger LOG = LoggerFactory.getLogger(TraceCall.class);

public TraceCall(
Expand All @@ -52,56 +50,35 @@ public String getName() {
}

@Override
protected Object resultByBlockNumber(
final JsonRpcRequestContext requestContext, final long blockNumber) {
final JsonCallParameter callParams =
JsonCallParameterUtil.validateAndGetCallParams(requestContext);
final TraceTypeParameter traceTypeParameter =
requestContext.getRequiredParameter(1, TraceTypeParameter.class);
final String blockNumberString = String.valueOf(blockNumber);
LOG.atTrace()
.setMessage("Received RPC rpcName={} callParams={} block={} traceTypes={}")
.addArgument(this::getName)
.addArgument(callParams)
.addArgument(blockNumberString)
.addArgument(traceTypeParameter)
.log();

final Optional<BlockHeader> maybeBlockHeader =
blockchainQueriesSupplier.get().getBlockHeaderByNumber(blockNumber);

if (maybeBlockHeader.isEmpty()) {
return new JsonRpcErrorResponse(requestContext.getRequest().getId(), BLOCK_NOT_FOUND);
}

final Set<TraceTypeParameter.TraceType> traceTypes = traceTypeParameter.getTraceTypes();
protected TraceOptions getTraceOptions(final JsonRpcRequestContext requestContext) {
return buildTraceOptions(getTraceTypes(requestContext));
}

final DebugOperationTracer tracer = new DebugOperationTracer(buildTraceOptions(traceTypes));
return transactionSimulator
.process(
callParams,
buildTransactionValidationParams(),
tracer,
(mutableWorldState, maybeSimulatorResult) ->
maybeSimulatorResult.map(
result -> {
if (result.isInvalid()) {
LOG.error(String.format("Invalid simulator result %s", result));
return new JsonRpcErrorResponse(
requestContext.getRequest().getId(), INTERNAL_ERROR);
}
private Set<TraceTypeParameter.TraceType> getTraceTypes(
final JsonRpcRequestContext requestContext) {
return requestContext.getRequiredParameter(1, TraceTypeParameter.class).getTraceTypes();
}

final TransactionTrace transactionTrace =
new TransactionTrace(
result.getTransaction(), result.getResult(), tracer.getTraceFrames());
@Override
protected PreCloseStateHandler<Object> getSimulatorResultHandler(
final JsonRpcRequestContext requestContext, final DebugOperationTracer tracer) {
return (mutableWorldState, maybeSimulatorResult) ->
maybeSimulatorResult.map(
result -> {
if (result.isInvalid()) {
LOG.error("Invalid simulator result {}", result);
return new JsonRpcErrorResponse(
requestContext.getRequest().getId(), INTERNAL_ERROR);
}

final Block block =
blockchainQueriesSupplier.get().getBlockchain().getChainHeadBlock();
final TransactionTrace transactionTrace =
new TransactionTrace(
result.getTransaction(), result.getResult(), tracer.getTraceFrames());

return getTraceCallResult(
protocolSchedule, traceTypes, result, transactionTrace, block);
}),
maybeBlockHeader.get())
.orElse(new JsonRpcErrorResponse(requestContext.getRequest().getId(), INTERNAL_ERROR));
final Block block =
blockchainQueriesSupplier.get().getBlockchain().getChainHeadBlock();
return getTraceCallResult(
protocolSchedule, getTraceTypes(requestContext), result, transactionTrace, block);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugTraceBlock;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugTraceBlockByHash;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugTraceBlockByNumber;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugTraceCall;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugTraceTransaction;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.JsonRpcMethod;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockReplay;
Expand All @@ -45,6 +46,7 @@
import org.hyperledger.besu.ethereum.eth.transactions.TransactionPool;
import org.hyperledger.besu.ethereum.mainnet.ProtocolSchedule;
import org.hyperledger.besu.ethereum.mainnet.ScheduleBasedBlockHeaderFunctions;
import org.hyperledger.besu.ethereum.transaction.TransactionSimulator;
import org.hyperledger.besu.metrics.ObservableMetricsSystem;

import java.nio.file.Path;
Expand Down Expand Up @@ -113,6 +115,13 @@ protected Map<String, JsonRpcMethod> create() {
new DebugGetRawHeader(blockchainQueries),
new DebugGetRawBlock(blockchainQueries),
new DebugGetRawReceipts(blockchainQueries),
new DebugGetRawTransaction(blockchainQueries));
new DebugGetRawTransaction(blockchainQueries),
new DebugTraceCall(
blockchainQueries,
protocolSchedule,
new TransactionSimulator(
blockchainQueries.getBlockchain(),
blockchainQueries.getWorldStateArchive(),
protocolSchedule)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ public void setup() throws Exception {
}

public static Object[][] specs() {
return findSpecFiles(
new String[] {"debug"},
"storageRange",
"accountRange"); // storageRange and accountRange are not working with bonsai trie
return AbstractJsonRpcHttpBySpecTest.findSpecFiles(
new String[] {
"debug/account-at", "debug/batch-send-raw-transaction", "debug/trace-transaction"
}); // storageRange and accountRange are not working with bonsai trie
}
}
Loading

0 comments on commit 2d5b16f

Please sign in to comment.