EIP-7732 -- Honest Builder¶
Note: This document is a work-in-progress for researchers and implementers.
- Introduction
- Becoming a builder
- Builder withdrawal credentials
- Submit deposit
- Process deposit
- Builder index
- Activation
- Builders attributions
- Constructing the payload bid
- Constructing the
BlobSidecar
s - Constructing the execution payload envelope
- Honest payload withheld messages
Introduction¶
This is an accompanying document which describes the expected actions of a "builder" participating in the Ethereum proof-of-stake protocol.
With the EIP-7732 Fork, the protocol includes new staked participants of the protocol called Builders. While Builders are a subset of the validator set, they have extra attributions that are optional. Validators may opt to not be builders and as such we collect the set of guidelines for those validators that want to act as builders in this document.
Becoming a builder¶
Builder withdrawal credentials¶
The withdrawal_credentials
field for builders has a specific format that
identifies them as registered builders in the network. Builders must use the
BUILDER_WITHDRAWAL_PREFIX
to participate in the EIP-7732 mechanism.
The withdrawal_credentials
field must be such that:
withdrawal_credentials[:1] == BUILDER_WITHDRAWAL_PREFIX
(i.e.,0x03
)withdrawal_credentials[1:12] == b'\x00' * 11
withdrawal_credentials[12:] == builder_execution_address
Where builder_execution_address
is a 20-byte execution layer address that will
receive:
- Withdrawal rewards (similar to
ETH1_ADDRESS_WITHDRAWAL_PREFIX
) - Compounding rewards (builders inherit compounding functionality)
Submit deposit¶
Builders follow the same deposit process as regular validators, but with the builder-specific withdrawal credentials. The deposit must include:
pubkey
: The builder's BLS public keywithdrawal_credentials
: Set withBUILDER_WITHDRAWAL_PREFIX
(0x03
)amount
: At leastMIN_DEPOSIT_AMOUNT
signature
: BLS signature over the deposit data
Process deposit¶
The beacon chain processes builder deposits identically to validator deposits,
with the withdrawal credentials using BUILDER_WITHDRAWAL_PREFIX
.
Builder index¶
Once the deposit is processed, the builder is assigned a unique
validator_index
within the validator registry. This index is used to identify
the builder in execution payload headers and envelopes.
Activation¶
Builder activation follows the same process as validator activation.
Builders attributions¶
Builders can submit bids to produce execution payloads. They can broadcast these
bids in the form of SignedExecutionPayloadHeader
objects, these objects encode
a commitment to reveal an execution payload in exchange for a payment. When
their bids are chosen by the corresponding proposer, builders are expected to
broadcast an accompanying SignedExecutionPayloadEnvelope
object honoring the
commitment.
Thus, builders tasks are divided in two, submitting bids, and submitting payloads.
Constructing the payload bid¶
Builders can broadcast a payload bid for the current or the next slot's proposer
to include. They produce a SignedExecutionPayloadHeader
as follows.
- Set
header.parent_block_hash
to the current head of the execution chain (this can be obtained from the beacon state asstate.latest_block_hash
). - Set
header.parent_block_root
to be the head of the consensus chain (this can be obtained from the beacon state ashash_tree_root(state.latest_block_header)
. Theparent_block_root
andparent_block_hash
must be compatible, in the sense that they both should come from the samestate
by the method described in this and the previous point. - Construct an execution payload. This can be performed with an external
execution engine with a call to
engine_getPayloadV4
. - Set
header.block_hash
to be the block hash of the constructed payload, that ispayload.block_hash
. - Set
header.gas_limit
to be the gas limit of the constructed payload, that ispayload.gas_limit
. - Set
header.builder_index
to be the validator index of the builder performing these actions. - Set
header.slot
to be the slot for which this bid is aimed. This slot MUST be either the current slot or the next slot. - Set
header.value
to be the value that the builder will pay the proposer if the bid is accepted. The builder MUST have enough balance to fulfill this bid and all pending payments. - Set
header.kzg_commitments_root
to be thehash_tree_root
of theblobsbundle.commitments
field returned byengine_getPayloadV4
. - Set
header.fee_recipient
to be an execution address to receive the payment. This address can be obtained from the proposer directly via a request or can be set from the withdrawal credentials of the proposer. The burn address can be used as a fallback.
After building the header
, the builder obtains a signature
of the header by
using
The builder assembles then
signed_execution_payload_header = SignedExecutionPayloadHeader(message=header, signature=signature)
and broadcasts it on the execution_payload_header
global gossip topic.
Constructing the BlobSidecar
s¶
[Modified in EIP7732]
The BlobSidecar
container is modified indirectly because the constant
KZG_COMMITMENT_INCLUSION_PROOF_DEPTH
is modified. The function
get_blob_sidecars
is modified because the KZG commitments are no longer
included in the beacon block but rather in the ExecutionPayloadEnvelope
, the
builder has to send the commitments as parameters to this function.
Constructing the execution payload envelope¶
When the proposer publishes a valid SignedBeaconBlock
containing a signed
commitment by the builder, the builder is later expected to broadcast the
corresponding SignedExecutionPayloadEnvelope
that fulfills this commitment.
See below for a special case of an honestly withheld payload.
To construct the execution_payload_envelope
the builder must perform the
following steps. We alias block
to be the corresponding beacon block and alias
header
to be the committed ExecutionPayloadHeader
in
block.body.signed_execution_payload_header.message
.
- Set the
payload
field to be theExecutionPayload
constructed when creating the corresponding bid. This payload MUST have the same block hash asheader.block_hash
. - Set the
execution_requests
field to be theExecutionRequests
associated withpayload
. - Set the
builder_index
field to be the validator index of the builder performing these steps. This field MUST beheader.builder_index
. - Set
beacon_block_root
to behash_tree_root(block)
. - Set
slot
to beblock.slot
. - Set
blob_kzg_commitments
to be thecommitments
field of the blobs bundle constructed when constructing the bid. This field MUST have ahash_tree_root
equal toheader.blob_kzg_commitments_root
.
After setting these parameters, the builder should run
process_execution_payload(state, signed_envelope, verify=False)
and this
function should not trigger an exception.
- Set
state_root
tohash_tree_root(state)
.
After preparing the envelope
the builder should sign the envelope using:
The builder assembles then
signed_execution_payload_envelope = SignedExecutionPayloadEnvelope(message=envelope, signature=signature)
and broadcasts it on the execution_payload
global gossip topic.
Honest payload withheld messages¶
An honest builder that has seen a SignedBeaconBlock
referencing his signed
bid, but that block was not timely and thus it is not the head of the builder's
chain, may choose to withhold their execution payload. For this the builder
should act as if no block was produced and not broadcast the payload.