feat: add EIP-7864 binary trie mode for state generation#1
Closed
CPerezz wants to merge 3 commits into
Closed
Conversation
Add --binary-trie flag to generate state using the EIP-7864 binary trie instead of the default Merkle Patricia Trie. This enables testing geth devnets with binary trie state (--override.verkle=0). Key changes: - Add TrieMode type and --binary-trie CLI flag - Implement writeStateBinaryTrie() using bintrie.BinaryTrie API - Extract batchWriter type to deduplicate batch writing infrastructure - Extend WriteGenesisBlock with binaryTrie parameter - Update integration scripts for binary trie support - Add "Trie Modes" section to README The binary trie uses a single global tree (no per-account storage subtries), so Account.Root is always EmptyRootHash in snapshot entries.
- TestGenerateBinaryTrie: basic generation + cross-mode root comparison - TestDatabaseContentBinaryTrie: snapshot prefixes + EmptyRootHash invariant - TestBinaryTrieReproducibility: deterministic roots with same seed - TestBinaryTrieStateRootValue: golden value test for upstream API changes - TestWriteGenesisBlockBinaryTrie: EnableVerkleAtGenesis persisted - TestEndToEndWithGenesisBinaryTrie: full workflow e2e test - TestGenesisAccountsIntegrationBinaryTrie: genesis alloc in binary trie mode
- Propagate rlp.EncodeToBytes error from encodeStorageValue instead of silently discarding it - Add sync.Once-guarded close() method to batchWriter preventing goroutine leaks on error paths - Log dropped batch worker errors instead of silently swallowing them - Sort storage keys in writeStateBinaryTrie for deterministic snapshot writes - Use local chainCfg variable in WriteGenesisBlock to avoid mutating caller's *Genesis struct - Reject unknown TrieMode values in New() and writeState() instead of silently defaulting to MPT - Use named return in writeStateBinaryTrie to propagate trieDB.Close() errors - Fix inaccurate "SHA256-based" comment on TrieModeBinary - Add regression test for WriteGenesisBlock non-mutation - Add EnableVerkleAtGenesis=false assertion for MPT genesis path
CPerezz
pushed a commit
that referenced
this pull request
Feb 13, 2026
feat: add EIP-7864 binary trie mode for state generation
CPerezz
added a commit
that referenced
this pull request
Apr 29, 2026
…refresh stale claims
Pure-doc pass following the pr-review-toolkit comment-analyzer
re-review. No behaviour change.
client/nethermind/doc.go: replaced 'PR#3 stage 2 scaffold (this commit)'
Status block (which still claimed run_cgo.go returns a wiring-only
error) with the current shipping description. Pin section now points
at internal/neth/ for the SHA-09bd5a2d wire-format reference and at
nethermind/nethermind:1.37.0 for what smoke + oracle actually run.
client/nethermind/run_cgo.go: file header dropped the 'Phase A (this
commit) / Phase B (next commit)' framing in favour of describing
the three live dispatch paths (empty alloc, genesis-alloc only,
synthetic + optional genesis-alloc) and linking to issue ethereum#22 for
the storage-bearing genesis + synthetic combination. runImpl doc
now lists the actual 6-step pipeline and labels ctx/opts as
reserved-for-future-wiring.
client/nethermind/genesis_alloc_cgo.go: stateDBSink doc now points
at 'internal/neth/trie.Builder' instead of the planning-doc 'B4'
tag. writeGenesisAllocAccounts's parameter doc reworded
to drop the misleading 'legacy callers' framing.
client/nethermind/dbs_cgo.go: '5+ separate Put calls' → '5 separate
Put calls' (matches genesis_cgo.go's exact-count phrasing).
docs/superpowers/specs/2026-04-28-nethermind-implementation-notes.md:
blockNumbers wire-format gotcha #1 now reads as past tense ('an
earlier revision … was wrong') with the fix-commit reference; the
pipeline diagram and smoke-evidence section drop the 'Phase A /
Phase B' labels in favour of empty-alloc / genesis-alloc /
synthetic which describe what actually shipped.
CPerezz
added a commit
that referenced
this pull request
May 3, 2026
…refresh stale claims
Pure-doc pass following the pr-review-toolkit comment-analyzer
re-review. No behaviour change.
client/nethermind/doc.go: replaced 'PR#3 stage 2 scaffold (this commit)'
Status block (which still claimed run_cgo.go returns a wiring-only
error) with the current shipping description. Pin section now points
at internal/neth/ for the SHA-09bd5a2d wire-format reference and at
nethermind/nethermind:1.37.0 for what smoke + oracle actually run.
client/nethermind/run_cgo.go: file header dropped the 'Phase A (this
commit) / Phase B (next commit)' framing in favour of describing
the three live dispatch paths (empty alloc, genesis-alloc only,
synthetic + optional genesis-alloc) and linking to issue ethereum#22 for
the storage-bearing genesis + synthetic combination. runImpl doc
now lists the actual 6-step pipeline and labels ctx/opts as
reserved-for-future-wiring.
client/nethermind/genesis_alloc_cgo.go: stateDBSink doc now points
at 'internal/neth/trie.Builder' instead of the planning-doc 'B4'
tag. writeGenesisAllocAccounts's parameter doc reworded
to drop the misleading 'legacy callers' framing.
client/nethermind/dbs_cgo.go: '5+ separate Put calls' → '5 separate
Put calls' (matches genesis_cgo.go's exact-count phrasing).
docs/superpowers/specs/2026-04-28-nethermind-implementation-notes.md:
blockNumbers wire-format gotcha #1 now reads as past tense ('an
earlier revision … was wrong') with the fix-commit reference; the
pipeline diagram and smoke-evidence section drop the 'Phase A /
Phase B' labels in favour of empty-alloc / genesis-alloc /
synthetic which describe what actually shipped.
CPerezz
added a commit
that referenced
this pull request
May 13, 2026
…invariant for free Replaces the parallel TestE2ESuiteSpec approach with the design the user asked for: each existing per-client TestE2ESuite drives its Config.PreAlloc from the same shared spec YAML. The existing cross-client-genesis-root aggregator job thus becomes the spec-driven invariant automatically (no new job, no new aggregator). Key change: cfg.InjectAddresses[SpamoorSenderAddr] removed from every client's e2e test. The spamoor sender is now entity #1 in the spec YAML, funded with 999_999_999 ETH. All other v1 schema variants land in the same YAML so every flavor is exercised through writer → boot → spamoor → RPC re-query → golden-hash on every client. Why this is robust across clients: - sizecal.NewFixed(64) (hardcoded in the shared helper) neutralizes per-client calibration divergence (geth=64, besu=64, neth=80, reth=60). Same YAML → same PreAlloc → same state root. - materializePreAlloc shim folds PreAlloc into the legacy GenesisAccounts/Code/Storage maps before any per-client writer runs, so the four writers all see identical input. - CheckInjections (Phase 4 RPC re-query) walks cfg.GenesisAccounts for balance verification (new) and cfg.GenesisCode for bytecode verification (existing). Every spec entity is RPC-asserted at runtime. Files changed: - examples/spec-ci-baseline.yaml: rewritten as the rich CI fixture (~12 entities: spamoor sender + 5 ERC-20 flavors + 2 raw + 2 7702 EOAs + 3 plain EOAs). Covers explicit/name-derived/position-derived addresses, `holders` parameter, `approximate_size_bytes`, explicit `nonce` override, 7702 markers, storage bloat, skeleton-only ERC-20. - examples/spec-ci-min.yaml: deleted (consolidated into baseline). - internal/e2e_testing/spec_setup.go: new LoadCISpecPreAlloc helper. Uses sizecal.NewFixed(64); shared by all 4 client tests. - internal/e2e_testing/spec_setup_test.go: TestCISpecMatchesSpamoorSender pins the YAML's spamoor entity to oracle.SpamoorSenderAddr (catches silent drift between YAML and devkeys.go). - internal/e2e_testing/check_entities.go: CheckInjections now also walks cfg.GenesisAccounts for eth_getBalance assertions on every non-zero-balance spec entity (spamoor sender + plain EOAs + 7702 EOAs). - client/{geth,besu,nethermind,reth}/{e2e_test,oracle_test}.go: - Drop `InjectAddresses: []common.Address{oracle.SpamoorSenderAddr},` - Add `PreAlloc: e2e.LoadCISpecPreAlloc(t, ".../spec-ci-baseline.yaml", "<client>")` - Drop now-unused common.Address import. - Keep oracle.AddPragueSystemContracts (system contracts are infrastructure, not feature-under-test). - Keep --accounts/--contracts synthetic-fill (state warmup unchanged). Reverts the previous geth-only TestE2ESuiteSpec (was the wrong shape). docs/SPEC.md + CHANGELOG.md: updated to describe the new design. go vet + go build + go test -short ./... green across the tree.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
--binary-trieflag to generate state using the EIP-7864 binary trie instead of the default Merkle Patricia Trie (MPT)batchWritertype to eliminate batch-writing duplication between MPT and binary trie paths--binary-trieCLI flagCommit breakdown
feat: add EIP-7864 binary trie mode— core implementation:writeStateBinaryTrie,batchWriterextraction, CLI flag, genesis integration, shell/Kurtosis scripts, READMEtest: add comprehensive binary trie test coverage— 7 new test functions covering generation, DB content, reproducibility, golden value pinning, genesis integration, and e2efix: address PR review findings— error propagation inencodeStorageValue, goroutine leak prevention viasync.Once-guardedbatchWriter.close(), deterministic storage key sorting,WriteGenesisBlocknon-mutation fix,TrieModevalidation, named return fortrieDB.Close()error propagation, regression tests