This EIP introduces eth/73, extending the cell retrieval protocol defined by EIP-8070. It adds indexed forms of GetCells and Cells in which each transaction hash references a mask in a deduplicated mask table. The existing shared-mask forms remain available for uniform requests, avoiding additional overhead in the common case.
Motivation
The eth/72GetCells message applies one cell mask to every transaction hash in a request. When transactions require different cell sets, a client must partition one scheduling batch into multiple requests by exact mask equality. Partial responses and differing peer availability can produce these heterogeneous missing-cell sets.
Using one mask per transaction would avoid partitioning but would repeat a 16-byte mask for every hash and increase the size of uniform requests. An indexed table represents each unique mask once and lets a sender retain the shared form when it is more efficient.
Synthetic request traces show substantial reductions in request frames for highly fragmented batches. A sparse devnet observation, however, recorded no fragmented batches in the measured window. This EIP is therefore a draft for evaluating a conditional optimization, not a claim that current network traffic requires a new protocol version.
Specification
The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “NOT RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119 and RFC 8174.
Protocol version
eth/73 extends eth/72. All eth/72 messages and semantics remain unchanged except for the additions to GetCells and Cells specified below.
The following notation is used:
P is an RLP-encoded positive integer.
B is an RLP byte string.
B_16 is a 16-byte cell mask.
B_32 is a 32-byte transaction hash.
B_2048 is a 2048-byte cell.
Mask table
An indexed message contains masks, a list of unique B_16 values, and mask_ids, a byte string containing one unsigned byte for each transaction hash. Each byte in mask_ids is the zero-based index of the mask applying to the hash at the same position.
An indexed message MUST satisfy all of the following requirements:
It contains between 1 and 64 transaction hashes.
len(mask_ids) equals the number of transaction hashes.
It contains between 1 and 64 masks.
Every mask identifier is less than len(masks).
Every mask is referenced by at least one mask identifier.
No two masks are equal.
Masks appear in order of their first reference in mask_ids.
Transaction hashes are unique within the message.
The eth/72 protocol recommends a soft limit of 64 transaction hashes for GetCells. This EIP adopts 64 transaction hashes as a mandatory validity limit for indexed requests and non-empty indexed responses, and introduces a separate mandatory limit of 64 masks. These limits apply only to the indexed forms. The shared forms retain their existing eth/72 semantics as defined by EIP-8070. A mask identifier remains one byte, allowing a future protocol version to raise the mask-table limit to at most 256 without changing the identifier encoding.
A peer receiving an indexed message that violates any of these requirements MUST treat the message as invalid.
The RLP list length distinguishes the two forms. The shared form has the same encoding and semantics as eth/72.
For an indexed request, the mask selected by mask_ids[i] specifies the cell indices requested from every blob of the transaction identified by hashes[i].
A sender selects the request form as follows:
It MUST use the shared form when all transaction hashes require the same mask.
When a scheduling batch contains multiple masks, it MAY either partition the batch into shared requests or send an indexed request.
It SHOULD use the indexed form only when doing so reduces the number of requests or the total encoded request size.
Responses are processed according to the following rules:
A response MUST use the same form as its corresponding request.
An indexed response MAY omit requested transaction hashes or cells according to the existing eth/72 response-size and serving-capacity rules.
Its masks and mask_ids fields describe only the hashes and cells actually present in that response and MUST satisfy the mask-table requirements above.
For each returned transaction, its response mask MUST be a subset of the mask requested for that transaction.
Cells for each transaction MUST be ordered first by blob order in the transaction and then by increasing cell index among the set bits of its response mask.
A requester MUST reject a response containing an unrequested transaction hash, a cell outside the corresponding requested mask, an invalid cell or proof, or a cell ordering inconsistent with the response mask.
An indexed response containing no transaction data MUST be encoded as [request_id: P, [], [], [], mask_ids: B], where mask_ids is the empty byte string. This empty response is exempt from mask-table requirements 1 and 3. Its empty mask_ids satisfies requirement 2, and the remaining requirements apply vacuously. An indexed request MUST NOT be empty.
Resource limits
Implementations enforce the following resource limits:
They MUST validate the transaction count, mask count, identifiers, and canonical mask-table ordering before allocating cell-response storage.
Indexed and shared requests MUST be charged against the same peer request and response quotas.
The eth/72 response soft limit continues to apply.
A responder MAY truncate an indexed response independently for each transaction, provided that every returned response mask remains a subset of the corresponding requested mask.
Rationale
Indexed masks
A parallel mask array has simple semantics but adds 16 bytes for every transaction. The indexed table is equivalent when every mask is unique and is smaller when masks repeat. Requiring first-reference order, unique entries, and no unused entries gives each mapping one canonical encoding.
Adaptive encoding
Custody-aligned sampling normally produces one shared mask across many transactions. Keeping the eth/72 form prevents a regression for this case. Indexed encoding targets recovery and partial-delivery states where missing-cell sets diverge.
Indexed responses
The eth/72Cells response contains one shared mask. It cannot describe different returned cell sets for different transaction hashes. An indexed request therefore requires a corresponding indexed response; changing only GetCells would leave partial and heterogeneous responses ambiguous.
Observed workload
Controlled traces demonstrate the mechanism but do not establish its frequency. In one corrected sparse-node observation, 92 scheduling batches contained zero fragmented batches. Implementers should collect mask-group cardinality, hashes per group, request frames, response frames, and end-to-end latency before recommending deployment of eth/73.
Backwards Compatibility
This EIP introduces a new negotiated eth capability. An eth/73 implementation can continue negotiating eth/72 with peers that do not support indexed cell requests. Such peers receive only the shared GetCells and Cells forms defined by EIP-8070.
Security Considerations
The security requirements are:
Implementations must enforce the 64-hash and 64-mask bounds before allocating response buffers. They must validate identifiers and canonical table structure before performing transaction or blob lookups.
Implementations must retain response-size, serving-time, and peer-rate limits and account for the total cells implied by all selected masks. Indexed requests must not receive a larger quota than equivalent shared requests.
Implementations should prefer shared requests for routine custody sampling because transaction-specific masks reveal more information about a requester’s missing data. Indexed requests should be used only when heterogeneous recovery state makes them beneficial.
Every returned cell and proof must be cryptographically validated against the transaction’s commitments. A response that maps valid cells to the wrong transaction or cell index is invalid.