Skip to content

Support custom JavaScript tracers in debug_trace* methods (Geth-compatible) #10696

Description

@parthdagia05

What is missing

Besu's debug_trace* methods support the opcode logger and a fixed set of named tracers (callTracer, prestateTracer, 4byteTracer), but there is no way to run a tracer that a user writes themselves. Geth has supported this for years. You pass a small JavaScript object with step, result, fault, and optionally setup, enter, and exit, and the node runs it against the transaction's EVM execution. Whatever result returns becomes the response.

Reference: https://geth.ethereum.org/docs/developers/evm-tracing/custom-tracer

Proposal

Add Geth-compatible custom JavaScript tracer support so the same JavaScript tracer that runs on Geth runs unchanged on Besu. The engine would be GraalJS (org.graalvm.polyglot), which runs on the JDK Besu already uses, similar to how Geth uses goja.

Why it helps

A lot of debugging, analytics, and security tooling ships its own JavaScript tracer and assumes a Geth-style node, so people relying on it have to keep a Geth node around. This closes that gap and lets users express new trace logic at request time without waiting for a new Besu release. It builds on request fields and the EVM hook interface Besu already has, so it is additive rather than a new subsystem.

Approach, validated with a short spike on current main

The existing named tracers are post-processing converters that run after execution on a recorded trace. A JavaScript tracer needs to run live, on every opcode, with its db object reflecting state at that step. So it would attach as a live OperationTracer, mapping tracePreExecution to step, traceEndTransaction to result, and the context enter and exit hooks to enter and exit. MessageFrame already exposes what the Geth log and db objects need, including live world state.

I ran a spike on current main. The affected modules (evm, ethereum/api) compile cleanly with a minimal JsOperationTracer wired in. The spike also confirmed the gates to plan for:

  • Dependency verification (gradle/verification-metadata.xml) needs regenerated checksums for the GraalJS artifacts.
  • The GraalVM license needs adding to gradle/allowed-licenses.json.
  • GraalJS is interpreted on a standard JDK, so it is slower than the native tracers. The feature is opt-in and off any hot path.
  • Native image needs reachability metadata, so the standard build is the initial target.

Scope

Wire it into debug_traceTransaction first, then extend to the other debug_trace* methods. Include execution timeouts and resource limits so a tracer cannot hang the node, and tests that run real unmodified Geth tracers and compare the output.

Would this be welcome as a contribution, and is there a preferred direction on the live tracer routing? Happy to take it on in small, reviewable phases.

cc @usmansaleem @Gabriel-Trintinalia @jflo

Proposal-js-tracer.pdf

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions