Skip to content
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

[PIE-2284] Add trace transaction api #441

Prev Previous commit
refactor add additional transaction part
Signed-off-by: Karim TAAM <[email protected]>
  • Loading branch information
matkt committed Mar 6, 2020
commit 11e240f3e8f6fa976074251407c6f2c4dd83fafc
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,15 @@
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.TransactionTrace;
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.tracing.flat.FlatTrace;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.tracing.flat.FlatTraceGenerator;
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.core.Hash;
import org.hyperledger.besu.ethereum.debug.TraceFrame;
import org.hyperledger.besu.ethereum.debug.TraceOptions;
import org.hyperledger.besu.ethereum.vm.DebugOperationTracer;

import java.util.Collections;
import java.util.Locale;
import java.util.Optional;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Supplier;

import com.fasterxml.jackson.databind.JsonNode;
Expand Down Expand Up @@ -83,19 +78,16 @@ private Object traceBlock(final Block block, final Hash transactionHash) {
.filter(trxTrace -> trxTrace.getTransaction().getHash().equals(transactionHash))
.findFirst()
.orElseThrow();
return generateTracesFromTransactionTrace(transactionTrace, block);
return generateTracesFromTransactionTraceAndBlock(transactionTrace, block);
}

private JsonNode generateTracesFromTransactionTrace(
private JsonNode generateTracesFromTransactionTraceAndBlock(
final TransactionTrace transactionTrace, final Block block) {
final ObjectMapper mapper = new ObjectMapper();

final ArrayNode resultArrayNode = mapper.createArrayNode();

FlatTraceGenerator.generateFromTransactionTrace(
transactionTrace,
new AtomicInteger(),
builder -> addAdditionalContextualInformationToTrace(builder, transactionTrace, block))
FlatTraceGenerator.generateFromTransactionTraceAndBlock(transactionTrace, block)
.forEachOrdered(resultArrayNode::addPOJO);

return resultArrayNode;
Expand All @@ -105,31 +97,4 @@ private Object emptyResult() {
final ObjectMapper mapper = new ObjectMapper();
return mapper.createArrayNode();
}

private void addAdditionalContextualInformationToTrace(
final FlatTrace.Builder builder, final TransactionTrace transactionTrace, final Block block) {
// add block information (hash and number)
builder.blockHash(block.getHash().toHexString()).blockNumber(block.getHeader().getNumber());
// add transaction information (position and hash)
builder
.transactionPosition(
block.getBody().getTransactions().indexOf(transactionTrace.getTransaction()))
.transactionHash(transactionTrace.getTransaction().getHash().toHexString());
// add creationMethod for create action
Optional.ofNullable(builder.getType())
.filter(type -> type.equals("create"))
.ifPresent(__ -> addContractCreationMethod(transactionTrace, builder));
}

private void addContractCreationMethod(
final TransactionTrace transactionTrace, final FlatTrace.Builder builder) {
final String creationMethod =
transactionTrace.getTraceFrames().stream()
.filter(frame -> "CREATE2".equals(frame.getOpcode()))
.findFirst()
.map(TraceFrame::getOpcode)
.orElse("CREATE")
.toLowerCase(Locale.US);
builder.getActionBuilder().creationMethod(creationMethod);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.tracing.Trace;
import org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.tracing.TracingUtils;
import org.hyperledger.besu.ethereum.core.Address;
import org.hyperledger.besu.ethereum.core.Block;
import org.hyperledger.besu.ethereum.core.Gas;
import org.hyperledger.besu.ethereum.core.Transaction;
import org.hyperledger.besu.ethereum.core.Wei;
Expand Down Expand Up @@ -166,6 +167,23 @@ public static Stream<Trace> generateFromTransactionTrace(
return generateFromTransactionTrace(transactionTrace, traceCounter, __ -> {});
}

/**
* Generates a stream of {@link Trace} from the passed {@link TransactionTrace} and {@link Block}
* data.
*
* @param transactionTrace the {@link TransactionTrace} to use
* @param block the {@link Block} to use
* @return a stream of generated traces {@link Trace}
*/
public static Stream<Trace> generateFromTransactionTraceAndBlock(
final TransactionTrace transactionTrace, final Block block) {
return generateFromTransactionTrace(
transactionTrace,
new AtomicInteger(),
builder ->
addAdditionalTransactionInformationToFlatTrace(builder, transactionTrace, block));
}

private static FlatTrace.Context handleCall(
final TransactionTrace transactionTrace,
final TraceFrame traceFrame,
Expand Down Expand Up @@ -400,4 +418,31 @@ private static List<Integer> calculateSelfDescructAddress(
.map(context -> context.getBuilder().getSubtraces())) // , Stream.of(0))
.collect(Collectors.toList());
}

private static void addAdditionalTransactionInformationToFlatTrace(
final FlatTrace.Builder builder, final TransactionTrace transactionTrace, final Block block) {
// add block information (hash and number)
builder.blockHash(block.getHash().toHexString()).blockNumber(block.getHeader().getNumber());
// add transaction information (position and hash)
builder
.transactionPosition(
block.getBody().getTransactions().indexOf(transactionTrace.getTransaction()))
.transactionHash(transactionTrace.getTransaction().getHash().toHexString());
// add creationMethod for create action
Optional.ofNullable(builder.getType())
.filter(type -> type.equals("create"))
.ifPresent(__ -> addContractCreationMethodToFlatTrace(transactionTrace, builder));
}

private static void addContractCreationMethodToFlatTrace(
final TransactionTrace transactionTrace, final FlatTrace.Builder builder) {
final String creationMethod =
transactionTrace.getTraceFrames().stream()
.filter(frame -> "CREATE2".equals(frame.getOpcode()))
.findFirst()
.map(TraceFrame::getOpcode)
.orElse("CREATE")
.toLowerCase(Locale.US);
builder.getActionBuilder().creationMethod(creationMethod);
}
}