How is rollup data verified with blobs

blobeip-4844rollups

Historically, rollups post compressed batches of transactions to the L1 which can be verified because all the data is stored in calldata.

However, as of EIP-4844 which was included in the Dencun upgrade to the Ethereum network (~March 2024), added a new transaction type (type 3) which enabled "blobs" or "Binary Large OBjects".

Now, rollups take advantage of this by posting most of their L2 compressed batch of transactions in a blob (like this sample transaction)

However, according to the EIP:

“blob-carrying transactions” which contain a large amount of data that cannot be accessed by EVM execution, but whose commitment can be accessed.

The data of the blob cannot be accessed by the EVM, which begs the questions:

How can blobs be programmatically used to verify the rollup from a zk or optimistic rollup?

Best Answer

To start off with some context - On the OP Stack, L2 blocks are posted to L1 in batches. These batches have two types (batch submission wire format, for reference):

  1. Singular batches (pre-Delta hardfork)
  2. Span batches (post-Delta hardfork)

Batches are posted to L1 by the batch submitter in order to advance the L2 safe head. Prior to the Ecotone hardfork, batches were submitted through calldata as EIP-1559 transactions sent to the batch inbox address. However, after Ecotone's activation, these batches are now submitted as blobs with the new 4844 transaction type.

The L2 safe chain is the chain that can be built entirely from the data available on L1, through the derivation pipeline. The unsafe chain sits on top of the safe chain as L2 blocks that have yet to be submitted to L1 by the batch submitter.

At a high level, the inputs to create the L2 chain is what the batch submitter is posting to L1. The derivation pipeline's role is then to read all batches available on L1, and processes them through several decoding / decompression / validation stages prior to creating L2 execution payloads from the batches and sending them off to the execution layer to process and validate.


On to fault-proving the L2 chain, now that the data to produce the safe chain is available in blobs - as the claims about the state of L2 are made on L1, the fault proof's objective is to validate a claim about the state of the safe L2 chain, as the data to reconstruct the claimed state is all present in the context of where the claim was made.

The fault proof program runs on top of Cannon (or, in the future, Cannon + other VMs like Asterisc), and performs a partial derivation of the L2 chain from data that is available on L1. After derivation is complete, the program executes the payloads required to produce the L2 state at the block that the claim was made about. At the very end, it asserts the correctness of the claim at the specified L2 block height.

When the program is executed in the context of a fault proof VM, it is sandboxed from the outside world except for one external data source: The PreimageOracle. Through the preimage oracle, the program can pull in external context such as field elements within blobs, preimages to intermediate MPT nodes, etc.

The VM is implemented both natively and in Solidity, where either a full run of the program may be executed natively or single instruction steps may be executed during on-chain disputes after bisection. The program is bootstrapped with a set of trusted inputs when a dispute is started on-chain, such as the L1 block hash that contains all of the data required to produce the L2 chain at the height of the claim, the latest finalized state of L2 that's available on L1, the L2 claim itself, etc.

When the program is executing on the native FPVM, the Preimage Oracle is just a host program that runs in a separate thread and performs synchronous data fetching as the program executes, from trusted sources. If an off-chain challenge agent's node(s) go out of sync, etc., the fault will be detected on-chain during the dispute process.

When the program is executing on-chain via the MIPS/RISC-V VM contracts during a dispute, the PreimageOracle contains only data that has been verified. The bootstrap information is loaded directly in from the dispute contract, and all other data such as preimages to keccak256 / sha256 hashes, blob field elements, etc. are verified to be correct as they are added to the PreimageOracle contract's mappings.

So, during L2 chain derivation within the fault proof program after Ecotone activation (where batches are available in blobs), blobs are pulled in one field element at a time to reconstruct them from their versioned hashes (it is assumed that the off-chain actor does have the contents of the blob as well as the preimage to the versioned hash available.) Each of these field elements are verified to exist within the blobs by creating a KZG opening on the blob commitment. Although the data of the blob cannot be accessed in a verifiable way within the context of the EVM without proving each field element's inclusion within the blob commitment (using the point-evaluation precompile), we only ever need to make the data available within the EVM for one field element at a time, as the terminal case of the on-chain dispute is only over a single instruction step of the broader program.

Related Topic