Skip to content

perf(txpool): reuse state provider across batch validation#87

Closed
panos-xyz wants to merge 17 commits intomainfrom
perf/txpool-reuse-state-provider
Closed

perf(txpool): reuse state provider across batch validation#87
panos-xyz wants to merge 17 commits intomainfrom
perf/txpool-reuse-state-provider

Conversation

@panos-xyz
Copy link
Copy Markdown
Contributor

@panos-xyz panos-xyz commented Apr 9, 2026

Summary

  • Reuse a single StateProvider across all transactions in validate_all(), instead of creating a new one per-tx
  • Leverages the existing validate_one_with_state() API from reth's EthTransactionValidator
  • As the state trie grows, opening a fresh provider per-tx becomes the dominant cost in txpool validation — this eliminates that overhead

Changes

Only crates/txpool/src/validator.rs:

  • Added validate_one_with_state() wrapper that accepts &mut Option<Box<dyn AccountInfoReader + Send>>
  • Modified validate_all() to lazily initialize and reuse the state provider across the batch
  • Original validate_one() delegates to the new method with &mut None (no behavior change for single-tx validation)

Test plan

  • Existing txpool unit tests pass
  • CI green
  • No behavior change — purely a performance optimization (same validation logic, same state snapshot)

Summary by CodeRabbit

Release Notes

  • New Features

    • Added bench-block-exec benchmarking tool with support for genesis generation, transaction workload execution, state verification, and automated results analysis.
    • Added benchmark orchestration script for multi-round performance testing across configurations.
  • Documentation

    • Added comprehensive benchmarking design and implementation specifications.

panos-xyz added 17 commits April 7, 2026 11:09
…ool txs are included

fix(bench): use txpool path for L2 transactions instead of direct Engine API injection
- Send transactions via eth_sendRawTransaction to enter txpool
- assembleL2Block with empty transactions array, node pulls from txpool
- Raise max_fee_per_gas and priority_fee for txpool acceptance
- Add jadeForkTime to genesis for geth compatibility
Comprehensive benchmark design covering three test modes (pure execution,
end-to-end pipeline, sustained block production), three workloads
(eth-transfer, erc20-transfer, uniswap-swap), multi-sender support,
state degradation testing, automatic inflection point discovery, and
chart generation.
14-task plan covering BenchSwap contract, tx_factory module,
three benchmark modes (exec/e2e/sustained), sweep automation,
extended metrics, chart generation, and orchestration script.
Avoid creating a new StateProvider for every transaction in
validate_all(). Instead, lazily initialize one on the first call and
reuse it for the rest of the batch. This leverages the existing
validate_one_with_state() API from reth's EthTransactionValidator.

The optimization matters as the state trie grows — opening a fresh
provider per-tx becomes the dominant cost in txpool validation.
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 9, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2234b748-bd81-46bc-9df8-3596b76d3ff2

📥 Commits

Reviewing files that changed from the base of the PR and between 7d75856 and 87f375c.

⛔ Files ignored due to path filters (1)
  • Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (16)
  • Cargo.toml
  • bin/bench-block-exec/Cargo.toml
  • bin/bench-block-exec/src/engine.rs
  • bin/bench-block-exec/src/genesis.rs
  • bin/bench-block-exec/src/main.rs
  • bin/bench-block-exec/src/report.rs
  • bin/bench-block-exec/src/verify.rs
  • bin/bench-block-exec/src/workload.rs
  • crates/engine-api/src/builder.rs
  • crates/txpool/src/validator.rs
  • docs/superpowers/plans/2026-04-07-max-tps-benchmark.md
  • docs/superpowers/specs/2026-04-07-max-tps-benchmark-design.md
  • local-test/bench-block-exec.sh
  • local-test/erc20-bench-contracts/.gitignore
  • local-test/erc20-bench-contracts/foundry.toml
  • local-test/erc20-bench-contracts/src/BenchToken.sol

📝 Walkthrough

Walkthrough

Adds a comprehensive benchmarking binary bench-block-exec with CLI subcommands for genesis generation, workload execution, state verification, and result reporting. Includes Solidity contract, orchestration scripts, and documentation. Also modifies payload builder resolution semantics and txpool validator to support state reuse across batches.

Changes

Cohort / File(s) Summary
Workspace Integration
Cargo.toml, bin/bench-block-exec/Cargo.toml
Added new workspace member bin/bench-block-exec with manifest defining dependencies (alloy-\*, reqwest, base64, etc.) and disabling publication.
Engine Client & JWT Auth
bin/bench-block-exec/src/engine.rs
Implements JWT-authenticated JSON-RPC client with HS256 token generation, hex/camelCase serialization helpers, typed RPC payloads (AssembleL2BlockParams, ExecutableL2Data, BlockTiming), and async methods for block assembly/import with wall-clock timing measurement.
Genesis Generation
bin/bench-block-exec/src/genesis.rs
Provides CLI args and build_genesis function to generate benchmark chain genesis JSON with configurable sender address, balance allocation, and fixed morph-specific config (chainId 99999, hardforks at block 0, zktrie disabled).
Workload Execution
bin/bench-block-exec/src/workload.rs
Runs transaction workload across multiple L2 blocks, supporting eth-transfer and erc20-transfer layers. Includes deterministic sender/receiver generation, batch transaction building (EIP-1559, EIP-2718), contract deployment, txpool submission, and per-block timing collection via JSONL output.
State Verification & Reporting
bin/bench-block-exec/src/verify.rs, bin/bench-block-exec/src/report.rs
verify.rs performs cross-node state consistency checks (block comparison, balance sampling). report.rs aggregates JSONL results into tab-separated summaries with per-group statistics (percentiles, TPS, warmup skip).
CLI Entrypoint
bin/bench-block-exec/src/main.rs
Tokio async main with clap-driven dispatch to WriteGenesis, RunWorkload, VerifyState, and Summarize subcommands.
Core Engine & Validator Updates
crates/engine-api/src/builder.rs, crates/txpool/src/validator.rs
Changed payload retrieval from best_payload to resolve_kind(PayloadKind::WaitForPending) for pending semantics. Added validate_one_with_state method; refactored validate_all to reuse single state provider across batch.
Benchmark Documentation
docs/superpowers/plans/..., docs/superpowers/specs/...
Added implementation plan and design spec for expanded "Maximum TPS" benchmark with exec/e2e/sustained modes, multi-sender support, Uniswap workload type, sweep inflection-point discovery, and chart generation infrastructure.
Local Test Infrastructure
local-test/bench-block-exec.sh, local-test/erc20-bench-contracts/*
Added orchestration Bash script that runs benchmarks across engines with fresh genesis per test, manages pm2 processes, and performs state verification. Includes Foundry-based BenchToken ERC20 contract and config.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant CLI as bench-block-exec
    participant Genesis
    participant Engine as Engine RPC
    participant Txpool as Txpool
    participant Node as L2 Node
    
    User->>CLI: RunWorkload (layer, txs_per_block, blocks)
    CLI->>Genesis: Load/read contract artifact (for ERC20)
    Genesis-->>CLI: Bytecode
    
    loop For each block
        CLI->>CLI: Build transaction batch (eth_transfer or erc20_transfer)
        CLI->>Txpool: eth_sendRawTransaction (batch)
        Txpool-->>CLI: tx hashes
        
        CLI->>Node: eth_getTransactionCount(..., "pending")
        Node-->>CLI: pending nonce (poll until batch submitted)
        
        CLI->>Engine: engine_assembleL2Block(params)
        Engine->>Node: Pull txs from txpool
        Node-->>Engine: Assembled block with txs
        Engine-->>CLI: ExecutableL2Data + timing
        
        CLI->>Engine: engine_newL2Block(data)
        Engine->>Node: Import block
        Node-->>Engine: Import complete
        Engine-->>CLI: Timing measurement
        
        CLI->>CLI: Record BlockTiming (block_number, tx_count, assemble_ms, import_ms, total_ms)
    end
    
    CLI->>CLI: Write results to JSONL
    CLI-->>User: Summary (avg total_ms, effective TPS)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested labels

enhancement

Suggested reviewers

  • chengwenxi
  • anylots

Poem

🐰 A benchmark binary hops into place,
With Genesis wand and RPC grace,
JWT tokens secure the payload flight,
Batches of txs speed through the night,
State verified and metrics compile—
Max TPS discovered with rabbit-style! 🚀

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch perf/txpool-reuse-state-provider
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch perf/txpool-reuse-state-provider

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@panos-xyz panos-xyz closed this Apr 9, 2026
@panos-xyz panos-xyz deleted the perf/txpool-reuse-state-provider branch April 9, 2026 03:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant