miner: supply a slot number when synthesising pending block post-Amsterdam - #34792
Merged
fjl merged 1 commit intoMay 28, 2026
Merged
Conversation
…erdam getPending builds the pending block on demand via generateWork, but after EIP-7843 (ethereum#33589) prepareWork rejects the call unless generateParams.slotNum is non-nil once Amsterdam is active: if miner.chainConfig.IsAmsterdam(header.Number, header.Time) { if genParams.slotNum == nil { return nil, errors.New("no slot number set post-amsterdam") } header.SlotNumber = genParams.slotNum } getPending never populated slotNum, so on any Amsterdam-activated chain eth_getBalance(addr, "pending") (and every other RPC that resolves through the pending state) fails with "pending state is not available", breaking faucets and nonce trackers that poll pending. Fix by synthesising a slot number from the parent header when available, mirroring how the Shanghai branch above already conditionally populates withdrawals. The pending block is empty post-merge so the exact slot value is not user-visible; SlotNumber+1 (or zero) is sufficient to satisfy the prepareWork invariant. Observed on a bal-devnet-3 Geth build: every eth_getBalance(...,"pending") returned -32000 "pending state is not available" until the faucet was repointed at a non-Geth EL. Other clients (Nethermind, Besu, Reth, Erigon, Ethrex) serve pending on the same chain without issue.
barnabasbusa
requested review from
MariusVanDerWijden,
fjl and
rjl493456442
as code owners
April 22, 2026 12:19
5 tasks
Member
Author
1 similar comment
Member
Author
fjl
approved these changes
May 28, 2026
rjl493456442
approved these changes
May 28, 2026
0xjvn
pushed a commit
to 0xjvn/go-ethereum
that referenced
this pull request
Jun 5, 2026
gballet
pushed a commit
to gballet/go-ethereum
that referenced
this pull request
Jun 12, 2026
AdityaSripal
pushed a commit
to AdityaSripal/go-ethereum
that referenced
this pull request
Jun 21, 2026
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
miner.getPending()builds the pending block on demand viagenerateWork. After EIP-7843 landed in #33589,prepareWorkrejects the call unlessgenerateParams.slotNumis non-nil once Amsterdam is active:getPendingwas never updated to populateslotNum, so on any Amsterdam-activated chain every RPC that resolves through the pending state will fail:This breaks faucets, nonce trackers, gas estimators, simulators — anything polling
pending.Why this is latent on master today
Amsterdam isn't activated on any production chain yet, so
IsAmsterdamreturns false and the guard is skipped. The bug is sitting there waiting to bite every Geth deployment the moment Amsterdam is turned on. Already visible onbal-devnet-3andglamsterdam-devnet-0devnet builds.Fix
Mirror the existing Shanghai branch above: when Amsterdam is active for the next block, synthesise a slot number from the parent header (
header.SlotNumber + 1, falling back to0when unset) and pass it throughgenerateParams. The pending block is empty post-merge (see #28440), so the exact slot value is not user-observable — it just has to satisfyprepareWork's invariant.+16/-3 in a single file.
Reproduction & verification
Reproduced on a Kurtosis enclave running two EL nodes on the same Amsterdam-active chain (block
0x12402, slot0x1870e):c30c846ceth_getBalance(addr, "latest")0xb37ea690xb37ea69eth_getBalance(addr, "pending")-32000 "pending state is not available"0xb37ea69eth_call({...}, "pending")-32000 "pending state is not available"0xeth_getBlockByNumber("pending", ...)-32000 "pending block is not available"eth_getTransactionCount(addr, "pending")0x0(txpool path)0x0Balances at
latestidentical on both nodes, confirming this is a pure fallback-path fix, not papering over state divergence.Other ELs on the same chain (Nethermind, Besu, Reth, Erigon, Ethrex) serve
pendingwithout issue — Nethermind aliasespending → head(BlockTree.PendingHash => Head?.Hash), so its engine-API slotnum enforcement is never reached from RPC.Test plan
go build ./miner/...go test ./miner/...(existing suite passes)go vet ./miner/...getPendingunder Amsterdam — happy to follow up if reviewers want one; the existingminer_test.godoesn't currently exercise pending post-fork and I didn't want to balloon the diffCompanion PRs
bal-devnet-3glamsterdam-devnet-0If preferred, those two can be dropped in favour of just merging this one and letting the devnet branches pull master.
Blame
Introduced by #33589 (EIP-7843 SLOTNUM, merged 2026-02-26). That PR added the
slotNum == nil → errorguard inprepareWorkbut didn't touchminer/miner.go, leavinggetPendingas the only caller that doesn't supply a slot.