Skip to content

Commit 250bd04

Browse files
marioevzCPerezz
andcommitted
feat(test-benchmark): add worst-case depth attack benchmarks for Ethereum state tries using deterministic deploy (ethereum#1976)
* feat: add worst-case depth attack benchmarks for Ethereum state tries This PR introduces comprehensive benchmarks to test Ethereum clients under worst-case scenarios involving extremely deep state and account tries. The attack scenario: - Pre-deployed contracts with deep storage tries (depth=9) maximizing traversal costs - CREATE2-based deterministic addressing for reproducible benchmarks - AttackOrchestrator contract that batches up to 2,510 attacks per transaction - Tests measure state root recomputation impact when modifying deep slots Key components: - depth_9.sol, depth_10.sol: Contracts with deep storage tries - s9_acc3.json: Pre-computed CREATE2 addresses and auxiliary accounts (15k contracts) - AttackOrchestrator.sol: Optimized attack coordinator (3,650 gas per attack) - deep_branch_testing.py: EEST test harness for pre-deployed contracts - README.md: Complete documentation and setup instructions Performance optimizations: - Reduced gas forwarding from 50k to 3,650 per attack (8.3x throughput increase) - MAX_ATTACKS_PER_TX increased from 303 to 2,510 - Precise EVM opcode cost analysis with safety margins - Read init_code_hash directly from JSON instead of recompiling Deployment setup and instructions available at: https://gist.github.com/CPerezz/44d521c0f9e6adf7d84187a4f2c11978 This benchmark helps identify performance bottlenecks in state trie handling and validates client implementations under extreme depth conditions. * fix(AttackOrchestrator): increase gas forwarded to 5300 for SSTORE The attack() call was forwarding only 3650 gas, which is insufficient for SSTORE operations on cold storage slots. SSTORE requires: - 2100 gas for cold slot access - 2900 gas for zero-to-nonzero write - Plus dispatch overhead (~200 gas) Updated to forward 5300 gas to ensure SSTORE succeeds. * feat(Verifier): add contract for post-attack storage verification Adds a minimal Verifier contract that checks if a target contract's deepest storage slot was updated to the expected attack value. This enables the test to verify attack success without expensive post-state checks on all attacked contracts. The verify() function calls getDeepest() on the target and compares the returned value against the expected attack value. * refactor(deep_branch_testing): use CREATE2 address derivation and fix gas Major refactor of the depth benchmark test for execute mode: - Remove stubs dependency; derive contract addresses directly from init_code_hash + Nick's deployer using CREATE2 formula - Deploy AttackOrchestrator and Verifier as part of test execution - Dynamically compute NUM_CONTRACTS based on gas_benchmark_value - Add verification transaction at end of block to confirm attack success - Fix gas constants based on empirical measurements: - GAS_PER_ATTACK: 8014 -> 8050 (measured ~8042) - MAX_ATTACKS_PER_TX: 1990 -> 1980 (safety margin) - TX_OVERHEAD: 22900 -> 22600 (more accurate) The previous gas constants caused all attack transactions to run out of gas, as the 28 gas/attack shortfall compounded over 1990 attacks to ~55k gas deficit. * refactor(depth-benchmarks): download assets from GitHub, embed bytecode - Embed AttackOrchestrator and Verifier bytecode directly in Python - Add download_mined_asset() to fetch JSON/SOL files from GitHub - Cache downloaded files locally in .cache/ directory - Remove local .sol and .json asset files (now downloaded on demand) - Update test parameters to use (10, 6) available from GitHub - Add gist reference for contract sources Contract sources: https://gist.github.com/CPerezz/8686da933fa5c045fbdf7c31e20e6c71 Mined assets: https://github.com/CPerezz/worst_case_miner/tree/master/mined_assets * style: run ruff format on deep_branch_testing.py * fix: add mypy type annotations for deep_branch_testing.py * refactor(depth-benchmarks): code review improvements - Remove unused ATTACK_SELECTOR constant - Extract magic numbers to named constants (gas limits, fees, etc.) - Add zero contracts validation to prevent edge case bugs - Fix unused fork parameter (rename to _fork) - Replace print warning with warnings.warn - Fix docstring math discrepancy (~2,742 not 2,750) - Fix line length issues and add proper type annotations * feat(git): Add `CPerezz/worst_case_miner` submodule * feat(tests/benchmarking): Update deep branch tests * fix: Update test file description * cleanup * refactor: Simplify using new tools * fix: Review comments * fix(tests): Update submodule * fix: review comments --------- Co-authored-by: CPerezz <cperezz19@pm.me>
1 parent 03527a9 commit 250bd04

5 files changed

Lines changed: 470 additions & 0 deletions

File tree

.gitmodules

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
[submodule "tests/benchmark/stateful/bloatnet/depth_benchmarks/.worst_case_miner"]
2+
path = tests/benchmark/stateful/bloatnet/depth_benchmarks/.worst_case_miner
3+
url = https://github.com/CPerezz/worst_case_miner
4+
branch = master
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# Depth Benchmark Tests
2+
3+
This directory contains tests for worst-case depth attacks on Ethereum state and account tries.
4+
5+
## Scenario Description
6+
7+
These benchmarks test the worst-case scenario for Ethereum clients when dealing with extremely deep state and account tries. The attack involves:
8+
9+
1. **Pre-deployed contracts** with deep storage tries that maximize trie traversal costs
10+
2. **CREATE2-based addressing** for deterministic contract addresses across test runs
11+
3. **Optimized batched attacks** using an AttackOrchestrator contract that can execute up to 1,980 attacks per transaction
12+
4. **Account trie depth** increased by funding auxiliary accounts that make the path deeper
13+
14+
The test measures the performance impact of state root recomputation and IO when modifying deep storage slots across thousands of contracts, simulating the maximum theoretical load on the state trie.
15+
16+
## Contract Sources
17+
18+
- **Pre-mined assets** (depth\__.sol, s_\_acc\*.json): https://github.com/CPerezz/worst_case_miner/tree/master/mined_assets
19+
20+
For complete deployment setup and instructions, see the gist: https://gist.github.com/CPerezz/44d521c0f9e6adf7d84187a4f2c11978
21+
22+
To update the submodule in this repository to the latest master in `CPerezz/worst_case_miner` run the following command: `git submodule update --remote --merge tests/benchmark/stateful/bloatnet/depth_benchmarks/.worst_case_miner`.
23+
24+
## Prerequisites
25+
26+
- Python with `uv` package manager
27+
- Anvil (Ethereum node implementation) or another EVM client
28+
- Nick's factory deployed at `0x4e59b44847b379578588920ca78fbf26c0b4956c` (automatically deployed by `execute` otherwise)
29+
30+
## Workflow
31+
32+
### Step 1: Start the Node (Anvil in this example)
33+
34+
```bash
35+
# Start Anvil with high gas limit and auto-mining
36+
anvil --hardfork prague --block-time 6 --steps-tracing --gas-limit 500000000 --balance 99999999999999 --port 8545
37+
```
38+
39+
### Step 2: Obtain the mined assets
40+
41+
```bash
42+
git submodule update --init --recursive
43+
```
44+
45+
### Step 3: Run Attack Test
46+
47+
Execute the worst-case depth attack test:
48+
49+
```bash
50+
# Run the attack test
51+
export RPC_ENDPOINT=<RPC endpoint>
52+
export RPC_SEED_KEY=<Account with funds>
53+
export RPC_CHAIN_ID=<RPC chain ID>
54+
uv run execute remote \
55+
--gas-benchmark-values 60 \
56+
--fork Prague \
57+
-m stateful \
58+
tests/benchmark/stateful/bloatnet/depth_benchmarks/test_deep_branch.py
59+
```
60+
61+
## Available Configurations
62+
63+
Currently available pre-mined assets from [worst_case_miner](https://github.com/CPerezz/worst_case_miner/tree/master/mined_assets):
64+
65+
| Storage Depth | Account Depth | File |
66+
| ------------- | ------------- | ------------- |
67+
| 10 | 6 | s10_acc6.json |
68+
| 10 | 7 | s10_acc7.json |
69+
| 11 | 6 | s11_acc6.json |
70+
| 11 | 7 | s11_acc7.json |
71+
72+
To generate new configurations, use [worst_case_miner](https://github.com/CPerezz/worst_case_miner).
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
"""
2+
abstract: BloatNet worst-case attack benchmark for maximum SSTORE stress.
3+
"""

0 commit comments

Comments
 (0)