Conversation
…20041) ## Summary - Fix `eth_getBlockReceipts` returning one fewer receipt than expected when the parallel executor (`Exec3Parallel=true`) is active - Root cause: the block-finalize `txResult` in the parallel executor reuses the system-tx-end's `txNum`, causing a second `DomainPut` on the RCacheDomain that overwrites the history entry preserving the last regular transaction's receipt - Tag the block-finalize `txResult` and skip the receipt-cache write for it ## Details The parallel executor sends two `txResult` entries at the same `txNum` to the apply loop: 1. The system-tx-end result (from the per-task publish loop) 2. The block-finalize result (from `processResults`, carrying `engine.Finalize` writes) Both trigger `WriteReceiptCacheV2(nil, lastTxNum)`. The first write correctly stores the previous value (the last regular tx's receipt) in domain history. The second write looks up the current value (now empty), and overwrites the history entry with empty — destroying the receipt. `ReadReceiptsCacheV2` then finds only 5 non-empty history entries instead of 6, and `GetReceipts` returns them without checking completeness. ## Test plan - [x] `make lint` clean - [x] `make erigon` builds - [x] Hive `rpc/compat` suite passes (previously failing `eth_getBlockReceipts/get-block-receipts-latest`): https://github.com/erigontech/erigon/actions/runs/23361325617 - [x] All 6 hive test suites green 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…Parallel=true - Always use finalizeWithIBS in parallel executor (the finalizeTx fast path produced incorrect state roots for non-Amsterdam blocks — regression from #20042) - Gate ProcessBAL and block assembler BAL IO on IsAmsterdam only - Simplify ProcessBAL signature (caller already gates on IsAmsterdam) - Create versionMap in GenerateChain for Amsterdam blocks regardless of Exec3Parallel, so BAL access tracking works during serial block generation - Default Exec3Parallel=true - Skip TestGeneratedTraceApiCollision with parallel (intra-block SELFDESTRUCT + CREATE2 reincarnation — fixed on exec3/remove-rwtx-threading branch) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… ordering
The `defer roTx.Rollback()` in updateForkChoice captured the interface
value at defer-registration time. When the CommitCycle callback
reassigned roTx to a new transaction, the defer still held the old
(already-rolled-back) value, leaking the new roTx and causing
waitTxsAllDoneOnClose to hang forever during test cleanup.
Fix: use a closure `defer func() { roTx.Rollback() }()` so the defer
captures roTx by reference and always rolls back the latest transaction.
Additionally:
- Move bgComponentsEg.Wait() before chainDB.Close() in Ethereum.Stop()
so background goroutines release DB transactions before the DB closes.
- Add ExecModule.WaitIdle() to wait for in-flight updateForkChoice
goroutines via the semaphore before closing the DB.
- Add WaitForWarmup() to wait for fire-and-forget read-ahead warmup
goroutines that hold DB transactions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
# Conflicts: # execution/exec/block_assembler.go
# Conflicts: # execution/execmodule/execmoduletester/exec_module_tester.go
# Conflicts: # execution/stagedsync/exec3_parallel.go # execution/tests/blockgen/chain_makers.go
# Conflicts: # execution/stagedsync/bal_create.go
Align bal-devnet-3 with main — the fork-gating booleans were lost during the last merge, causing hive tests to fail with "missing block access list hash" on pre-Amsterdam blocks. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
bal-devnet-3 intentionally defaults ExperimentalBAL to true; update assertions to match. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Same merge-conflict loss as ProcessBAL — the || cfg.ExperimentalBAL condition was dropped, so experimental-only chains skipped BAL assembly. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
# Conflicts: # execution/stagedsync/bal_create.go
…)" This reverts commit c9833c4.
The parallel executor's block-end finalize creates a fresh IBS (unlike the assembler which reuses the same IBS with cached state objects). This fresh IBS generates BalancePath reads for accounts that were already written during the same block — the initialize-phase system calls (EIP-4788 beacon root, EIP-2935 history storage), the burnt contract (EIP-1559 base-fee burn), or any account whose tx-1 write was pre-populated into the version map from a stored BAL sidecar in the chain-tip FCU validation path. These post-write reads were treated as the "initial" (pre-block) balance by `updateRead`, so `applyToBalance`'s net-zero filter would later drop the legitimate write whose value happened to equal the post-write read. The block's computed BAL hash then disagreed with the header-attested BAL hash, putting the node in an unrecoverable retry loop on the offending payload. Tighten the guard to only set `initialBalanceValue` from a balance read that arrives BEFORE any balance writes have been recorded. Reads arriving after a write reflect post-write state and cannot be used as a pre-block reference. Reproduced on bal-devnet-3 at block 91648 where the node looped on "BAL mismatch: got 0x973750... expected 0xff40db...". The diff was a single missing entry: balanceChanges=[1:0x16eaeb76] for the zero address (the EIP-1559 burnt contract on this devnet). The fresh IBS read at finalize observed the value already pre-populated from the sidecar BAL for tx 1 (0x16eaeb76), set initialBalanceValue to that, and the net-zero filter then dropped the very write whose value the read had borrowed. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…oning Captures the bal-devnet-3 block-91648 BAL hash mismatch in a single-file test: a balance write at txIndex=1 followed by a later BalancePath read of the same value (the pattern emitted by the parallel executor's fresh-IBS finalize, or by a BAL-prepopulated read of a tx's predicted write). Without the previous commit's `updateRead` guard, the late read seeds `initialBalanceValue` and `applyToBalance`'s net-zero filter then drops the legitimate write — the exact symptom that put `lighthouse-erigon-super-1` into a retry loop on the offending payload. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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.
No description provided.