|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Development Commands |
| 6 | + |
| 7 | +**Important**: Always branch from `unstable` and target `unstable` when creating pull requests. |
| 8 | + |
| 9 | +### Building and Installation |
| 10 | +- `make install` - Build and install the main Lighthouse binary in release mode |
| 11 | +- `make install-lcli` - Build and install the `lcli` utility binary |
| 12 | +- `cargo build --release` - Standard Rust release build |
| 13 | +- `cargo build --bin lighthouse --features "gnosis,slasher-lmdb"` - Build with specific features |
| 14 | + |
| 15 | +### Testing |
| 16 | +- `make test` - Run the full test suite in release mode (excludes EF tests, beacon_chain, slasher, network, http_api) |
| 17 | +- `make nextest-release` - Run tests using nextest (faster parallel test runner) |
| 18 | +- `make test-beacon-chain` - Run beacon chain tests for all supported forks |
| 19 | +- `make test-slasher` - Run slasher tests with all database backend combinations |
| 20 | +- `make test-ef` - Download and run Ethereum Foundation test vectors |
| 21 | +- `make test-full` - Complete test suite including linting, EF tests, and execution engine tests |
| 22 | +- `cargo test -p <package_name>` - Run tests for a specific package |
| 23 | +- `cargo test -p <package_name> <test_name>` - Run individual test (preferred during development iteration) |
| 24 | +- `FORK_NAME=electra cargo nextest run -p beacon_chain` - Run tests for specific fork |
| 25 | + |
| 26 | +**Note**: Full test suite takes ~20 minutes. When iterating, prefer running individual tests. |
| 27 | + |
| 28 | +### Linting and Code Quality |
| 29 | +- `make lint` - Run Clippy linter with project-specific rules |
| 30 | +- `make lint-full` - Run comprehensive linting including tests (recommended for thorough checking) |
| 31 | +- `make cargo-fmt` - Check code formatting with rustfmt |
| 32 | +- `make check-benches` - Typecheck benchmark code |
| 33 | +- `make audit` - Run security audit on dependencies |
| 34 | + |
| 35 | +### Cross-compilation |
| 36 | +- `make build-x86_64` - Cross-compile for x86_64 Linux |
| 37 | +- `make build-aarch64` - Cross-compile for ARM64 Linux |
| 38 | +- `make build-riscv64` - Cross-compile for RISC-V 64-bit Linux |
| 39 | + |
| 40 | +## Architecture Overview |
| 41 | + |
| 42 | +Lighthouse is a modular Ethereum consensus client with two main components: |
| 43 | + |
| 44 | +### Core Components |
| 45 | + |
| 46 | +**Beacon Node** (`beacon_node/`) |
| 47 | +- Main consensus client that syncs with the Ethereum network |
| 48 | +- Contains the beacon chain state transition logic (`beacon_node/beacon_chain/`) |
| 49 | +- Handles networking, storage, and P2P communication |
| 50 | +- Provides HTTP API for validator clients and external tools |
| 51 | +- Entry point: `beacon_node/src/lib.rs` |
| 52 | + |
| 53 | +**Validator Client** (`validator_client/`) |
| 54 | +- Manages validator keystores and performs validator duties |
| 55 | +- Connects to beacon nodes via HTTP API |
| 56 | +- Handles block proposals, attestations, and sync committee duties |
| 57 | +- Includes slashing protection and doppelganger detection |
| 58 | +- Entry point: `validator_client/src/lib.rs` |
| 59 | + |
| 60 | +### Key Subsystems |
| 61 | + |
| 62 | +**Consensus Types** (`consensus/types/`) |
| 63 | +- Core Ethereum consensus data structures (BeaconState, BeaconBlock, etc.) |
| 64 | +- Ethereum specification implementations for different networks (mainnet, gnosis) |
| 65 | +- SSZ encoding/decoding and state transition primitives |
| 66 | + |
| 67 | +**Storage** (`beacon_node/store/`) |
| 68 | +- Hot/cold database architecture for efficient beacon chain storage |
| 69 | +- Supports multiple backends (LevelDB, RocksDB, REDB) |
| 70 | +- Handles state pruning and historical data management |
| 71 | + |
| 72 | +**Networking** (`beacon_node/lighthouse_network/`, `beacon_node/network/`) |
| 73 | +- Libp2p-based P2P networking stack |
| 74 | +- Gossipsub for message propagation |
| 75 | +- Discovery v5 for peer discovery |
| 76 | +- Request/response protocols for sync |
| 77 | + |
| 78 | +**Fork Choice** (`consensus/fork_choice/`, `consensus/proto_array/`) |
| 79 | +- Implements Ethereum's fork choice algorithm (proto-array) |
| 80 | +- Manages chain reorganizations and finality |
| 81 | + |
| 82 | +**Execution Layer Integration** (`beacon_node/execution_layer/`) |
| 83 | +- Interfaces with execution clients |
| 84 | +- Retrieves payloads from local execution layer or external block builders |
| 85 | +- Handles payload validation and builder integration |
| 86 | + |
| 87 | +**Slasher** (`slasher/`) |
| 88 | +- Optional slashing detection service |
| 89 | +- Supports LMDB, MDBX, and REDB database backends |
| 90 | +- Can be enabled with `--slasher` flag |
| 91 | + |
| 92 | +### Utilities |
| 93 | + |
| 94 | +**Account Manager** (`account_manager/`) - CLI tool for managing validator accounts and keystores |
| 95 | +**LCLI** (`lcli/`) - Lighthouse command-line utilities for debugging and testing |
| 96 | +**Database Manager** (`database_manager/`) - Database maintenance and migration tools |
| 97 | + |
| 98 | +### Build System Notes |
| 99 | + |
| 100 | +- Uses Cargo workspace with 90+ member crates |
| 101 | +- Supports multiple Ethereum specifications via feature flags (`gnosis`, `spec-minimal`) |
| 102 | +- Cross-compilation support for Linux x86_64, ARM64, and RISC-V |
| 103 | +- Multiple build profiles: `release`, `maxperf`, `reproducible` |
| 104 | +- Feature-based compilation for different database backends and optional components |
| 105 | + |
| 106 | +### Network Support |
| 107 | + |
| 108 | +- **Mainnet**: Default production network |
| 109 | +- **Gnosis**: Alternative network (requires `gnosis` feature) |
| 110 | +- **Testnets**: Holesky, Sepolia via built-in network configs |
| 111 | +- **Custom networks**: Via `--testnet-dir` flag |
| 112 | + |
| 113 | +### Key Configuration |
| 114 | + |
| 115 | +- Default data directory: `~/.lighthouse/{network}` |
| 116 | +- Beacon node data: `~/.lighthouse/{network}/beacon` |
| 117 | +- Validator data: `~/.lighthouse/{network}/validators` |
| 118 | +- Configuration primarily via CLI flags and YAML files |
| 119 | + |
| 120 | +## Common Review Standards |
| 121 | + |
| 122 | +### CI/Testing Requirements |
| 123 | +- All checks must pass before merge |
| 124 | +- Test coverage expected for significant changes |
| 125 | +- Flaky tests are actively addressed and fixed |
| 126 | +- New features often require corresponding tests |
| 127 | +- `beacon_chain` and `http_api` tests support fork-specific testing using `FORK_NAME` env var when `beacon_chain/fork_from_env` feature is enabled |
| 128 | + |
| 129 | +### Code Quality Standards |
| 130 | +- Clippy warnings must be fixed promptly (multiple PRs show this pattern) |
| 131 | +- Code formatting with `cargo fmt` enforced |
| 132 | +- Must run `cargo sort` when adding dependencies - dependency order is enforced on CI |
| 133 | +- Performance considerations for hot paths |
| 134 | + |
| 135 | +### Documentation and Context |
| 136 | +- PRs require clear descriptions of what and why |
| 137 | +- Breaking changes need migration documentation |
| 138 | +- API changes require documentation updates |
| 139 | +- When CLI is updated, run `make cli-local` to generate updated help text in lighthouse book |
| 140 | +- Comments appreciated for complex logic |
| 141 | + |
| 142 | +### Security and Safety |
| 143 | +- Careful review of consensus-critical code paths |
| 144 | +- Error handling patterns must be comprehensive |
| 145 | +- Input validation for external data |
| 146 | + |
| 147 | +## Development Patterns and Best Practices |
| 148 | + |
| 149 | +### Panics and Error Handling |
| 150 | +- **Panics should be avoided at all costs** |
| 151 | +- Always prefer returning a `Result` or `Option` over causing a panic (e.g., prefer `array.get(1)?` over `array[1]`) |
| 152 | +- Avoid `expect` or `unwrap` at runtime - only acceptable during startup when validating CLI flags or configurations |
| 153 | +- If you must make assumptions about panics, use `.expect("Helpful message")` instead of `.unwrap()` and provide detailed reasoning in nearby comments |
| 154 | +- Use proper error handling with `Result` types and graceful error propagation |
| 155 | + |
| 156 | +### Rayon Usage |
| 157 | +- Avoid using the rayon global thread pool as it results in CPU oversubscription when the beacon processor has fully allocated all CPUs to workers |
| 158 | +- Use scoped rayon pools started by beacon processor for computational intensive tasks |
| 159 | + |
| 160 | +### Locks |
| 161 | +- Take great care to avoid deadlocks when working with fork choice locks - seek detailed review ([reference](beacon_node/beacon_chain/src/canonical_head.rs:9)) |
| 162 | +- Keep lock scopes as narrow as possible to avoid blocking fast-responding functions like the networking stack |
| 163 | + |
| 164 | +### Async Patterns |
| 165 | +- Avoid blocking computations in async tasks |
| 166 | +- Spawn a blocking task instead for CPU-intensive work |
| 167 | + |
| 168 | +### Tracing |
| 169 | +- Design spans carefully and avoid overuse of spans just to add context data to events |
| 170 | +- Avoid using spans on simple getter methods as it can result in performance overhead |
| 171 | +- Be cautious of span explosion with recursive functions |
| 172 | +- Use spans per meaningful step or computationally critical step |
| 173 | +- Avoid using `span.enter()` or `span.entered()` in async tasks |
| 174 | + |
| 175 | +### Database |
| 176 | +- Maintain schema continuity on `unstable` branch |
| 177 | +- Database migrations must be backward compatible |
| 178 | + |
| 179 | +### Consensus Crate |
| 180 | +- Use safe math methods like `saturating_xxx` or `checked_xxx` |
| 181 | +- Critical that this crate behaves deterministically and MUST not have undefined behavior |
| 182 | + |
| 183 | +### Testing Patterns |
| 184 | +- **Use appropriate test types for the right scenarios**: |
| 185 | + - **Unit tests** for single component edge cases and isolated logic |
| 186 | + - **Integration tests** using [`BeaconChainHarness`](beacon_node/beacon_chain/src/test_utils.rs:668) for end-to-end workflows |
| 187 | +- **`BeaconChainHarness` guidelines**: |
| 188 | + - Excellent for integration testing but slower than unit tests |
| 189 | + - Prefer unit tests instead for testing edge cases of single components |
| 190 | + - Reserve for testing component interactions and full workflows |
| 191 | +- **Mocking strategies**: |
| 192 | + - Use `mockall` crate for unit test mocking |
| 193 | + - Use `mockito` for HTTP API mocking (see [`validator_test_rig`](testing/validator_test_rig/src/mock_beacon_node.rs:20) for examples) |
| 194 | +- **Event-based testing for sync components**: |
| 195 | + - Use [`TestRig`](beacon_node/network/src/sync/tests/mod.rs) pattern for testing sync components |
| 196 | + - Sync components interact with the network and beacon chain via events (their public API), making event-based testing more suitable than using internal functions and mutating internal states |
| 197 | + - Enables testing of complex state transitions and timing-sensitive scenarios |
| 198 | +- **Testing `BeaconChain` dependent components**: |
| 199 | + - `BeaconChain` is difficult to create for TDD |
| 200 | + - Create intermediate adapter structs to enable easy mocking |
| 201 | + - See [`beacon_node/beacon_chain/src/fetch_blobs/tests.rs`](beacon_node/beacon_chain/src/fetch_blobs/tests.rs) for the adapter pattern |
| 202 | +- **Local testnet for manual/full E2E testing**: |
| 203 | + - Use Kurtosis-based local testnet setup for comprehensive testing |
| 204 | + - See [`scripts/local_testnet/README.md`](scripts/local_testnet/README.md) for setup instructions |
| 205 | + |
| 206 | +### TODOs and Comments |
| 207 | +- All `TODO` statements must be accompanied by a GitHub issue link |
| 208 | +- Prefer line (`//`) comments to block comments (`/* ... */`) |
| 209 | +- Use doc comments (`///`) before attributes for public items |
| 210 | +- Keep documentation concise and clear - avoid verbose explanations |
| 211 | +- Provide examples in doc comments for public APIs when helpful |
| 212 | + |
| 213 | +## Logging Guidelines |
| 214 | +Use appropriate log levels for different scenarios: |
| 215 | +- **`crit`**: Critical issues with major impact to Lighthouse functionality - Lighthouse may not function correctly without resolving. Needs immediate attention. |
| 216 | +- **`error`**: Error cases that may have moderate impact to Lighthouse functionality. Expect to receive reports from users for this level. |
| 217 | +- **`warn`**: Unexpected code paths that don't have major impact - fully recoverable. Expect user reports if excessive warning logs occur. |
| 218 | +- **`info`**: High-level logs indicating beacon node status and block import status. Should not be used excessively. |
| 219 | +- **`debug`**: Events lower level than info useful for developers. Can also log errors expected during normal operation that users don't need to action. |
| 220 | + |
| 221 | +## Code Examples |
| 222 | + |
| 223 | +### Safe Math in Consensus Crate |
| 224 | +```rust |
| 225 | +// ❌ Avoid - could panic |
| 226 | +let result = a + b; |
| 227 | + |
| 228 | +// ✅ Preferred |
| 229 | +let result = a.saturating_add(b); |
| 230 | +// or |
| 231 | +use safe_arith::SafeArith; |
| 232 | + |
| 233 | +let result = a.safe_add(b)?; |
| 234 | +``` |
| 235 | + |
| 236 | +### Panics and Error Handling |
| 237 | +```rust |
| 238 | +// ❌ Avoid - could panic at runtime |
| 239 | +let value = some_result.unwrap(); |
| 240 | +let item = array[1]; |
| 241 | + |
| 242 | +// ✅ Preferred - proper error handling |
| 243 | +let value = some_result.map_err(|e| CustomError::SomeVariant(e))?; |
| 244 | +let item = array.get(1)?; |
| 245 | + |
| 246 | +// ✅ Acceptable during startup for CLI/config validation |
| 247 | +let config_value = matches.get_one::<String>("required-flag") |
| 248 | + .expect("Required flag must be present due to clap validation"); |
| 249 | + |
| 250 | +// ✅ If you must make runtime assumptions, use expect with explanation |
| 251 | +let item = array.get(1).expect("Array always has at least 2 elements due to validation in constructor"); |
| 252 | +// Detailed reasoning should be provided in nearby comments |
| 253 | +``` |
| 254 | + |
| 255 | +### TODO Format |
| 256 | +```rust |
| 257 | +pub fn my_function(&mut self, _something: &[u8]) -> Result<String, Error> { |
| 258 | + // TODO: Implement proper validation here |
| 259 | + // https://github.com/sigp/lighthouse/issues/1234 |
| 260 | +} |
| 261 | +``` |
| 262 | + |
| 263 | +### Async Task Spawning for Blocking Work |
| 264 | +```rust |
| 265 | +// ❌ Avoid - blocking in async context |
| 266 | +async fn some_handler() { |
| 267 | + let result = expensive_computation(); // blocks async runtime |
| 268 | +} |
| 269 | + |
| 270 | +// ✅ Preferred |
| 271 | +async fn some_handler() { |
| 272 | + let result = tokio::task::spawn_blocking(|| { |
| 273 | + expensive_computation() |
| 274 | + }).await?; |
| 275 | +} |
| 276 | +``` |
| 277 | + |
| 278 | +### Tracing Span Usage |
| 279 | +```rust |
| 280 | +// ❌ Avoid - span on simple getter |
| 281 | +#[instrument] |
| 282 | +fn get_head_block_root(&self) -> Hash256 { |
| 283 | + self.head_block_root |
| 284 | +} |
| 285 | + |
| 286 | +// ✅ Preferred - span on meaningful operations |
| 287 | +#[instrument(skip(self))] |
| 288 | +async fn process_block(&self, block: Block) -> Result<(), Error> { |
| 289 | + // meaningful computation |
| 290 | +} |
| 291 | +``` |
| 292 | + |
| 293 | +## Build and Development Notes |
| 294 | +- Full builds and tests take 5+ minutes - use large timeouts (300s+) for any `cargo build`, `cargo test`, or `make` commands |
| 295 | +- Use `cargo check` for faster iteration during development and always run after code changes |
| 296 | +- Prefer targeted package tests (`cargo test -p <package>`) and individual tests over full test suite when debugging specific issues |
| 297 | +- Always understand the broader codebase patterns before making changes |
| 298 | +- Minimum Supported Rust Version (MSRV) is documented in `lighthouse/Cargo.toml` - ensure Rust version meets or exceeds this requirement |
0 commit comments