-
Notifications
You must be signed in to change notification settings - Fork 54
howto evm
Here's what to think about if you want to add an evm
to evmlab.
The evm
should take the following inputs:
-
--code <code>
- code to be executed. -
--codeFile <file>
- file containing code to be executed. Sometimes really large chunks of input cannot be passed through bash. --gas <int>
--price <int>
-
--sender <address>
- address ofORIGIN
-
--receiver <address
- address ofADDRESS
-
--input <code>
:CALLDATA
--value <int>
-
--json
- boolean flag, output json output for each opcode or not (it's useful to disable json when benchmarking) -
--nomemory
- disable showing the full memory output for each op -
--create
- if specified, it's executed as initcode -
--prestate
- a chain specification, the same one that the client normally would use.
Basically, the evm
should be able to run things very simply, like so:
$evm --code 6040 --json run
{"pc":0,"op":96,"gas":"0x2540be400","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"depth":1,"error":null,"opName":"PUSH1"}
{"pc":2,"op":0,"gas":"0x2540be3fd","gasCost":"0x0","memory":"0x","memSize":0,"stack":["0x40"],"depth":1,"error":null,"opName":"STOP"}
{"output":"","gasUsed":"0x3","time":141485}
But it should also be able to reconstruct an actual on-chain transaction, with complex options including prestate, where no code
is passed, since it's already been showed into the prestate
:
$evm --prestate /home/martin/workspace/evmlab/output//0xd6d519-genesis-geth_wq38zsy5.json --gas 150000 --sender 0x69ea6b31ef305d6b99bb2d4c9d99456fa108b02a --receiver 0xb97048628db6b661d4c2aa833e95dbe1a905b280 --input a9059cbb0000000000000000000000008eef795fd9150f118bddeca556a5a2a2438ab865000000000000000000000000000000000000000000000081ebd8ffd6b2a58000 --json run
The fuzzing engine produces statetests, so the CUT (client under test) must be able to execute a statetest. Example :
evm --json --nomemory statetest foobar.json
The vm should not spit out jsonl as defined below, and it should also report the final stateRoot
hash after executing the test. If the client also spits out info about whether the test succeeded or failed, that doesn't matter -- we can ignore things we're not interested in.
The evm
should output a json
object for each operation. Example:
{"pc":0,"op":96,"gas":"0x2540be400","gasCost":"0x3","memory":"0x","memSize":0,"stack":[],"depth":1,"error":null,"opName":"PUSH1"}
Required: pc
, op
, gas
, stack
, depth
Optional: opName
, gasCost
, error
The stack
, memory
and memSize
are the values before execution of the op.
At the end of execution, some summarical info is good, e.g.
{"output":"","gasUsed":"0x3","time":141485}
When errors occur, geth and parity handles them differently.
Minor changes to how things work is ok, we can handle discrepancies in format and minor quirks.