Skip to content

Commit

Permalink
Merge pull request #1 from ferranbt/patch-1
Browse files Browse the repository at this point in the history
Update external-block-production.md
  • Loading branch information
dmarzzz authored Sep 19, 2024
2 parents 1f9ed56 + 0c89821 commit c74ac28
Showing 1 changed file with 33 additions and 23 deletions.
56 changes: 33 additions & 23 deletions protocol/external-block-production.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ The purpose of this design-doc is to propose and get buy-in in on a first step t

# Summary

This document proposes a sidecar to `op-node` for requesting block production from an external party. This sidecar has two roles: 1) obfuscate the presence of builder software from the `op-node` and `op-geth` and 2) manage communication with a block builder and handle block delivery to `op-node`. The first role is achieved via the sidecar forwarding all engine API calls to it's local `op-geth` and delivering 1 block exactly for each block request from `op-node`. The second role is achieved by the sidecar implementing the communication protocol with the builder, including authentication, and payload selection rules.
This document proposes a sidecar to `op-node` for requesting block production from an external party. This sidecar has two roles: 1) obfuscate the presence of builder software from the `op-node` and `op-geth` and 2) manage communication with a block builder and handle block delivery to `op-node`. The first role is achieved via the sidecar forwarding all API calls to it's local `op-geth` and delivering 1 block exactly for each block request from `op-node`. The second role is achieved by the sidecar implementing the communication protocol with the builder, including authentication, and payload selection rules.

By decoupling the block construction process from the Sequencer's Execution Engine, operators can tailor transaction sequencing rules without diverging from the standard Optimism Protocol Client. This flexibility allows individual chains to experiment on seqeuncing features, providing a means for differentiation. This minimum viable design also includes a local block production fallback as a training wheel to ensure liveness and network performance in the event of local Block Builder failure.
By decoupling the block construction process from the Sequencer's Execution Engine, operators can tailor transaction sequencing rules without diverging from the standard Optimism Protocol Client. This flexibility allows individual chains to experiment on sequencing features, providing a means for differentiation. This minimum viable design also includes a local block production fallback as a training wheel to ensure liveness and network performance in the event of local Block Builder failure.

# Problem Statement + Context

Expand All @@ -25,7 +25,7 @@ The tight coupling of proposer and sequencer roles in the `op-node` limits the a

As of September 2024, the `op-node` sofware in `sequencer` mode performs both the role of "proposer" and "sequencer". As the "proposer", the `op-node` propagates a proposal, with full authority, for the next block in the canonical L2 chain to the network. Unlike a layer 1 "proposer", it does not have a "vote" in the finality of that block, other than by committing it to the L1 chain. As a "sequencer", it is also responsible for the ordering of transactions in the L2 block's it proposes. Today, it uses a `op-geth`, a diff-minimized fork of the Layer 1 Execution client `geth`, and it's stock transaction ordering algorithm.

On Ethereum Layer 1, a concept known as "Proposer Builder Separation" has become popularized as a client architecture decision to purposefully enable the "proposer" to request a block from an external party. These parties run modified versions of `geth` and newer clients like `reth` to build blocks with numerous ordering algorithms and features.On Layer 1, the communication between the proposer and the builder is achieved via the [`mev-boost` software](https://github.com/flashbots/mev-boost).
On Ethereum Layer 1, a concept known as "Proposer Builder Separation" has become popularized as a client architecture decision to purposefully enable the "proposer" to request a block from an external party. These parties run modified versions of `geth` and newer clients like `reth` to build blocks with numerous ordering algorithms and features. On Layer 1, the communication between the proposer and the builder is achieved via the [`mev-boost` software](https://github.com/flashbots/mev-boost).

# Proposed Solution

Expand All @@ -34,31 +34,41 @@ The proposed solution introduces a yet-to-be named "block builder sidecar" softw
Key components and their interactions:

1. Proposer System:
- `op-node`: Initiates the block production process via engine API call.
- block builder sidecar: Forwards all engine API calls to local `op-geth` and multiplexes `engine_FCU` (with Payload Attribtues)
- `op-node`: Initiates the block production process via engine API calls.
- block builder sidecar: Forwards all API calls to local `op-geth` and multiplexes `engine_FCU` (with Payload Attributes)
- `op-geth`: The local execution engine.

2. Builder System:
- `builder`: The external block builder's execution engine.
- `builder-op-node`: A stock version of the op-node client.
- `builder-op-geth`: The external block builder's execution engine.

3. Communication Flow:
4. Communication Flow:
- The `op-node` sends an `engine_FCU` (Fork Choice Update) call with attributes to the sidecar.
- The sidecar forwards this call to the local op-geth.
- The sidecar forwards this call both to the local op-geth and to the builder-op-geth if the node is synced to the tip of the chain.
- When the op-node makes an `engine_getPayload` call, the sidecar intercepts it.
- The sidecar communicates with the external Builder's `op-geth` to request an externally built block.
- Upon receiving the external block, the sidecar forwards it to the op-node, or falls back to the locally produced block.
- The sidecar communicates with the external `builder-op-geth` to request an externally built block.
- Upon receiving the external block, the sidecar validates it with the local `op-geth` node. If valid, it forwards it to the op-node, otherwise it falls back to the locally produced block.

This design achieves the two main roles of the sidecar:

1. Obfuscation: The presence of the external builder is hidden from both op-node and op-geth. From their perspective, they are communicating with each other as usual.

2. External Communication Management: The sidecar handles all communication with the external builder, including authentication and payload selection.

## Boost sync

Our experience has shown that there can be a notable delay in the synchronization process of the builder-op-geth with the latest tip of the chain. When relying solely on p2p communication and the op-node, we've observed this delay to typically range from about 200 to 300 milliseconds, though this can vary. To address this issue and improve efficiency, we are implementing a `boost sync` mechanism to rapidly transmit the tip of the block to the builder-op-geth.

The boost sync process operates as follows:
- The sidecar monitors the `builder-op-geth` sync status.
- If the sidecar detects that the `builder-op-geth` is synced with the tip of chain, it relays the `engine_newPayload` and `engine_FCU` (without attributes) API calls.

Preemptively sending these API calls from the sidecar, instead of waiting for them to come from the op-node, helps the builder sync up the latest block faster. We have observed times reduced to approximately 3-4 ms.

## Resource Usage

This approach doubles the amount of bandwidth needed for sending a block to the `op-node` by accepting an external block from the block builder. However, the sidecar only forwards one payload to `op-node` based on its selection criteria.


## Tradeoffs

### Benefits
Expand All @@ -84,25 +94,25 @@ This approach doubles the amount of bandwidth needed for sending a block to the
# Alternatives Considered
A variety of alternate desgns we're considered and some implemented.

1. Proposer `op-node` <> Builder `op-geth` (payload attributes stream):
- Proposer's` op-node` requests block from builder's op-geth
- Proposer's` op-node` provides payload attributes stream to Builder'sop-geth
- Pros: uses alternative and customizable communication channel for payload attributes stream
- Cons: requires modification to `op-node`
1. Proposer `op-node` <> `builder-op-geth` (payload attributes stream):
- Proposer's` op-node` requests block from builder's op-geth.
- Proposer's` op-node` provides payload attributes stream to Builder'sop-geth.
- Pros: uses alternative and customizable communication channel for payload attributes stream.
- Cons: requires modification to `op-node`.

2. Proposer `op-node` <> Builder `op-geth` (no payload attributes stream):
- Similar to design 1 above, but without payload attributes stream
- Block building triggered by enabling block payload attributes in engine_forkchoiceUpdated call
- Similar to design 1 above, but without payload attributes stream.
- Block building triggered by enabling block payload attributes in engine_forkchoiceUpdated call.
- Pros: fewer modifications than design 1.
- Cons: stil requires modification to `op-node`
- Cons: stil requires modification to `op-node`.

3. Proposer `op-node` <> Builder `op-node`: (builder API)
- Proposer's` op-node` requests block from builder's` op-node` using a special API
- Pros: more modifications to `op-node` than design 2 but less than design 1.
- Cons: allows for more flexibility in information requested from block builders since request isn't restricted to payloadAttributes
- Proposer's` op-node` requests block from builder's` op-node` using a special API.
- Pros: more modifications to `op-node` than design 2 but less than design 1.
- Cons: allows for more flexibility in information requested from block builders since request isn't restricted to payloadAttributes.

4. Proposer `op-geth` <> Builder `op-geth`:
- Proposer's op-geth requests block directly from builder's op-geth
- Proposer's op-geth requests block directly from builder's op-geth.
- Pros: likely the fastest approach since proposers `op-geth` is the ultimate executor of the payload.
- Cons: requires modification to `op-geth` which is in some ways more sacred than `op-geth` due to it's policy of a minized code diff to upstream geth.

Expand Down

0 comments on commit c74ac28

Please sign in to comment.