Search in sources :

Example 1 with TraceOptions

use of org.hyperledger.besu.ethereum.debug.TraceOptions in project besu by hyperledger.

the class DebugTraceBlockByNumber method resultByBlockNumber.

@Override
protected Object resultByBlockNumber(final JsonRpcRequestContext request, final long blockNumber) {
    final Optional<Hash> blockHash = getBlockchainQueries().getBlockHashByNumber(blockNumber);
    final TraceOptions traceOptions = request.getOptionalParameter(1, TransactionTraceParams.class).map(TransactionTraceParams::traceOptions).orElse(TraceOptions.DEFAULT);
    return blockHash.flatMap(hash -> blockTracerSupplier.get().trace(hash, new DebugOperationTracer(traceOptions)).map(BlockTrace::getTransactionTraces).map(DebugTraceTransactionResult::of)).orElse(null);
}
Also used : TraceOptions(org.hyperledger.besu.ethereum.debug.TraceOptions) BlockchainQueries(org.hyperledger.besu.ethereum.api.query.BlockchainQueries) DebugOperationTracer(org.hyperledger.besu.ethereum.vm.DebugOperationTracer) Supplier(java.util.function.Supplier) RpcMethod(org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod) BlockParameter(org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.BlockParameter) JsonRpcRequestContext(org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext) BlockTrace(org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockTrace) DebugTraceTransactionResult(org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.DebugTraceTransactionResult) Optional(java.util.Optional) TransactionTraceParams(org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.TransactionTraceParams) Hash(org.hyperledger.besu.datatypes.Hash) BlockTracer(org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockTracer) DebugTraceTransactionResult(org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.DebugTraceTransactionResult) DebugOperationTracer(org.hyperledger.besu.ethereum.vm.DebugOperationTracer) TraceOptions(org.hyperledger.besu.ethereum.debug.TraceOptions) Hash(org.hyperledger.besu.datatypes.Hash)

Example 2 with TraceOptions

use of org.hyperledger.besu.ethereum.debug.TraceOptions in project besu by hyperledger.

the class DebugTraceTransaction method response.

@Override
public JsonRpcResponse response(final JsonRpcRequestContext requestContext) {
    final Hash hash = requestContext.getRequiredParameter(0, Hash.class);
    final Optional<TransactionWithMetadata> transactionWithMetadata = blockchain.transactionByHash(hash);
    if (transactionWithMetadata.isPresent()) {
        final TraceOptions traceOptions = requestContext.getOptionalParameter(1, TransactionTraceParams.class).map(TransactionTraceParams::traceOptions).orElse(TraceOptions.DEFAULT);
        final DebugTraceTransactionResult debugTraceTransactionResult = debugTraceTransactionResult(hash, transactionWithMetadata.get(), traceOptions);
        return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), debugTraceTransactionResult);
    } else {
        return new JsonRpcSuccessResponse(requestContext.getRequest().getId(), null);
    }
}
Also used : DebugTraceTransactionResult(org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.DebugTraceTransactionResult) TransactionWithMetadata(org.hyperledger.besu.ethereum.api.query.TransactionWithMetadata) TraceOptions(org.hyperledger.besu.ethereum.debug.TraceOptions) Hash(org.hyperledger.besu.datatypes.Hash) JsonRpcSuccessResponse(org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse)

Example 3 with TraceOptions

use of org.hyperledger.besu.ethereum.debug.TraceOptions in project besu by hyperledger.

the class TransactionTracer method traceTransactionToFile.

public List<String> traceTransactionToFile(final Hash blockHash, final Optional<TransactionTraceParams> transactionTraceParams, final Path traceDir) {
    final Optional<Hash> 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 RuntimeException(String.format("Trace directory '%s' does not exist and could not be made.", traceDir));
    }
    return blockReplay.performActionWithBlock(blockHash, (body, header, blockchain, worldState, transactionProcessor) -> {
        WorldUpdater stackedUpdater = worldState.updater().updater();
        final List<String> traces = new ArrayList<>();
        for (int i = 0; i < body.getTransactions().size(); i++) {
            ((StackedUpdater<?, ?>) stackedUpdater).markTransactionBoundary();
            final Transaction transaction = body.getTransactions().get(i);
            if (selectedHash.isEmpty() || selectedHash.filter(isEqual(transaction.getHash())).isPresent()) {
                final File traceFile = generateTraceFile(traceDir, blockHash, i, transaction);
                try (PrintStream out = new PrintStream(new FileOutputStream(traceFile))) {
                    final Stopwatch timer = Stopwatch.createStarted();
                    final TransactionProcessingResult result = processTransaction(header, blockchain, stackedUpdater, transaction, transactionProcessor, new StandardJsonTracer(out, showMemory));
                    out.println(summaryTrace(transaction, timer.stop().elapsed(TimeUnit.NANOSECONDS), result));
                    traces.add(traceFile.getPath());
                } catch (FileNotFoundException e) {
                    throw new RuntimeException("Unable to create transaction trace : " + e.getMessage());
                }
            } else {
                processTransaction(header, blockchain, stackedUpdater, transaction, transactionProcessor, OperationTracer.NO_TRACING);
            }
        }
        return Optional.of(traces);
    }).orElse(new ArrayList<>());
}
Also used : TraceOptions(org.hyperledger.besu.ethereum.debug.TraceOptions) StackedUpdater(org.hyperledger.besu.evm.worldstate.StackedUpdater) WorldUpdater(org.hyperledger.besu.evm.worldstate.WorldUpdater) Stopwatch(com.google.common.base.Stopwatch) OperationTracer(org.hyperledger.besu.evm.tracing.OperationTracer) ObjectNode(com.fasterxml.jackson.databind.node.ObjectNode) ArrayList(java.util.ArrayList) TransactionTraceParams(org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.TransactionTraceParams) UInt256(org.apache.tuweni.units.bigints.UInt256) Path(java.nio.file.Path) PrintStream(java.io.PrintStream) Files(java.nio.file.Files) BlockHeader(org.hyperledger.besu.ethereum.core.BlockHeader) Blockchain(org.hyperledger.besu.ethereum.chain.Blockchain) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper) Predicate.isEqual(java.util.function.Predicate.isEqual) FileOutputStream(java.io.FileOutputStream) MainnetTransactionProcessor(org.hyperledger.besu.ethereum.mainnet.MainnetTransactionProcessor) BlockHashLookup(org.hyperledger.besu.ethereum.vm.BlockHashLookup) DebugOperationTracer(org.hyperledger.besu.ethereum.vm.DebugOperationTracer) File(java.io.File) FileNotFoundException(java.io.FileNotFoundException) TransactionProcessingResult(org.hyperledger.besu.ethereum.processing.TransactionProcessingResult) TimeUnit(java.util.concurrent.TimeUnit) List(java.util.List) ImmutableTransactionValidationParams(org.hyperledger.besu.ethereum.mainnet.ImmutableTransactionValidationParams) Optional(java.util.Optional) Transaction(org.hyperledger.besu.ethereum.core.Transaction) StandardJsonTracer(org.hyperledger.besu.evm.tracing.StandardJsonTracer) Hash(org.hyperledger.besu.datatypes.Hash) PrintStream(java.io.PrintStream) WorldUpdater(org.hyperledger.besu.evm.worldstate.WorldUpdater) Stopwatch(com.google.common.base.Stopwatch) FileNotFoundException(java.io.FileNotFoundException) TransactionTraceParams(org.hyperledger.besu.ethereum.api.jsonrpc.internal.parameters.TransactionTraceParams) Hash(org.hyperledger.besu.datatypes.Hash) StandardJsonTracer(org.hyperledger.besu.evm.tracing.StandardJsonTracer) TransactionProcessingResult(org.hyperledger.besu.ethereum.processing.TransactionProcessingResult) Transaction(org.hyperledger.besu.ethereum.core.Transaction) FileOutputStream(java.io.FileOutputStream) ArrayList(java.util.ArrayList) List(java.util.List) File(java.io.File)

Example 4 with TraceOptions

use of org.hyperledger.besu.ethereum.debug.TraceOptions in project besu by hyperledger.

the class TraceTransactionIntegrationTest method shouldTraceSStoreOperation.

@Test
public void shouldTraceSStoreOperation() {
    final KeyPair keyPair = SignatureAlgorithmFactory.getInstance().generateKeyPair();
    final Transaction createTransaction = Transaction.builder().type(TransactionType.FRONTIER).gasLimit(300_000).gasPrice(Wei.ZERO).nonce(0).payload(Bytes.fromHexString(CONTRACT_CREATION_DATA)).value(Wei.ZERO).signAndBuild(keyPair);
    final BlockHeader genesisBlockHeader = genesisBlock.getHeader();
    final MutableWorldState worldState = worldStateArchive.getMutable(genesisBlockHeader.getStateRoot(), genesisBlockHeader.getHash()).get();
    final WorldUpdater createTransactionUpdater = worldState.updater();
    TransactionProcessingResult result = transactionProcessor.processTransaction(blockchain, createTransactionUpdater, genesisBlockHeader, createTransaction, genesisBlockHeader.getCoinbase(), blockHashLookup, false, TransactionValidationParams.blockReplay());
    assertThat(result.isSuccessful()).isTrue();
    final Account createdContract = createTransactionUpdater.getTouchedAccounts().stream().filter(account -> !account.getCode().isEmpty()).findAny().get();
    createTransactionUpdater.commit();
    // Now call the transaction to execute the SSTORE.
    final DebugOperationTracer tracer = new DebugOperationTracer(new TraceOptions(true, true, true));
    final Transaction executeTransaction = Transaction.builder().type(TransactionType.FRONTIER).gasLimit(300_000).gasPrice(Wei.ZERO).nonce(1).payload(Bytes.fromHexString(CALL_SET_OTHER)).to(createdContract.getAddress()).value(Wei.ZERO).signAndBuild(keyPair);
    final WorldUpdater storeUpdater = worldState.updater();
    result = transactionProcessor.processTransaction(blockchain, storeUpdater, genesisBlockHeader, executeTransaction, genesisBlockHeader.getCoinbase(), tracer, blockHashLookup, false);
    assertThat(result.isSuccessful()).isTrue();
    // No storage changes before the SSTORE call.
    TraceFrame frame = tracer.getTraceFrames().get(170);
    assertThat(frame.getOpcode()).isEqualTo("DUP6");
    assertStorageContainsExactly(frame);
    // Storage changes show up in the SSTORE frame.
    frame = tracer.getTraceFrames().get(171);
    assertThat(frame.getOpcode()).isEqualTo("SSTORE");
    assertStorageContainsExactly(frame, entry("0x01", "0x6261720000000000000000000000000000000000000000000000000000000006"));
    // And storage changes are still present in future frames.
    frame = tracer.getTraceFrames().get(172);
    assertThat(frame.getOpcode()).isEqualTo("PUSH2");
    assertStorageContainsExactly(frame, entry("0x01", "0x6261720000000000000000000000000000000000000000000000000000000006"));
}
Also used : Account(org.hyperledger.besu.evm.account.Account) KeyPair(org.hyperledger.besu.crypto.KeyPair) Transaction(org.hyperledger.besu.ethereum.core.Transaction) MutableWorldState(org.hyperledger.besu.ethereum.core.MutableWorldState) WorldUpdater(org.hyperledger.besu.evm.worldstate.WorldUpdater) TraceOptions(org.hyperledger.besu.ethereum.debug.TraceOptions) BlockHeader(org.hyperledger.besu.ethereum.core.BlockHeader) TraceFrame(org.hyperledger.besu.ethereum.debug.TraceFrame) TransactionProcessingResult(org.hyperledger.besu.ethereum.processing.TransactionProcessingResult) Test(org.junit.jupiter.api.Test)

Example 5 with TraceOptions

use of org.hyperledger.besu.ethereum.debug.TraceOptions in project besu by hyperledger.

the class TraceTransactionIntegrationTest method shouldTraceContractCreation.

@Test
public void shouldTraceContractCreation() {
    final DebugOperationTracer tracer = new DebugOperationTracer(new TraceOptions(true, true, true));
    final Transaction transaction = Transaction.readFrom(new BytesValueRLPInput(Bytes.fromHexString(CONTRACT_CREATION_TX), false));
    final BlockHeader genesisBlockHeader = genesisBlock.getHeader();
    transactionProcessor.processTransaction(blockchain, worldStateArchive.getMutable(genesisBlockHeader.getStateRoot(), genesisBlockHeader.getHash()).get().updater(), genesisBlockHeader, transaction, genesisBlockHeader.getCoinbase(), tracer, new BlockHashLookup(genesisBlockHeader, blockchain), false);
    // Reference impl returned 1. Why the difference?
    final int expectedDepth = 0;
    final List<TraceFrame> traceFrames = tracer.getTraceFrames();
    assertThat(traceFrames).hasSize(17);
    TraceFrame frame = traceFrames.get(0);
    assertThat(frame.getDepth()).isEqualTo(expectedDepth);
    assertThat(frame.getGasRemaining()).isEqualTo(4632748L);
    assertThat(frame.getGasCost()).isEqualTo(OptionalLong.of(3));
    assertThat(frame.getOpcode()).isEqualTo("PUSH1");
    assertThat(frame.getPc()).isEqualTo(0);
    assertStackContainsExactly(frame);
    assertMemoryContainsExactly(frame);
    assertStorageContainsExactly(frame);
    frame = traceFrames.get(1);
    assertThat(frame.getDepth()).isEqualTo(expectedDepth);
    assertThat(frame.getGasRemaining()).isEqualTo(4632745L);
    assertThat(frame.getGasCost()).isEqualTo(OptionalLong.of(3L));
    assertThat(frame.getOpcode()).isEqualTo("PUSH1");
    assertThat(frame.getPc()).isEqualTo(2);
    assertStackContainsExactly(frame, "0000000000000000000000000000000000000000000000000000000000000080");
    assertMemoryContainsExactly(frame);
    assertStorageContainsExactly(frame);
    frame = traceFrames.get(2);
    assertThat(frame.getDepth()).isEqualTo(expectedDepth);
    assertThat(frame.getGasRemaining()).isEqualTo(4632742L);
    assertThat(frame.getGasCost()).isEqualTo(OptionalLong.of(12L));
    assertThat(frame.getOpcode()).isEqualTo("MSTORE");
    assertThat(frame.getPc()).isEqualTo(4);
    assertStackContainsExactly(frame, "0000000000000000000000000000000000000000000000000000000000000080", "0000000000000000000000000000000000000000000000000000000000000040");
    assertMemoryContainsExactly(frame, "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000000", "0x0000000000000000000000000000000000000000000000000000000000000080");
    assertStorageContainsExactly(frame);
    // Reference implementation actually records the memory after expansion but before the store.
    // assertMemoryContainsExactly(frame,
    // "0000000000000000000000000000000000000000000000000000000000000000",
    // "0000000000000000000000000000000000000000000000000000000000000000",
    // "0000000000000000000000000000000000000000000000000000000000000000");
    frame = traceFrames.get(3);
    assertThat(frame.getDepth()).isEqualTo(expectedDepth);
    assertThat(frame.getGasRemaining()).isEqualTo(4632730L);
    assertThat(frame.getGasCost()).isEqualTo(OptionalLong.of(2L));
    assertThat(frame.getOpcode()).isEqualTo("CALLVALUE");
    assertThat(frame.getPc()).isEqualTo(5);
    assertStackContainsExactly(frame);
    assertMemoryContainsExactly(frame, "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000080");
    assertStorageContainsExactly(frame);
}
Also used : Transaction(org.hyperledger.besu.ethereum.core.Transaction) TraceOptions(org.hyperledger.besu.ethereum.debug.TraceOptions) BlockHeader(org.hyperledger.besu.ethereum.core.BlockHeader) BytesValueRLPInput(org.hyperledger.besu.ethereum.rlp.BytesValueRLPInput) TraceFrame(org.hyperledger.besu.ethereum.debug.TraceFrame) Test(org.junit.jupiter.api.Test)

Aggregations

TraceOptions (org.hyperledger.besu.ethereum.debug.TraceOptions)17 TraceFrame (org.hyperledger.besu.ethereum.debug.TraceFrame)9 DebugOperationTracer (org.hyperledger.besu.ethereum.vm.DebugOperationTracer)7 Test (org.junit.Test)7 Hash (org.hyperledger.besu.datatypes.Hash)5 BlockTrace (org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockTrace)5 Optional (java.util.Optional)4 UInt256 (org.apache.tuweni.units.bigints.UInt256)4 DebugTraceTransactionResult (org.hyperledger.besu.ethereum.api.jsonrpc.internal.results.DebugTraceTransactionResult)4 MessageFrame (org.hyperledger.besu.evm.frame.MessageFrame)4 List (java.util.List)3 Supplier (java.util.function.Supplier)3 RpcMethod (org.hyperledger.besu.ethereum.api.jsonrpc.RpcMethod)3 JsonRpcRequestContext (org.hyperledger.besu.ethereum.api.jsonrpc.internal.JsonRpcRequestContext)3 BlockTracer (org.hyperledger.besu.ethereum.api.jsonrpc.internal.processor.BlockTracer)3 JsonRpcSuccessResponse (org.hyperledger.besu.ethereum.api.jsonrpc.internal.response.JsonRpcSuccessResponse)3 BlockchainQueries (org.hyperledger.besu.ethereum.api.query.BlockchainQueries)3 BlockHeader (org.hyperledger.besu.ethereum.core.BlockHeader)3 Transaction (org.hyperledger.besu.ethereum.core.Transaction)3 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)2