Test helpers `add_attested_block_at_slot` and `add_attested_blocks_at_slot` accepted `state_root` argument which was computed before applying the block.
Co-Authored-By: hopinheimer <knmanas6@gmail.com>
We got in a little bit of trouble in devnet-3. After gossip verifying an envelope and before importing it, we got the following error
```
May 07 08:04:24.383 WARN Execution payload envelope rejected reason: "EnvelopeProcessingError(WithdrawalsRootMismatch { state: 0x852d38aaecc9f4e2e309919f74020c7bbcf050fea4a20edf3304f171e44ee9d5, payload:
```
The envelope had already passed gossip verification checks and was correctly propagated to the network, we should not penalize peers for doing this. This caused our node to isolate itself from the rest of the network. This PR removes peer penalties for any envelope that passes gossip validation
Co-Authored-By: Eitan Seri-Levi <eserilev@ucsc.edu>
Part of #8828 for the stateful path and helps align gloas `produceBlockV4` with beacon-APIs [PR](https://github.com/ethereum/beacon-APIs/pull/580)
- Plumb `include_payload` query through the handler. Ignored for now since stateless mode isn't wired up yet
- Add `execution_payload_included` metadata field + `Eth-Execution-Payload-Included` header per spec. Both `false` until stateless lands
- Drop the `{builder_index}` segment from the envelope GET URL since no longer included in spec
Co-Authored-By: shane-moore <skm1790@gmail.com>
Co-Authored-By: Eitan Seri-Levi <eserilev@ucsc.edu>
The previous check triggered ParentEnvelopeUnknown for any block whose
parent didn't have its envelope received, even when the block's bid
didn't actually reference that parent's payload (e.g. building on
grandparent's execution state).
This caused a permanent stall when an envelope was rejected (e.g.
WithdrawalsRootMismatch from a buggy proposer): the parent's
payload_received stayed false, and all subsequent child blocks would
trigger infinite lookup retries for the broken envelope.
Fix: only require the parent's envelope if the block's bid
parent_block_hash matches the parent's execution_payload_block_hash,
meaning this block directly depends on the parent's payload.
When gloas envelopes are imported optimistically (EL returns SYNCING),
the payload status is Pending. Previously, Pending used
execution_payload_parent_hash for the head_hash in forkchoiceUpdated,
which tells geth to stay at the parent — never advancing.
Fix: use execution_payload_block_hash (the bid's committed hash) for
Pending status, same as Full. This tells geth to sync to the new head,
which is the purpose of optimistic sync. Geth will validate it and
transition from SYNCING to VALID on subsequent newPayload calls.
Also re-enables backfill sync for gloas with a dedicated
import_historical_gloas_block_batch that properly handles RangeSyncBlock::Gloas
variants (storing envelopes alongside blocks).
Remove the OptimisticSyncNotSupported check in into_executed_payload_envelope.
When the EL returns SYNCING (optimistic) for a payload envelope's newPayload
call, the envelope import should proceed rather than being rejected. This
commonly occurs after range sync imports blocks that the EL hasn't yet
validated - subsequent envelopes arriving via gossip would be rejected because
the EL is still catching up.
The downstream import path already handles optimistic status correctly:
- fork choice marks the payload as received regardless of EL status
- the payload_verification_status is propagated to SSE events/metrics
- if the payload is later found invalid, the normal invalidation mechanism
handles it (same as for blocks)
1. Remove on_valid_payload_envelope_received call before process_block
in chain segment import. The block isn't in fork choice yet, so it
always fails with NodeUnknown. import_envelope_from_range_sync
handles this correctly after process_block.
2. Disable backfill sync when GLOaS is scheduled. Backfill calls
into_available_block which panics on GLOaS RangeSyncBlock variant.
Backfill for GLOaS is not yet implemented.
Two fixes for GLOaS range sync:
1. DuplicateFullyImported: persist envelope for blocks that are already
in fork choice (e.g. post-checkpoint-sync blocks between finalized
and head).
2. load_parent: if parent envelope isn't in store, check if parent is
already in fork choice. If it is, the parent was already imported
and validated — proceed without requiring the envelope in store.
This handles the case where PayloadEnvelopesByRange doesn't return
envelopes for all blocks (fewer envelopes than blocks).
After checkpoint sync, blocks between the finalized checkpoint and head
are already in fork choice but their envelopes aren't in the store.
When range sync downloads these blocks, they get skipped as
DuplicateFullyImported without persisting the envelope. The next new
block then fails load_parent because it can't find its parent's envelope.
Fix: persist the envelope in the DuplicateFullyImported path, same as
the existing WouldRevertFinalizedSlot path.
We have a legacy `TestRandom` trait which generates random types for testing and fuzzing.
This function overlaps with `arbitrary` which is used very commonly in the ecosystem.
Remove `TestRandom` and generate random type instances using `Arbitrary`.
Co-Authored-By: Mac L <mjladson@pm.me>
Co-Authored-By: Michael Sproul <michael@sigmaprime.io>
Addresses issue #9220
The `payload_attestation_data` endpoint returns 400 when no block has been received for the requested slot. This causes the VC to log at CRIT level for what is expected behaviour per spec: validators should simply not submit a payload attestation when no block has been seen.
- Return 404 (Not Found) instead of 400 from `payload_attestation_data` when no block exists for the slot. This is consistent with other beacon api endpoints.
- Downgrade the VC log from `crit` to `debug` when a 503 is received, since this is an expected no-op per spec.
- Add `BlockNotFound` rejection type to `warp_utils`.
- Add a test asserting the 404 response for an empty slot.
Co-Authored-By: Josh King <josh@sigmaprime.io>
Co-Authored-By: Eitan Seri-Levi <eserilev@ucsc.edu>
Co-Authored-By: Jimmy Chen <jchen.tc@gmail.com>
Allow for the vc to submit its proposer preferences to the network
Co-Authored-By: Eitan Seri-Levi <eserilev@ucsc.edu>
Co-Authored-By: Jimmy Chen <jchen.tc@gmail.com>
Fixes a flaky CI failure in `data_column_reconstruction_at_deadline` where 2 `column_reconstruction` events are emitted instead of the expected 1.
- Change `queued_column_reconstructions` from `HashMap<Hash256, DelayKey>` to `HashMap<Hash256, Option<DelayKey>>`, where `None` indicates reconstruction was already dispatched.
- On dispatch (`ReadyColumnReconstruction`), set the entry to `None` instead of removing it. This prevents a subsequent gossip column from inserting a fresh reconstruction request into the now-vacant slot.
- Prune stale `None` entries on each dispatch to keep the map bounded.
Co-Authored-By: Josh King <josh@sigmaprime.io>
- Avoid sending 0x00 block hashes for the safe and finalized block hashes post-Gloas.
- Add code to check this inside the mock EL, which will be reached in all Gloas beacon chain tests
Co-Authored-By: Michael Sproul <michael@sigmaprime.io>