feat: gloas range sync#9242
Conversation
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Nico Flaig <nflaig@protonmail.com>
Implement the `should_apply_proposer_boost` logic from consensus-specs commit 71d1151 (PR #4807). This addresses the builder reveal safety concern where a colluding next-slot proposer could use proposer boost to override a legitimately revealed block. Changes: - Add `ptcTimeliness` and `proposerIndex` fields to ProtoBlock - Add `isBlockPtcTimely` to track PTC deadline timeliness - Add `shouldApplyProposerBoost` which withholds boost when the parent is a weak, equivocating block from the previous slot - Add `findEquivocatingBlocks` in ProtoArray to detect proposer equivocations by scanning for PTC-timely blocks at the same slot from the same proposer - Gate proposer boost in `getWeight` on `shouldApplyProposerBoost()` - Pre-gloas blocks retain unconditional boost (backward compatible) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…cs#5094) - Add executionRequestsRoot to ExecutionPayloadBid - Remove stateRoot from ExecutionPayloadEnvelope - Add parentExecutionRequests to BeaconBlockBody Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…eturn New function implements deferred parent execution payload processing (consensus-specs#5094). Moves execution requests, builder payment, and availability updates from envelope processing to block processing. Removes the isParentBlockFull early return in processWithdrawals since processParentExecutionPayload now runs before withdrawals. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…lock New ordering for Gloas blocks: 1. processParentExecutionPayload (NEW - before header) 2. processBlockHeader 3. processWithdrawals (no longer has empty-parent early return) 4. processExecutionPayloadBid 5. ... rest unchanged Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Envelope verification no longer mutates state. All state effects (execution requests, builder payment, availability, latestBlockHash) have moved to processParentExecutionPayload in the next block. Changes: - Remove state cloning, execution request processing, builder payment, availability/latestBlockHash updates, and state root verification - Add executionRequestsRoot check against bid commitment - Return void instead of post-state - Remove verifyStateRoot and dontTransferCache options - Rename stateView method to verifyExecutionPayloadEnvelope Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…onPayload With deferred payload processing, the envelope no longer produces a separate post-state. The FULL variant node shares the same stateRoot as the PENDING node. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- importExecutionPayload now does pure verification only — no state cloning, no post-payload state computation, no state root check, no regen.processState(), no checkpoint caching - Remove stateRoot from executionPayload and executionPayloadGossip events - Remove stateRoot from envelope construction in validator API - Remove stateRoot from fork choice onExecutionPayload call - Envelope verification runs via verifyExecutionPayloadEnvelope (void) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…rocessing Block production: - Add executionRequestsRoot to ExecutionPayloadBid construction - Add parentExecutionRequests to BeaconBlockBody via getParentExecutionRequests() - Add getParentExecutionRequests() to BeaconChain (returns parent's execution requests from cached envelope, or empty if EMPTY parent) Gossip validation: - Add executionRequestsRoot check in envelope validation - Add EXECUTION_REQUESTS_ROOT_MISMATCH error code Cleanup: - Remove stateRoot from validator envelope logging - Fix spec test for void-returning processExecutionPayloadEnvelope - Update stale TODO comment in writePayloadEnvelopeInputToDb Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use electra.ExecutionRequests type instead of unknown[] - Fix parentBlockRootHex -> parentBlock.blockRoot variable name Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Range sync now fetches and validates execution payload envelopes alongside blocks for Gloas forks. With deferred processing, blocks can sync optimistically without envelopes, but envelopes are fetched in parallel for fork-choice FULL/EMPTY variant accuracy. Changes: - Batch carries payloadEnvelopes across all state transitions - downloadByRange fetches envelopes via sendExecutionPayloadEnvelopesByRange - validateEnvelopesByRangeResponse verifies beaconBlockRoot matches blocks - processChainSegment accepts payloadEnvelopes parameter - SyncChainFns types updated for envelope data flow - Add INVALID_ENVELOPE_BEACON_BLOCK_ROOT error code Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When a gossip block claims its parent was FULL but the parent's envelope hasn't been seen, the block is queued and the parent envelope is fetched via sendExecutionPayloadEnvelopesByRoot. Changes: - Add PARENT_PAYLOAD_UNKNOWN block error code and gossip validation - Add PendingPayloadEnvelope type for tracking missing envelopes - BlockInputSync: pendingPayloads map, triggerPayloadSearch, fetchPayloadEnvelope, onUnknownPayloadEnvelope handler - Subscribe to unknownEnvelopeBlockRoot and executionPayloadAvailable events - Add metrics for payload fetch tracking - Handle PARENT_PAYLOAD_UNKNOWN in processBlock error recovery Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Handle both Fulu and Gloas column shapes in validateColumnsByRangeResponse. Fulu columns use signedBlockHeader.message.slot, Gloas columns use slot directly. Dispatch to validateGloasBlockDataColumnSidecars vs validateFuluBlockDataColumnSidecars based on fork. Gloas columns in cacheByRangeResponses are skipped (routed to PayloadEnvelopeInput by the caller, not to IBlockInput). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Only check payload-seen when block is known; unknown blocks are handled later by verifyHeadBlockAndTargetRoot which enables the API retry path for unknown roots - Use chain.seenPayloadEnvelope which checks both the gossip cache (seenPayloadEnvelopeInputCache) and fork choice FULL variant Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move slot from ExecutionPayloadEnvelope to ExecutionPayload as slotNumber (uint64) and add slotNumber to PayloadAttributes per consensus-specs#4840. Updates all verification, gossip validation, signing, serialization, and SSZ byte extraction accordingly. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ibe-te/range_sync
There was a problem hiding this comment.
Code Review
This pull request implements deferred payload processing and data availability handling for the Gloas fork. Key changes include refactoring the block and envelope import paths to be independent, updating range sync to manage payload envelopes alongside blocks, and adjusting caching strategies to ensure consistency across the execution hash chain. Feedback focuses on an inconsistency in warning reporting for orphaned envelopes at the start of a chain segment and potential queue saturation risks in the payload envelope processor due to increased residency time for incomplete envelopes.
| if (lastFullSlot !== null && payloadEnvelopes !== null) { | ||
| const orphanedInput = payloadEnvelopes.get(lastFullSlot); | ||
| if (orphanedInput != null) { | ||
| warnings.push({slot: lastFullSlot, payloadEnvelopeInput: orphanedInput}); | ||
| } | ||
| } |
There was a problem hiding this comment.
The warning for an orphaned payload envelope is only pushed if lastFullSlot is not null. However, if the very first block in the segment (i=0) has a bid.parentBlockHash mismatch with the parentBlock.executionPayloadBlockHash, lastFullSlot will be null and no warning will be recorded, even though the recovery logic currentExecHash = prevExecHash still executes. While this might be rare if sanity checks pass, it's inconsistent with how subsequent mismatches are handled.
3b7e592 to
89e60ae
Compare
Motivation
test/e2e/sync/finalizedSync.test.tspassing end-to-end: Node B range-syncs across the fulu→gloas fork boundary and reaches Node A's head.Description
Range sync for gloas
processChainSegmentcarriesMap<Slot, PayloadEnvelopeInput>end-to-end through batch → chain → block processor.cacheByRangeResponsesbuildsPayloadEnvelopeInputwrappers from downloaded envelopes + columns and seedsseenPayloadEnvelopeInputCache.assertLinearChainSegmentported to validate the gloas execution-hash chain + envelope binding; returns orphaned-envelope warnings instead of throwing onbid.parentBlockHashmismatch (per feat: enhance processChainSegment for ePBS #9103 shape).verifyBlock.tsawaitsverifyPayloadsDataAvailabilityon the gloas path in parallel with state-transition + signature verification.importExecutionPayloadis now called inline fromprocessBlocks(DA is already awaited upstream). Split out of the existing function: DA wait + import moved into a thin wrapperprocessExecutionPayloadthat the envelope queue calls instead.Included block-production fixes (may be lifted into separate PRs)
These are needed for Node A to produce a FULL canonical chain that Node B can range-sync from, but are otherwise independent of the range-sync changes above:
produceBlockBody:bid.parentBlockHash = executionPayload.parentHash(previouslycurrentState.latestBlockHash, which always encoded the EMPTY-parent hash).persistPayloadEnvelopeInput: stop pruningseenPayloadEnvelopeInputCacheimmediately after DB persist — synchronous consumers still read the envelope from here on subsequent slots. Cache is now pruned only on finalization; TODO added to cap it under non-finality.shouldApplyProposerBoost: pick the rightPayloadStatusvariant when looking up the parent node instead of hard-codingPENDING(threwINVALID_NODE_INDEXfor pre-gloas parents at the fork boundary).Verified:
pnpm vitest run --project e2e test/e2e/sync/finalizedSync.test.tspasses (sync / finalized sync for gloas, ~76 s).AI Assistance Disclosure
Used Claude Code to assist with implementation and review.