ChainSafe / ChainSafe/lodestar

Track blinded payload-envelope storage + EL-backed sync serving (incl. BAL restore)

Open
#9,282 2 comments 0 reactions 0 assignees View on GitHub
spec-gloas
Dominant language
TypeScript
Stars
1.4k
Forks
483
Avg merge
1d 16h
Merged PRs (30d)
150

Description

## Problem
We already know Lodestar should avoid persisting duplicate full execution payload bodies on the CL side and instead keep a blinded representation + reconstruct the missing EL-side body data on demand.

There is already a broad tracking issue for the storage dedup idea:
- #5671 `De-duplicate payload from persisted beacon blocks`

But we should keep a **more specific pre-testnet reminder** for the serve path:

> if Lodestar stores the execution payload envelope / block in blinded form, it must still be able to serve peers correctly during sync (especially `beacon_blocks_by_range` / `beacon_blocks_by_root` style serving), reconstructing the missing execution payload body data from EL and restoring any Gloas-specific fields such as BAL before serving.

Terence warned that Prysm hit a late bug in this area: they were not unblinding / re-adding BAL correctly when serving to peers.

## Why this needs a dedicated reminder
This can easily be missed if we only test:
- local import / processing
- proposer-side flows
- REST full-block reconstruction

The tricky part is the **sync serving** path:
- range sync serving works
- block/root serving works
- the served payload is reconstructed from EL correctly
- BAL / other body-only fields are restored correctly before serving
- peers can consume the served block/payload without blinded/full mismatch bugs

## Prysm reference points
I could not cleanly pull the exact `ethpandaops/prysm:glamsterdam-devnet-0` branch into the local checkout, but the current local Prysm repo already shows the relevant shape:

### 1. Store the envelope in blinded form
`beacon-chain/db/kv/execution_payload_envelope.go`
- `SaveExecutionPayloadEnvelope()` replaces the full payload with its `blockHash`
- keeps metadata like `executionRequests`, `builderIndex`, `beaconBlockRoot`, `slot`, `stateRoot`
- comment explicitly says the full payload can later be retrieved from EL via `engine_getPayloadBodiesByHash`

### 2. Reconstruct full payload bodies from EL on demand
`beacon-chain/execution/payload_body.go`
- `reconstructBlindedBlockBatch()`
- `requestBodiesByHash()` using `engine_getPayloadBodiesByHashV1`
- fallback `requestBodiesByRange()` using `engine_getPayloadBodiesByRangeV1`
- `fullPayloadFromPayloadBody()` rebuilds the full execution payload from the blinded header + EL body data

### 3. Use reconstructed full blocks for serving/API paths
`beacon-chain/rpc/eth/beacon/handlers.go`
- `GetBlockV2()` reconstructs the full block when the stored block is blinded:
- `ExecutionReconstructor.ReconstructFullBlock(ctx, blk)`

## Lodestar context
Lodestar already has the relevant TODO in:
- `packages/beacon-node/src/chain/blocks/writePayloadEnvelopeInputToDb.ts`

```ts
// TODO GLOAS: Persist envelope metadata (stateRoot, executionRequests, builderIndex, etc.) without the full
// execution payload body — only keep the blockHash reference. The EL already stores the payload.
// See https://github.com/ChainSafe/lodestar/issues/5671
```

Lodestar also already has EL payload body fetch methods:
- `packages/beacon-node/src/execution/engine/http.ts`
- `getPayloadBodiesByHash()`
- `getPayloadBodiesByRange()`

## Requested work / acceptance criteria
Before testnets, we should make sure Lodestar either implements or explicitly tests the full serve path for blinded envelope storage:

- [ ] Persist execution payload envelope / block metadata in blinded form without duplicating the full EL body
- [ ] Reconstruct missing execution payload body data from EL when serving full data back out
- [ ] Verify `beacon_blocks_by_range` serving works
- [ ] Verify `beacon_blocks_by_root` serving works
- [ ] Verify Gloas-specific body fields (including BAL) are restored correctly before serving
- [ ] Add a mixed-client interop / regression test so we do not repeat Prysm's late unblinding/BAL serve bug

## Related
- #5671 `De-duplicate payload from persisted beacon blocks`

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.