# Builder-API designs for Unstaked Builders We document 2 potential designs for the Builder-API if we have unstaked builders. ## Type definitions We define some of the types we will be frequently using in our discussion of the API. ```python class ExecutionPayloadBid(Container): parent_block_hash: Hash32 parent_block_root: Root block_hash: Hash32 prev_randao: Bytes32 fee_recipient: ExecutionAddress gas_limit: uint64 builder_index: ValidatorIndex slot: Slot value: Gwei execution_payment: Gwei blob_kzg_commitments_root: Root ``` ```python class SignedExecutionPayloadBid(Container): message: ExecutionPayloadBid signature: BLSSignature ``` ```python class ExecutionPayloadEnvelope(Container): payload: ExecutionPayload execution_requests: ExecutionRequests builder_index: ValidatorIndex beacon_block_root: Root slot: Slot blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK] state_root: Root ``` ```python class SignedExecutionPayloadEnvelope(Container): message: ExecutionPayloadEnvelope signature: BLSSignature ``` ```python class BlindedExecutionPayloadEnvelope(Container): payload: Root execution_requests: Root builder_index: ValidatorIndex beacon_block_root: Root slot: Slot blob_kzg_commitments: Root state_root: Root ``` ```python class SignedBlindedExecutionPayloadEnvelope(Container): message: BlindedExecutionPayloadEnvelope signature: BLSSignature ``` ## Design 1 On a high level, the proposer<>relay/builder interactions could look like the following: 1. The proposer sends a `getHeader` request to the relay. It receives the `ExecutionPayloadBid` along with the `ExecutionPayloadHeader`, `ExecutionRequests` and `BlobKZGCommitments`. Similar to the data sent in the `getHeader` call today : https://github.com/ethereum/builder-specs/blob/main/types/electra/bid.yaml 2. If the proposer accepts this bid, it creates a `SignedBeaconBlock` with the `ExecutionPayloadBid` embedded into it. It also creates a `SignedBlindedExecutionPayloadEnvelope`. The proposer will have enough information to run a modified version of [process_execution_payload](https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/beacon-chain.md#new-process_execution_payload). More details on this in an upcoming section. 3. The proposer sends the relay back the `SignedBeaconBlock` and `SignedBlindedExecutionPayloadEnvelope`. The relay and proposer can both broadcast the `SignedBeaconBlock`. The relay can construct a `SignedExecutionPayloadEnvelope` and broadcast it to the PTC commitee. The API is generally unopinionated about how the builder pays the proposer but we can assume the status quo as today where the builder inserts a payment transaction at the end of the block to the proposer's fee recipient. ### API definitions #### Execution Payload Bid retrival The proposer queries this API and receives the `SignedExecutionPayloadBid` along with the `ExecutionPayloadHeader`, `ExecutionRequests` and `BlobKZGCommitments` for this slot. GET `/eth/v1/builder/execution_payload_bid/{slot}/{parent_hash}/{pub_key}` #### Execution Payload Bid commitment The proposer commits to the `ExecutionPayloadBid` by sending back to the relay, the `SignedBeaconBlock` which embeds the `ExecutionPayloadBid`. It also sends a `SignedBlindedExecutionPayloadEnvelope` to the relay which it has constructed. POST `/eth/v1/builder/beacon_block` ### Sequence Diagram ![BuilderApiV2](https://hackmd.io/_uploads/B1_mScVzbg.png) ### Creating the BlindedExecutionPayloadEnvelope The proposer receives the `ExecutionPayloadBid`, `ExecutionPayloadHeader`, `ExecutionRequests` and `BlobKZGCommitments` from the relay. The proposer can run a modified version of `process_execution_payload` without the engine_api invocation to validate the payload. The proposer runs `process_execution_payload` on the post-state after creating the `SignedBeaconBlock` To create a `BlindedExecutionPayloadEnvelope`, the proposer can set the fields in the `BlindedExecutionPayloadEnvelope` as the following: - *payload*: This is the hash tree root of the `ExecutionPayloadHeader` sent by the relay. - *execution_requests*: This is the hash tree root of the `ExecutionRequests` sent by the relay - *builder_index*: This is to be set to the index of the validator. - *beacon_block_root*: This is the hash tree root of the `SignedBeaconBlock` with the `SignedExecutionPayload` embedded in it. - *slot*: This is the slot of the proposing block. - *blob_kzg_commitments*: This is the hash tree root of the blob kzg commitments - *state_root*: This is the state root of the beacon state post processing the `SignedBeaconBlock`. ## Design 2 On a high level, the proposer<>relay/builder interactions could look like the following: 1. The proposer queries the relay for an `ExecutionPayloadBid`. The relay sends an `ExecutionPayloadBid` and sets the `execution_payment` field to the value of the bid. 2. If the proposer accepts this bid, it sends a `SignedBeaconBlock` with the `ExecutionPayloadBid` embedded into it to the relay via a POST request. 3. The relay now has enough information to construct the `ExecutionPayloadEnvelope` from the `SignedBeaconBlock` sent. We detail more about constructing the `ExecutionPayloadEnvelope` in an upcoming section. 4. The proposer queries the relay for the `BlindedExecutionPayloadEnvelope` corresponding to the `ExecutionPayloadBid`. The relay returns the corresponding `BlindedExecutionPayloadEnvelope`. 5. The proposer signs it and sends the `SignedBlindedExecutionPayloadEnvelope` back to the relay. 6. The relay is responsible for broadcasting the `SignedExecutionPayloadEnvelope` to the PTC commitee. The API is generally unopinionated about how the builder pays the proposer but we can assume the status quo as today where the builder inserts a payment transaction at the end of the block to the proposer's fee recipient. ### API definitions #### Execution Payload Bid retrival The proposer queries this API and receives the `SignedExecutionPayloadBid` for this slot. GET `/eth/v1/builder/execution_payload_bid/{slot}/{parent_hash}/{pub_key}` #### Execution Payload Bid commitment The proposer commits to the `ExecutionPayloadBid` by sending back to the relay, the `SignedBeaconBlock` which embeds the `ExecutionPayloadBid`. POST `/eth/v1/builder/beacon_block` ### BlindedExecutionPayloadEnvelope Retrival The proposer queries this API and receives the blinded execution payload envelope corresponding to the execution payload bid. GET `/eth/v1/builder/blinded_execution_payload_env` #### BlindedExecutionPayloadEnvelope Commitment The proposer signs the `BlindedExecutionPayloadEnvelope` and sends it to the relay. The relay is responsible for broadcasting the `SignedExecutionPayloadEnvelope` to the PTC commitee. ### Sequence Diagram ![BuilderApiUnstakedBuilders](https://hackmd.io/_uploads/BkiKb74fZe.png) ### Creating the ExecutionPayloadEnvelope When the relay receives the beacon block from the proposer via `sendSignedBeaconBlock`, they need to construct the `ExecutionPayloadEnvelope`. The `payload`, `execution_requests` and `blob_kzg_commitments` will be available to the relay since they are part of the block submitted by the builder to the relay. The `beacon_block_root` will be available from the signed beacon block submitted by the proposer. The latest `slot` will be available to the relay. The relay will have to compute the `state_root` of the `ExecutionPayloadEnvelope`. It will have to compute this state root by running [process_execution_payload](https://github.com/ethereum/consensus-specs/blob/master/specs/gloas/beacon-chain.md#new-process_execution_payload) on the beacon state after running STF on the beacon block with `beacon_block_root`.