-
Notifications
You must be signed in to change notification settings - Fork 20.2k
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
cmd/evm: improve block/state test runner #30633
base: master
Are you sure you want to change the base?
Conversation
Both |
One upside in having it inside |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code changes LGTM
I personally prefer to have these as separate commands and I don't think we should be concerned about the build scripts etc. Eofdump has as very small audience (Martin and I), same with t8ntool (Mario and Matt) so the only really user-facing function is evm state-test and evm blocktest that are used by hive, testing and fuzzing. Everything else is functionality that we use internally that is not really intended for a wider audience imo
@fjl wdyt? I don't see much advantage of only needing one binary everywhere. There aren't many consumers and those consumers are somewhat independent (as Marius says). The advantage is that the tools can be simpler, less thought needed in organization since each tool only does a few related things, and different people can own different packages. |
Added some nice stuff in c594c87:
-- example $ go run ./cmd/evm --verbosity=0 blocktest --human --run="zero_inputs" ./tests/spec-tests/fixtures/blockchain_tests/cancun
[PASS] eip5656_mcopy test_valid_mcopy_operations, param=zero_inputs
--
1 tests passed, 0 tests failed. |
ahh great! |
From triage: seems like there is desire to not split the evm command. I'll combine them again with the other refactors I did. |
20ad594
to
b37356f
Compare
@@ -995,7 +996,7 @@ func (api *ConsensusAPI) executeStatelessPayload(params engine.ExecutableData, v | |||
api.lastNewPayloadLock.Unlock() | |||
|
|||
log.Trace("Executing block statelessly", "number", block.Number(), "hash", params.BlockHash) | |||
stateRoot, receiptRoot, err := core.ExecuteStateless(api.eth.BlockChain().Config(), block, witness) | |||
stateRoot, receiptRoot, err := core.ExecuteStateless(api.eth.BlockChain().Config(), vm.Config{}, block, witness) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any reason not to pass *api.eth.BlockChain().GetVMConfig()
here? or at least the live logger?
still haven't done this, will get to it soon |
0cb4c48
to
270925f
Compare
Okay this should be good to go. Have reverted the refactoring out the subcommands, but retained the other improvements. PTAL! |
…utput, stateless cross-checking option
270925f
to
7c34200
Compare
if state.StateDB != nil { | ||
root = state.StateDB.IntermediateRoot(false) | ||
result.Root = &root | ||
// Dump any state to aid debugging. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you just drop the fmt.Fprintf(os.Stderr
- output of the stateRoot?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The state root is recorded in the result and output via report(..)
.
Some diffs when I run the reference tests in goevmlab. diff --git a/evms/testdata/run.sh b/evms/testdata/run.sh
index 4c38810..eee91c2 100755
--- a/evms/testdata/run.sh
+++ b/evms/testdata/run.sh
@@ -15,7 +15,8 @@ if [[ -n "$evm" ]]; then
cd ./cases
# The traces
for i in *.json; do
- $evm --json --nomemory --noreturndata statetest $i \
+# $evm --json --nomemory --noreturndata statetest $i \
+ $evm statetest --trace --trace.format=json --trace.nomemory --trace.noreturndata $i \
2>../traces/$i.geth.stderr.txt \
1>../traces/$i.geth.stdout.txt
done
|
I'm not sure why output step might be missing. That should come from the tracer and the tracer is configured the same before and after this PR? I can add the You can see it is written to stdout after the execution completes: [
{
"name": "tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_call_set_code[fork_Prague-call_opcode_CALL-evm_code_type_LEGACY-state_test-value_1]",
"pass": true,
"stateRoot": "0xa489cbd2d4e37e8b6b27fa5a66242d3732fbe346aea1aa011d3aa4545765ec13",
"fork": "Prague"
}
] When there is a full dump, it is also there: [
{
"name": "tests/prague/eip7702_set_code_tx/test_set_code_txs.py::test_set_code_call_set_code[fork_Prague-call_opcode_CALL-evm_code_type_LEGACY-state_test-value_0]",
"pass": true,
"stateRoot": "0x21331f3c18a3cf737d68e396e32bfef23a8f7cec32971f0265850453b82afe9f",
"fork": "Prague",
"state": {
"root": "21331f3c18a3cf737d68e396e32bfef23a8f7cec32971f0265850453b82afe9f",
"accounts": {
"0x0000000000000000000000000000000000001000": {
"balance": "0",
"nonce": 1,
"root": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"codeHash": "0xe90b835ed0c9ae43182bcfe017e4e9776a804d20e0bf7061ae73758bcc5e9cde",
"code": "0x60006000600060006000738a0a19589531694250d570040a0c4b74576919b85af1600055600160015500",
"address": "0x0000000000000000000000000000000000001000",
"key": "0x1d7dcb6a0ce5227c5379fc5b0e004561d7833b063355f69bfea3178f08fbaab4"
}
}
}
}
] |
Ah, but I'm reading |
Added back the fprint for the state root 👍 |
Ah, wait, it's broken on master too, not your fault.. Bisecting |
For some reason, this PR makes the |
doing a |
The
As opposed to:
// OnExit is called a call frame finishes processing.
func (l *StructLogger) OnExit(depth int, output []byte, gasUsed uint64, err error, reverted bool) {
if depth != 0 {
return
}
l.output = output
l.err = err
if l.cfg.Debug {
fmt.Printf("%#x\n", output)
if err != nil {
fmt.Printf(" error: %v\n", err)
}
}
} EDIT: No, althought |
So, as far as I can tell, the only way to get
It can never be output from the statetest command. These emit no output:
In order to make
Putting the
See // StartGoTrace turns on tracing, writing to the given file.
func (h *HandlerT) StartGoTrace(file string) error { If user puts
IMO, we should
|
We should also make the markdown logger usable, and perhaps even default.
(Note: strange assymetry there, where the NewJSONLogger returns
Or, without quoting: [user@work testdata]$ /home/user/go/src/github.com/ethereum/go-ethereum/evm run --json --trace --trace.format=json 6040
Output: `` |
All users of Also, the struct logger is a non-streaming logger. It was originally used in RPC, where we need to store the logs in-memory before we marshal to json. For So I think we should align them, behaviourally (json, struct and markdown), and if we need a special type of non-streaming tracer just for the rpc, it can be a separate one for that purpose. Or we put a collector on the outside of a streaming outputter, for that purpose. |
The
However, said dirty-tracking does not handle reverted scopes, so it's pretty random wether it will present accurate or false information. IMO we should drop that. Dunno if it needs to go into this PR, just noting it. |
Had the idea for a while to refactor
cmd/evm
. It feels like a lot of it has grown organically to meet demands -> test running, test fill, eof validation, etc.original motivation
Unfortunately this had led to several subcommands with little relation beyond a general relationship to the EVM. This makes using the `evm` command confusing. Both `evm run` and `evm t8n` specify their own set of tracing flags ([1][runner-trace], [2][t8n-trace]). Flags like `--input` are reused for different things between the test runners and disassemblers. `eofparse` adds `--hex` which is basically `--input` but for it's own purposes.There isn't a coherent story for the set of tools. I think we should either spend a fair bit of work ensuring the flags are meaningful across all subcommands and avoid duplicate behavior, or some of the subcommands should live in their own package. My preference is the latter, because it more accurately represents today's maintenance: t8n is the highest prio and has many external contributions from the testing team. Enforcing and ensuring their changes make sense across
evm
will slow down everyone involved. The interface fort8n
is the most robust and it makes sense for it to be it's own package.eofparse
is much newer, but similarly seems like an unrelated project that can live on it's own. Which leaves us with the runner commands and the compilation tools. I opted to delete the compilation tools since they are used much any more and it was suggested we delete them last year.Updated this PR to focus mostly on harmonizing the staterunner / blockrunner while also tidying up in
cmd/evm/main.go
where I could.In summary:
movet8n
,t9n
, andb11r
to their own commandcmd/t8ntool
evm compile
andevm disasm
moveevm eofparse
tocmd/eofparse
staterunner
andblockrunner
CLI flags, especially around tracinginsertChain
panics when struct tracer is set #30658)--cross-check
flag to validate the stateless witness collection / execution matches stateful--human
for more readable test summarytests/spec-tests/fixtures/blockchain_tests
it will execute all blockchain tests--
example
--