perf: remove inmemory call storage - #2648
Conversation
PR Reviewer Guide 🔍(Review updated until commit 1567219)Here are some key observations to aid the review process:
|
PR Code Suggestions ✨Latest suggestions up to 1567219
Previous suggestionsSuggestions up to commit 9c069f1
|
|
Benchmark: Git Info:
Leader Stats: Follower Stats: Plots: |
5ec6f65 to
3de5211
Compare
3de5211 to
60cfe4d
Compare
60cfe4d to
1567219
Compare
There was a problem hiding this comment.
Summary
LGTM based on the provided diff context. The refactor consistently separates transaction execution outcome from state (TransactionExecutionResult vs State<Complete>) and threads the new state parameter through executor → miner → storage paths, while removing the in-memory call-specific TxCount machinery.
I did not find a concrete correctness/security/data-loss issue in the shown changes. Concurrency-sensitive paths in finish_pending_block still preserve lock ordering and now return cloned finalized state from the same stored snapshot, which is consistent with the new model.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 1567219143
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
Persistent review updated to latest commit 1567219 |
There was a problem hiding this comment.
Summary
I found one blocking correctness issue in the eth_call path after removing call-specific temporary storage.
Blocking
PointInTime::Pending is now converted into ExecutionKind::CallLatest in CallExecutionInput::from_mined_block, and rpc_call always builds call input from read_block(point_in_time.into()) using a mined BlockHeader. This means pending calls are no longer anchored to the pending header/state snapshot and can observe latest-mined semantics instead of pending semantics, which changes RPC behavior for eth_call(..., "pending").
Please restore an explicit pending-input path (or equivalent header/state source) so pending calls are executed against pending state, not coerced through mined/latest header construction.
3b3e1a2 to
02882e2
Compare
There was a problem hiding this comment.
Summary
I found one blocking correctness issue in the eth_call(..., "pending") path after the in-memory call storage removal.
Blocking
PointInTime::Pending is now coerced into ExecutionKind::CallLatest in CallExecutionInput::from_mined_block, and Executor::execute_local_call now always builds call input from read_block(point_in_time.into()) using a mined block header. This changes pending-call semantics from pending snapshot/state to latest-mined semantics (or equivalent mined-path behavior), which is a user-visible RPC contract regression for eth_call/eth_estimateGas with pending.
Please restore an explicit pending-header/state input path for pending calls (instead of mapping Pending to CallLatest through mined block construction).
02882e2 to
9df243d
Compare
There was a problem hiding this comment.
Summary
I found one blocking RPC correctness regression in the pending-call path after removing in-memory call storage.
Blocking
eth_call/eth_estimateGas with "pending" is now coerced into ExecutionKind::CallLatest via CallExecutionInput::from_mined_block (PointInTime::Pending => CallLatest(block.number)), while Executor::execute_local_call always builds call input from read_block(point_in_time.into()) using a mined BlockHeader. This changes the API contract: pending-tagged calls no longer execute against pending snapshot semantics, and instead follow latest-mined input construction.
Please restore an explicit pending-header/state input path for pending calls (or an equivalent route that preserves pending snapshot semantics) instead of mapping Pending through mined-block call construction.
|
Benchmark: Git Info:
Leader Stats: Follower Stats: Plots: |
There was a problem hiding this comment.
Found one blocking API correctness regression around pending-call semantics.
Blocking: eth_call/eth_estimateGas with "pending" no longer uses pending snapshot semantics
In this PR, call-specific temp storage and ExecutionKind::CallPending were removed, and pending calls are now mapped to ExecutionKind::CallLatest:
CallExecutionInput::from_pending_blocksetskind: CallLatest(block.number.prev().unwrap_or_default())resolve_pending::resolve_call_pointnow resolves only by block number, no tx position/pinningEntityRead::read_tempno longer receivesExecutionKind, so reads cannot distinguish pending-call position
Impact: a request explicitly targeting pending can observe latest/mined-style resolution instead of a stable pending-point view. That is a user-visible RPC contract change and can return different results under concurrent mining/tx ingestion.
Suggested fix:
- Reintroduce an execution kind/path that preserves pending context (including call position/pinning), or
- Introduce an equivalent pending snapshot mechanism used by
eth_call(..., pending)andeth_estimateGas(..., pending)so resolution is stable and not coerced through latest semantics.
Also recommend adding regression tests specifically for:
eth_call(..., pending)consistency while pending tx set changes- behavior when pending block gets mined during a call (no silent switch to a different state basis).
012754f to
0e9d389
Compare
There was a problem hiding this comment.
Summary
I found one blocking RPC correctness regression in the pending call path.
Blocking
eth_call/eth_estimateGas with "pending" is now mapped to ExecutionKind::CallLatest and loses pending-snapshot semantics. In CallExecutionInput::from_pending_block, pending calls are assigned CallLatest(block.number.prev().unwrap_or_default()), and in from_mined_block PointInTime::Pending is also coerced to CallLatest; combined with removal of CallPending/TxCount and read_temp(..., kind) this removes the ability to pin reads to a pending tx position under concurrent execution/mining.
This is a user-visible API contract change for pending-tagged calls and can return different results than the pending view clients requested.
Pull Request is not mergeable
Pull Request is not mergeable
Pull Request is not mergeable
The merge-base changed after approval.
0e9d389 to
3317ab1
Compare
There was a problem hiding this comment.
Summary
I found one blocking RPC correctness issue that is still present in the current diff.
Blocking
eth_call/eth_estimateGas with "pending" is no longer executed with pending semantics. In CallExecutionInput::from_pending_block, pending calls are mapped to ExecutionKind::CallLatest(block.number.prev().unwrap_or_default()), and from_mined_block also maps PointInTime::Pending to CallLatest; combined with removal of CallPending/TxCount and read_temp(..., kind), this drops the pending-position-aware resolution path. This is a user-visible API contract regression under concurrent tx ingestion/mining (pending-tagged calls can observe latest-mined behavior instead of the requested pending view).
Please restore an explicit pending call execution/resolution path (or equivalent pinning semantics) instead of coercing pending into CallLatest.
3317ab1 to
fffac33
Compare
There was a problem hiding this comment.
Summary
I found one blocking RPC correctness regression still present in this diff after removing call-specific temporary storage.
Blocking
eth_call / eth_estimateGas with "pending" no longer preserves pending semantics. In CallExecutionInput::from_pending_block, pending calls are converted to ExecutionKind::CallLatest(block.number.prev().unwrap_or_default()), and from_mined_block also maps PointInTime::Pending to CallLatest; combined with the removal of CallPending + TxCount and read_temp(..., kind), this eliminates the per-pending-position path and coerces pending-tagged calls into latest/mined-style resolution.
This is a user-visible API contract change under concurrent tx ingestion/mining: callers asking for pending can observe different state than the pending view they requested.
fffac33 to
526df68
Compare
There was a problem hiding this comment.
Summary
I found one blocking RPC correctness regression in the current diff.
Blocking
eth_call/eth_estimateGas with "pending" is still being coerced to latest/mined semantics after removing call-specific temporary storage. In CallExecutionInput::from_pending_block, pending calls are now created with ExecutionKind::CallLatest(block.number.prev().unwrap_or_default()), and from_mined_block also maps PointInTime::Pending to CallLatest; combined with removal of CallPending + TxCount and read_temp(..., kind), this removes pending-position-aware behavior.
This is a user-visible API contract change under concurrent tx ingestion/mining: callers asking for pending can observe a different state view than pending.
PR Type
Enhancement
Description
Remove in-memory call storage and
TxCountExtract
TransactionExecutionResultfrom execution outputsPropagate execution
stateseparately through executor and storageSimplify pending resolution and RPC call paths
File Walkthrough
3 files
Remove pending-block constructor and TxCountRemove unused `TxCount` exportRemove call storage, unify transaction temp store9 files
Export `TransactionExecutionResult` typeAdd `is_success` helper methodSplit output into `outcome` and `state`Pass `state` through executor and minerReplace output with `TransactionExecutionResult`Finalize and compare full state changesExtend `save_execution` with state parameterMap to `TransactionExecutionResult`Derive `Copy` for pending header2 files
Use `TransactionExecutionResult` in testsUpdate tests to use `TransactionExecutionResult`2 files
Fix RPC call return type to `CallExecutionOutput`Correct pending-header read without TxCount4 files
Simplify cache API signatureDrop `TxCount` and call-pending logicUpdate `save_execution` signature with stateMerge state updates without TxCount6 files