rpc/jsonrpc: keep trace_call's unrequested trace empty and stop attaching the tracer for stateDiff - #23572
Merged
Merged
Conversation
trace_call returned the full call trace for stateDiff-only and vmTrace-only requests. Call was the only ad-hoc path missing the final reset that doCall, doCallBlock and RawTransaction all have. The reset is not redundant: the OE tracer appends call frames to the result regardless of the requested trace types, so a vmTrace-only request fills Trace as a side effect. The field stays an empty array rather than null. That is what OpenEthereum returns, what the other trace_* endpoints already return, and what cmd/rpcdaemon/postman/Trace_Testing.json asserts.
Call and RawTransaction attached the tracer for stateDiff-only requests as well, collecting a trace they then discard. doCall and doCallBlock already attach it only for trace and vmTrace. Both also passed the tracer hooks to the EVM unconditionally. With an empty trace-type list the tracer has no result to write into, so the first OnEnter dereferenced a nil pointer and the request failed with "method handler crashed". Reachable on trace_call and on trace_rawTransaction. Both paths now build a vm.Config the way the sibling paths do, so the hooks exist only when a trace is actually collected. parseOeTracerConfig stays outside the branch: trace_* must keep rejecting custom tracers whatever the requested trace types are.
ReplayTransaction built and populated a TraceCallResult that it never returned. doCall already rejects unrecognized trace types, so dropping the block keeps the error behaviour, now covered by a test. The trace docs said unrequested trace types are null. That holds for stateDiff and vmTrace but not for trace, which is an empty array.
lupin012
marked this pull request as ready for review
August 27, 2026 08:53
lupin012
requested review from
AskAlexSharov,
bloxster,
lystopad,
mriccobene and
yperbasis
as code owners
August 27, 2026 08:53
AskAlexSharov
approved these changes
Aug 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #23326.
The report expected an unrequested
traceto benull; the reporter withdrew that, sincetracefollows OpenEthereum'sTraceResults.trace: Vec<Trace>and is an array, nevernull. The captured response shows the real defect: with["stateDiff"]thetracefield carries the full call trace.Three defects, all present on
release/3.6too:tracepopulated when not requested. With["stateDiff"]or["vmTrace"],trace_callreturns the full call trace.Callwas the only ad-hoc path missing the final reset thatdoCall,doCallBlockandRawTransactionhave.stateDiff-only requests.CallandRawTransactionattached it for all three trace types, collecting a trace they then discard.OnEnternil-dereferenced. Recovered per request, so the client getsmethod handler crashed. Reachable ontrace_callandtrace_rawTransaction.Changes
Call: resetTracewhentracewas not requested. Still needed after the tracer change, because the OE tracer appends call frames regardless of the requested types, sovmTrace-only fillsTraceas a side effect.CallandRawTransaction: build avm.Configlike the sibling paths, so the hooks exist only when a trace is collected. Closes both the wasted work and the panic.parseOeTracerConfigstays outside the branch, so custom tracers keep being rejected for any trace types.ReplayTransaction: drop aTraceCallResultit built, populated and never returned.doCallalready rejects unrecognized trace types.null, true forstateDiffandvmTracebut not fortrace.Behaviour change
trace_callwith["stateDiff"]or["vmTrace"]now returns"trace": []. This matches OpenEthereum, the othertrace_*endpoints, andcmd/rpcdaemon/postman/Trace_Testing.json, whose"trace_call - stateDiff only"case expects"trace": []and fails against the current code.Tests
Regression coverage for the three defects, plus non-regression on
["trace"], ontracecombined with the other types, and on a custom tracer rejected for astateDiff-only request.Also verified over HTTP with the old and new
rpcdaemonside by side against one dev-chain node:traceTypes["stateDiff"],["vmTrace"],["vmTrace","stateDiff"]tracelength 1tracelength 0[]method handler crashedtracelength 0["trace"],["trace","stateDiff"]tracelength 1tracelength 1trace_rawTransactionwith[]goes frommethod handler crashedto"trace": []; with["stateDiff"]it was already correct.