Skip to content

Validate bid gas limit against the payload at bid.parent_block_hash - #864

Merged
hangleang merged 1 commit into
grandinetech:glamsterdam-devnet-8from
barnabasbusa:bbusa/bid-gas-limit-parent-hash
Aug 26, 2026
Merged

Validate bid gas limit against the payload at bid.parent_block_hash#864
hangleang merged 1 commit into
grandinetech:glamsterdam-devnet-8from
barnabasbusa:bbusa/bid-gas-limit-parent-hash

Conversation

@barnabasbusa

Copy link
Copy Markdown
Contributor

What

Store::validate_execution_payload_bid derived parent_gas_limit from state_at(bid.parent_block_root).latest_execution_payload_bid().gas_limit — the parent block's own bid — regardless of which payload the bid builds on. The spec keys the check on the payload the bid actually extends:

parent_gas_limit = seen.execution_payloads[bid.parent_block_hash].gas_limit

(https://github.com/ethereum/consensus-specs/blob/a670e0193446474bb1775ec94a93ca6fbaa11a89/specs/gloas/p2p-interface.md#L995-L1000)

A bid with parent_block_root = head and parent_block_hash = head_bid.parent_block_hash (head payload treated as withheld — which is_bid_compatible_with_head permits when should_build_on_full is false) must be checked against the grandparent payload's gas limit. Whenever the gas limit is moving, that differs from the head bid's gas limit by one EIP-1559 step, so a spec-correct bid was dropped with bid gas_limit is not compatible with target_gas_limit — on gossip, and via POST /eth/v1/beacon/execution_payload_bids, where it results in a 200 with an Ignore and no broadcast.

This PR resolves the chain link carrying the payload identified by bid.parent_block_hash through the existing execution_payload_locations index (replacing the bare contains_key existence check) and uses the gas limit committed by that block: its bid post-Gloas, the execution payload itself for a pre-Gloas block at the fork boundary. Envelopes must match their bid's gas_limit (already enforced at envelope processing), so the bid value is the payload value. ExecutionPayload::gas_limit is added to the trait for the pre-Gloas case.

Why

Seen on glamsterdam-devnet-8 (gas limit ramping under EIP-8261). Slot 85165: payload at 85163 had gas limit 199411976, payload at 85164 (head) had 199606713, target 200000000. A builder's parent-empty bid carried 199606713 = 199411976 + 199411976/1024 − 1, correct for the payload it builds on; comparing against the head bid (199606713) makes it look like it failed to step toward the target.

Same class of bug was found in prysm (OffchainLabs/prysm#17405), lighthouse (sigp/lighthouse#9905) and nimbus (status-im/nimbus-eth2#8941); lodestar and teku are correct. The spec gossip test vectors don't cover empty-head bids yet (every case uses the head's own payload as parent_block_hash); a vector PR is in progress.

Testing

cargo check / cargo clippy -p grandine --no-default-features --features default-networks,bls/blst,kzg_utils/blst and cargo fmt --check on the changed crates. Targeting glamsterdam-devnet-8 per the devnet image; happy to retarget or forward-port.

validate_execution_payload_bid derived parent_gas_limit from the parent
block's post-state latest_execution_payload_bid, i.e. the parent block's own
bid, regardless of which payload the bid builds on. The spec keys
parent_gas_limit on bid.parent_block_hash: a bid that builds on the parent's
parent payload (parent payload withheld) must be checked against that
payload's gas limit, which differs from the parent bid's gas limit whenever
the gas limit is moving. Such bids were dropped with "bid gas_limit is not
compatible with target_gas_limit" on gossip and via the publish REST
endpoint (200 + Ignore, never broadcast).

Resolve the chain link carrying the payload identified by
bid.parent_block_hash (the existing execution_payload_locations index) and
use the gas limit committed by that block: its bid post-Gloas, the payload
itself pre-Gloas. Adds ExecutionPayload::gas_limit for the latter.
@hangleang
hangleang merged commit 9d22f7c into grandinetech:glamsterdam-devnet-8 Aug 26, 2026
1 of 9 checks passed
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