# `eth_sendBlobs` and `eth_getBlobsStatus`
## Abstract
This EIP proposes two new JSON-RPC methods, `eth_sendBlobs` and `eth_getBlobsStatus`.
The `eth_sendBlobs` method allows originators to submit a bundle of candidate EIP-4844 Type 3 transactions that share the same `sender` address and `nonce`. The receiving RPC node, often connected to specialized block-building infrastructure, can select the most advantageous transaction from the bundle based on available blob capacity in a block (per EIP-4844 limits) and other mempool conditions. This maximizes the probability of the sender's blob data being included without requiring the originator to guess the optimal number of blobs. A successful submission returns a unique `bundleId`.
The `eth_getBlobsStatus` method allows originators to query the status of a previously submitted bundle using its `bundleId`. It provides information on whether the bundle is pending, included in a block (and which transaction/block), expired, or not found.
## Motivation
EIP-4844 introduced Shard Blob Transactions but imposed a strict limit on the number of blobs per block (initially 6). This creates uncertainty for blob transaction originators:
1. **Competition:** Other blob transactions, potentially with higher fees, might consume available blob slots.
2. **Fixed Submission:** Standard methods like `eth_sendRawTransaction` handle only one transaction per `sender`/`nonce`, forcing the originator to commit to a specific blob count.
3. **Inefficiency & Exclusion:** A transaction with N blobs might be excluded if fewer than N slots are available, even if a variant with fewer blobs could have fit. Originators must guess the optimal count, risking under-utilization or complete exclusion.
`eth_sendBlobs` addresses this by allowing submission of multiple variants (e.g., transactions with 1 to 6 blobs) for the same `sender`/`nonce`. The receiving infrastructure, having a better view of block construction, selects the best-fitting variant, increasing inclusion probability.
However, tracking these submissions poses challenges:
1. **Uncertainty:** The originator doesn't know which specific transaction hash (if any) from the bundle will be included.
2. **Visibility:** Bundles reside in specialized, potentially off-chain pools, invisible to standard mempool explorers.
3. **Lifecycle:** Bundles can expire based on `maxBlockNumber` or provider policy.
`eth_getBlobsStatus` provides a standard way to query the bundle's state using the `bundleId` obtained from `eth_sendBlobs`, addressing these tracking needs.
## Specification
### Method: `eth_sendBlobs`
Allows submitting a bundle of alternative blob transactions for a single nonce.
#### Parameters
The method accepts a single `Array` parameter containing one `Object` with the following fields:
1. `txs`: `Array[DATA]`
* An array of hex-encoded, RLP-serialized signed EIP-4844 Type 3 transactions.
* **Constraint:** All transactions within this array *MUST* originate from the same `sender` address.
* **Constraint:** All transactions within this array *MUST* use the identical `nonce`.
* **Constraint:** Each transaction string `DATA` must represent a valid, signed EIP-4844 transaction.
* **Recommendation:** Transactions should ideally differ primarily in the number of blobs (`blobVersionedHashes`) to represent inclusion options.
* **Recommendation:** Transactions should have consistent fee parameters (`maxFeePerGas`, `maxPriorityFeePerGas`, `maxFeePerBlobGas`) to allow for predictable selection based on blob count.
2. `maxBlockNumber`: `QUANTITY | TAG` (Optional)
* A hex-encoded block number (`0x...`) or a tag (`"latest"`, `"pending"`).
* If provided, the bundle should not be considered for inclusion in any block *after* this block number. Provides an expiry hint.
* If omitted, lifespan is determined by the receiving node's policy.
#### Returns
* `result`: `DATA | Null`
* On success: A unique identifier (`DATA`, e.g., hex-encoded string) for the submitted bundle, generated by the receiving node. This `bundleId` is used for `eth_getBlobsStatus`.
* On failure: `null`.
* `error`: `Object | Null`
* If an error occurs (validation, processing), contains a JSON-RPC 2.0 error object. `result` will be `null`.
* Potential error codes:
* `-32602: Invalid params` (Invalid structure, type mismatches, non-hex `DATA`, txs violate constraints).
* `-32000` (or other server-defined errors): Internal server error, invalid signature, non-EIP-4844 transaction, etc.
* If successful, `error` is `null`.
#### Example Request (`eth_sendBlobs`)
```json
{
"jsonrpc": "2.0",
"id": 1,
"method": "eth_sendBlobs",
"params": [{
"txs": [
"0xf8eabc...", // Signed Tx, 1 blob, nonce N, Addr A
"0xf8eade...", // Signed Tx, 2 blobs, nonce N, Addr A
"0xf8eaf0...", // Signed Tx, 3 blobs, nonce N, Addr A
"0xf8eb12...", // Signed Tx, 4 blobs, nonce N, Addr A
"0xf8eb34...", // Signed Tx, 5 blobs, nonce N, Addr A
"0xf8eb56..." // Signed Tx, 6 blobs, nonce N, Addr A
],
"maxBlockNumber": "0xAFEBE1" // Optional: Expire after block 11529953
}]
}
```
#### Example Response (Success) (`eth_sendBlobs`)
```json
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x7b9d8f61a3f1f6d9b8e0c2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3", // Unique Bundle ID
"error": null
}
```
#### Expected Node Behavior (`eth_sendBlobs`)
Nodes implementing this method (likely specialized endpoints) *MUST*:
1. **Validate Request:** Check JSON-RPC structure and parameter types.
2. **Validate Transactions:** For each `DATA` string in `txs`:
* Decode RLP.
* Verify it's a valid signed EIP-4844 Type 3 transaction.
* Extract `sender` and `nonce`.
3. **Enforce Constraints:**
* Verify all transactions share the *exact same* `sender` address.
* Verify all transactions share the *exact same* `nonce`.
* Fail the request (`Invalid params` error) if constraints are violated.
4. **Validate `maxBlockNumber`:** If present, check if it's a valid hex quantity or tag.
5. **Generate ID & Store:** If validation passes:
* Generate a unique `bundleId`.
* Store the bundle (associated transactions, sender, nonce, `maxBlockNumber`, initial status `PENDING`) indexed by the `bundleId`.
* Accept the bundle into a specialized pool that allows multiple transactions per `sender`/`nonce`.
6. **Return ID:** Respond with the generated `bundleId`.
The node (or associated block builder) *SHOULD* implement selection logic:
* During block construction, consider bundles from the specialized pool.
* For a given `sender`/`nonce`, select *at most one* transaction from the corresponding bundle.
* Selection *SHOULD* prioritize fitting the maximum number of blobs possible within block limits, potentially using fees as a factor.
* Once one transaction from a bundle is included canonically, invalidate all other variants of that bundle (same `sender`/`nonce`).
* Discard bundles if `maxBlockNumber` is passed or per internal timeout policy, updating the status to `EXPIRED`.
### Method: `eth_getBlobsStatus`
Allows querying the status of a bundle submitted via `eth_sendBlobs`.
#### Parameters
1. `bundleId`: `DATA`
* The unique bundle identifier received from a successful `eth_sendBlobs` call.
#### Returns
* `result`: `Object | Null`
* An object describing the bundle status, or `null` if `bundleId` is not found (alternative: object with `status: "NOT_FOUND"`). Contains:
* `status`: `String` - The current status:
* `"PENDING"`: Accepted, eligible for inclusion.
* `"INCLUDED"`: One transaction from the bundle is included on-chain.
* `"EXPIRED"`: No longer eligible for inclusion (deadline passed or timed out).
* `"NOT_FOUND"`: The `bundleId` is unknown or invalid.
* `includedTxHash`: `DATA` (Only if `status` is `"INCLUDED"`) - The hash of the included transaction.
* `inclusionBlockNumber`: `QUANTITY` (Only if `status` is `"INCLUDED"`) - Hex block number of inclusion.
* `inclusionBlockHash`: `DATA` (Only if `status` is `"INCLUDED"`) - Hash of the block containing the inclusion.
* `expiryReason`: `String` (Optional, if `status` is `"EXPIRED"`) - Reason for expiration (e.g., `"Max block number reached"`, `"Node timeout policy"`).
* `error`: `Object | Null`
* If an error occurs (e.g., invalid `bundleId` format), contains a JSON-RPC 2.0 error object. `result` will be `null`.
* If successful, `error` is `null`.
#### Example Request (`eth_getBlobsStatus`)
```json
{
"jsonrpc": "2.0",
"id": 2,
"method": "eth_getBlobsStatus",
"params": [
"0x7b9d8f61a3f1f6d9b8e0c2a3b4c5d6e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3" // Bundle ID from eth_sendBlobs
]
}
```
#### Example Responses (`eth_getBlobsStatus`)
##### Pending
```json
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"status": "PENDING"
},
"error": null
}
```
##### Included
```json
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"status": "INCLUDED",
"includedTxHash": "0xf8eb56...", // Hash of the actual included TX (e.g., the 6-blob one)
"inclusionBlockNumber": "0xAFF001", // e.g., 11531393
"inclusionBlockHash": "0xabc123..."
},
"error": null
}
```
##### Expired
```json
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"status": "EXPIRED",
"expiryReason": "Max block number reached"
},
"error": null
}
```
##### Not Found
```json
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"status": "NOT_FOUND"
},
// Alternatively: "result": null
"error": null
}
```
#### Expected Node Behavior (`eth_getBlobsStatus`)
Nodes implementing this method *MUST*:
1. **Validate Request:** Check JSON-RPC structure and `bundleId` format (`DATA`).
2. **Lookup Bundle:** Attempt to retrieve the bundle state associated with the provided `bundleId` from its specialized storage.
3. **Determine Status:**
* If no bundle is found: Return `NOT_FOUND` status (or `null` result).
* If found, check internal state:
* Has an associated transaction been included in the canonical chain? -> Return `INCLUDED` with details.
* Has the bundle been marked expired (deadline/policy)? -> Return `EXPIRED` with optional reason.
* Otherwise -> Return `PENDING`.
4. **Format Response:** Construct the JSON response according to the specification for the determined status.
## Sublets
The pending pool for these transactions is a subection of a private mempool, called a *sublet*. This subdivision is not strictly necessary.
## Rationale
1. **Necessity of New Methods:** Standard RPC methods (`eth_sendRawTransaction`, `eth_getTransactionReceipt`) and public mempools do not support the concept of bundled alternative transactions for a single nonce or the required specialized status tracking. `eth_sendBlobs` and `eth_getBlobsStatus` provide a dedicated interface.
2. **Bundle Submission (`txs` array):** Efficiently submits all variants at once, signaling their relationship clearly.
3. **Shared Nonce Constraint:** Essential for safety. Ensures only one transaction from the bundle can ever be executed on-chain, preventing unintended replays or state conflicts, leveraging the core Ethereum nonce mechanism.
4. **`maxBlockNumber` Parameter:** Gives originators control over the time-sensitivity of blob data inclusion, a common requirement for time-critical data or avoiding stale submissions in volatile fee markets.
5. **`bundleId` Return (`eth_sendBlobs`):** Provides a necessary, unique handle specific to the submitted bundle, enabling reliable status tracking via `eth_getBlobsStatus`. It decouples tracking from potentially reusable `sender`/`nonce` pairs.
6. **`eth_getBlobsStatus` Method:** Offers a standardized way to poll the outcome of a bundle submission, covering its lifecycle from acceptance to final state (inclusion or expiry), which is crucial given the off-chain nature of the initial pool.
7. **Specialized Infrastructure:** Acknowledges that these methods primarily target specialized RPC endpoints (e.g., builder relays, dedicated node services) capable of managing the required off-chain pool and selection logic, rather than all standard Ethereum clients.
## Backwards Compatibility
This EIP introduces two new JSON-RPC methods. It does not modify or deprecate any existing methods or alter Ethereum's consensus rules.
## Security Considerations
1. **Nonce Integrity:** The system's safety relies heavily on the Ethereum protocol's nonce enforcement. The specialized pool and selection logic *MUST NOT* allow more than one transaction from a bundle (sharing the same `sender`/`nonce`) to be included in the canonical chain. Implementers must ensure their off-chain logic respects this.
2. **Centralization and Trust:** Users implicitly trust the RPC provider/builder implementing these methods to:
* Faithfully execute the selection logic (e.g., not unfairly discard bundles, select optimally).
* Accurately report bundle status via `eth_getBlobsStatus`.
* Not censor submissions unduly.
* Handle transactions securely. This introduces a reliance similar to using private transaction relays.
3. **Resource Consumption / DoS:**
* `eth_sendBlobs`: Receiving large bundles frequently can consume significant bandwidth and processing power. Endpoints *MUST* implement protective measures like rate limiting, limits on the `txs` array size/count, and potentially authentication or stake-based access.
* `eth_getBlobsStatus`: While primarily read-only, frequent polling could strain the status tracking database. Rate limiting *SHOULD* be applied.
4. **Transaction Confidentiality:** Transactions submitted via `eth_sendBlobs` might be visible to the RPC provider and associated infrastructure (e.g., builders) before potential on-chain inclusion. Users requiring strong pre-execution privacy should be aware of this. Querying status might also leak information about submission activity.
5. **Fee Consistency:** Inconsistent fee parameters across transactions within a bundle could lead to unpredictable or undesirable selection outcomes. The specification recommends consistency. Implementations *SHOULD* document their selection behavior if fees differ.
6. **`maxBlockNumber` Reliability:** Enforcement of `maxBlockNumber` depends entirely on the implementing service. Users rely on the provider to honor this and correctly report expiry status.
7. **`bundleId` Management:** Service providers must ensure the uniqueness and proper lifecycle management (storage, lookup, garbage collection) of `bundleId`s. The scope of uniqueness (e.g., globally unique, unique per provider, time-limited) *SHOULD* be documented.
8. **Status Accuracy:** The status reported by `eth_getBlobsStatus` depends on the provider's view of the chain and internal state updates. There might be delays in detecting inclusion or processing expiry, leading to temporarily stale status information.
## Copyright
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/).
{"title":"`eth_sendBlobs` and `eth_getBlobsStatus`","description":"JSON-RPC Methods for Optimal Blob Inclusion and Status Tracking","image":"https://hackmd.io/_uploads/SJlHK_Iayg.jpg","contributors":"[{\"id\":\"61692723-37e2-4aaf-9583-0d68d223ae70\",\"add\":15560,\"del\":0}]"}