Skip to content

Commit 574d6ff

Browse files
authored
Merge 59dc5b2 into 267e35f
2 parents 267e35f + 59dc5b2 commit 574d6ff

File tree

1 file changed

+372
-0
lines changed

1 file changed

+372
-0
lines changed
Lines changed: 372 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,372 @@
1+
---
2+
title: Transaction Inclusion Subscription
3+
description: Submit transactions and subscribe to transaction inclusion events using eth_subscribe
4+
author: Łukasz Rozmej (@LukaszRozmej)
5+
discussions-to: <TBD>
6+
status: Draft
7+
type: Standards Track
8+
category: Interface
9+
created: 2025-10-31
10+
---
11+
12+
## Abstract
13+
14+
This EIP extends the existing `eth_subscribe` JSON-RPC method with a new subscription type `transactionInclusion` that enables clients to receive real-time notifications when transactions are included in blocks. This subscription-based approach provides efficient transaction confirmation monitoring without blocking connections, supporting both combined transaction submission and monitoring in a single call, as well as monitoring of already-submitted transactions.
15+
16+
## Motivation
17+
18+
Current transaction submission workflows require separate calls to `eth_sendRawTransaction` followed by repeated polling of `eth_getTransactionReceipt`, creating unnecessary latency and network overhead. While [EIP-7966](https://github.com/ethereum/EIPs/blob/master/EIPS/eip-7966.md) proposes `eth_sendRawTransactionSync` to address this through a synchronous blocking approach, blocking HTTP connections presents significant drawbacks:
19+
20+
- **Connection hogging**: Each transaction blocks one HTTP connection until confirmation or timeout
21+
- **Limited scalability**: Cannot efficiently monitor multiple transactions over a single connection
22+
- **Timeout complexity**: Requires careful tuning of timeout parameters for different blockchain slot times
23+
- **Resource inefficiency**: Repeated polling consumes bandwidth and server resources
24+
25+
The subscription-based approach leverages the battle-tested `eth_subscribe` mechanism already implemented across all major Ethereum clients, providing superior resource efficiency and scalability while maintaining feature parity with synchronous approaches.
26+
27+
## Specification
28+
29+
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](https://www.rfc-editor.org/rfc/rfc2119) and [RFC 8174](https://www.rfc-editor.org/rfc/rfc8174).
30+
31+
### New Subscription Type
32+
33+
A new subscription type `transactionInclusion` is added to the `eth_subscribe` method.
34+
35+
### Subscription Request
36+
37+
```json
38+
{
39+
"jsonrpc": "2.0",
40+
"id": 1,
41+
"method": "eth_subscribe",
42+
"params": ["transactionInclusion", {
43+
"transaction": "0x...",
44+
"includeReorgs": false
45+
}]
46+
}
47+
```
48+
49+
Or for monitoring an already-submitted transaction:
50+
51+
```json
52+
{
53+
"jsonrpc": "2.0",
54+
"id": 1,
55+
"method": "eth_subscribe",
56+
"params": ["transactionInclusion", {
57+
"hash": "0x...",
58+
"includeReorgs": false
59+
}]
60+
}
61+
```
62+
63+
### Parameters
64+
65+
The subscription parameters object accepts the following fields:
66+
67+
- `transaction` (DATA, optional): Signed transaction data to submit and monitor. When provided, the node MUST immediately submit this transaction to the network.
68+
- `hash` (DATA, 32 bytes, optional): Transaction hash to monitor for already-submitted transactions.
69+
- `includeReorgs` (boolean, optional, default: `false`): Controls reorg monitoring behavior.
70+
- If `false`: Subscription auto-unsubscribes immediately after first inclusion notification. Reorgs are not monitored.
71+
- If `true`: Subscription actively monitors for reorgs and sends notifications for reorgs, re-inclusions, and finalization.
72+
73+
**Exactly one** of `transaction` or `hash` MUST be provided. If both or neither are provided, the node MUST return a JSON-RPC error with code `-32602` (Invalid params).
74+
75+
### Subscription Response
76+
77+
Upon successful subscription, the node MUST return a subscription ID:
78+
79+
```json
80+
{
81+
"jsonrpc": "2.0",
82+
"id": 1,
83+
"result": "0x1234567890abcdef"
84+
}
85+
```
86+
87+
### Notification Format
88+
89+
When the transaction status changes, the node MUST send a notification:
90+
91+
```json
92+
{
93+
"jsonrpc": "2.0",
94+
"method": "eth_subscription",
95+
"params": {
96+
"subscription": "0x1234567890abcdef",
97+
"result": {
98+
"status": "included",
99+
"blockHash": "0x...",
100+
"blockNumber": "0x...",
101+
"transactionIndex": "0x...",
102+
"receipt": {
103+
"transactionHash": "0x...",
104+
"transactionIndex": "0x...",
105+
"blockHash": "0x...",
106+
"blockNumber": "0x...",
107+
"from": "0x...",
108+
"to": "0x...",
109+
"cumulativeGasUsed": "0x...",
110+
"gasUsed": "0x...",
111+
"contractAddress": null,
112+
"logs": [],
113+
"logsBloom": "0x...",
114+
"status": "0x1"
115+
}
116+
}
117+
}
118+
}
119+
```
120+
121+
The `status` field MAY be one of:
122+
- `"included"`: Transaction has been included in a block
123+
- `"finalized"`: Transaction's block has reached finality (only sent when `includeReorgs` is `false`)
124+
- `"reorged"`: Transaction was removed from the canonical chain (only sent if `includeReorgs` is `true`)
125+
126+
The `receipt` field MUST contain the complete transaction receipt object as defined by `eth_getTransactionReceipt`.
127+
128+
### Behavior
129+
130+
The node MUST implement the following behavior:
131+
132+
1. **When `transaction` is provided**:
133+
- The node MUST immediately submit the transaction to the network using the same semantics as `eth_sendRawTransaction`
134+
- The node MUST derive the transaction hash and begin monitoring for inclusion
135+
- If submission fails, the node MUST return a JSON-RPC error and MUST NOT create the subscription
136+
137+
2. **Transaction Already Included**:
138+
- If the monitored transaction is already included in a block at subscription time:
139+
- If `includeReorgs` is `false`: The node MUST immediately send an inclusion notification and automatically unsubscribe
140+
- If `includeReorgs` is `true`: The node MUST immediately send an inclusion notification and continue monitoring until finalization
141+
142+
3. **Pending Transaction**:
143+
- The node MUST monitor the transaction pool and canonical chain
144+
- When the transaction is included in a block, the node MUST send an inclusion notification
145+
- If `includeReorgs` is `false`, the node MUST then automatically unsubscribe
146+
- If `includeReorgs` is `true`, the node MUST continue monitoring
147+
148+
4. **Reorg Monitoring** (when `includeReorgs` is `true`):
149+
- The node MUST continue monitoring the transaction after initial inclusion
150+
- If the transaction is removed from the canonical chain due to a reorg, the node MUST send a notification with `"status": "reorged"`
151+
- If the transaction is re-included in a different block, the node MUST send a new inclusion notification with `"status": "included"`
152+
- When the block containing the transaction reaches finality, the node MUST send a finalization notification with `"status": "finalized"`
153+
- The node MUST automatically unsubscribe after sending the finalization notification
154+
155+
5. **Auto-unsubscribe**:
156+
- If `includeReorgs` is `false`, the node MUST automatically unsubscribe after sending the first inclusion notification
157+
- The node SHOULD send an `eth_subscription` unsubscribe confirmation
158+
159+
6. **Transaction Not Found**:
160+
- If monitoring a transaction by `txHash` that doesn't exist in the mempool or chain, the subscription remains active
161+
- The node SHOULD monitor for the transaction appearing in the future
162+
- Clients MAY manually unsubscribe if desired
163+
164+
## Rationale
165+
166+
### Why Subscription Over Synchronous?
167+
168+
Subscriptions provide several advantages over the synchronous approach proposed in EIP-7966:
169+
170+
- **Non-blocking**: Clients can perform other operations while waiting for confirmation
171+
- **Multiplexing**: Multiple transactions can be monitored over a single WebSocket connection
172+
- **No timeout complexity**: Subscriptions naturally handle varying confirmation times without timeout parameters
173+
- **Proven infrastructure**: Leverages existing `eth_subscribe` implementation present in all major clients
174+
175+
The addition of the `transaction` parameter provides complete feature parity with `eth_sendRawTransactionSync` by enabling submission and monitoring in a single call.
176+
177+
### Why Extend `eth_subscribe`?
178+
179+
The `eth_subscribe` mechanism is battle-tested and already implemented across all major Ethereum clients. Extending it with a new subscription type requires minimal implementation effort compared to introducing entirely new RPC methods.
180+
181+
### Why Support Both `transaction` and `hash`?
182+
183+
Supporting both parameters provides maximum flexibility:
184+
185+
- `transaction`: Optimal for new transactions, matching the convenience of synchronous methods
186+
- `hash`: Enables monitoring of transactions submitted through other means or by other parties
187+
188+
### Why Support Reorg Monitoring?
189+
190+
Applications requiring high confidence in transaction finality benefit from reorg notifications. This is particularly important on chains with faster block times where reorgs may be more common. The optional nature of this feature allows applications to choose the appropriate trade-off between functionality and resource usage.
191+
192+
### Resource Efficiency
193+
194+
A single WebSocket connection can support unlimited concurrent transaction subscriptions, whereas synchronous approaches require one blocking HTTP connection per transaction. This represents a significant improvement in resource utilization for applications monitoring multiple transactions.
195+
196+
### Why Always Auto-unsubscribe?
197+
198+
Both modes auto-unsubscribe to prevent unbounded subscription accumulation and provide clear lifecycle management:
199+
200+
- **`includeReorgs: false`**: Unsubscribes immediately after first inclusion for fast feedback with minimal resource usage. Users accepting this mode understand the transaction may still be reorged and can manually monitor if needed.
201+
- **`includeReorgs: true`**: Unsubscribes after finalization when reorgs are no longer possible, providing complete transaction lifecycle monitoring.
202+
203+
The key difference is the level of guarantee:
204+
- `includeReorgs: false`: Fast notification, transaction is included (may still reorg)
205+
- `includeReorgs: true`: Complete lifecycle tracking until finality (cannot reorg)
206+
207+
## Backwards Compatibility
208+
209+
This EIP is fully backwards compatible. It extends the existing `eth_subscribe` method with a new subscription type. Clients that have not implemented this feature will return a standard JSON-RPC error indicating the subscription type is not supported. Existing applications continue to function unchanged.
210+
211+
## Test Cases
212+
213+
### Test Case 1: Submit and Monitor
214+
215+
**Request:**
216+
```json
217+
{
218+
"jsonrpc": "2.0",
219+
"id": 1,
220+
"method": "eth_subscribe",
221+
"params": ["transactionInclusion", {
222+
"transaction": "0xf86c098504a817c800825208943535353535353535353535353535353535353535880de0b6b3a76400008025a028ef61340bd939bc2195fe537567866003e1a15d3c71ff63e1590620aa636276a067cbe9d8997f761aecb703304b3800ccf555c9f3dc64214b297fb1966a3b6d83"
223+
}]
224+
}
225+
```
226+
227+
**Expected Behavior:**
228+
1. Node submits transaction to network
229+
2. Node returns subscription ID
230+
3. When transaction is included, node sends notification with `"status": "included"` and receipt
231+
4. Subscription automatically closes immediately
232+
233+
### Test Case 2: Monitor Existing Transaction
234+
235+
**Request:**
236+
```json
237+
{
238+
"jsonrpc": "2.0",
239+
"id": 1,
240+
"method": "eth_subscribe",
241+
"params": ["transactionInclusion", {
242+
"hash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
243+
"includeReorgs": false
244+
}]
245+
}
246+
```
247+
248+
**Expected Behavior:**
249+
1. If transaction already included, immediately send notification with `"status": "included"`
250+
2. If transaction pending, wait and send notification upon inclusion
251+
3. Subscription automatically closes immediately after notification
252+
253+
### Test Case 3: Reorg Monitoring
254+
255+
**Request:**
256+
```json
257+
{
258+
"jsonrpc": "2.0",
259+
"id": 1,
260+
"method": "eth_subscribe",
261+
"params": ["transactionInclusion", {
262+
"hash": "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef",
263+
"includeReorgs": true
264+
}]
265+
}
266+
```
267+
268+
**Expected Behavior:**
269+
1. Send inclusion notification when transaction is included (with `"status": "included"`)
270+
2. Continue monitoring for reorgs
271+
3. If reorg occurs, send reorg notification (with `"status": "reorged"`)
272+
4. If re-included, send new inclusion notification (with `"status": "included"`)
273+
5. When block is finalized, send finalization notification (with `"status": "finalized"`)
274+
6. Subscription automatically closes after finalization
275+
276+
### Test Case 4: Invalid Parameters
277+
278+
**Request:**
279+
```json
280+
{
281+
"jsonrpc": "2.0",
282+
"id": 1,
283+
"method": "eth_subscribe",
284+
"params": ["transactionInclusion", {
285+
"includeReorgs": false
286+
}]
287+
}
288+
```
289+
290+
**Expected Response:**
291+
```json
292+
{
293+
"jsonrpc": "2.0",
294+
"id": 1,
295+
"error": {
296+
"code": -32602,
297+
"message": "Invalid params: exactly one of transaction or hash must be provided"
298+
}
299+
}
300+
```
301+
302+
## Reference Implementation
303+
304+
A minimal reference implementation can be realized by:
305+
306+
1. For `signedTransaction` parameter: Call internal `eth_sendRawTransaction` logic and capture the transaction hash
307+
2. Register the transaction hash in a subscription manager
308+
3. Monitor the transaction pool and canonical chain for the transaction
309+
4. When the transaction is included in a block, query the receipt and send notification
310+
5. If `includeReorgs` is false, automatically unsubscribe after first inclusion
311+
6. If `includeReorgs` is true, continue monitoring for chain reorganizations
312+
313+
Implementation pseudo-code:
314+
315+
```python
316+
def handle_transaction_inclusion_subscription(params):
317+
if 'transaction' in params:
318+
tx_hash = submit_transaction(params['transaction'])
319+
elif 'hash' in params:
320+
tx_hash = params['hash']
321+
else:
322+
raise InvalidParamsError()
323+
324+
include_reorgs = params.get('includeReorgs', False)
325+
subscription_id = generate_subscription_id()
326+
327+
register_subscription(subscription_id, tx_hash, include_reorgs)
328+
return subscription_id
329+
330+
def on_block_added(block):
331+
for tx in block.transactions:
332+
subscriptions = get_subscriptions_for_tx(tx.hash)
333+
for sub in subscriptions:
334+
receipt = get_transaction_receipt(tx.hash)
335+
send_notification(sub.id, 'included', receipt)
336+
if not sub.include_reorgs:
337+
unsubscribe(sub.id)
338+
339+
def on_chain_reorg(old_blocks, new_blocks):
340+
removed_txs = get_transactions_from_blocks(old_blocks)
341+
for tx_hash in removed_txs:
342+
subscriptions = get_subscriptions_for_tx(tx_hash)
343+
for sub in subscriptions:
344+
if sub.include_reorgs:
345+
send_notification(sub.id, 'reorged', None)
346+
347+
def on_block_finalized(block):
348+
for tx in block.transactions:
349+
subscriptions = get_subscriptions_for_tx(tx.hash)
350+
for sub in subscriptions:
351+
receipt = get_transaction_receipt(tx.hash)
352+
send_notification(sub.id, 'finalized', receipt)
353+
unsubscribe(sub.id)
354+
```
355+
356+
## Security Considerations
357+
358+
### Transaction Submission Validation
359+
360+
When `transaction` is provided, nodes MUST perform the same validation as `eth_sendRawTransaction` before creating the subscription. Invalid transactions MUST result in an error response without creating a subscription.
361+
362+
### Privacy Considerations
363+
364+
Monitoring transactions by hash does not introduce new privacy concerns beyond existing `eth_getTransactionReceipt` polling. However, applications should be aware that subscribing to transaction hashes reveals interest in those transactions to the node operator.
365+
366+
### Reorg Attack Considerations
367+
368+
Applications using `includeReorgs: true` should implement appropriate logic to handle reorg notifications, particularly on chains where reorgs may be used maliciously. The notification mechanism provides transparency but does not prevent reorg-based attacks.
369+
370+
## Copyright
371+
372+
Copyright and related rights waived via [CC0](../LICENSE.md).

0 commit comments

Comments
 (0)