REP-0019 Title: Implement EIP-4844: Shard Blob Transactions on Ronin Author: Bui Quang Minh Type: Standard Status: Approved Created: 2024-07-25
REP-0019 describes the process of porting "blob-carrying transactions" (blob transactions) from Ethereum to Ronin. The blob transaction contains large amount of data which can be pruned after the predefined time.
Today, rollups (e.g. zkEVM) use calldata to post data to Ronin so that every one can recover the full state of rollup without depending on the rollup operator. However, calldata consumes a lot of gas and is stored permanently on Ronin. Blob transaction is introduced to tackles these issues. The transaction carries data in their blobs, these blobs are stored in a short time but still long enough for anyone who interests can fetch the data. As the data is not stored permanently in the Ronin storage, it alleviates the storage burden for network. As a result, blob transaction data is charged lower than the calldata.
This proposal follows EIP-4844: Shard Blob Transactions to introduce new blob transaction type, block header extension, blob gas, fee market and a point evaluation precompile. Please refer to EIP-4844 for the detailed specification on these topics.
Constant | Value |
---|---|
MIN_BLOCKS_FOR_BLOB_SIDECARS_REQUESTS | 518_400 |
Since Ronin does not have consensus layer like Ethereum, execution layer is extended to stored the blobs from the mined block. Blobs are stored at least MIN_BLOCKS_FOR_BLOB_SIDECARS_REQUESTS
blocks (roughly 18 days) from the time they are included in the mined block. New APIs are introduced for user to query blobs from mined blocks.
Unlike Ethereum consensus layer which propagates the "sidecars" (sidecars contain blobs, commitments and proofs) separately from block body, in Ronin, the sidecars are embedded into the block body P2P packets.
We extend BlockBodies and NewBlock packets in P2P Ethereum Wire Protocol (eth)
BlockBodies
[request-id, [block-body-1, block-body-2, ...], [sidecar-1, sidecar-2, ...]]
NewBlock
[block, td, [sidecar-1, sidecar-2, ...]]
With new P2P packet extensions, we introduce a new eth protocol version: ETH/100. The version 100 is selected to avoid further conflicts with future protocol upgrades in Ethereum.
We need to extend the block validity check as follows
def validate_block(block: Block, sidecars: list[BlobTxSidecar]) -> None:
...
# check that the excess blob gas was updated correctly
assert block.header.excess_blob_gas == calc_excess_blob_gas(block.parent.header)
blob_gas_used = 0
num_blob_txs = 0
is_data_available = is_data_available()
for tx in block.transactions:
...
# modify the check for sufficient balance
max_total_fee = tx.gas * tx.max_fee_per_gas
if get_tx_type(tx) == BLOB_TX_TYPE:
max_total_fee += get_total_blob_gas(tx) * tx.max_fee_per_blob_gas
assert signer(tx).balance >= max_total_fee
...
# add validity logic specific to blob txs
if get_tx_type(tx) == BLOB_TX_TYPE:
# there must be at least one blob
assert len(tx.blob_versioned_hashes) > 0
if is_data_available:
assert num_blob_txs < len(sidecars)
commitments = sidecars[num_blob_txs].commitments
# ensure number of versioned hashes is equal to number of commitments
assert len(tx.blob_versioned_hashes) == len(commitments)
for i in range(len(tx.blob_versioned_hashes)):
h = tx.blob_versioned_hashes[i]
# all versioned blob hashes must start with VERSIONED_HASH_VERSION_KZG
assert h[0] == VERSIONED_HASH_VERSION_KZG
# versioned blob hashes must be equal to sidecar commitment's hash
if is_data_available:
assert h == calc_blob_hash(commitments[i])
# ensure that the user was willing to at least pay the current blob gasprice
assert tx.max_fee_per_blob_gas >= get_blob_gasprice(block.header)
# keep track of total blob gas spent in the block
blob_gas_used += get_total_blob_gas(tx)
num_blob_txs += 1
# ensure number of blob transactions is equal to number of sidecars
assert num_blob_txs == len(sidecars)
# ensure the total blob gas spent is at most equal to the limit
assert blob_gas_used <= MAX_BLOB_GAS_PER_BLOCK
# ensure blob_gas_used matches header
assert block.header.blob_gas_used == blob_gas_used
# verify the sidecars
if is_data_available:
for sidecar in sidecars:
assert len(sidecar.blobs) == len(sidecar.commitments)
assert len(sidecar.blobs) == len(sidecar.proofs)
for i in range(len(sidecar.blobs)):
assert verify_kzg_proof(sidecar.blob[i], sidecar.commitment[i], sidecar.proof[i])
The blob transaction fee is separated from normal transaction fee, the blob transaction fee is transfered to Ronin Treasury instead of burning like Ethereum.
This proposal increases the bandwidth requirements per block by a maximum of ~0.75 MB. However, the worst case bandwidth is unchanged as it is capped at 10 MB by the eth protocol max packet's size. So in the worst case, there is no change in the network bandwidth.
The content is licensed under CC0.