use of org.hyperledger.besu.evm.tracing.StandardJsonTracer 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.evm.tracing.StandardJsonTracer in project besu by hyperledger.
the class EvmToyCommand method run.
@Override
public void run() {
final WorldUpdater worldUpdater = new ToyWorld();
worldUpdater.getOrCreate(sender).getMutable().setBalance(Wei.of(BigInteger.TWO.pow(20)));
worldUpdater.getOrCreate(receiver).getMutable().setCode(codeBytes);
int repeat = this.repeat;
final EVM evm = MainnetEVMs.berlin(EvmConfiguration.DEFAULT);
final Code code = evm.getCode(Hash.hash(codeBytes), codeBytes);
final PrecompileContractRegistry precompileContractRegistry = new PrecompileContractRegistry();
MainnetPrecompiledContracts.populateForIstanbul(precompileContractRegistry, evm.getGasCalculator());
final Stopwatch stopwatch = Stopwatch.createUnstarted();
long lastTime = 0;
do {
final boolean lastLoop = repeat == 0;
final // You should have picked Mercy.
OperationTracer tracer = lastLoop && showJsonResults ? new StandardJsonTracer(System.out, !noMemory) : OperationTracer.NO_TRACING;
final Deque<MessageFrame> messageFrameStack = new ArrayDeque<>();
messageFrameStack.add(MessageFrame.builder().type(MessageFrame.Type.MESSAGE_CALL).messageFrameStack(messageFrameStack).worldUpdater(worldUpdater.updater()).initialGas(gas).contract(Address.ZERO).address(receiver).originator(sender).sender(sender).gasPrice(gasPriceGWei).inputData(callData).value(ethValue).apparentValue(ethValue).code(code).blockValues(new ToyBlockValues()).depth(0).completer(c -> {
}).miningBeneficiary(Address.ZERO).blockHashLookup(h -> null).build());
final MessageCallProcessor mcp = new MessageCallProcessor(evm, precompileContractRegistry);
final ContractCreationProcessor ccp = new ContractCreationProcessor(evm.getGasCalculator(), evm, false, List.of(), 0);
stopwatch.start();
while (!messageFrameStack.isEmpty()) {
final MessageFrame messageFrame = messageFrameStack.peek();
switch(messageFrame.getType()) {
case CONTRACT_CREATION:
ccp.process(messageFrame, tracer);
break;
case MESSAGE_CALL:
mcp.process(messageFrame, tracer);
break;
}
if (lastLoop) {
if (messageFrame.getExceptionalHaltReason().isPresent()) {
out.println(messageFrame.getExceptionalHaltReason().get());
}
if (messageFrame.getRevertReason().isPresent()) {
out.println(new String(messageFrame.getRevertReason().get().toArray(), StandardCharsets.UTF_8));
}
}
if (messageFrameStack.isEmpty()) {
stopwatch.stop();
if (lastTime == 0) {
lastTime = stopwatch.elapsed().toNanos();
}
}
if (lastLoop && messageFrameStack.isEmpty()) {
final long evmGas = gas - messageFrame.getRemainingGas();
out.println();
out.printf("{ \"gasUser\": \"0x%s\", \"timens\": %d, \"time\": %d }%n", Long.toHexString(evmGas), lastTime, lastTime / 1000);
}
}
lastTime = stopwatch.elapsed().toNanos();
stopwatch.reset();
} while (repeat-- > 0);
}
use of org.hyperledger.besu.evm.tracing.StandardJsonTracer in project besu by hyperledger.
the class EvmToolCommand method run.
@Override
public void run() {
try {
final EvmToolComponent component = DaggerEvmToolComponent.builder().dataStoreModule(new DataStoreModule()).genesisFileModule(network == null ? genesisFile == null ? GenesisFileModule.createGenesisModule(NetworkName.DEV) : GenesisFileModule.createGenesisModule(genesisFile) : GenesisFileModule.createGenesisModule(network)).evmToolCommandOptionsModule(daggerOptions).metricsSystemModule(new MetricsSystemModule()).build();
final BlockHeader blockHeader = BlockHeaderBuilder.create().parentHash(Hash.EMPTY).coinbase(Address.ZERO).difficulty(Difficulty.ONE).number(1).gasLimit(5000).timestamp(Instant.now().toEpochMilli()).ommersHash(Hash.EMPTY_LIST_HASH).stateRoot(Hash.EMPTY_TRIE_HASH).transactionsRoot(Hash.EMPTY).receiptsRoot(Hash.EMPTY).logsBloom(LogsBloomFilter.empty()).gasUsed(0).extraData(Bytes.EMPTY).mixHash(Hash.EMPTY).nonce(0).blockHeaderFunctions(new MainnetBlockHeaderFunctions()).buildBlockHeader();
Log4j2ConfiguratorUtil.setAllLevels("", repeat == 0 ? Level.INFO : Level.OFF);
int repeat = this.repeat;
Log4j2ConfiguratorUtil.setLevel("org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder", Level.OFF);
final ProtocolSpec protocolSpec = component.getProtocolSpec().apply(0);
Log4j2ConfiguratorUtil.setLevel("org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder", null);
final PrecompileContractRegistry precompileContractRegistry = protocolSpec.getPrecompileContractRegistry();
final EVM evm = protocolSpec.getEvm();
Code code = evm.getCode(Hash.hash(codeHexString), codeHexString);
final Stopwatch stopwatch = Stopwatch.createUnstarted();
long lastTime = 0;
do {
final boolean lastLoop = repeat == 0;
final // You should have picked Mercy.
OperationTracer tracer = lastLoop && showJsonResults ? new StandardJsonTracer(System.out, !noMemory) : OperationTracer.NO_TRACING;
var updater = component.getWorldUpdater();
updater.getOrCreate(sender);
updater.getOrCreate(receiver);
final Deque<MessageFrame> messageFrameStack = new ArrayDeque<>();
messageFrameStack.add(MessageFrame.builder().type(MessageFrame.Type.MESSAGE_CALL).messageFrameStack(messageFrameStack).worldUpdater(updater).initialGas(gas).contract(Address.ZERO).address(receiver).originator(sender).sender(sender).gasPrice(gasPriceGWei).inputData(callData).value(ethValue).apparentValue(ethValue).code(code).blockValues(blockHeader).depth(0).completer(c -> {
}).miningBeneficiary(blockHeader.getCoinbase()).blockHashLookup(new BlockHashLookup(blockHeader, component.getBlockchain())).build());
final MessageCallProcessor mcp = new MessageCallProcessor(evm, precompileContractRegistry);
stopwatch.start();
while (!messageFrameStack.isEmpty()) {
final MessageFrame messageFrame = messageFrameStack.peek();
mcp.process(messageFrame, tracer);
if (lastLoop) {
if (messageFrame.getExceptionalHaltReason().isPresent()) {
out.println(messageFrame.getExceptionalHaltReason().get());
}
if (messageFrame.getRevertReason().isPresent()) {
out.println(new String(messageFrame.getRevertReason().get().toArray(), StandardCharsets.UTF_8));
}
}
if (messageFrameStack.isEmpty()) {
stopwatch.stop();
if (lastTime == 0) {
lastTime = stopwatch.elapsed().toNanos();
}
}
if (lastLoop && messageFrameStack.isEmpty()) {
final Transaction tx = new Transaction(0, Wei.ZERO, Long.MAX_VALUE, Optional.ofNullable(receiver), Wei.ZERO, null, callData, sender, Optional.empty());
final long intrinsicGasCost = protocolSpec.getGasCalculator().transactionIntrinsicGasCost(tx.getPayload(), tx.isContractCreation());
final long accessListCost = tx.getAccessList().map(list -> protocolSpec.getGasCalculator().accessListGasCost(list)).orElse(0L);
final long evmGas = gas - messageFrame.getRemainingGas();
out.println();
out.println(new JsonObject().put("gasUser", "0x" + Long.toHexString(evmGas)).put("timens", lastTime).put("time", lastTime / 1000).put("gasTotal", "0x" + Long.toHexString(evmGas + intrinsicGasCost) + accessListCost));
}
}
lastTime = stopwatch.elapsed().toNanos();
stopwatch.reset();
} while (repeat-- > 0);
} catch (final IOException e) {
LOG.error("Unable to create Genesis module", e);
}
}
use of org.hyperledger.besu.evm.tracing.StandardJsonTracer in project besu by hyperledger.
the class StateTestSubCommand method traceTestSpecs.
private void traceTestSpecs(final String test, final List<GeneralStateTestCaseEipSpec> specs) {
Log4j2ConfiguratorUtil.setLevel("org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder", Level.OFF);
final var referenceTestProtocolSchedules = ReferenceTestProtocolSchedules.create();
Log4j2ConfiguratorUtil.setLevel("org.hyperledger.besu.ethereum.mainnet.ProtocolScheduleBuilder", null);
final // You should have picked Mercy.
OperationTracer tracer = parentCommand.showJsonResults ? new StandardJsonTracer(output, !parentCommand.noMemory) : OperationTracer.NO_TRACING;
for (final GeneralStateTestCaseEipSpec spec : specs) {
final BlockHeader blockHeader = spec.getBlockHeader();
final WorldState initialWorldState = spec.getInitialWorldState();
final Transaction transaction = spec.getTransaction();
final ObjectNode summaryLine = objectMapper.createObjectNode();
if (transaction == null) {
// Check the world state root hash.
summaryLine.put("test", test);
summaryLine.put("fork", spec.getFork());
summaryLine.put("d", spec.getDataIndex());
summaryLine.put("g", spec.getGasIndex());
summaryLine.put("v", spec.getValueIndex());
summaryLine.put("pass", spec.getExpectException() != null);
summaryLine.put("validationError", "Transaction had out-of-bounds parameters");
} else {
final MutableWorldState worldState = new DefaultMutableWorldState(initialWorldState);
// `TransactionProcessor`, so these tests are skipped.
if (transaction.getGasLimit() > blockHeader.getGasLimit() - blockHeader.getGasUsed()) {
return;
}
final String forkName = fork == null ? spec.getFork() : fork;
final ProtocolSchedule protocolSchedule = referenceTestProtocolSchedules.getByName(forkName);
if (protocolSchedule == null) {
throw new UnsupportedForkException(forkName);
}
final MainnetTransactionProcessor processor = protocolSchedule.getByBlockNumber(0).getTransactionProcessor();
final WorldUpdater worldStateUpdater = worldState.updater();
final ReferenceTestBlockchain blockchain = new ReferenceTestBlockchain(blockHeader.getNumber());
final Stopwatch timer = Stopwatch.createStarted();
final TransactionProcessingResult result = processor.processTransaction(blockchain, worldStateUpdater, blockHeader, transaction, blockHeader.getCoinbase(), new BlockHashLookup(blockHeader, blockchain), false, TransactionValidationParams.processingBlock(), tracer);
timer.stop();
if (shouldClearEmptyAccounts(spec.getFork())) {
final Account coinbase = worldStateUpdater.getOrCreate(spec.getBlockHeader().getCoinbase());
if (coinbase != null && coinbase.isEmpty()) {
worldStateUpdater.deleteAccount(coinbase.getAddress());
}
final Account sender = worldStateUpdater.getAccount(transaction.getSender());
if (sender != null && sender.isEmpty()) {
worldStateUpdater.deleteAccount(sender.getAddress());
}
}
worldStateUpdater.commit();
summaryLine.put("output", result.getOutput().toUnprefixedHexString());
final UInt256 gasUsed = UInt256.valueOf(transaction.getGasLimit() - result.getGasRemaining());
summaryLine.put("gasUsed", StandardJsonTracer.shortNumber(gasUsed));
summaryLine.put("time", timer.elapsed(TimeUnit.NANOSECONDS));
// Check the world state root hash.
summaryLine.put("test", test);
summaryLine.put("fork", spec.getFork());
summaryLine.put("d", spec.getDataIndex());
summaryLine.put("g", spec.getGasIndex());
summaryLine.put("v", spec.getValueIndex());
summaryLine.put("postHash", worldState.rootHash().toHexString());
final List<Log> logs = result.getLogs();
final Hash actualLogsHash = Hash.hash(RLP.encode(out -> out.writeList(logs, Log::writeTo)));
summaryLine.put("postLogsHash", actualLogsHash.toHexString());
summaryLine.put("pass", spec.getExpectException() == null && worldState.rootHash().equals(spec.getExpectedRootHash()) && actualLogsHash.equals(spec.getExpectedLogsHash()));
if (result.isInvalid()) {
summaryLine.put("validationError", result.getValidationResult().getErrorMessage());
} else if (spec.getExpectException() != null) {
summaryLine.put("validationError", "Exception '" + spec.getExpectException() + "' was expected but did not occur");
}
}
output.println(summaryLine);
}
}
Aggregations