#35641 kernel: Add script evaluation tracer

full analysis

https://github.com/bitcoin/bitcoin/pull/35641 · sedited · +617/-2 in 9 files, 1 commits · labels: Validation

Goal

  • Allow external kernel consumers and debugger tools to observe intermediate script execution state
  • Avoids the need for custom Bitcoin Core forks or reimplementations when inspecting or debugging scripts

Adds an optional script evaluation tracing mechanism to libbitcoinkernel gated behind the ENABLE_SCRIPT_TRACE CMake flag. When enabled, a registered callback receives snapshot frames at the start, step, and end of script evaluation in EvalScript, exposing stack items, opcodes, execution state, and script errors.

Problem: External applications and debuggers built on libbitcoinkernel lack visibility into internal script evaluation steps, making it difficult to write interactive script debuggers or trace interpreter execution.

Category: Kernel (libbitcoinkernel) (#10 of 18)

P3 · new feature

  • P3 because external tooling and debuggers gain visibility into script execution
  • It provides an optional compile-time utility rather than essential kernel validation infrastructure

Adds an optional script execution tracing API to the C kernel interface, allowing external tools like rust-bitcoinkernel to inspect script evaluation step by step. While valuable for developer tooling and script debugging, it is gated behind an optional build flag and does not block core node or validation library functionality.

Membership: Adds C API functions, headers, and CMake options to libbitcoinkernel under src/kernel/.

Factors: security/stability 0, bug 0, performance 0, user value 2, leverage 1

Reviewability: Paused: Waiting on author

  • Author response is pending on a material assertion bug when serror is null

Reviewer w0xlt reported a reproducible assertion failure when EvalScript is called with a null serror pointer, which has been open for 15 days without an author reply.

Author status: silent since 2026-08-31 after addressing alexanderwiederin's comments

Open concerns:

  • An assertion failure triggers when tracing is enabled and EvalScript is invoked with a null serror pointer (e.g. in CheckSignetBlockSolution).
  • Oversized scripts are rejected before ScriptTraceScope is instantiated, preventing BEGIN and END trace frames from being emitted.

Resolved concerns:

  • Opaque C API types and getters adopted instead of exposing internal struct layouts.
  • Enum conversions between internal and kernel wrapper types made exhaustive.
  • Thread safety documentation and callback unregistration cleanup in kernel test suite.

Agreement: Mild

  • Strong concept and approach support across multiple contributors
  • Concept approval noting it would benefit testing greatly (furszy, w0xlt)
  • Approach approval (haanhvu)
  • Verified by testing with Python bindings and a transaction visualizer (elmeriniemela)
  • Unaddressed bug: assertion failure when serror is null (w0xlt)

Concept supported by multiple reviewers, but w0xlt found an unaddressed assertion bug when serror is null.

The PR has broad concept approval for exposing script tracing hooks in the kernel API, but w0xlt identified a real bug where internal callers passing null error pointers crash an assertion when tracing is enabled.

  • furszy: 'Concept ACK... something that would benefit testing greatly'
  • haanhvu: 'Approach ACK'
  • w0xlt: 'The tracing code assumes serror is non-null whenever a callback is registered... This triggers the assertion'

Objections:

ReviewerKindHarmStatusBlockingAuthor repliedQuote
w0xltcorrectnessEvalScript triggers an assertion failure when tracing is enabled if called with a null serror pointer, such as in CheckSignetBlockSolution.opennono2026-09-01: 'The tracing code assumes serror is non-null whenever a callback is registered, but EvalScript permits nullptr... This triggers the assertion assert(!m_callback || error); when tracing is enabled.'
alexanderwiederincorrectnesstest suite fails when compiled with ENABLE_SCRIPT_TRACE=ON due to lingering callback pushing into destroyed vector in subsequent testsresolvednoyes2026-08-31: "Add ScriptTraceUnsetCallback() to avoid the next test case push into a destroyed vector. Test suite currently does not pass with the feature flag."
Settled: 2026-08-31: "unsetting the callback after the trace tests are complete."
haanhvucorrectnessBOOST_CHECK_EQUAL on vector size allows test execution to continue and access out-of-bounds indices, causing undefined behaviorresolvednoyes2026-07-29: "BOOST_CHECK_EQUAL(states.size(), 11) is non-fatal, but the test checks states[0] through states[10] after this. So if the size check fails, the test still continues and may access out-of-bound items, resulting in an undefined behavior instead of a clean test failure."
Settled: 2026-08-28: "made the boost size check a hard requirement."

Support:

  • furszy: would benefit testing greatly
  • theStack: Concept ACK [not substantive]
  • alexanderwiederin: ACK 114e48e968a087f74c1ab611ac2a31a9266812e1 [not substantive]
  • haanhvu: Approach ACK [not substantive]
  • w0xlt: Strong Concept ACK [not substantive]
  • elmeriniemela: tested with python bindings and visualizer, confirmed no issues found

Participants: furszy (support), w0xlt (objection), alexanderwiederin (objection), theStack (support), elmeriniemela (support), haanhvu (support), stringintech (neutral)

State derived from the lists: nonblocking objection open (w0xlt)

Review verdicts (DrahtBot): 0 (+1)

Files

78 lines under test/bench/ci.

  • src/kernel/bitcoinkernel.cpp +144/-1
  • src/kernel/bitcoinkernel.h +134/-0
  • src/script/trace.h +118/-0
  • src/kernel/bitcoinkernel_wrapper.h +89/-0
  • src/test/kernel/test_kernel.cpp +74/-0
  • src/script/trace.cpp +40/-0
  • src/script/interpreter.cpp +8/-1
  • src/kernel/CMakeLists.txt +6/-0
  • src/test/kernel/CMakeLists.txt +4/-0

Card

This PR introduces an optional script execution tracer in libbitcoinkernel, gated behind the ENABLE_SCRIPT_TRACE build option. It exposes a C callback interface providing snapshot frames for opcode execution, stack items, and script errors, enabling external tools like rust-bitcoinkernel to build interactive script debuggers. Multiple reviewers support the concept and API design, but review is currently paused waiting on the author to resolve a recently reported assertion crash when EvalScript receives null error pointers. It has no external dependencies.

Data

dossier JSON · extract JSON · model openrouter/google/gemini-3.8-flash, generated 2026-09-17T21:36, confidence high, input hash eb3a3c209c06dae6