It is expected that in the future, home stakers will not be able to locally produce full blocks. This is in particular true after full Danksharding in which we do not expect a home computer to be able to compute the KZG commitments on time.
This forces proposers to rely on external builders to prepare these blocks, which in turn imposes a threat to censorship resistance: a few external players (the builders) will have ultimate decision of what transactions are included or not on L1.
While it is true that a non-censoring proposer may always propose execution blocks without any blobs, this becomes a strong centralizing force in that non-censoring validators have to forfeit their earnings from blobs (which in a rollup-centric roadmap are expected to be a large part of the block) if they want to control their execution contents.
We propose a separation of blob transactions from the rest of the execution payload. This achieves the following objectives:
- Home computers are still able to produce execution blocks and defer blob production to builders.
- The validity of blobs and execution payload can be verified in an independent manner, thus this mechanism is more resilient to bugs in the builder that produce invalid commitments for example.
- Fully compatible with the current design with minimal protocol changes
The main con is in the extra complexity needed on relayers and external software like MEV-Boost. Another con is that transactions will not be able to interact with blob transactions immediately, as blob transaction processing is deferred for one block.
We propose that the
ExecutionPayload structure has an extra field
blob_transactions containing all blob transactions and that the field
transactions does not have any blob transactions allowed. Additionally, the
ExecutionPayloadHeader will include a field
blob_transactions_root containing the root for the
blob_transactions field serialized as an SSZ list of byte slices.
The idea is that a proposer may sign blindly an
ExecutionPayloadHeader without knowing the full
blob_transactions lists, or may choose to include it’s own transactions and sign blindly without knowing the
blob_transactions list. Implementation of the Builder API is left unspecified, but it could be for example that the builder submits a full header but the proposer sends back a signed header with it’s own transactions lists. The relay will recognize the builder’s
blob_transactions_root in the header, but a different
transactions_root and different values for the execution part of the header, thus the relayer will assemble a full block by including the builder’s
blob_transactions and broadcasting.
It may be needed to have different blockhash values, for the execution part and the blob part of the block. Or simply keep the
BlockHash value to be the execution hash, this plus the
blob_transactions_root should be enough of an identifier.
When receiving an
engine_NewPayload, the execution client will receive both transactions and blob transactions for block
N and it has still the blob transactions for block
It will start by processing the
blob_transactions from block
N-1 (if they were deemed valid) and then processing the
transactions for block
N. After that it will check if the
blob_transactions for block
N are valid with the post-state after applying the
transactions for block
Thus, after each block
N, the next proposer of
N+1 knows if the
N were valid or not. If they were invalid, the block
N+1 will act as if the block
N had no blobs in it.
This system allows for the network can progress even if there’s failure in producing blobs by centralized builders. It allows for home computers to produce execution blocks and it can be customized so that specialized builders only bid for blob transactions and/or execution transactions separately.