{"owner":"paradigmxyz","repo":"reth","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md"],"skills":{"AGENTS.md":"# Reth Development Guide for AI Agents\n\nThis guide provides comprehensive instructions for AI agents working on the Reth codebase. It covers the architecture, development workflows, and critical guidelines for effective contributions.\n\n## Project Overview\n\nReth is a high-performance Ethereum execution client written in Rust, focusing on modularity, performance, and contributor-friendliness. The codebase is organized into well-defined crates with clear boundaries and responsibilities.\n\n## Architecture Overview\n\n### Core Components\n\n1. **Consensus (`crates/consensus/`)**: Validates blocks according to Ethereum consensus rules\n2. **Storage (`crates/storage/`)**: Hybrid database using MDBX + static files for optimal performance\n3. **Networking (`crates/net/`)**: P2P networking stack with discovery, sync, and transaction propagation\n4. **RPC (`crates/rpc/`)**: JSON-RPC server supporting all standard Ethereum APIs\n5. **Execution (`crates/evm/`, `crates/ethereum/`)**: Transaction execution and state transitions\n6. **Pipeline (`crates/stages/`)**: Staged sync architecture for blockchain synchronization\n7. **Trie (`crates/trie/`)**: Merkle Patricia Trie implementation with a sparse trie state root task and parallel proof computation\n8. **Node Builder (`crates/node/`)**: High-level node orchestration and configuration\n9. **The Consensus Engine (`crates/engine/`)**: Handles processing blocks received from the consensus layer with the Engine API (newPayload, forkchoiceUpdated)\n\n### Key Design Principles\n\n- **Modularity**: Each crate can be used as a standalone library\n- **Performance**: Extensive use of parallelism, memory-mapped I/O, and optimized data structures\n- **Extensibility**: Traits and generic types allow for different chain implementations\n- **Type Safety**: Strong typing throughout with minimal use of dynamic dispatch\n\n## Development Workflow\n\n### Code Style and Standards\n\n1. **Formatting**: Always use nightly rustfmt\n   ```bash\n   cargo +nightly fmt --all\n   ```\n\n2. **Linting**: Run clippy with all features\n   ```bash\n   cargo +nightly clippy --workspace --lib --examples --tests --benches --all-features \n   ```\n\n3. **Testing**: Use nextest for faster test execution\n   ```bash\n   cargo nextest run --workspace\n   ```\n\n### Common Contribution Types\n\nBased on actual recent PRs, here are typical contribution patterns:\n\n#### 1. Small Bug Fixes (1-10 lines)\nReal example: Fixing beacon block root handling ([#16767](https://github.com/paradigmxyz/reth/pull/16767))\n```rust\n// Changed a single line to fix logic error\n- parent_beacon_block_root: parent.parent_beacon_block_root(),\n+ parent_beacon_block_root: parent.parent_beacon_block_root().map(|_| B256::ZERO),\n```\n\n#### 2. Integration with Upstream Changes\nReal example: Integrating revm updates ([#16752](https://github.com/paradigmxyz/reth/pull/16752))\n```rust\n// Update code to use new APIs from dependencies\n- if self.fork_tracker.is_shanghai_activated() {\n-     if let Err(err) = transaction.ensure_max_init_code_size(MAX_INIT_CODE_BYTE_SIZE) {\n+ if let Some(init_code_size_limit) = self.fork_tracker.max_initcode_size() {\n+     if let Err(err) = transaction.ensure_max_init_code_size(init_code_size_limit) {\n```\n\n#### 3. Adding Comprehensive Tests\nReal example: ETH69 protocol tests ([#16759](https://github.com/paradigmxyz/reth/pull/16759))\n```rust\n#[tokio::test(flavor = \"multi_thread\")]\nasync fn test_eth69_peers_can_connect() {\n    // Create test network with specific protocol versions\n    let p0 = PeerConfig::with_protocols(NoopProvider::default(), Some(EthVersion::Eth69.into()));\n    // Test connection and version negotiation\n}\n```\n\n#### 4. Making Components Generic\nReal example: Making EthEvmConfig generic over chainspec ([#16758](https://github.com/paradigmxyz/reth/pull/16758))\n```rust\n// Before: Hardcoded to ChainSpec\n- pub struct EthEvmConfig<EvmFactory = EthEvmFactory> {\n-     pub executor_factory: EthBlockExecutorFactory<RethReceiptBuilder, Arc<ChainSpec>, EvmFactory>,\n\n// After: Generic over any chain spec type\n+ pub struct EthEvmConfig<C = ChainSpec, EvmFactory = EthEvmFactory>\n+ where\n+     C: EthereumHardforks,\n+ {\n+     pub executor_factory: EthBlockExecutorFactory<RethReceiptBuilder, Arc<C>, EvmFactory>,\n```\n\n#### 5. Resource Management Improvements\nReal example: ETL directory cleanup ([#16770](https://github.com/paradigmxyz/reth/pull/16770))\n```rust\n// Add cleanup logic on startup\n+ if let Err(err) = fs::remove_dir_all(&etl_path) {\n+     warn!(target: \"reth::cli\", ?etl_path, %err, \"Failed to remove ETL path on launch\");\n+ }\n```\n\n#### 6. Feature Additions\nReal example: Sharded mempool support ([#16756](https://github.com/paradigmxyz/reth/pull/16756))\n```rust\n// Add new filtering policies for transaction announcements\npub struct ShardedMempoolAnnouncementFilter<T> {\n    pub inner: T,\n    pub shard_bits: u8,\n    pub node_id: Option<B256>,\n}\n```\n\n### Testing Guidelines\n\n1. **Unit Tests**: Test individual functions and components\n2. **Integration Tests**: Test interactions between components\n3. **Benchmarks**: For performance-critical code\n4. **Fuzz Tests**: For parsing and serialization code\n5. **Property Tests**: For checking component correctness on a wide variety of inputs\n\nExample test structure:\n```rust\n#[cfg(test)]\nmod tests {\n    use super::*;\n    \n    #[test]\n    fn test_component_behavior() {\n        // Arrange\n        let component = Component::new();\n        \n        // Act\n        let result = component.operation();\n        \n        // Assert\n        assert_eq!(result, expected);\n    }\n}\n```\n\n### Performance Considerations\n\n1. **Avoid Allocations in Hot Paths**: Use references and borrowing\n2. **Parallel Processing**: Use rayon for CPU-bound parallel work\n3. **Async/Await**: Use tokio for I/O-bound operations\n4. **File Operations**: Use `reth_fs_util` instead of `std::fs` for better error handling\n\n### Common Pitfalls\n\n1. **Don't Block Async Tasks**: Use `spawn_blocking` for CPU-intensive work or work with lots of blocking I/O\n2. **Handle Errors Properly**: Use `?` operator and proper error types\n\n### What to Avoid\n\nBased on PR patterns, avoid:\n\n1. **Large, sweeping changes**: Keep PRs focused and reviewable\n2. **Mixing unrelated changes**: One logical change per PR\n3. **Ignoring CI failures**: All checks must pass\n4. **Incomplete implementations**: Finish features before submitting\n5. **Modifying libmdbx sources**: Never modify files in `crates/storage/libmdbx-rs/mdbx-sys/libmdbx/` - this is vendored third-party code\n\n### CI Requirements\n\nBefore submitting changes, ensure:\n\n1. **Format Check**: `cargo +nightly fmt --all --check`\n2. **Clippy**: No warnings\n3. **Tests Pass**: All unit and integration tests\n4. **Documentation**: Update relevant docs and add doc comments with `cargo docs --document-private-items`\n5. **CLI Docs** (if CLI changed): Run `make update-book-cli` (see below)\n6. **Commit Messages**: Follow conventional format (feat:, fix:, chore:, etc.)\n\n### CLI Reference Docs (`book` CI Job)\n\nThe CLI reference pages under `docs/vocs/docs/pages/cli/` are **auto-generated** from the `reth` binary's `--help` output. **Do not edit these files manually** — any hand edits will be overwritten and CI will fail regardless.\n\nWhen you add, remove, or modify CLI commands, subcommands, or flags, regenerate the CLI docs by running:\n\n```bash\nmake update-book-cli\n```\n\nThis builds `reth` in debug mode and runs `docs/cli/update.sh` to regenerate all CLI pages. Commit the resulting changes.\n\nThe `book` CI job (`.github/workflows/lint.yml`) enforces this by regenerating the docs and running `git diff --exit-code`. If the committed docs don't match the generated output, CI fails. Manually editing these pages is never productive — always use `make update-book-cli`.\n\n### Opening PRs against <https://github.com/paradigmxyz/reth>\n\n#### Titles\n\nUse [Conventional Commits](https://www.conventionalcommits.org/) with an optional scope:\n\n```\n<type>(<scope>): <short description>\n```\n\n**Types**: `feat`, `fix`, `perf`, `refactor`, `docs`, `test`, `chore`\n\n**Scope** (optional): crate or area, e.g. `evm`, `trie`, `rpc`, `engine`, `net`\n\nExamples:\n- `fix(rpc): correct gas estimation for ERC-20 transfers`\n- `perf: batch trie updates to reduce cursor overhead`\n- `feat(engine): add new_payload_interval metric`\n\n#### Descriptions\n\nKeep it short. Say what changed and why — nothing more.\n\n**Do:**\n- Write 1–3 sentences summarizing the change\n- Explain _why_ if the diff doesn't make it obvious\n- Link related issues or EIPs\n- Include benchmark numbers for perf changes\n\n**Don't:**\n- List every file changed — that's what the diff is for\n- Repeat the title in the body\n- Add \"Files changed\" or \"Changes\" sections\n- Write walls of text that go stale when the diff is updated\n- Use filler like \"This PR introduces...\", \"comprehensive\", \"robust\", \"enhance\", \"leverage\"\n\n**Template:**\n\n```\nCloses #<issue>\n\n<what changed, 1-3 sentences>\n\n<why, if not obvious from the diff>\n```\n\n**Good example:**\n\n```\nCloses #16800\n\nAdds fallback for external IP resolution so node startup doesn't fail\nwhen STUN is unreachable. Falls back to the configured default.\n```\n\n**Bad example:**\n\n```\n## Summary\nThis PR introduces comprehensive improvements to the IP resolution system.\n\n## Changes\n- Modified `crates/net/discv4/src/lib.rs` to add fallback\n- Modified `crates/net/discv4/src/config.rs` to add default IP\n- Added tests in `crates/net/discv4/src/tests/ip.rs`\n\n## Files Changed\n- crates/net/discv4/src/lib.rs\n- crates/net/discv4/src/config.rs\n- crates/net/discv4/src/tests/ip.rs\n```\n\n#### Labels and CI\n\nLabel PRs appropriately, first check the available labels and then apply the relevant ones:\n* when changes are RPC related, add A-rpc label\n* when changes are docs related, add C-docs label\n* ... and so on, check the available labels for more options.\n* if being tasked to open a pr, ensure that all changes are properly formatted: `cargo +nightly fmt --all`\n\nIf changes in reth include changes to dependencies, run commands `zepter` and `make lint-toml` before finalizing the pr. Assume `zepter` binary is installed.\n\n### Debugging Tips\n\n1. **Logging**: Use `tracing` crate with appropriate levels\n   ```rust\n   tracing::debug!(target: \"reth::component\", ?value, \"description\");\n   ```\n\n2. **Metrics**: Add metrics for monitoring\n   ```rust\n   metrics::counter!(\"reth_component_operations\").increment(1);\n   ```\n\n3. **Test Isolation**: Use separate test databases/directories\n\n### Finding Where to Contribute\n\n1. **Check Issues**: Look for issues labeled `good-first-issue` or `help-wanted`\n2. **Review TODOs**: Search for `TODO` comments in the codebase\n3. **Improve Tests**: Areas with low test coverage are good targets\n4. **Documentation**: Improve code comments and documentation\n5. **Performance**: Profile and optimize hot paths (with benchmarks)\n\n### Common PR Patterns\n\n#### Small, Focused Changes\nMost PRs change only 1-5 files. Examples:\n- Single-line bug fixes\n- Adding a missing trait implementation\n- Updating error messages\n- Adding test cases for edge conditions\n\n#### Integration Work\nWhen dependencies update (especially revm), code needs updating:\n- Check for breaking API changes\n- Update to use new features (like EIP implementations)\n- Ensure compatibility with new versions\n\n#### Test Improvements\nTests often need expansion for:\n- New protocol versions (ETH68, ETH69)\n- Edge cases in state transitions\n- Network behavior under specific conditions\n- Concurrent operations\n\n#### Making Code More Generic\nCommon refactoring pattern:\n- Replace concrete types with generics\n- Add trait bounds for flexibility\n- Enable reuse across different chain types\n\n#### When to Comment\n\nWrite comments that remain valuable after the PR is merged. Future readers won't have PR context - they only see the current code.\n\n##### ✅ DO: Add Value\n\n**Explain WHY and non-obvious behavior:**\n```rust\n// Process must handle allocations atomically to prevent race conditions\n// between dealloc on drop and concurrent limit checks\nunsafe impl GlobalAlloc for LimitedAllocator { ... }\n\n// Binary search requires sorted input. Panics on unsorted slices.\nfn find_index(items: &[Item], target: &Item) -> Option<usize>\n\n// Timeout set to 5s to match EVM block processing limits\nconst TRACER_TIMEOUT: Duration = Duration::from_secs(5);\n```\n\n**Document constraints and assumptions:**\n```rust\n/// Returns heap size estimate.\n/// \n/// Note: May undercount shared references (Rc/Arc). For precise\n/// accounting, combine with an allocator-based approach.\nfn deep_size_of(&self) -> usize\n```\n\n**Explain complex logic:**\n```rust\n// We reset limits at task start because tokio reuses threads in\n// spawn_blocking pool. Without reset, second task inherits first\n// task's allocation count and immediately hits limit.\nTHREAD_ALLOCATED.with(|allocated| allocated.set(0));\n```\n\n##### ❌ DON'T: Describe Changes\n```rust\n// ❌ BAD - Describes the change, not the code\n// Changed from Vec to HashMap for O(1) lookups\n\n// ✅ GOOD - Explains the decision\n// HashMap provides O(1) symbol lookups during trace replay\n```\n```rust\n// ❌ BAD - PR-specific context\n// Fix for issue #234 where memory wasn't freed\n\n// ✅ GOOD - Documents the actual behavior\n// Explicitly drop allocations before limit check to ensure\n// accurate accounting\n```\n```rust\n// ❌ BAD - States the obvious\n// Increment counter\ncounter += 1;\n\n// ✅ GOOD - Explains non-obvious purpose\n// Track allocations across all threads for global limit enforcement\nGLOBAL_COUNTER.fetch_add(1, Ordering::SeqCst);\n```\n\n✅ **Comment when:**\n- Non-obvious behavior or edge cases\n- Performance trade-offs\n- Safety requirements (unsafe blocks must always be documented)\n- Limitations or gotchas\n- Why simpler alternatives don't work\n\n❌ **Don't comment when:**\n- Code is self-explanatory\n- Just restating the code in English\n- Describing what changed in this PR\n\n##### The Test: \"Will this make sense in 6 months?\"\n\nBefore adding a comment, ask: Would someone reading just the current code (no PR, no history) find this helpful?\n\n\n#### Rust Style Guides\n\n##### Type Ordering in Files\n\nWhen defining structs, traits, and functions in a file, follow this ordering convention. The file's primary type (matching the file name) comes first, followed by supporting public types, then private types and helpers.\n\n```rust\nuse ...;\n\n/// The primary type of this file (matches filename).\npub struct PayloadProcessor { ... }\n\nimpl PayloadProcessor { ... }\n\n// Followed by public auxiliary types that support the primary type\n\n/// Configuration for the processor.\npub struct PayloadProcessorConfig { ... }\n\n/// Result type returned by processor operations.\npub struct ProcessorResult { ... }\n\n// Followed by public traits related to the primary type\n\npub trait ProcessorExt { ... }\n\n// Followed by private helper types\n\nstruct InternalState { ... }\n\n// Followed by private helper functions\n\nfn validate_input() { ... }\n```\n\n❌ **Bad**: Adding new traits and auxiliary types **above** the file's primary type (see [#22133](https://github.com/paradigmxyz/reth/pull/22133)):\n\n```rust\nuse ...;\n\n// ❌ BAD - new auxiliary struct added before the file's main type\npub struct CacheWaitDurations { ... }\n\n// ❌ BAD - new trait added before the file's main type  \npub trait WaitForCaches { ... }\n\n// The file's primary type is buried below unrelated additions\npub struct PayloadProcessor { ... }\n```\n\n✅ **Good**: New types go **after** the primary type:\n\n```rust\nuse ...;\n\n// ✅ The file's primary type stays at the top\npub struct PayloadProcessor { ... }\n\nimpl PayloadProcessor { ... }\n\n// ✅ Auxiliary types follow the primary type\npub struct CacheWaitDurations { ... }\n\npub trait WaitForCaches { ... }\n\nimpl WaitForCaches for PayloadProcessor { ... }\n```\n\n### Example Contribution Workflow\n\nLet's say you want to fix a bug where external IP resolution fails on startup:\n\n1. **Create a branch**:\n   ```bash\n   git checkout -b fix-external-ip-resolution\n   ```\n\n2. **Find the relevant code**:\n   ```bash\n   # Search for IP resolution code\n   rg \"external.*ip\" --type rust\n   ```\n\n3. **Reason about the problem, when the problem is identified, make the fix**:\n   ```rust\n   // In crates/net/discv4/src/lib.rs\n   pub fn resolve_external_ip() -> Option<IpAddr> {\n       // Add fallback mechanism\n       nat::external_ip()\n           .or_else(|| nat::external_ip_from_stun())\n           .or_else(|| Some(DEFAULT_IP))\n   }\n   ```\n\n4. **Add a test**:\n   ```rust\n   #[test]\n   fn test_external_ip_fallback() {\n       // Test that resolution has proper fallbacks\n   }\n   ```\n\n5. **Run checks** (IMPORTANT!):\n   ```bash\n   cargo +nightly fmt --all\n   cargo clippy --workspace --all-features # Make sure WHOLE WORKSPACE compiles!\n   cargo nextest run -p reth-discv4\n   ```\n\n6. **Commit with clear message**:\n   ```bash\n   git commit -m \"fix: add fallback for external IP resolution\n\n   Previously, node startup could fail if external IP resolution\n   failed. This adds fallback mechanisms to ensure the node can\n   always start with a reasonable default.\"\n   ```\n\n## Quick Reference\n\n### Essential Commands\n\n```bash\n# Format code\ncargo +nightly fmt --all\n\n# Run lints\ncargo +nightly clippy --workspace --all-features\n\n# Run tests\ncargo nextest run --workspace\n\n# Run specific benchmark\ncargo bench --bench bench_name\n\n# Build optimized binary\ncargo build --release\n\n# Check compilation for all features\ncargo check --workspace --all-features\n\n# Check documentation\ncargo docs --document-private-items\n\n# Regenerate CLI reference docs (after CLI changes)\nmake update-book-cli\n```\n"},"files":{"AGENTS.md":"# Reth Development Guide for AI Agents\n\nThis guide provides comprehensive instructions for AI agents working on the Reth codebase. It covers the architecture, development workflows, and critical guidelines for effective contributions.\n\n## Project Overview\n\nReth is a high-performance Ethereum execution client written in Rust, focusing on modularity, performance, and contributor-friendliness. The codebase is organized into well-defined crates with clear boundaries and responsibilities.\n\n## Architecture Overview\n\n### Core Components\n\n1. **Consensus (`crates/consensus/`)**: Validates blocks according to Ethereum consensus rules\n2. **Storage (`crates/storage/`)**: Hybrid database using MDBX + static files for optimal performance\n3. **Networking (`crates/net/`)**: P2P networking stack with discovery, sync, and transaction propagation\n4. **RPC (`crates/rpc/`)**: JSON-RPC server supporting all standard Ethereum APIs\n5. **Execution (`crates/evm/`, `crates/ethereum/`)**: Transaction execution and state transitions\n6. **Pipeline (`crates/stages/`)**: Staged sync architecture for blockchain synchronization\n7. **Trie (`crates/trie/`)**: Merkle Patricia Trie implementation with a sparse trie state root task and parallel proof computation\n8. **Node Builder (`crates/node/`)**: High-level node orchestration and configuration\n9. **The Consensus Engine (`crates/engine/`)**: Handles processing blocks received from the consensus layer with the Engine API (newPayload, forkchoiceUpdated)\n\n### Key Design Principles\n\n- **Modularity**: Each crate can be used as a standalone library\n- **Performance**: Extensive use of parallelism, memory-mapped I/O, and optimized data structures\n- **Extensibility**: Traits and generic types allow for different chain implementations\n- **Type Safety**: Strong typing throughout with minimal use of dynamic dispatch\n\n## Development Workflow\n\n### Code Style and Standards\n\n1. **Formatting**: Always use nightly rustfmt\n   ```bash\n   cargo +nightly fmt --all\n   ```\n\n2. **Linting**: Run clippy with all features\n   ```bash\n   cargo +nightly clippy --workspace --lib --examples --tests --benches --all-features \n   ```\n\n3. **Testing**: Use nextest for faster test execution\n   ```bash\n   cargo nextest run --workspace\n   ```\n\n### Common Contribution Types\n\nBased on actual recent PRs, here are typical contribution patterns:\n\n#### 1. Small Bug Fixes (1-10 lines)\nReal example: Fixing beacon block root handling ([#16767](https://github.com/paradigmxyz/reth/pull/16767))\n```rust\n// Changed a single line to fix logic error\n- parent_beacon_block_root: parent.parent_beacon_block_root(),\n+ parent_beacon_block_root: parent.parent_beacon_block_root().map(|_| B256::ZERO),\n```\n\n#### 2. Integration with Upstream Changes\nReal example: Integrating revm updates ([#16752](https://github.com/paradigmxyz/reth/pull/16752))\n```rust\n// Update code to use new APIs from dependencies\n- if self.fork_tracker.is_shanghai_activated() {\n-     if let Err(err) = transaction.ensure_max_init_code_size(MAX_INIT_CODE_BYTE_SIZE) {\n+ if let Some(init_code_size_limit) = self.fork_tracker.max_initcode_size() {\n+     if let Err(err) = transaction.ensure_max_init_code_size(init_code_size_limit) {\n```\n\n#### 3. Adding Comprehensive Tests\nReal example: ETH69 protocol tests ([#16759](https://github.com/paradigmxyz/reth/pull/16759))\n```rust\n#[tokio::test(flavor = \"multi_thread\")]\nasync fn test_eth69_peers_can_connect() {\n    // Create test network with specific protocol versions\n    let p0 = PeerConfig::with_protocols(NoopProvider::default(), Some(EthVersion::Eth69.into()));\n    // Test connection and version negotiation\n}\n```\n\n#### 4. Making Components Generic\nReal example: Making EthEvmConfig generic over chainspec ([#16758](https://github.com/paradigmxyz/reth/pull/16758))\n```rust\n// Before: Hardcoded to ChainSpec\n- pub struct EthEvmConfig<EvmFactory = EthEvmFactory> {\n-     pub executor_factory: EthBlockExecutorFactory<RethReceiptBuilder, Arc<ChainSpec>, EvmFactory>,\n\n// After: Generic over any chain spec type\n+ pub struct EthEvmConfig<C = ChainSpec, EvmFactory = EthEvmFactory>\n+ where\n+     C: EthereumHardforks,\n+ {\n+     pub executor_factory: EthBlockExecutorFactory<RethReceiptBuilder, Arc<C>, EvmFactory>,\n```\n\n#### 5. Resource Management Improvements\nReal example: ETL directory cleanup ([#16770](https://github.com/paradigmxyz/reth/pull/16770))\n```rust\n// Add cleanup logic on startup\n+ if let Err(err) = fs::remove_dir_all(&etl_path) {\n+     warn!(target: \"reth::cli\", ?etl_path, %err, \"Failed to remove ETL path on launch\");\n+ }\n```\n\n#### 6. Feature Additions\nReal example: Sharded mempool support ([#16756](https://github.com/paradigmxyz/reth/pull/16756))\n```rust\n// Add new filtering policies for transaction announcements\npub struct ShardedMempoolAnnouncementFilter<T> {\n    pub inner: T,\n    pub shard_bits: u8,\n    pub node_id: Option<B256>,\n}\n```\n\n### Testing Guidelines\n\n1. **Unit Tests**: Test individual functions and components\n2. **Integration Tests**: Test interactions between components\n3. **Benchmarks**: For performance-critical code\n4. **Fuzz Tests**: For parsing and serialization code\n5. **Property Tests**: For checking component correctness on a wide variety of inputs\n\nExample test structure:\n```rust\n#[cfg(test)]\nmod tests {\n    use super::*;\n    \n    #[test]\n    fn test_component_behavior() {\n        // Arrange\n        let component = Component::new();\n        \n        // Act\n        let result = component.operation();\n        \n        // Assert\n        assert_eq!(result, expected);\n    }\n}\n```\n\n### Performance Considerations\n\n1. **Avoid Allocations in Hot Paths**: Use references and borrowing\n2. **Parallel Processing**: Use rayon for CPU-bound parallel work\n3. **Async/Await**: Use tokio for I/O-bound operations\n4. **File Operations**: Use `reth_fs_util` instead of `std::fs` for better error handling\n\n### Common Pitfalls\n\n1. **Don't Block Async Tasks**: Use `spawn_blocking` for CPU-intensive work or work with lots of blocking I/O\n2. **Handle Errors Properly**: Use `?` operator and proper error types\n\n### What to Avoid\n\nBased on PR patterns, avoid:\n\n1. **Large, sweeping changes**: Keep PRs focused and reviewable\n2. **Mixing unrelated changes**: One logical change per PR\n3. **Ignoring CI failures**: All checks must pass\n4. **Incomplete implementations**: Finish features before submitting\n5. **Modifying libmdbx sources**: Never modify files in `crates/storage/libmdbx-rs/mdbx-sys/libmdbx/` - this is vendored third-party code\n\n### CI Requirements\n\nBefore submitting changes, ensure:\n\n1. **Format Check**: `cargo +nightly fmt --all --check`\n2. **Clippy**: No warnings\n3. **Tests Pass**: All unit and integration tests\n4. **Documentation**: Update relevant docs and add doc comments with `cargo docs --document-private-items`\n5. **CLI Docs** (if CLI changed): Run `make update-book-cli` (see below)\n6. **Commit Messages**: Follow conventional format (feat:, fix:, chore:, etc.)\n\n### CLI Reference Docs (`book` CI Job)\n\nThe CLI reference pages under `docs/vocs/docs/pages/cli/` are **auto-generated** from the `reth` binary's `--help` output. **Do not edit these files manually** — any hand edits will be overwritten and CI will fail regardless.\n\nWhen you add, remove, or modify CLI commands, subcommands, or flags, regenerate the CLI docs by running:\n\n```bash\nmake update-book-cli\n```\n\nThis builds `reth` in debug mode and runs `docs/cli/update.sh` to regenerate all CLI pages. Commit the resulting changes.\n\nThe `book` CI job (`.github/workflows/lint.yml`) enforces this by regenerating the docs and running `git diff --exit-code`. If the committed docs don't match the generated output, CI fails. Manually editing these pages is never productive — always use `make update-book-cli`.\n\n### Opening PRs against <https://github.com/paradigmxyz/reth>\n\n#### Titles\n\nUse [Conventional Commits](https://www.conventionalcommits.org/) with an optional scope:\n\n```\n<type>(<scope>): <short description>\n```\n\n**Types**: `feat`, `fix`, `perf`, `refactor`, `docs`, `test`, `chore`\n\n**Scope** (optional): crate or area, e.g. `evm`, `trie`, `rpc`, `engine`, `net`\n\nExamples:\n- `fix(rpc): correct gas estimation for ERC-20 transfers`\n- `perf: batch trie updates to reduce cursor overhead`\n- `feat(engine): add new_payload_interval metric`\n\n#### Descriptions\n\nKeep it short. Say what changed and why — nothing more.\n\n**Do:**\n- Write 1–3 sentences summarizing the change\n- Explain _why_ if the diff doesn't make it obvious\n- Link related issues or EIPs\n- Include benchmark numbers for perf changes\n\n**Don't:**\n- List every file changed — that's what the diff is for\n- Repeat the title in the body\n- Add \"Files changed\" or \"Changes\" sections\n- Write walls of text that go stale when the diff is updated\n- Use filler like \"This PR introduces...\", \"comprehensive\", \"robust\", \"enhance\", \"leverage\"\n\n**Template:**\n\n```\nCloses #<issue>\n\n<what changed, 1-3 sentences>\n\n<why, if not obvious from the diff>\n```\n\n**Good example:**\n\n```\nCloses #16800\n\nAdds fallback for external IP resolution so node startup doesn't fail\nwhen STUN is unreachable. Falls back to the configured default.\n```\n\n**Bad example:**\n\n```\n## Summary\nThis PR introduces comprehensive improvements to the IP resolution system.\n\n## Changes\n- Modified `crates/net/discv4/src/lib.rs` to add fallback\n- Modified `crates/net/discv4/src/config.rs` to add default IP\n- Added tests in `crates/net/discv4/src/tests/ip.rs`\n\n## Files Changed\n- crates/net/discv4/src/lib.rs\n- crates/net/discv4/src/config.rs\n- crates/net/discv4/src/tests/ip.rs\n```\n\n#### Labels and CI\n\nLabel PRs appropriately, first check the available labels and then apply the relevant ones:\n* when changes are RPC related, add A-rpc label\n* when changes are docs related, add C-docs label\n* ... and so on, check the available labels for more options.\n* if being tasked to open a pr, ensure that all changes are properly formatted: `cargo +nightly fmt --all`\n\nIf changes in reth include changes to dependencies, run commands `zepter` and `make lint-toml` before finalizing the pr. Assume `zepter` binary is installed.\n\n### Debugging Tips\n\n1. **Logging**: Use `tracing` crate with appropriate levels\n   ```rust\n   tracing::debug!(target: \"reth::component\", ?value, \"description\");\n   ```\n\n2. **Metrics**: Add metrics for monitoring\n   ```rust\n   metrics::counter!(\"reth_component_operations\").increment(1);\n   ```\n\n3. **Test Isolation**: Use separate test databases/directories\n\n### Finding Where to Contribute\n\n1. **Check Issues**: Look for issues labeled `good-first-issue` or `help-wanted`\n2. **Review TODOs**: Search for `TODO` comments in the codebase\n3. **Improve Tests**: Areas with low test coverage are good targets\n4. **Documentation**: Improve code comments and documentation\n5. **Performance**: Profile and optimize hot paths (with benchmarks)\n\n### Common PR Patterns\n\n#### Small, Focused Changes\nMost PRs change only 1-5 files. Examples:\n- Single-line bug fixes\n- Adding a missing trait implementation\n- Updating error messages\n- Adding test cases for edge conditions\n\n#### Integration Work\nWhen dependencies update (especially revm), code needs updating:\n- Check for breaking API changes\n- Update to use new features (like EIP implementations)\n- Ensure compatibility with new versions\n\n#### Test Improvements\nTests often need expansion for:\n- New protocol versions (ETH68, ETH69)\n- Edge cases in state transitions\n- Network behavior under specific conditions\n- Concurrent operations\n\n#### Making Code More Generic\nCommon refactoring pattern:\n- Replace concrete types with generics\n- Add trait bounds for flexibility\n- Enable reuse across different chain types\n\n#### When to Comment\n\nWrite comments that remain valuable after the PR is merged. Future readers won't have PR context - they only see the current code.\n\n##### ✅ DO: Add Value\n\n**Explain WHY and non-obvious behavior:**\n```rust\n// Process must handle allocations atomically to prevent race conditions\n// between dealloc on drop and concurrent limit checks\nunsafe impl GlobalAlloc for LimitedAllocator { ... }\n\n// Binary search requires sorted input. Panics on unsorted slices.\nfn find_index(items: &[Item], target: &Item) -> Option<usize>\n\n// Timeout set to 5s to match EVM block processing limits\nconst TRACER_TIMEOUT: Duration = Duration::from_secs(5);\n```\n\n**Document constraints and assumptions:**\n```rust\n/// Returns heap size estimate.\n/// \n/// Note: May undercount shared references (Rc/Arc). For precise\n/// accounting, combine with an allocator-based approach.\nfn deep_size_of(&self) -> usize\n```\n\n**Explain complex logic:**\n```rust\n// We reset limits at task start because tokio reuses threads in\n// spawn_blocking pool. Without reset, second task inherits first\n// task's allocation count and immediately hits limit.\nTHREAD_ALLOCATED.with(|allocated| allocated.set(0));\n```\n\n##### ❌ DON'T: Describe Changes\n```rust\n// ❌ BAD - Describes the change, not the code\n// Changed from Vec to HashMap for O(1) lookups\n\n// ✅ GOOD - Explains the decision\n// HashMap provides O(1) symbol lookups during trace replay\n```\n```rust\n// ❌ BAD - PR-specific context\n// Fix for issue #234 where memory wasn't freed\n\n// ✅ GOOD - Documents the actual behavior\n// Explicitly drop allocations before limit check to ensure\n// accurate accounting\n```\n```rust\n// ❌ BAD - States the obvious\n// Increment counter\ncounter += 1;\n\n// ✅ GOOD - Explains non-obvious purpose\n// Track allocations across all threads for global limit enforcement\nGLOBAL_COUNTER.fetch_add(1, Ordering::SeqCst);\n```\n\n✅ **Comment when:**\n- Non-obvious behavior or edge cases\n- Performance trade-offs\n- Safety requirements (unsafe blocks must always be documented)\n- Limitations or gotchas\n- Why simpler alternatives don't work\n\n❌ **Don't comment when:**\n- Code is self-explanatory\n- Just restating the code in English\n- Describing what changed in this PR\n\n##### The Test: \"Will this make sense in 6 months?\"\n\nBefore adding a comment, ask: Would someone reading just the current code (no PR, no history) find this helpful?\n\n\n#### Rust Style Guides\n\n##### Type Ordering in Files\n\nWhen defining structs, traits, and functions in a file, follow this ordering convention. The file's primary type (matching the file name) comes first, followed by supporting public types, then private types and helpers.\n\n```rust\nuse ...;\n\n/// The primary type of this file (matches filename).\npub struct PayloadProcessor { ... }\n\nimpl PayloadProcessor { ... }\n\n// Followed by public auxiliary types that support the primary type\n\n/// Configuration for the processor.\npub struct PayloadProcessorConfig { ... }\n\n/// Result type returned by processor operations.\npub struct ProcessorResult { ... }\n\n// Followed by public traits related to the primary type\n\npub trait ProcessorExt { ... }\n\n// Followed by private helper types\n\nstruct InternalState { ... }\n\n// Followed by private helper functions\n\nfn validate_input() { ... }\n```\n\n❌ **Bad**: Adding new traits and auxiliary types **above** the file's primary type (see [#22133](https://github.com/paradigmxyz/reth/pull/22133)):\n\n```rust\nuse ...;\n\n// ❌ BAD - new auxiliary struct added before the file's main type\npub struct CacheWaitDurations { ... }\n\n// ❌ BAD - new trait added before the file's main type  \npub trait WaitForCaches { ... }\n\n// The file's primary type is buried below unrelated additions\npub struct PayloadProcessor { ... }\n```\n\n✅ **Good**: New types go **after** the primary type:\n\n```rust\nuse ...;\n\n// ✅ The file's primary type stays at the top\npub struct PayloadProcessor { ... }\n\nimpl PayloadProcessor { ... }\n\n// ✅ Auxiliary types follow the primary type\npub struct CacheWaitDurations { ... }\n\npub trait WaitForCaches { ... }\n\nimpl WaitForCaches for PayloadProcessor { ... }\n```\n\n### Example Contribution Workflow\n\nLet's say you want to fix a bug where external IP resolution fails on startup:\n\n1. **Create a branch**:\n   ```bash\n   git checkout -b fix-external-ip-resolution\n   ```\n\n2. **Find the relevant code**:\n   ```bash\n   # Search for IP resolution code\n   rg \"external.*ip\" --type rust\n   ```\n\n3. **Reason about the problem, when the problem is identified, make the fix**:\n   ```rust\n   // In crates/net/discv4/src/lib.rs\n   pub fn resolve_external_ip() -> Option<IpAddr> {\n       // Add fallback mechanism\n       nat::external_ip()\n           .or_else(|| nat::external_ip_from_stun())\n           .or_else(|| Some(DEFAULT_IP))\n   }\n   ```\n\n4. **Add a test**:\n   ```rust\n   #[test]\n   fn test_external_ip_fallback() {\n       // Test that resolution has proper fallbacks\n   }\n   ```\n\n5. **Run checks** (IMPORTANT!):\n   ```bash\n   cargo +nightly fmt --all\n   cargo clippy --workspace --all-features # Make sure WHOLE WORKSPACE compiles!\n   cargo nextest run -p reth-discv4\n   ```\n\n6. **Commit with clear message**:\n   ```bash\n   git commit -m \"fix: add fallback for external IP resolution\n\n   Previously, node startup could fail if external IP resolution\n   failed. This adds fallback mechanisms to ensure the node can\n   always start with a reasonable default.\"\n   ```\n\n## Quick Reference\n\n### Essential Commands\n\n```bash\n# Format code\ncargo +nightly fmt --all\n\n# Run lints\ncargo +nightly clippy --workspace --all-features\n\n# Run tests\ncargo nextest run --workspace\n\n# Run specific benchmark\ncargo bench --bench bench_name\n\n# Build optimized binary\ncargo build --release\n\n# Check compilation for all features\ncargo check --workspace --all-features\n\n# Check documentation\ncargo docs --document-private-items\n\n# Regenerate CLI reference docs (after CLI changes)\nmake update-book-cli\n```\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","title":"AGENTS.md","content":"# Reth Development Guide for AI Agents\n\nThis guide provides comprehensive instructions for AI agents working on the Reth codebase. It covers the architecture, development workflows, and critical guidelines for effective contributions.\n\n## Project Overview\n\nReth is a high-performance Ethereum execution client written in Rust, focusing on modularity, performance, and contributor-friendliness. The codebase is organized into well-defined crates with clear boundaries and responsibilities.\n\n## Architecture Overview\n\n### Core Components\n\n1. **Consensus (`crates/consensus/`)**: Validates blocks according to Ethereum consensus rules\n2. **Storage (`crates/storage/`)**: Hybrid database using MDBX + static files for optimal performance\n3. **Networking (`crates/net/`)**: P2P networking stack with discovery, sync, and transaction propagation\n4. **RPC (`crates/rpc/`)**: JSON-RPC server supporting all standard Ethereum APIs\n5. **Execution (`crates/evm/`, `crates/ethereum/`)**: Transaction execution and state transitions\n6. **Pipeline (`crates/stages/`)**: Staged sync architecture for blockchain synchronization\n7. **Trie (`crates/trie/`)**: Merkle Patricia Trie implementation with a sparse trie state root task and parallel proof computation\n8. **Node Builder (`crates/node/`)**: High-level node orchestration and configuration\n9. **The Consensus Engine (`crates/engine/`)**: Handles processing blocks received from the consensus layer with the Engine API (newPayload, forkchoiceUpdated)\n\n### Key Design Principles\n\n- **Modularity**: Each crate can be used as a standalone library\n- **Performance**: Extensive use of parallelism, memory-mapped I/O, and optimized data structures\n- **Extensibility**: Traits and generic types allow for different chain implementations\n- **Type Safety**: Strong typing throughout with minimal use of dynamic dispatch\n\n## Development Workflow\n\n### Code Style and Standards\n\n1. **Formatting**: Always use nightly rustfmt\n   ```bash\n   cargo +nightly fmt --all\n   ```\n\n2. **Linting**: Run clippy with all features\n   ```bash\n   cargo +nightly clippy --workspace --lib --examples --tests --benches --all-features \n   ```\n\n3. **Testing**: Use nextest for faster test execution\n   ```bash\n   cargo nextest run --workspace\n   ```\n\n### Common Contribution Types\n\nBased on actual recent PRs, here are typical contribution patterns:\n\n#### 1. Small Bug Fixes (1-10 lines)\nReal example: Fixing beacon block root handling ([#16767](https://github.com/paradigmxyz/reth/pull/16767))\n```rust\n// Changed a single line to fix logic error\n- parent_beacon_block_root: parent.parent_beacon_block_root(),\n+ parent_beacon_block_root: parent.parent_beacon_block_root().map(|_| B256::ZERO),\n```\n\n#### 2. Integration with Upstream Changes\nReal example: Integrating revm updates ([#16752](https://github.com/paradigmxyz/reth/pull/16752))\n```rust\n// Update code to use new APIs from dependencies\n- if self.fork_tracker.is_shanghai_activated() {\n-     if let Err(err) = transaction.ensure_max_init_code_size(MAX_INIT_CODE_BYTE_SIZE) {\n+ if let Some(init_code_size_limit) = self.fork_tracker.max_initcode_size() {\n+     if let Err(err) = transaction.ensure_max_init_code_size(init_code_size_limit) {\n```\n\n#### 3. Adding Comprehensive Tests\nReal example: ETH69 protocol tests ([#16759](https://github.com/paradigmxyz/reth/pull/16759))\n```rust\n#[tokio::test(flavor = \"multi_thread\")]\nasync fn test_eth69_peers_can_connect() {\n    // Create test network with specific protocol versions\n    let p0 = PeerConfig::with_protocols(NoopProvider::default(), Some(EthVersion::Eth69.into()));\n    // Test connection and version negotiation\n}\n```\n\n#### 4. Making Components Generic\nReal example: Making EthEvmConfig generic over chainspec ([#16758](https://github.com/paradigmxyz/reth/pull/16758))\n```rust\n// Before: Hardcoded to ChainSpec\n- pub struct EthEvmConfig<EvmFactory = EthEvmFactory> {\n-     pub executor_factory: EthBlockExecutorFactory<RethReceiptBuilder, Arc<ChainSpec>, EvmFactory>,\n\n// After: Generic over any chain spec type\n+ pub struct EthEvmConfig<C = ChainSpec, EvmFactory = EthEvmFactory>\n+ where\n+     C: EthereumHardforks,\n+ {\n+     pub executor_factory: EthBlockExecutorFactory<RethReceiptBuilder, Arc<C>, EvmFactory>,\n```\n\n#### 5. Resource Management Improvements\nReal example: ETL directory cleanup ([#16770](https://github.com/paradigmxyz/reth/pull/16770))\n```rust\n// Add cleanup logic on startup\n+ if let Err(err) = fs::remove_dir_all(&etl_path) {\n+     warn!(target: \"reth::cli\", ?etl_path, %err, \"Failed to remove ETL path on launch\");\n+ }\n```\n\n#### 6. Feature Additions\nReal example: Sharded mempool support ([#16756](https://github.com/paradigmxyz/reth/pull/16756))\n```rust\n// Add new filtering policies for transaction announcements\npub struct ShardedMempoolAnnouncementFilter<T> {\n    pub inner: T,\n    pub shard_bits: u8,\n    pub node_id: Option<B256>,\n}\n```\n\n### Testing Guidelines\n\n1. **Unit Tests**: Test individual functions and components\n2. **Integration Tests**: Test interactions between components\n3. **Benchmarks**: For performance-critical code\n4. **Fuzz Tests**: For parsing and serialization code\n5. **Property Tests**: For checking component correctness on a wide variety of inputs\n\nExample test structure:\n```rust\n#[cfg(test)]\nmod tests {\n    use super::*;\n    \n    #[test]\n    fn test_component_behavior() {\n        // Arrange\n        let component = Component::new();\n        \n        // Act\n        let result = component.operation();\n        \n        // Assert\n        assert_eq!(result, expected);\n    }\n}\n```\n\n### Performance Considerations\n\n1. **Avoid Allocations in Hot Paths**: Use references and borrowing\n2. **Parallel Processing**: Use rayon for CPU-bound parallel work\n3. **Async/Await**: Use tokio for I/O-bound operations\n4. **File Operations**: Use `reth_fs_util` instead of `std::fs` for better error handling\n\n### Common Pitfalls\n\n1. **Don't Block Async Tasks**: Use `spawn_blocking` for CPU-intensive work or work with lots of blocking I/O\n2. **Handle Errors Properly**: Use `?` operator and proper error types\n\n### What to Avoid\n\nBased on PR patterns, avoid:\n\n1. **Large, sweeping changes**: Keep PRs focused and reviewable\n2. **Mixing unrelated changes**: One logical change per PR\n3. **Ignoring CI failures**: All checks must pass\n4. **Incomplete implementations**: Finish features before submitting\n5. **Modifying libmdbx sources**: Never modify files in `crates/storage/libmdbx-rs/mdbx-sys/libmdbx/` - this is vendored third-party code\n\n### CI Requirements\n\nBefore submitting changes, ensure:\n\n1. **Format Check**: `cargo +nightly fmt --all --check`\n2. **Clippy**: No warnings\n3. **Tests Pass**: All unit and integration tests\n4. **Documentation**: Update relevant docs and add doc comments with `cargo docs --document-private-items`\n5. **CLI Docs** (if CLI changed): Run `make update-book-cli` (see below)\n6. **Commit Messages**: Follow conventional format (feat:, fix:, chore:, etc.)\n\n### CLI Reference Docs (`book` CI Job)\n\nThe CLI reference pages under `docs/vocs/docs/pages/cli/` are **auto-generated** from the `reth` binary's `--help` output. **Do not edit these files manually** — any hand edits will be overwritten and CI will fail regardless.\n\nWhen you add, remove, or modify CLI commands, subcommands, or flags, regenerate the CLI docs by running:\n\n```bash\nmake update-book-cli\n```\n\nThis builds `reth` in debug mode and runs `docs/cli/update.sh` to regenerate all CLI pages. Commit the resulting changes.\n\nThe `book` CI job (`.github/workflows/lint.yml`) enforces this by regenerating the docs and running `git diff --exit-code`. If the committed docs don't match the generated output, CI fails. Manually editing these pages is never productive — always use `make update-book-cli`.\n\n### Opening PRs against <https://github.com/paradigmxyz/reth>\n\n#### Titles\n\nUse [Conventional Commits](https://www.conventionalcommits.org/) with an optional scope:\n\n```\n<type>(<scope>): <short description>\n```\n\n**Types**: `feat`, `fix`, `perf`, `refactor`, `docs`, `test`, `chore`\n\n**Scope** (optional): crate or area, e.g. `evm`, `trie`, `rpc`, `engine`, `net`\n\nExamples:\n- `fix(rpc): correct gas estimation for ERC-20 transfers`\n- `perf: batch trie updates to reduce cursor overhead`\n- `feat(engine): add new_payload_interval metric`\n\n#### Descriptions\n\nKeep it short. Say what changed and why — nothing more.\n\n**Do:**\n- Write 1–3 sentences summarizing the change\n- Explain _why_ if the diff doesn't make it obvious\n- Link related issues or EIPs\n- Include benchmark numbers for perf changes\n\n**Don't:**\n- List every file changed — that's what the diff is for\n- Repeat the title in the body\n- Add \"Files changed\" or \"Changes\" sections\n- Write walls of text that go stale when the diff is updated\n- Use filler like \"This PR introduces...\", \"comprehensive\", \"robust\", \"enhance\", \"leverage\"\n\n**Template:**\n\n```\nCloses #<issue>\n\n<what changed, 1-3 sentences>\n\n<why, if not obvious from the diff>\n```\n\n**Good example:**\n\n```\nCloses #16800\n\nAdds fallback for external IP resolution so node startup doesn't fail\nwhen STUN is unreachable. Falls back to the configured default.\n```\n\n**Bad example:**\n\n```\n## Summary\nThis PR introduces comprehensive improvements to the IP resolution system.\n\n## Changes\n- Modified `crates/net/discv4/src/lib.rs` to add fallback\n- Modified `crates/net/discv4/src/config.rs` to add default IP\n- Added tests in `crates/net/discv4/src/tests/ip.rs`\n\n## Files Changed\n- crates/net/discv4/src/lib.rs\n- crates/net/discv4/src/config.rs\n- crates/net/discv4/src/tests/ip.rs\n```\n\n#### Labels and CI\n\nLabel PRs appropriately, first check the available labels and then apply the relevant ones:\n* when changes are RPC related, add A-rpc label\n* when changes are docs related, add C-docs label\n* ... and so on, check the available labels for more options.\n* if being tasked to open a pr, ensure that all changes are properly formatted: `cargo +nightly fmt --all`\n\nIf changes in reth include changes to dependencies, run commands `zepter` and `make lint-toml` before finalizing the pr. Assume `zepter` binary is installed.\n\n### Debugging Tips\n\n1. **Logging**: Use `tracing` crate with appropriate levels\n   ```rust\n   tracing::debug!(target: \"reth::component\", ?value, \"description\");\n   ```\n\n2. **Metrics**: Add metrics for monitoring\n   ```rust\n   metrics::counter!(\"reth_component_operations\").increment(1);\n   ```\n\n3. **Test Isolation**: Use separate test databases/directories\n\n### Finding Where to Contribute\n\n1. **Check Issues**: Look for issues labeled `good-first-issue` or `help-wanted`\n2. **Review TODOs**: Search for `TODO` comments in the codebase\n3. **Improve Tests**: Areas with low test coverage are good targets\n4. **Documentation**: Improve code comments and documentation\n5. **Performance**: Profile and optimize hot paths (with benchmarks)\n\n### Common PR Patterns\n\n#### Small, Focused Changes\nMost PRs change only 1-5 files. Examples:\n- Single-line bug fixes\n- Adding a missing trait implementation\n- Updating error messages\n- Adding test cases for edge conditions\n\n#### Integration Work\nWhen dependencies update (especially revm), code needs updating:\n- Check for breaking API changes\n- Update to use new features (like EIP implementations)\n- Ensure compatibility with new versions\n\n#### Test Improvements\nTests often need expansion for:\n- New protocol versions (ETH68, ETH69)\n- Edge cases in state transitions\n- Network behavior under specific conditions\n- Concurrent operations\n\n#### Making Code More Generic\nCommon refactoring pattern:\n- Replace concrete types with generics\n- Add trait bounds for flexibility\n- Enable reuse across different chain types\n\n#### When to Comment\n\nWrite comments that remain valuable after the PR is merged. Future readers won't have PR context - they only see the current code.\n\n##### ✅ DO: Add Value\n\n**Explain WHY and non-obvious behavior:**\n```rust\n// Process must handle allocations atomically to prevent race conditions\n// between dealloc on drop and concurrent limit checks\nunsafe impl GlobalAlloc for LimitedAllocator { ... }\n\n// Binary search requires sorted input. Panics on unsorted slices.\nfn find_index(items: &[Item], target: &Item) -> Option<usize>\n\n// Timeout set to 5s to match EVM block processing limits\nconst TRACER_TIMEOUT: Duration = Duration::from_secs(5);\n```\n\n**Document constraints and assumptions:**\n```rust\n/// Returns heap size estimate.\n/// \n/// Note: May undercount shared references (Rc/Arc). For precise\n/// accounting, combine with an allocator-based approach.\nfn deep_size_of(&self) -> usize\n```\n\n**Explain complex logic:**\n```rust\n// We reset limits at task start because tokio reuses threads in\n// spawn_blocking pool. Without reset, second task inherits first\n// task's allocation count and immediately hits limit.\nTHREAD_ALLOCATED.with(|allocated| allocated.set(0));\n```\n\n##### ❌ DON'T: Describe Changes\n```rust\n// ❌ BAD - Describes the change, not the code\n// Changed from Vec to HashMap for O(1) lookups\n\n// ✅ GOOD - Explains the decision\n// HashMap provides O(1) symbol lookups during trace replay\n```\n```rust\n// ❌ BAD - PR-specific context\n// Fix for issue #234 where memory wasn't freed\n\n// ✅ GOOD - Documents the actual behavior\n// Explicitly drop allocations before limit check to ensure\n// accurate accounting\n```\n```rust\n// ❌ BAD - States the obvious\n// Increment counter\ncounter += 1;\n\n// ✅ GOOD - Explains non-obvious purpose\n// Track allocations across all threads for global limit enforcement\nGLOBAL_COUNTER.fetch_add(1, Ordering::SeqCst);\n```\n\n✅ **Comment when:**\n- Non-obvious behavior or edge cases\n- Performance trade-offs\n- Safety requirements (unsafe blocks must always be documented)\n- Limitations or gotchas\n- Why simpler alternatives don't work\n\n❌ **Don't comment when:**\n- Code is self-explanatory\n- Just restating the code in English\n- Describing what changed in this PR\n\n##### The Test: \"Will this make sense in 6 months?\"\n\nBefore adding a comment, ask: Would someone reading just the current code (no PR, no history) find this helpful?\n\n\n#### Rust Style Guides\n\n##### Type Ordering in Files\n\nWhen defining structs, traits, and functions in a file, follow this ordering convention. The file's primary type (matching the file name) comes first, followed by supporting public types, then private types and helpers.\n\n```rust\nuse ...;\n\n/// The primary type of this file (matches filename).\npub struct PayloadProcessor { ... }\n\nimpl PayloadProcessor { ... }\n\n// Followed by public auxiliary types that support the primary type\n\n/// Configuration for the processor.\npub struct PayloadProcessorConfig { ... }\n\n/// Result type returned by processor operations.\npub struct ProcessorResult { ... }\n\n// Followed by public traits related to the primary type\n\npub trait ProcessorExt { ... }\n\n// Followed by private helper types\n\nstruct InternalState { ... }\n\n// Followed by private helper functions\n\nfn validate_input() { ... }\n```\n\n❌ **Bad**: Adding new traits and auxiliary types **above** the file's primary type (see [#22133](https://github.com/paradigmxyz/reth/pull/22133)):\n\n```rust\nuse ...;\n\n// ❌ BAD - new auxiliary struct added before the file's main type\npub struct CacheWaitDurations { ... }\n\n// ❌ BAD - new trait added before the file's main type  \npub trait WaitForCaches { ... }\n\n// The file's primary type is buried below unrelated additions\npub struct PayloadProcessor { ... }\n```\n\n✅ **Good**: New types go **after** the primary type:\n\n```rust\nuse ...;\n\n// ✅ The file's primary type stays at the top\npub struct PayloadProcessor { ... }\n\nimpl PayloadProcessor { ... }\n\n// ✅ Auxiliary types follow the primary type\npub struct CacheWaitDurations { ... }\n\npub trait WaitForCaches { ... }\n\nimpl WaitForCaches for PayloadProcessor { ... }\n```\n\n### Example Contribution Workflow\n\nLet's say you want to fix a bug where external IP resolution fails on startup:\n\n1. **Create a branch**:\n   ```bash\n   git checkout -b fix-external-ip-resolution\n   ```\n\n2. **Find the relevant code**:\n   ```bash\n   # Search for IP resolution code\n   rg \"external.*ip\" --type rust\n   ```\n\n3. **Reason about the problem, when the problem is identified, make the fix**:\n   ```rust\n   // In crates/net/discv4/src/lib.rs\n   pub fn resolve_external_ip() -> Option<IpAddr> {\n       // Add fallback mechanism\n       nat::external_ip()\n           .or_else(|| nat::external_ip_from_stun())\n           .or_else(|| Some(DEFAULT_IP))\n   }\n   ```\n\n4. **Add a test**:\n   ```rust\n   #[test]\n   fn test_external_ip_fallback() {\n       // Test that resolution has proper fallbacks\n   }\n   ```\n\n5. **Run checks** (IMPORTANT!):\n   ```bash\n   cargo +nightly fmt --all\n   cargo clippy --workspace --all-features # Make sure WHOLE WORKSPACE compiles!\n   cargo nextest run -p reth-discv4\n   ```\n\n6. **Commit with clear message**:\n   ```bash\n   git commit -m \"fix: add fallback for external IP resolution\n\n   Previously, node startup could fail if external IP resolution\n   failed. This adds fallback mechanisms to ensure the node can\n   always start with a reasonable default.\"\n   ```\n\n## Quick Reference\n\n### Essential Commands\n\n```bash\n# Format code\ncargo +nightly fmt --all\n\n# Run lints\ncargo +nightly clippy --workspace --all-features\n\n# Run tests\ncargo nextest run --workspace\n\n# Run specific benchmark\ncargo bench --bench bench_name\n\n# Build optimized binary\ncargo build --release\n\n# Check compilation for all features\ncargo check --workspace --all-features\n\n# Check documentation\ncargo docs --document-private-items\n\n# Regenerate CLI reference docs (after CLI changes)\nmake update-book-cli\n```\n","category":"root","tokens":4384}]}