-
Notifications
You must be signed in to change notification settings - Fork 318
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
towards a standard EVM trace format #249
Comments
I like the idea of standarization very much! 👍 But if we are about to do that, there can't be any temporary workarounds. Can't a single operation result in two logs? One created before operation execution with the operation itself and the other one with result of the operation. |
@debris this is to document a work-in-progress, so hopefully it will see incremental improvement. If a single operation resulted in two logs, lots of information would be duplicated. I do like the idea of an error field, which would tell whether an operation failed due to an OOG or some other exception. But that would complicate the tracing logic quite a bit, and it would be non-trivial to implement in the clients I've worked with so far. Maybe if the failed operations are logged twice (the second with the failure) it would be easier for clients to implement? |
see also ethereum/go-ethereum#14900 |
Can you describe what data is logged? Is logging the stack and memory feasible? |
The stack is logged on every step. Logging the memory should be feasible, but at the moment its not included in the equivalence test. |
Full stack is logged or only the changes? |
The full stack is logged. I agree that just the changes would be more compact. |
There is always a STOP opcode, if you count the virtual extension of the code with an indefinite number of zeros. So geth may be right. I suspect eth will also report a STOP for that reason, but am on the road and can't check the code right now. |
Yes, logging the full stack is horrible. For eth the stack grows towards low addresses, so the code has to copy it all out backwards. Only the changes should be logged. |
VM trace data:
Notes:
|
I think it would make sense naming it differently since usually pc (program counter) refers to the byte offset.
Would name it gas left or gas remaining. |
I think I confused |
How about instead of the flat stack array:
|
Please specify how the values are represented:
|
Note that the "standardized trace" now also logs a
|
Because the the step report describes the EVM state before the opcode execution:
|
@chfast I think so, yes. instructions are logged before execution, whether the last step in the call depth (if the call OOGs), or the last step in the whole trace. |
@chfast sure, feel free to prototype this.
I'm not sure its worth the trouble to log the gas cost of a step/instruction, since it can be calculated anyway from the difference in gas remaining between two steps. Currently for equivalence testing, we don't use the gas cost of a step that some clients include in the trace. We only use gas remaining. |
@cdetrio, ok, but "gas remaining" should also be lowered by the cost of the just-to-be-executed instruction. So in case of an instruction resulting in OOG, the gas remaining must be negative. And in case of a call, we don't know the cost up front, so we only can take the "gas" argument of the call into consideration (C++ does it this way - a call cost it the basic CALL instruction cost + value transfer penalty + account creation penalty + the gas argument value). |
Each step is logged with all values just before the execution, so the gas remaining should never be negative. |
So in case an instruction is causing an exception, this step is not logged? |
@chfast The only exception is invalid opcode steps, technically these could be logged too but currently they're filtered from the canonicalized trace (before doing the equivalence comparison check, for fuzz testing). This helps accommodate clients that don't log invalid opcodes, or that only log a generic exception but not the opcode itself. I can't remember which client (maybe pyeth). All other steps (those with valid opcodes) are logged before execution. Also, the exceptions themselves are not explicitly logged (if a client does log exceptions, then its filtered when converting to the canonicalized trace). So where exceptions occur has to be deduced from the trace (e.g. by checking gas remaining where call depth decreases). Not labeling steps that cause exceptions is kind of annoying when reading a (canonicalized) trace, but for the purpose of equivalence fuzz testing its sufficient to just compare all steps without explicitly labeling where exceptions occur. |
I think the term "just before execution" is a bit misleading. So in case of
not
|
@chfast the trace would be
because on each step, its the gas remaining before execution and before gas deduction. |
The json trace output from clients should be |
@winsvega perhaps |
you mean compare logs instead of root hashes? |
I suggested adding a new kind of test. I did not suggest replacing any existing tests that compare root hashes. |
the goal is actually to get rid of different test types and come to a general test format. |
@winsvega please use a separate GitHub issue for the most general test format. |
@cdetrio @holiman I'm back to this issue because I want finally to implement this in EVMC. I still believe it would be more convenient to report the effect of the instruction execution, not the state before the execution. In this case it might be enough to only report the top stack item being the result of the execution of the current opcode. Also the cost of the execution and exceptions can be reported. |
It's in the EIP process: https://eips.ethereum.org/EIPS/eip-3155 |
Devs and protocols are quite incompatible as we found out. Also being a top second cryptocurrency the teams can't afford or find the devs to work on concensus non critical issues. Everyone on their own. You want a vmtrace standard - you dig into everyones code and impliment it as your own fork. Fund an organization. Make public demonstrations, become a president to propose thise idea. |
@winsvega I've taken action and opened a new issue for that ethereumjs/ethereumjs-monorepo#1215 (so maybe no need to become president here, we'll see). 😛 |
Currently geths evm trace is a standard. |
Towards a standard EVM trace format
The purpose of this standard trace format is to facilitate automated equivalence testing of different EVM implementations.
Temporary workarounds
Noted quirks
geth logs STOP operations on all successful exits, even when there is no STOP opcode. For example, where pyethereum logs:
geth will log:
Example trace
This trace is produced by executing the stCallCodes/callcall_00 state test.
The text was updated successfully, but these errors were encountered: