Skip to content

Yperbasis/test20843#20844

Draft
yperbasis wants to merge 185 commits intomainfrom
yperbasis/test20843
Draft

Yperbasis/test20843#20844
yperbasis wants to merge 185 commits intomainfrom
yperbasis/test20843

Conversation

@yperbasis
Copy link
Copy Markdown
Member

No description provided.

yperbasis and others added 30 commits March 26, 2026 08:45
…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
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>
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