Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* 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.tests.acceptance.jsonrpc;

import java.io.IOException;
import java.net.URISyntaxException;
import java.util.stream.Stream;

import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.params.provider.Arguments;

public class FlatCallTracerAcceptanceTest extends AbstractJsonRpcTest {
private static final String GENESIS_FILE = "/jsonrpc/debug/trace/genesis.json";
private static final String TEST_CASE_PATH = "/jsonrpc/debug/trace/flat-call-tracer/test-cases/";

private static AbstractJsonRpcTest.JsonRpcTestsContext testsContext;

public FlatCallTracerAcceptanceTest() {
super(testsContext);
}

@BeforeAll
public static void init() throws IOException {
testsContext = new JsonRpcTestsContext(GENESIS_FILE);
}

public static Stream<Arguments> testCases() throws URISyntaxException {
return testCasesFromPath(TEST_CASE_PATH);
}

@AfterAll
public static void tearDown() {
testsContext.cluster.close();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
{
"request": {
"jsonrpc": "2.0",
"method": "debug_traceTransaction",
"params": [
"0x3b8fb240d288781d4aac94d3fd16809ee413bc99294a085798a589dae51ddd4a",
{
"tracer": "flatCallTracer"
}
],
"id": 1
},
"response": {
"jsonrpc": "2.0",
"id": 1,
"result": [
{
"type": "call",
"action": {
"from": "0xa94f5374fce5edbc8e2a8697c15331677e6ebf0b",
"to": "0x531f76bad925f6a925474996c7d738c1008045f6",
"value": "0xde0b6b3a7640000",
"gas": "0x40b28",
"input": "0x",
"callType": "call"
},
"result": {
"gasUsed": "0x19c3e",
"output": "0x"
},
"traceAddress": [],
"subtraces": 1,
"transactionPosition": 5,
"transactionHash": "0x04d2029a5cbbed30969cdc0a2ca9e9fc6b719e323af0802b52466f07ee0ecada",
"blockNumber": 553416,
"blockHash": "0x8df024322173d225a09681d35edeaa528aca60743a11a70f854c158862bf5282"
},
{
"type": "call",
"action": {
"from": "0x531f76bad925f6a925474996c7d738c1008045f6",
"to": "0xb49180d443dc4ca6028de0031ac09337891fd8ce",
"value": "0x0",
"gas": "0x2164e",
"input": "0x90b98a11000000000000000000000000877bd459c9b7d8576b44e59e09d076c25946f443"
}
}
]
},
"statusCode": 200
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.TransactionTrace;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.CallTracerResultConverter;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.DebugTraceTransactionResult;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.FlatCallTracerResult;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.OpCodeLoggerTracerResult;
import org.hyperledger.besu.ethereum.debug.TracerType;

Expand Down Expand Up @@ -66,9 +67,12 @@ public static Function<TransactionTrace, DebugTraceTransactionResult> create(
};
case FLAT_CALL_TRACER ->
transactionTrace -> {
// TODO: Implement flatCallTracer logic and wire it here
var result = new UnimplementedTracerResult();
return new DebugTraceTransactionResult(transactionTrace, result);
if (enableExtraTracers) {
final FlatCallTracerResult result = FlatCallTracerResult.from(transactionTrace);
return new DebugTraceTransactionResult(transactionTrace, result);
}
return new DebugTraceTransactionResult(
transactionTrace, new UnimplementedTracerResult());
};
case PRESTATE_TRACER ->
transactionTrace -> {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*
* 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.results;

import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.TransactionTrace;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.tracing.flat.FlatTrace;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.tracing.flat.FlatTraceGenerator;

import java.util.List;
import java.util.Set;
import java.util.stream.Stream;

import com.fasterxml.jackson.annotation.JsonGetter;

public class FlatCallTracerResult {
// CALL, CALLCODE, DELEGATECALL, STATICCALL
private static final Set<String> CALL_OPCODES =
Set.of("call", "callcode", "delegatecall", "staticcall");

// CREATE, CREATE2
private static final Set<String> CREATE_OPCODES = Set.of("create", "create2");

private final List<FlatTrace> callTraces;

private FlatCallTracerResult(final List<FlatTrace> callTraces) {
this.callTraces = callTraces;
}

@JsonGetter
public List<FlatTrace> getCalls() {
return callTraces;
}

public static FlatCallTracerResult from(final TransactionTrace transactionTrace) {
return new FlatCallTracerResult(generateFlatCallTrace(transactionTrace));
}

private static List<FlatTrace> generateFlatCallTrace(final TransactionTrace transactionTrace) {
final Stream<FlatTrace> allFlatTraces =
FlatTraceGenerator.generateFromTransactionTraceAndBlock(
null, transactionTrace, transactionTrace.getBlock().orElse(null))
.map(FlatTrace.class::cast);

return allFlatTraces
.filter(
trace ->
isCall(trace.getAction().getCallType())
|| isCreate(trace.getAction().getCallType()))
.toList();
}

private static boolean isCall(final String callType) {
return CALL_OPCODES.contains(callType);
}

private static boolean isCreate(final String callType) {
return CREATE_OPCODES.contains(callType);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ protected FlatTrace(
this.revertReason = revertReason;
}

static Builder freshBuilder(final TransactionTrace transactionTrace) {
public static Builder freshBuilder(final TransactionTrace transactionTrace) {
return FlatTrace.builder()
.resultBuilder(Result.builder())
.actionBuilder(Action.Builder.from(transactionTrace));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
* Copyright contributors to 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.bonsai;

import static org.assertj.core.api.Assertions.assertThat;

import org.hyperledger.besu.ethereum.api.jsonrpc.AbstractJsonRpcHttpBySpecTest;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.methods.DebugTraceTransactionStepFactory;
import org.hyperledger.besu.ethereum.core.BlockchainSetupUtil;
import org.hyperledger.besu.plugin.services.storage.DataStorageFormat;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;

public class DebugGethTraceJsonRpcHttpBySpecTest extends AbstractJsonRpcHttpBySpecTest {
@Override
@BeforeEach
public void setup() throws Exception {
setupBonsaiBlockchain();
startService();

// Enable extra tracers for this test
DebugTraceTransactionStepFactory.enableExtraTracers = true;
}

@Override
protected BlockchainSetupUtil getBlockchainSetupUtil(final DataStorageFormat storageFormat) {
return createBlockchainSetupUtil(
"debug-geth/chain-data/genesis.json", "debug-geth/chain-data/blocks.bin", storageFormat);
}

public static Object[][] specs() {
return AbstractJsonRpcHttpBySpecTest.findSpecFiles(
new String[] {"debug-geth/specs/flat-call-tracer"});
}

@Test
void dryRunDetector() {
assertThat(true)
.withFailMessage("This test is here so gradle --dry-run executes this class")
.isTrue();
}
}
Binary file not shown.
Loading
Loading