Skip to content

fix(traces): tracing consistency between input and output alloc formatting#2832

Open
felix314159 wants to merge 2 commits into
ethereum:forks/amsterdamfrom
felix314159:forks/amsterdam
Open

fix(traces): tracing consistency between input and output alloc formatting#2832
felix314159 wants to merge 2 commits into
ethereum:forks/amsterdamfrom
felix314159:forks/amsterdam

Conversation

@felix314159
Copy link
Copy Markdown
Contributor

@felix314159 felix314159 commented May 11, 2026

🗒️ Description

while looking into how our different tracing flags work I noticed that the same values are represented differently in input vs output alloc. for instance, a storage key would be 0x22 in the input (no padding) but 0x000..22 in the output (32 byte padded). another example is how an empty storage in the input would be shown as {} whereas empty fields are completely emitted in the output (same for empty balances and empty code). also nonces in the input are shown like e.g. 0x01 (always at least two chars) but shown as 0x1 in the output (minimal representation)

this PR fixes all these inconsistencies and adds a unit tests that ensures input and output alloc formatting remains consistent. the output of course can still be different, this PR is only about the format in which values are shown

i think this is a good feature because if we ever want to actually look at the diff between input and output alloc we currently would have a lot of noise, after the PR only the actual differences would be left (less bloating of our human context windows)

i don't think this PR breaks anything, because it only changes the input alloc formatting and leaves the output alloc (that might be read be client software) exactly as is

Command to run the new unit test

uv run pytest packages/testing/src/execution_testing/cli/pytest_commands/plugins/filler/tests/test_alloc_dump_canonical.py::test_input_alloc_matches_output_alloc_format -v

🔗 Related Issues or PRs

N/A.

✅ Checklist

  • All: Ran fast static checks to avoid unnecessary CI fails, see also Code Standards and Enabling Pre-commit Checks:
    just static
  • All: PR title adheres to the repo standard - it will be used as the squash commit message and should start type(scope):.
  • All: Considered updating the online docs in the ./docs/ directory.
  • All: Set appropriate labels for the changes (only maintainers can apply labels).
  • Tests: Ran mkdocs serve locally and verified the auto-generated docs for new tests in the Test Case Reference are correctly formatted.
  • Tests: For PRs implementing a missed test case, update the post-mortem document to add an entry the list.
  • Ported Tests: All converted JSON/YML tests from ethereum/tests or tests/static have been assigned @ported_from marker.

Cute Animal Picture

Cute Animal Picture

@codecov
Copy link
Copy Markdown

codecov Bot commented May 11, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.63%. Comparing base (462ee80) to head (602dc8e).

Additional details and impacted files
@@               Coverage Diff                @@
##           forks/amsterdam    #2832   +/-   ##
================================================
  Coverage            88.62%   88.63%           
================================================
  Files                  577      577           
  Lines                35659    35659           
  Branches              3490     3490           
================================================
+ Hits                 31604    31607    +3     
+ Misses                3492     3489    -3     
  Partials               563      563           
Flag Coverage Δ
unittests 88.63% <ø> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Member

@marioevz marioevz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks ok to me, just a couple of comments. I do agree that having the input and output in the same folder be in different formats is annoying.

I think ideally we should coalesce types used in both sides of the t8n to get rid of this issue from the root.

cc @gurukamath since he is working on refactoring t8n.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the purpose of the changes to this file?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i had to add the second commit to fix CI failure:

36 tests in test-tests and test-tests-pypy failed. in all casestest_filler.py gave the same exception:

E   FileNotFoundError: [Errno 2] No such file or directory:
    '/tmp/tmpmepzcz2k/trace-0-0x1997...jsonl'
    at .../evm_trace/eip3155.py:324: json_file = open(output_path, "w")

there was a pre-existing bug that was exposed by the first commit of this PR.
so first T8N.__init__ called trace.set_evm_trace(tracers) (in t8n/init.py:336). but set_evm_trace is global (there's one tracer slot for the whole process, and if the next t8n does not use traces the previous trace slot is still live). so every time a T8N was constructed it used that slot, and once a T8N's run() ended the slot was left pointing at that T8N's tracer, holding that T8N's tempdir in its output_basedir attribute. then the next T8N (constructed by the next test) would create a fresh tempfile.TemporaryDirectory() but never re-installed its own tracer if tracing was disabled for that call. EVM execution still fired the leaked previous tracer, which tried to write trace-*.jsonl into a tempdir that had since been cleaned up by TemporaryDirectory.__exit__. so that's why we got FileNotFoundError in CI

and it is a bit weird that output_traces never used mkdir for the output_basedir. so even in the happy path, the trace writer assumed someone else had created the directory.

so the second commit fixes both the t8n-leak-between-instances and also ensures the directory we try to write to exists

return Alloc.model_validate(accumulated)


def _alloc_to_canonical_dict(alloc: Alloc) -> Dict[str, Dict[str, Any]]:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One small downside of this function is that it's decoupled from the Alloc model, so if we change it (very unlikely) this function would break.

@gurukamath
Copy link
Copy Markdown
Contributor

It looks ok to me, just a couple of comments. I do agree that having the input and output in the same folder be in different formats is annoying.

I think ideally we should coalesce types used in both sides of the t8n to get rid of this issue from the root.

cc @gurukamath since he is working on refactoring t8n.

That's right. Once we manage to replace the current t8n's Alloc parsing mechanism and just start using the EEST Alloc, we should be able to have consistent input and output formats. In that world, the pydantic models alone will be responsible for json serialization/de-serialization, leading to a fundamental consistency. Incidentally, that is the next agenda on my list. Just waiting for #2750 to be merged first.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants