Skip to content

chore: state bloat benchmarks#2175

Merged
0xKitsune merged 13 commits intomainfrom
tanishk/state-bloat-benchmarks
Jan 28, 2026
Merged

chore: state bloat benchmarks#2175
0xKitsune merged 13 commits intomainfrom
tanishk/state-bloat-benchmarks

Conversation

@legion2002
Copy link
Copy Markdown
Contributor

@legion2002 legion2002 commented Jan 20, 2026

Summary

Adds benchmarking infrastructure and results for comparing 2D nonces vs expiring nonces (TIP-1009) state bloat.

Key Changes

New CLI flags for tempo-bench max-tps:

  • --expiring-nonces: Use expiring nonces (TIP-1009) instead of 2D nonces
  • --expiring-batch-secs: Control batch size for pipelined signing (default: 15s worth of txs)

New ExpiringNonceFiller in tempo-alloy:

  • Sets nonce_key = U256::MAX, nonce = 0, valid_before = now + expiry_secs
  • Enables transactions to use circular buffer replay protection

Transaction request updates:

  • Added valid_before field to TempoTransactionRequest
  • Propagated through RPC compat layer

Benchmark report:

Benchmark Results (100k txs)

Metric 2D Nonces Expiring Nonces Difference
Final DB Size 4,342.85 MB 4,332.18 MB -10.67 MB
Per-Tx Savings - - ~107 bytes

Stacked on #2121

@legion2002 legion2002 changed the base branch from main to tanishk/temporary-nonces January 20, 2026 11:36
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 16612ca324

ℹ️ 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".

Comment thread crates/alloy/src/fillers/nonce.rs Outdated
Comment on lines +85 to +87
/// Returns `true` if the nonce key is already set to the expiring nonce key.
fn is_filled(tx: &TempoTransactionRequest) -> bool {
tx.nonce_key == Some(TEMPO_EXPIRING_NONCE_KEY)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Don’t skip filling when only nonce_key is set

Here ExpiringNonceFiller::is_filled returns true as soon as nonce_key is TEMPO_EXPIRING_NONCE_KEY, so the filler will skip setting valid_before (and nonce = 0) if a caller pre-populates the nonce key to opt into expiring nonces. That yields transactions missing valid_before or carrying a non‑zero nonce, which are rejected during execution (tempo_revm::handler enforces valid_before for expiring nonce txs and requires nonce == 0). This will break any client that sets nonce_key explicitly and relies on the filler for the rest. Consider treating the filler as “complete” only when both nonce_key and valid_before are set (and nonce is 0), or always overwriting these fields when the expiring key is present.

Useful? React with 👍 / 👎.

@legion2002 legion2002 force-pushed the tanishk/temporary-nonces branch from a9138b6 to 1bcc84a Compare January 21, 2026 10:31
@legion2002 legion2002 force-pushed the tanishk/temporary-nonces branch from 1bcc84a to c77380f Compare January 21, 2026 10:34
Base automatically changed from tanishk/temporary-nonces to main January 21, 2026 15:23
@legion2002 legion2002 force-pushed the tanishk/state-bloat-benchmarks branch from 5e36988 to 20e7ddb Compare January 21, 2026 18:35
Comment thread bin/tempo-bench/src/cmd/max_tps.rs
Comment thread docs/benchmarks/tip1009-state-bloat-benchmark.md Outdated
Comment thread crates/alloy/src/fillers/nonce.rs Outdated
Copy link
Copy Markdown
Contributor

@0xKitsune 0xKitsune left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pending @klkvr, can you PTAL at the alloy and rpc changes?

legion2002 and others added 10 commits January 28, 2026 19:33
Adds support for benchmarking with TIP-1009 expiring nonces:
- Add ExpiringNonceFiller to tempo-alloy that sets nonce_key=U256::MAX, nonce=0, valid_before=now+25s
- Add valid_before field to TempoTransactionRequest
- Add --expiring-nonces CLI flag to tempo-bench run-max-tps command
- Make TempoFillers type public for use in benchmarks

This enables comparing state bloat between:
- 2D nonces: unbounded state growth (new slot per tx)
- Expiring nonces: fixed 300k entry circular buffer
…mark

The expiring nonces benchmark was failing because transactions were pre-generated
with a 25-second validity window, but by the time they were sent, they had expired.

Fix:
- Make ExpiringNonceFiller configurable with custom expiry window
- Set expiry_secs = duration + 120 for benchmarking (covers generation + send time)
- Add ExpiringNonceFiller::with_expiry_secs() constructor

This ensures all pre-generated transactions remain valid throughout the benchmark.
…duration

The protocol enforces a 30-second max expiry window for expiring nonces.
For benchmarking, use shorter duration (< 20s) to ensure transactions
don't expire before being sent.
Expiring nonces have a 25-second validity window, so transactions must be
signed close to when they're sent. This adds --expiring-batch-secs flag to
control the batch size for generate/sign/send cycles.

For a 10-minute benchmark at 5k TPS with expiring nonces:
  tempo-bench run-max-tps --duration 600 --tps 5000 --expiring-nonces

The benchmark will automatically batch in 15-second chunks (75k txs each).
- Use ~100 bytes/tx from controlled 20-second test
- Note that 10-minute test had confounding factors (different block counts)
- Add clear scaling projections based on conservative estimate
- Explain circular buffer behavior and capacity
Generate next batch while sending current batch using tokio::join!
to ensure continuous transaction flow and consistent block counts.
- Fix ExpiringNonceFiller::is_filled to check all fields (nonce_key, nonce=0, valid_before)
- Handle clock drift in current_timestamp() to avoid panic
- Condense benchmark report into TIP-1009 and remove separate doc

Amp-Thread-ID: https://ampcode.com/threads/T-019c04e2-422c-72ab-9abe-4e0d6ca0085d
@legion2002 legion2002 force-pushed the tanishk/state-bloat-benchmarks branch from 6278c01 to 4937124 Compare January 28, 2026 14:04
Comment thread crates/alloy/src/fillers/nonce.rs
@0xKitsune 0xKitsune enabled auto-merge January 28, 2026 18:31
@0xKitsune 0xKitsune added this pull request to the merge queue Jan 28, 2026
Merged via the queue into main with commit d5cd4aa Jan 28, 2026
14 checks passed
@0xKitsune 0xKitsune deleted the tanishk/state-bloat-benchmarks branch January 28, 2026 18:39
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.

3 participants