Skip to content

feat(test-fill): Optimistic grouping flag - #3390

Open
marioevz wants to merge 11 commits into
ethereum:forks/amsterdamfrom
marioevz:optimistic-grouping-flag
Open

feat(test-fill): Optimistic grouping flag#3390
marioevz wants to merge 11 commits into
ethereum:forks/amsterdamfrom
marioevz:optimistic-grouping-flag

Conversation

@marioevz

Copy link
Copy Markdown
Member

Description

Makes pre-allocation group packing optional, and replaces the untyped string hashes used across the pre-alloc group and fixture index machinery with fixed-size types.

--disable-optimistic-pre-alloc-grouping

New fill flag. Phase 1 skips the packing pass so groups stay fine-grained, and phase 2 then resolves a test's group by recomputing its hash directly instead of looking it up in the packed index. Packing stays the default.

Typed group hashes

  • New AllocGroupHash (8-byte truncated sha256) replaces the str/int hashes that were assembled by hand in several places.
  • Environment.__hash__ is replaced by Environment.canonical_json(), so the grouping pre-image is an explicit canonical JSON encoding rather than a process-stable __hash__ whose value was persisted as a folder name.
  • PreAllocGroupBuilder carries its own group_hash, and GroupPreAlloc.get_pre_alloc_grouping_hash() lets an allocation report the group it belongs to.
  • GroupIndexEntry/GroupIndexEntries are pydantic models; the test → group index is read and written through them instead of hand-rolled JSON.

Engine X fixtures

  • pre_hash is set when the fixture is constructed, from the allocation's own group hash, rather than patched onto the model afterwards.
  • postStateDiff was never populated: post_state is not a field of BlockchainEngineXFixture, so the filler's hasattr(fixture, "post_state") guard never fired. It is now computed in BlockchainTest.make_hive_fixture through the new Alloc.calculate_diff() (moved out of filler.py) and is a required field.

Fixture index

  • TestCaseBase.fixture_hash and IndexFile.root_hash are Hash instead of HexNumber; hasher and compare_fixtures follow.
  • FixtureCollector writes index entries through TestCaseIndexFile instead of an ad-hoc dict.
  • HashableItem.from_folder no longer strips the first two characters of a hash unconditionally, which mis-parsed unprefixed generatedTestHash values into 31 bytes.

Compatibility

Group hashes change, so existing pre_alloc folders must be regenerated. Engine X fixtures and .meta/index.json files written by earlier versions no longer validate, since postStateDiff and fixture_hash are now required.

Related Issues or PRs

N/A.

Checklist

  • Ran fast static checks to avoid CI fails, see Code Standards & Verifying Changes: just static
  • PR title has the form <type>(<area>): <title>, where <type> and <area> come from an appropriate C-<type>, respectively A-<area>, label. The title should match the target squash commit message.

Cute Animal Picture

Put a link to a cute animal picture inside the parenthesis-->

@marioevz
marioevz requested a review from spencer-tb August 18, 2026 00:31
@codecov

codecov Bot commented Aug 18, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 91.33%. Comparing base (3d473e8) to head (e20e161).

Additional details and impacted files
@@                 Coverage Diff                 @@
##           forks/amsterdam    #3390      +/-   ##
===================================================
- Coverage            93.53%   91.33%   -2.21%     
===================================================
  Files                  624      624              
  Lines                37074    37074              
  Branches              3394     3394              
===================================================
- Hits                 34679    33863     -816     
- Misses                1645     2758    +1113     
+ Partials               750      453     -297     
Flag Coverage Δ
unittests 91.33% <ø> (-2.21%) ⬇️

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

☔ View full report in Codecov by Harness.
📢 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.

@danceratopz
danceratopz self-requested a review August 18, 2026 14:57
config = MockConfig(use_pre_alloc_groups=True)

# Mock the file system operations
group_hash = AllocGroupHash.from_hash("test_hash")

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

For reviewers: Maybe from_hash is not the best name for this function. It's supposed to mean "calculate the AllocGroupHash from sha56'ing the input, string or bytes, and then truncate".

@danceratopz danceratopz left a comment

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.

Thanks a lot for cleaning up the types here Mario 🙏

This looks good to me, just a few comments below. But I think we should align on a release strategy before merge.

If you're busy, I can PR the changes below; as you like.

pre_hash: AllocGroupHash
"""Hash of the pre-allocation group this test belongs to."""

post_state_diff: Alloc | None = None

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.

This change will break loading v20.0.0/v20.0.1. It would be nice to be stricter with these fields going forward, although adding an empty Alloc has little value.

From our side, this is currently only relevant for the generic test flow, I can fix that by pinning the EELS branch until the next release.

For client infra: The easiest solution to avoid breaking their infra would be to build and release v20.0.2 immediately after merging this and telling clients to update.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

I think we can do Alloc | None = None and then eventually remove the None once we've made enough releases with this field populated. Thanks for spotting this, I'll rollback the change!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

After some checking I've discovered that the pre-alloc groups in v20.0.0/v20.0.1 are broken anyway due to a bug introduced in #2140: They contain the "builder" variant and therefore do not include the genesis header in them, and the only way to ingest them is to load them using the builder's model and then build them internally, which is fine for consume, but if anyone wants to use them out-of-the-box it's very inconvenient.

It's possible to include a ton of workarounds in this PR to try to load the broken variants but I feel we are just digging ourselves in a deeper tech debt hole. I suggest we merge this PR with the strict models and then make the v20.1.0 release, stating that there are breaking changes in the format.

cc @danceratopz

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.

hasher still breaks by default with engine_x when ran as:

hasher compare <fill-a> <fill-b>

due to the presence of blockchain_tests_engine_x/pre_alloc/*.json. As we're touching hasher here anyway, we could consider excluding pre_alloc/. But very happy to do this as a follow-up!

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Very nice idea, I'll give it a go while time boxing it 👍

"groups, phase 2 generates all supported fixture formats."
),
)
test_group.addoption(

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.

We could consider adding a pytester test for invoking fill with this to pin the behavior down.

Comment on lines +31 to +32
"testCount": 88,
"preAccountCount": 174,

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.

These never got written to the JSON (pre-existing issue); they're only tracked internally in the in-memory PreAllocGroup. We should remove them here (consumers can use len(testIds) and len(pre).

Suggested change
"testCount": 88,
"preAccountCount": 174,

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

It's a bug, see #3390 (comment). Along with the genesis header, they are missing from v20.0.0/1.

Comment on lines +44 to +45
- **`testCount`**: Number of tests in this pre-allocation group
- **`preAccountCount`**: Number of accounts in the pre-allocation group

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.

They can be removed here, too.

Suggested change
- **`testCount`**: Number of tests in this pre-allocation group
- **`preAccountCount`**: Number of accounts in the pre-allocation group

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

See previous comment.

Comment thread packages/testing/src/execution_testing/fixtures/pre_alloc_groups.py Outdated
Comment thread packages/testing/src/execution_testing/cli/hasher.py Outdated
Comment thread packages/testing/src/execution_testing/cli/hasher.py Outdated
Comment thread packages/testing/src/execution_testing/cli/hasher.py Outdated
Comment thread packages/testing/src/execution_testing/cli/hasher.py Outdated
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.

2 participants