My experience is limited to some knowledge about tracing implementations inside EVMs and using tracing for debugging convoluted state tests.
The most confusing part of the current tracing is that it reports a kind of “in progress” state of an instruction execution if you consider precondition-checking a part of the execution. I.e. it reports the gas cost of the instruction (hopefully total gas cost but that was not the case in Aleth; does it also report total CREATE
and CALL
costs?) but not the execution result.
In one of my prototypes I changed that. The tracing there was reporting the state after instruction execution. This was in my opinion much more DevEx friendly.
Moreover, I also focused on limiting the amount data transferred from EVM. Together these provided additional nice options:
-
Instead of dumping whole EVM stack, you can always dump only the top item. It can be noticed that an instruction pushes at most one value to the stack so the “stack top dump” is also the instruction execution result.
{"opName":"PUSH1", "stackTop":"0x02"}
{"opName":"DUP1", "stackTop":"0x02"}
{"opName":"ADD", "stackTop":"0x04"}
-
Instead of full memory dump, you can only report the modifiedMemory
: the memory area where the instruction has written to. It can be noticed that an instruction may at most modify single continuous memory area. This also can be seen as the instruction execution result. If you report the instruction before execution the “modified memory” has no meaning.
{"opName":"MSTORE", "modifiedMemoryOffset":"0x20", "modifiedMemory":"0x000000000000000000000000aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}
-
It is enough to just report gasLeft
after the execution. The instruction gas cost can be easily computed from the gasLeft
of the previous instruction.
-
An error code can be meaningfully added to an instruction trace. Is this the meaning of the error
field? However, this only make sense for the last instruction in a call as other instructions must be successful.
{"opName":"POP", "error":"stack underflow"}
Lastly, the “new” tracing should provide the same information as the “legacy” tracing. Therefore, the “legacy” tracing format can be emulated by a statefull wrapper. If that is not the case, consider this a bug.
Many of these options have variants and alternatives. At this moment I only want to present an overview. Let me know if this direction is something you would like to explore.
References
-
EVMC tracing prototype (and introducing PR) — never fully utilized by any EVM and finally removed from EVMC.
-
Aleth implementation of the EVMC tracing prototype.