Skip to content

Conversation

niran
Copy link

@niran niran commented Oct 1, 2025

Introduces a shadow block building stack that runs in parallel with the production sequencer for testing purposes. The builder syncs from production but does not submit blocks to L1, making it safe for testing TIPS bundle integration.

Changes:

  • Add builder-cl and builder services to docker-compose.yml
    • builder-cl: op-node in sequencer mode syncing from production via P2P
    • builder: op-rbuilder instance that queries TIPS datastore and builds blocks with eligible bundles (blocks are not submitted to L1)
  • Add build-rbuilder command to justfile for building op-rbuilder Docker image with TIPS datastore integration
  • Consolidate op-node environment configuration into .env.example and use env_file in docker-compose.yml to share common config between simulator-cl and builder-cl
  • Update justfile commands to support multiple compose profiles
    • Rename start-playground to start-builder
    • Update stop-all/start-all to accept comma-separated profiles
  • Document simulator and shadow block builder stack in README.md with prerequisites and quick start instructions

niran added 7 commits October 1, 2025 11:27
Introduces a shadow block building stack that runs in parallel with the production sequencer for testing purposes. The builder syncs from production but does not submit blocks to L1, making it safe for testing TIPS bundle integration.

Changes:
- Add builder-cl and builder services to docker-compose.yml
  - builder-cl: op-node in sequencer mode syncing from production via P2P
  - builder: op-rbuilder instance that queries TIPS datastore and builds
    blocks with eligible bundles (blocks are not submitted to L1)
- Add build-rbuilder command to justfile for building op-rbuilder Docker
  image with TIPS datastore integration
- Consolidate op-node environment configuration into .env.example and use
  env_file in docker-compose.yml to share common config between
  simulator-cl and builder-cl
- Update justfile commands to support multiple compose profiles
  - Rename start-playground to start-builder
  - Update stop-all/start-all to accept comma-separated profiles
- Document simulator and shadow block builder stack in README.md with
  prerequisites and quick start instructions
Replace BundleWithLatestSimulation struct with a simple tuple
(BundleWithMetadata, Simulation) for select_bundles_with_latest_simulation
return values.

This eliminates awkward naming in consuming code by allowing direct
destructuring instead of verbose field access patterns like
`result.bundle_with_metadata.bundle.block_number`.
niran added 5 commits October 9, 2025 23:39
Introduces shadow-boost, an Engine API proxy that sits between a non-sequencer op-node and shadow builder. Intercepts forkchoiceUpdated to force block building while keeping op-node synced with canonical chain via P2P.

Solves P2P block rejection and L1-triggered reorg issues that occur when running shadow builders in sequencer mode.
When op-node sends FCU without payload attributes (follower mode), shadow-boost now synthesizes attributes from the last newPayload to trigger continuous shadow building. Tracks payload info (timestamp, gas_limit, randao, etc.) and injects them with updated timestamps to maintain building cadence.

Improves logging throughout proxy and server with structured fields and clearer messages.
…al sync handling

Fixes two critical issues with synthetic payload attribute injection:

1. Timestamp skew: Changed synthetic timestamp calculation from
   SystemTime::now() to last_block_timestamp + 2, eliminating large
   time differences (300-700+ seconds) that caused "FCU arrived too
   late" errors in the shadow builder.

2. Historical P2P sync: Added 30-second age threshold to detect and
   skip synthetic attribute injection for historical blocks during
   P2P sync. Proxy still forwards FCU to builder for chain state
   updates (head/safe/finalized) without triggering unnecessary
   block building.

Changes:
- Use chain-relative timestamps instead of wall clock time
- Calculate block_age_seconds to detect historical sync
- Skip synthetic attributes for blocks >30s old
- Always forward FCU to builder (with or without attributes)
- Log block age for monitoring and debugging
- Suppress warnings when intentionally skipping builds

Results:
- Eliminated FCU timing errors during normal operation
- Prevented unnecessary shadow building during catchup
- Maintained proper chain state in builder during historical sync
- Reduced resource usage during P2P sync
…injection

Refactor shadow-boost to a minimal pass-through proxy that logs all
Engine API traffic and injects synthetic payload attributes to trigger
shadow building in non-sequencer mode.

Key changes:
- Switch to generic JSON Value handling for all Engine API methods
- Remove response modification (except payload_id suppression for injected attrs)
- Remove request modification of existing payload attributes
- Remove async newPayload forwarding, historical sync detection, duplicate
  detection, and shadow block fetching
- Store parent_beacon_block_root in LastPayloadInfo for synthetic attributes

Behavior:
- FCU without payload attributes: inject synthetic attributes from last
  newPayload to trigger shadow building, suppress payload_id in response
- FCU with payload attributes: pass through unchanged
- All other methods: pass through with request/response logging
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