Skip to content

[bal-devnet-3] execution/state: don't seed initial BAL balance from post-write reads#20864

Merged
mh0lt merged 2 commits intobal-devnet-3from
cp/20843-to-bal-devnet-3
Apr 28, 2026
Merged

[bal-devnet-3] execution/state: don't seed initial BAL balance from post-write reads#20864
mh0lt merged 2 commits intobal-devnet-3from
cp/20843-to-bal-devnet-3

Conversation

@mh0lt
Copy link
Copy Markdown
Contributor

@mh0lt mh0lt commented Apr 28, 2026

Cherry-pick of #20843 to bal-devnet-3.

yperbasis and others added 2 commits April 28, 2026 08:40
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>
@mh0lt mh0lt requested a review from yperbasis as a code owner April 28, 2026 08:41
@mh0lt mh0lt merged commit 2f80e1f into bal-devnet-3 Apr 28, 2026
1 check failed
@mh0lt mh0lt deleted the cp/20843-to-bal-devnet-3 branch April 28, 2026 09:03
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