Skip to content

feat(builder): observe beacon node blocks - #48

Closed
krisoshea-eth wants to merge 19 commits into
unstablefrom
krisoshea/lod-12-api-02-consume-bn-block-events-and-retrieve-fork-correct
Closed

krisoshea-eth wants to merge 19 commits into
unstablefrom
krisoshea/lod-12-api-02-consume-bn-block-events-and-retrieve-fork-correct

Conversation

@krisoshea-eth

@krisoshea-eth krisoshea-eth commented Aug 10, 2026

Copy link
Copy Markdown
Owner

Motivation

The Lodestar Builder needs a source beacon node REST fallback for learning that a proposer selected a bid without joining libp2p. API-02 implements that bounded observation path.

The standardized external Builder flow merged in beacon-APIs ChainSafe#630 and implemented by draft Lodestar ChainSafe#9832 can instead forward the signed winning beacon block directly to the selected Builder. This draft asks maintainers whether packages/builder should keep API-02 as a compatibility and recovery fallback, or whether direct submitSignedBeaconBlock delivery should replace it as the primary path.

Behavior

  • Subscribe only to the standard block SSE topic.
  • Deduplicate block roots before asynchronous work and retain a FIFO window of 256 roots.
  • Skip locally pre-Gloas slots.
  • Retrieve each new post-Gloas block by root with getBlockV2, using the Builder abort signal for both SSE and HTTP.
  • Retry 404, server, timeout, and transport failures for up to six attempts with five 200 ms delays. Other 4xx responses, cancellation, response decoding, and structural failures are not retried.
  • Keep the API client's request timeout unchanged. This PR bounds attempt count and explicit retry delay, not total wall-clock or slot-relative time. SELECT-01 and REV-01 own deadline policy.
  • Treat response version metadata as fork authority, require a Gloas-compatible body, and verify that the returned slot matches the event slot.
  • Preserve the exact post-Gloas signed bid, including Heze fields, exact-width values, and BUILDER_INDEX_SELF_BUILD.
  • Dispatch observations concurrently through isolated runOnBlock callbacks. One slow, cancelled, or failing consumer does not prevent the others from running.
  • Keep each root consumed through success, skip, malformed response, or terminal failure until normal FIFO eviction. REL-01 owns resubscription, replay, and recovery.

The observer starts after the existing genesis, configuration, readiness, Gloas, and Builder identity gates. It joins the clock and BuilderStatusTracker as a long-lived Builder duty and shares their abort controller.

This PR does not add p2p, block_gossip, canonical-chain filtering, local-bid matching, reveal behavior, metrics, reconnect, replay, restart recovery, multi-BN failover, or a new API endpoint.

API audit

The standard block event contains the slot, beacon block root, and execution optimism, but not the fork version, selected Builder index, or execution block hash. getBlockV2 supplies the signed fork-correct block and Eth-Consensus-Version metadata. The standard flow is sufficient for the API-02 fallback at the cost of one fetch per newly observed post-Gloas block. head and head_v2 are not substitutes because an imported non-head block can be omitted.

Lodestar emits block after state transition and fork-choice import. Root lookup checks fork choice for presence, then serves the block from the seen-block input cache or database. The current import and retrieval order provides no expected Lodestar event-before-block 404 window. The Beacon API does not require equivalent ordering across clients, so bounded 404 retry remains a cross-client precaution.

The audit and decision record are in Builder docs PR #13. Implementation evidence was posted to beacon-APIs #599. The optional event-design notebook was introduced in Builder docs PR #14, refreshed in merged PR #16, and reconciled with current PoC and review evidence in PR #17. SPEC-01 owns that separate cross-client decision.

Marco's open Lodestar PRs #9854, #9875, #9876, and #9896 compare enriched block, two complete-bid event shapes, and block_v2. Nico's draft #9832 separately implements the standardized proposer-to-external-Builder flow from beacon-APIs ChainSafe#630. The relationship between that direct block-forwarding flow, API-02, and beacon-APIs ChainSafe#599 is the primary architecture question for upstream review.

Upstream reconciliation

Current unstable base: 2fba076c28.

Integrated incrementally through merge commit 03d4ebd1b4:

The API-02 diff remains limited to five Builder files. The merge preserved upstream's clock, identity, metrics, epoch polling, shared test-helper, and payload-cache patterns.

Specification baseline: consensus-specs v1.7.0-alpha.14.

Project issue: krisoshea-eth/lodestar#12.

Testing

Validated with Node 24.13.0 and pnpm 11.0.0:

  • focused observer and Builder lifecycle tests: 26 passing tests;
  • complete Builder unit directory: 53 passing tests;
  • Builder package type-check;
  • Builder source and test Biome check;
  • git diff --check.

Earlier validation on the same implementation also passed the Builder package build and build-import check. The latest upstream merge does not touch packages/builder.

Coverage includes SSE wiring, shared cancellation, Builder startup and shutdown wiring, Gloas and Heze fork-correct output, exact signed-bid identity, returned-slot consistency, sequential and concurrent deduplication, bounded transient recovery, terminal failure retention, retry classification, decoding failures, fork and body guards, FIFO eviction, self-build, stream failure and closure handling, and concurrent callback isolation.

This PR should remain a draft while maintainers decide the observer's role relative to direct submitSignedBeaconBlock delivery. LOD-12 remains open until the issue-specific real-BN event-to-block and shutdown smoke is recorded if this fallback remains part of the agreed architecture.

AI assistance disclosure

  • External Contributors: I have read the contributor guidelines and disclosed my usage of AI below.

AI assistance was used during codebase research, implementation drafting, testing, and review. The submitted code and PR text were reviewed and revised by the authors, with manual edits and technical decisions incorporated throughout. The authors take responsibility for the final result.

@linear-code

linear-code Bot commented Aug 10, 2026

Copy link
Copy Markdown

LOD-12

LOD-48

@coderabbitai

coderabbitai Bot commented Aug 10, 2026

Copy link
Copy Markdown

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch krisoshea/lod-12-api-02-consume-bn-block-events-and-retrieve-fork-correct

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@krisoshea-eth
krisoshea-eth marked this pull request as ready for review August 10, 2026 20:40
@krisoshea-eth krisoshea-eth self-assigned this Aug 10, 2026
@krisoshea-eth krisoshea-eth moved this from Todo to In Review in Lodestar EIP-7732 Builder Aug 10, 2026
@krisoshea-eth
krisoshea-eth marked this pull request as draft August 10, 2026 21:03
@krisoshea-eth krisoshea-eth changed the title feat(builder): consume beacon node block events and retrieve fork-correct blocks feat(builder): observe beacon node blocks Aug 11, 2026
krisoshea-eth and others added 4 commits August 13, 2026 16:34
…2-api-02-consume-bn-block-events-and-retrieve-fork-correct

# Conflicts:
#	packages/builder/src/builder.ts
…2-api-02-consume-bn-block-events-and-retrieve-fork-correct

# Conflicts:
#	packages/builder/src/builder.ts
…2-api-02-consume-bn-block-events-and-retrieve-fork-correct
…2-api-02-consume-bn-block-events-and-retrieve-fork-correct
…2-api-02-consume-bn-block-events-and-retrieve-fork-correct
…2-api-02-consume-bn-block-events-and-retrieve-fork-correct
…2-api-02-consume-bn-block-events-and-retrieve-fork-correct
@krisoshea-eth

Copy link
Copy Markdown
Owner Author

Superseded by upstream ChainSafe#9931. The upstream PR now carries the current implementation, review discussion, and evidence.

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.

1 participant