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);
}
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);
}
}
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<>());
}
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"));
}
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);
}
Aggregations