public List<String> traceTransactionToFile(
      final MutableWorldState mutableWorldState,
      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::traceMemory)
            .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, transactionProcessor, protocolSpec) -> {
              WorldUpdater stackedUpdater = mutableWorldState.updater().updater();
              final List<String> traces = new ArrayList<>();
              final Wei blobGasPrice =
                  protocolSpec
                      .getFeeMarket()
                      .blobGasPricePerGas(
                          blockchain
                              .getBlockHeader(header.getParentHash())
                              .map(parent -> calculateExcessBlobGasForParent(protocolSpec, parent))
                              .orElse(BlobGas.ZERO));
              for (int i = 0; i < body.getTransactions().size(); i++) {
                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, true, true, false, true),
                            blobGasPrice);
                    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,
                      blobGasPrice);
                }
              }
              return Optional.of(traces);
            })
        .orElse(new ArrayList<>());
  }
Used to produce debug traces of transactions
ethereum/api/src/main/java/org/hyperledger/besu/ethereum/api/jsonrpc/internal/processor/TransactionTracer.java