EIP-4844: Shard Blob Transactions

I made this for myself, just so I can anticipate what this will do to the nodes running on my machines. Sorry for any mistakes. I’ll correct it if there are any. Please let me know.

Thought I’d share:

Can we add something like below from 2718 to the beginning of the specification section to define the || operator? It’s used in several places in the EIP and can be interpreted in a variety of ways, depending on which programming language(s) one happens to be familiar with.


  • || is the byte/byte-array concatenation operator.

Moving the discussion from Clarify & rationalize blob transaction hash computations in EIP-4844 · Issue #6245 · ethereum/EIPs · GitHub here.

  • Enable 0-blob transactions to use SSZ format: On devp2p eth/68, 4844 suggests that the EIP-2718 transaction type is advertised to indicate Gossip and mempool behaviour. The EIP-2718 transaction type should solely be used to (1) denote the serialization format of a tx on the wire (also, as part of GetBlockBodys), (2) for the purpose of signing, and (3) for deriving the transaction hash. Giving it mempool specific meaning leads to problems and unnecessary discussions, e.g., for the 0-blob transaction case. It would be preferrable to advertise the number (or presence) of blobs instead of the transaction type on eth/68. Type 5 based 0-blob transactions could then be prossed the same as any type 0x01, 0x02, or 0xc0-0xfe transactions; Transactions with blobs (of type 0x05, or any future types that also have blobs) would use the req/resp based solution using the network wrapper.

  • SSZ encoding: EIP-6475: SSZ Optional SSZ Optional[Address] is preferrable over Union[None, Address], as it makes the SSZ merkle tree shape static, meaning that proof requests including the address can’t randomly fail based on union selector. Note that for fixed length items such as Address, Optional[Address] is equivalent to List[Address, 1] for the purpose of SSZ serialization and merkleization.

  • Constant tuning: MAX_VERSIONED_HASHES_LIST_SIZE is matching the maximum number of blobs per transaction, and is currently set to 16 million. This exceeds any rational design space; keep in mind that SSZ serialization caps out at 4 GB, so such transactions could not even be serialized. If devp2p eth/68 is updated to indicate the number of blobs, note that this number also is part of the advertisement and making it fit into a uint8 or uint16 may be desirable.

There’s been ongoing discussion around mempool DoS concerns, so perhaps we can start adding more recommendations to the spec around mempool handling of blob txs. Right now the spec suggests increasing data gas price by at least 10% for replacement, and the mempool already requires increasing regular gas price by 10% for replacement. Additional constraints that prevent specific DoS scenarios without being too burdensome on clients include:

  • Blob-holding txs should only be replaced by blob txs consuming at least as much datagas (e.g. # of blobs can never decrease). This prevents mempools from being spammed with multiple-blob txs to have them later deleted by (much cheaper) 0 or 1 blob txs.

  • There can only be one blob-containing tx per account. This prevents someone from spamming the mempool with multiple blob-holding txs each with sequential nonces in a way where none of them beyond the first would successfully execute & incur fees.

The suggestion from Etan in a comment above around announcing # of blobs in eth/68 instead of tx type would also help mempools better deal with blob-related DoS risk.

1 Like

Made a concrete proposal for eth/68 changes here:

For SSZ Optional, opened a PR:

1 Like

Re: data blob transaction replacement. From today’s 4844 client devs call, Dankrad noted that requiring increasing data gas (whether 10 or 100%) for blob tx replacement may not be a suitable disincentive for DoS since the gas is priced using 1559-type rules.

Ansgar suggested we might then also require that replacement txs contain the exact blob as before (so it would not have to be reverified). Depending on if it’s important, we could also allow replacement txs to add additional blobs, though this may be too much of an edge case to worry about.

Hey I just noticed that EIP-4844 doesn’t actually specify the ReceiptPayload format anywhere and probably should. For example EIP-1559 includes the line:

The EIP-2718 ReceiptPayload for this transaction is rlp([status, cumulative_transaction_gas_used, logs_bloom, logs])

But, before we add the ReceiptPayload I’m curious what others think of this idea I expressed on the ACD discord, where we remove the logs_bloom field from type 0x5 tx receipts? As discussed over there, most tx receipts only include a single event if any, so dedicating a full 256 bytes to the logs_bloom in the tx receipt feels a bit heavy (if the number of events in a tx receipt is small, it’s probably more effecient to just go ahead and scan the events vs. using the bloom since you have to scan the events anyways to double check against false positives in the bloom filter).


Re: Receipts, it was also noted in discord during the workshop that we should return dataGasUsed as part of the non-consensus receipt values.

On today’s 4844 client devs call, Marius from geth suggested we consider making the blob tx type more specialized, e.g. by removing access list and ability to create contracts. Wanted to open that up for discussion here. Does anyone have any concrete use cases for access lists and/or contracts in blob txs?

PEEPanEIP-4844: Shard Blob Transactions with Terence & Kasey

I know it’s kind of the Ethereum convention to add new cryptographic primitives as precompiles, but why? Why does the kzg point evaluation function have to be called via this round-about way using memory + staticcall?

There’s almost a full “row” of EVM instructions (0x21-0x2f) that have remained unclaimed so far and that could be allocated to important functions such as those required for this EIP.

Opcodes 0x21-0x26 are planned to be claimed by EVMMAX (EIP-6601) so 0x27 might be a good next candidate for point_evaluation function with similar semantics, popping 6 EVM words from the stack for the function and pushing the returndata.

Another question I have is why the function is returning constants and not a success flag / nothing. What’s the intention behind the function returning two constants?


Hi all, thanks all for working on this proposal

I got a question from an app developer point of view.

the proposal does not seem to specify any api to consume the data

It says

This EIP introduces a transaction type that has a distinct mempool version and execution-payload version, with only one-way convertibility between the two. The blobs are in the network representation and not in the consensus representation; instead, they are coupled with the beacon block. This means that there is now a part of a transaction that will not be accessible from the web3 API.

If i understand correctly it means the actual blob data is not directly available to execution client and as such these cannot provide it, but the consensus client can. Am I right here?

Furthermore it means that the execution client still have access to some data, is that the commitment and so a reference to the blob ?

it would be great if the eip would specify the api for what is available both for the execution client and consensus client. It seems to me that the EIP would not be complete without these. Or maybe there is another EIP that deals with that ?

Also i am wondering if is possible for the execution client to still provide the blob data api by simply forwarding the request to consensus client.

Note that my perspective is that of a app developer that is potentially interested to make use of EIP-4844 to retrieve data from the blobs by calling the user’s wallet rpc endpoint (EIP-1193) and so I am interested to know what this proposal will allow the user to fetch.,

Please correct me if any of my assumption are wrong


1 Like

There is a beacon-API that can be used to access blob sidecars. The client needs to be configured with both an execution-API and beacon-API provider.


1 Like

Hi. From the spec it’s not clear to me what is exactly the blob_versioned_hash. It’s supposed to start with VERSIONED_HASH_VERSION_KZG byte, initially set to 1. Does this mean that the hash is 33 bytes long? And second question if the blob_versioned_hash does not start with version byte is the transaction considered as invalid and sender balance remains unchanged or something opposite, data_fee is deducted from sender balance and burned?

LIMIT_BLOBS_PER_TX is currently defined in Parameters, but not used.

The precompile pointevaluation internally depends on another precompile sha256. This looks like design mistake: the hash function cannot be changed by users. None of the rationale or comments here explain this decision.

Congrats! As this is going to final soon, Congrats on authors and developers who work days and nights to carry out EIP-4844, hurah!!!

I know the implementation is done mostly, comments here are mostly about editorial clarification to ensure a smooth finalization.

  1. for a hash specification, such as
keccak256(BLOB_TX_TYPE || rlp([chain_id, nonce, max_priority_fee_per_gas, max_fee_per_gas, gas_limit, to, value, data, access_list, max_fee_per_blob_gas, blob_versioned_hashes]))

can I suggest we specify the length of data? I know it’s probably implied in the execution-spec, but sometimes when it’s implied, we don’t know for sure, resulting in confusions that need to be resolved, such as this attempt EIP-2294: Explicit bound to Chain ID size

  1. This “MUST NOT” specification seems unenforcable from what it reads today.
Nodes MUST NOT automatically broadcast blob transactions to 
their peers. Instead, those transactions are only announced using NewPooledTransactionHashes messages, and can then be 
manually requested via GetPooledTransactions.

Maybe a better way to say it is that

Nodes MUST ONLY rely on NewPooledTransactionHashes
messages for announcement, and Nodes MUST provide a pull
interface for query named `GetPooledTransactions` etc.
  1. A rationale discussion of POINT_EVALUATION_PRECOMPILE_GAS to be specified as 50000 was not included in the Rationale section. I have no doubt deep thoughts has been put in to finding the right amount. But it would be good if authors could include that analysis in this proposal.

I would like to see the nomenclature around the “gas price”/“base fee” changed to be consistent with type 2 transactions and London blocks. I have created a PR that just renames “gas price” to “base fee” throughout the document. I don’t believe this has any actual impact on the specification itself or consensus, but it is useful for communication within the community to use consistent naming for similar concepts, and as we start working on standardizing the 4844 JSON-RPC methods it may become necessary to standardize on a name.


This EIP does not make it clear to users or node implementations how users would send blob transactions. Is there going to be a new eth_sendBlobTransaction RPC call or will nodes accept the encoded form at eth_sendTransaction as given in the Networking section, which, if I am not mistaken, does not even include the EIP-2718 number for blobs (3)?

edit: The networking section is not very clear, imo it should also mention that the TransactionType is BLOB_TX_TYPE again. Yes, you send it through eth_sendTransaction but with the transaction type (0x03) prepended to that rlp array it says in that section.