ethereum-optimism / ethereum-optimism/optimism
op-service/sources: recover the transaction hash / decode caching lost with RawTransactions
- Dominant language
- Go
- Stars
- 6.5k
- Forks
- 4k
- Avg merge
- 2d 9h
- Merged PRs (30d)
- 165
Description
`op-service/sources` now keeps block transactions as canonical bytes
([`RawTransactions`](https://github.com/ethereum-optimism/optimism/blob/454d3080862a38faa3e8a11688969fefe1108b88/op-service/sources/raw_transaction.go#L120-L141))
instead of `types.Transactions` (#21908, part of #20264). That trade is deliberate — it is what
lets an L2 block round-trip OP synthetic transactions without go-ethereum's typed decoding — but
it drops two memoizations that `types.Transaction` provided for free. Observed by @joshklop while
reviewing #21908.
## What is lost
1. **Hash cache.** `types.Transaction` caches its hash after the first `Hash()` call.
[`RawTransaction.Hash()`](https://github.com/ethereum-optimism/optimism/blob/454d3080862a38faa3e8a11688969fefe1108b88/op-service/sources/raw_transaction.go#L36-L40)
keccaks the bytes on every call, and
[`RawTransactions.Hashes()`](https://github.com/ethereum-optimism/optimism/blob/454d3080862a38faa3e8a11688969fefe1108b88/op-service/sources/raw_transaction.go#L134-L141)
does it for the whole block.
2. **Decoded-tx reuse.** The client's
[`transactionsCache`](https://github.com/ethereum-optimism/optimism/blob/454d3080862a38faa3e8a11688969fefe1108b88/op-service/sources/eth_client.go#L137)
holds raw bytes, so the typed views —
[`Geth()`](https://github.com/ethereum-optimism/optimism/blob/454d3080862a38faa3e8a11688969fefe1108b88/op-service/sources/raw_transaction.go#L149-L159),
`UserTxs()`, `Deposits()` — RLP-decode the block again on every cache hit, where the old cache
returned already-decoded transactions.
Both are per-call costs on cache hits; the first fetch of a block is not slower (it was decoding
and hashing then too). The paths that pay repeatedly:
- [`FetchReceipts`](https://github.com/ethereum-optimism/optimism/blob/454d3080862a38faa3e8a11688969fefe1108b88/op-service/sources/eth_client.go#L529-L543)
— rehashes every transaction of the block per call, including on cache hits and retries.
- [`HeaderAndTxsByHash`](https://github.com/ethereum-optimism/optimism/blob/454d3080862a38faa3e8a11688969fefe1108b88/op-service/sources/eth_client.go#L339-L352)
/ `InfoAndTxsBy*` and the class-partitioned accessors — re-decode per call.
## What is gained (the other side of the trade)
Transactions-root derivation and execution-payload construction operate on the canonical bytes
directly and no longer re-encode each transaction, and JSON ingress encodes once per transaction
rather than decode-then-re-encode on demand.
## Possible fix
Measure first — for L1 blocks in op-node derivation this is likely noise next to the RPC round
trip, and no cache is worth adding blind. If it does show up:
- **Cache next to the bytes, not inside them.** Have `transactionsCache` hold the raw transactions
plus their lazily-derived hashes (and possibly the decoded typed view), keyed by block hash.
Keeps `RawTransaction` a plain `[]byte` alias.
- **Memoize on the type.** Turn `RawTransaction` into a struct with a lazily computed hash. Costs
the `[]byte` semantics that `EncodeIndex`, the JSON codecs, and payload pass-through rely on.
The first option looks cheaper and is confined to the client.
Refs #20264, #21908.
🤖 *Co-created with Claude Opus 5*
Contributor guide
Research direction
Start in op-service/sources/raw_transaction.go and eth_client.go, then measure cache-hit behavior through FetchReceipts, HeaderAndTxsByHash, and the class-partitioned accessors. Compare repeated hashing and decoding costs before choosing an approach; done means the impact is documented and, if significant, the selected caching design is implemented with evidence that repeated work is reduced.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go
- Domain
- backend, performance
- Issue type
- Refactor
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 32/100