v3.5.0 parallel execution (Block-STM) serves incorrect receipt (wrong status + gasUsed) for mainnet tx — distinct from #22106/#22110
RPC
## Summary
On Erigon **v3.5.0** with the default parallel block execution path (Block-STM, `EXEC3_PARALLEL=true`), the node serves an **incorrect transaction receipt** for at least one Ethereum mainnet transaction: the wrong `status`, the wrong `gasUsed`, and an empty `logs` array where a log should exist.
This is **distinct** from the already-filed logIndex corruption (#22106 / PR #22110), which corrupts only `logIndex` / `cumulativeGasUsed` metadata and does not change a receipt's `status`, `gasUsed`, or drop its logs. The corruption reported here is not explained by the #22110 diff and, as far as we can find, has no existing issue.
## Environment
- **Erigon version:** v3.5.0 (`erigon/3.5.0/linux-amd64`)
- **Chain:** Ethereum mainnet
- **Node type:** archive
- **Execution mode:** parallel block execution (Block-STM), `EXEC3_PARALLEL=true` (v3.5.0 default)
## Affected transaction
| Field | Value |
|---|---|
| Block number | `25439102` (`0x1842b7e`) |
| Transaction index | `229` |
| Transaction hash | `0x6a835c4fe9782ef4376ebb0dc73d1323bff6c72b9120f27b2ba241b03f8e49c3` |
## Steps to reproduce
```bash
curl -s http://<erigon-v3.5.0-node>:8545 \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"eth_getBlockReceipts","params":["0x1842b7e"]}' \
| jq '.result[] | select(.transactionIndex=="0xe5")'
```
(`0xe5` = index 229.) `eth_getTransactionReceipt` for the tx hash returns the same incorrect values.
## Expected vs actual (tx index 229)
**Actual — served by erigon v3.5.0:**
```json
{ "status": "0x0", "gasUsed": "0x1b21a", "logs": [] }
```
**Expected — canonical:**
```json
{ "status": "0x1", "gasUsed": "0x204dc", "logs": [ /* 1 log */ ] }
```
Canonical values confirmed by 5 independent public RPC providers and an independent **geth v1.17.4** node.
## receiptsRoot mismatch (key observation)
The block header stored on the erigon node carries the **correct canonical** `receiptsRoot` `0xd95c17b2a2efc5c9a49ea84847d9698e1a3a5bcd760fce3fcdd406701294e9a8`, but the receipts the node **serves** for this block do not hash to it. The corruption is persisted in the **ReceiptDomain**, not the header.
## Broader block symptoms
- Downstream transactions show shifted `cumulativeGasUsed` and `logIndex` (the #22106 symptom).
- Tx index 229 **additionally** has wrong `status`, wrong `gasUsed`, and a missing log — the part not covered by #22106/#22110.
## Impact
- **OP-stack L1 derivation breaks.** op-node validates L1 receipts against the block's receipt root; because the served receipts don't hash to the (correct) header root, it fails with `expected receipt root X but computed Y from retrieved receipts`, **stalling L2 finality** for every L2 using this node as its L1 source.
- **Silent correctness failure.** The on-chain-canonical receipt is `status 0x1` (success); the node serves `status 0x0` (failed) with wrong `gasUsed` and a missing log. A successful transaction is served as reverted, and any consumer relying on receipt status/gas/logs is served incorrect data with no error surfaced.
## Suspected cause (not confirmed)
The Block-STM path appears to persist a receipt from a **non-final transaction incarnation** (an aborted/re-executed speculative attempt under optimistic concurrency) rather than the committed final incarnation — which would explain both the downstream `cumulativeGasUsed`/`logIndex` shift and the wrong `status`/`gasUsed`/missing-log on tx 229, while the header root (computed elsewhere) stays canonical. Hypothesis based on symptoms + confinement to the parallel-execution path.
## Relation to existing issues
- **#22106 / PR #22110** — logIndex + cumulativeGasUsed corruption under parallel execution. Does not cover the wrong `status`/`gasUsed`/dropped-log here.
- **#21490** (closed, inconclusive) — earlier parallel-execution receipt discrepancy report; possibly the same underlying class.
## Confirmed vs suspected
**Confirmed:** v3.5.0 serves `status 0x0`/`gasUsed 0x1b21a`/empty logs for tx 229; canonical is `status 0x1`/`gasUsed 0x204dc`/1 log (5 public RPCs + geth v1.17.4); header `receiptsRoot` is canonical and served receipts don't hash to it; downstream `cumulativeGasUsed`/`logIndex` shifted; op-node L1 derivation fails against this node.
**Suspected:** non-final Block-STM incarnation persisted to ReceiptDomain; same class as #21490.
## Mitigation note
`EXEC3_PARALLEL=false` stops **new** corruption but already-persisted receipts remain wrong and require **re-derivation** (re-execution of affected blocks).
14 条评论