Skip to content

Commit a7df3eb

Browse files
committed
add additional details and style conventions from ajj example
1 parent 7f2820d commit a7df3eb

2 files changed

Lines changed: 99 additions & 28 deletions

File tree

.claude/CLAUDE.md

Lines changed: 98 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
1-
# CLAUDE.md
1+
# Signet Block Builder Development Guide
22

3-
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
3+
## Crate Summary
44

5-
## Project Overview
6-
7-
Signet Block Builder - a Rust application that simulates transactions and bundles against rollup state to create valid Signet rollup blocks, then submits them to Ethereum as EIP-4844 blob transactions via Flashbots.
5+
Single-crate Rust application (not a workspace) that builds Signet rollup blocks. Actor-based async task system: watches host/rollup chains, ingests transactions and bundles, simulates them against rollup state, then submits valid blocks to Ethereum as EIP-4844 blob transactions via Flashbots. Built on alloy, trevm, tokio, and the `signet-*` SDK crates. Binary: `zenith-builder-example`. Minimum Rust 1.88, Edition 2024.
86

97
## Build Commands
108

@@ -17,43 +15,115 @@ make fmt # Format code
1715
make clippy # Lint with warnings denied
1816
```
1917

20-
Equivalent cargo commands work directly (`cargo build`, `cargo test`, etc.).
18+
Always lint before committing. The Makefile provides shortcuts (`make fmt`, `make clippy`, `make test`)
2119

2220
## Architecture
2321

24-
The builder uses an actor-based async task system with five main tasks communicating via channels:
22+
Five actor tasks communicate via tokio channels:
23+
24+
1. **EnvTask** (`src/tasks/env.rs`) - Subscribes to rollup blocks, fetches matching host headers, runs Quincey preflight slot check, constructs `SimEnv` (host + rollup `BlockEnv`), broadcasts via `watch` channel.
25+
2. **CacheTasks** (`src/tasks/cache/`) - `TxPoller` and `BundlePoller` ingest transactions/bundles into a shared `SimCache`.
26+
3. **SimulatorTask** (`src/tasks/block/sim.rs`) - Receives `SimEnv`, clones the cache, builds a `BlockBuild` with a slot-derived deadline, produces `SimResult`.
27+
4. **FlashbotsTask** (`src/tasks/submit/flashbots.rs`) - Receives `SimResult`, prepares signed EIP-4844 blob transaction via `SubmitPrep` + Quincey, bundles with host txs, submits to Flashbots relay.
28+
5. **MetricsTask** (`src/tasks/metrics.rs`) - Tracks tx mining status and records metrics.
29+
30+
**Data flow:** `EnvTask → (watch) → SimulatorTask ← (SimCache) ← CacheTasks` `SimulatorTask → (mpsc) → FlashbotsTask → Quincey → Flashbots`
31+
32+
### Source Layout
33+
34+
```
35+
bin/
36+
builder.rs - Binary entry point, spawns all tasks, select! on join handles
37+
src/
38+
lib.rs - Crate root, global CONFIG OnceLock, lint directives
39+
config.rs - BuilderConfig (FromEnv), provider type aliases, connect_* methods
40+
quincey.rs - Quincey enum (Remote/Owned), signing + preflight
41+
service.rs - Axum /healthcheck endpoint
42+
macros.rs - span_scoped!, span_debug/info/warn/error!, res/opt_unwrap_or_continue!
43+
utils.rs - Signature extraction, gas population helpers
44+
test_utils.rs - setup_test_config, new_signed_tx, test_block_env helpers
45+
tasks/
46+
mod.rs - Module re-exports
47+
env.rs - EnvTask, SimEnv, Environment types
48+
block/
49+
mod.rs - Module re-exports
50+
sim.rs - SimulatorTask, SimResult, block building + deadline calc
51+
cfg.rs - SignetCfgEnv for simulation
52+
cache/
53+
mod.rs - Module re-exports
54+
task.rs - CacheTask
55+
tx.rs - TxPoller
56+
bundle.rs - BundlePoller
57+
system.rs - CacheSystem, CacheTasks orchestration
58+
submit/
59+
mod.rs - Module re-exports
60+
flashbots.rs - FlashbotsTask, bundle preparation + submission
61+
prep.rs - SubmitPrep (tx preparation + Quincey signing), Bumpable
62+
sim_err.rs - SimErrorResp, SimRevertKind
63+
metrics.rs - MetricsTask
64+
```
65+
66+
## Repo Conventions
67+
68+
- Global static config: `CONFIG: OnceLock<BuilderConfig>` initialized via `config_from_env()`. Tasks access config via `crate::config()`.
69+
- Provider type aliases: `HostProvider`, `RuProvider`, `FlashbotsProvider`, `ZenithInstance` are defined in `config.rs` and used throughout.
70+
- `connect_*` methods on `BuilderConfig` use `OnceCell`/`OnceLock` for memoization -- providers and signers are connected once, then cloned.
71+
- Internal macros: `span_scoped!`, `span_debug/info/warn/error!` log within an unentered span. `res_unwrap_or_continue!` and `opt_unwrap_or_continue!` unwrap-or-log-and-continue in loops.
72+
- Quincey has two modes: `Remote` (HTTP/OAuth for production) and `Owned` (local/AWS KMS for dev). Configured by presence of `SEQUENCER_KEY` env var.
73+
- Tasks follow a `new() -> spawn()` pattern: `new()` connects providers, `spawn()` returns channel endpoints + `JoinHandle`.
74+
- Block simulation uses `trevm` with `concurrent-db` and `AlloyDB` backed by alloy providers.
75+
- EIP-4844 blob encoding uses `SimpleCoder` and the 7594 sidecar builder.
76+
77+
## init4 Organization Style
78+
79+
### Research
80+
81+
- Prefer building crate docs (`cargo doc`) and reading them over grepping.
82+
83+
### Code Style
84+
85+
- Functional combinators over imperative control flow. No unnecessary nesting.
86+
- Terse Option/Result handling: `option.map(Thing::do_something)` or `let Some(a) = option else { return; };`.
87+
- Small, focused functions and types.
88+
- Never add incomplete code. No `TODO`s for core logic.
89+
- Never use glob imports. Group imports from the same crate. No blank lines between imports.
90+
- Visibility: private by default, `pub(crate)` for internal, `pub` for API. Never use `pub(super)`.
91+
92+
### Error Handling
2593

26-
1. **EnvTask** (`src/tasks/env.rs`) - Watches host/rollup blocks, maintains block environment state via watch channel
27-
2. **CacheTasks** (`src/tasks/cache/`) - TxPoller and BundlePoller ingest transactions/bundles into SimCache
28-
3. **SimulatorTask** (`src/tasks/block/sim.rs`) - Simulates txs/bundles against rollup state, builds blocks with 1.5s buffer deadline
29-
4. **FlashbotsTask** (`src/tasks/submit/flashbots.rs`) - Signs blocks via Quincey, submits to Flashbots relay
30-
5. **MetricsTask** (`src/tasks/metrics.rs`) - Tracks tx mining status and records metrics
94+
- `thiserror` for library errors. Never `anyhow`. `eyre` is allowed in this binary crate but not in library code.
95+
- Propagate with `?` and `map_err`.
3196

32-
**Data flow:** EnvTask → (block_env) → SimulatorTask ← (SimCache) ← CacheTasks; SimulatorTask → (built block) → FlashbotsTask → Quincey → Flashbots
97+
### Tracing
3398

34-
## Key Components
99+
- Use `tracing` crate. Instrument work items, not long-lived tasks.
100+
- `skip(self)` when instrumenting methods. Add only needed fields.
101+
- Levels: TRACE (rare, verbose), DEBUG (sparingly), INFO (default), WARN (potential issues), ERROR (prevents operation).
102+
- Propagate spans through task boundaries with `Instrument`.
103+
- This crate uses `span_scoped!` macros to log within unentered spans.
35104

36-
- **Quincey** (`src/quincey.rs`): Block signing client - supports remote (HTTP/OAuth) or local (AWS KMS) signing
37-
- **BuilderConfig** (`src/config.rs`): Environment variable loading, provider connections
38-
- **Service** (`src/service.rs`): HTTP server with `/healthcheck` endpoint
105+
### Async
39106

40-
## Dependencies
107+
- Tokio multi-thread runtime. No blocking in async functions.
108+
- Long-lived tasks: return a spawnable future via `spawn()`, don't run directly.
109+
- Short-lived spawned tasks: consider span propagation with `.instrument()`.
41110

42-
Key external crates:
43-
- `signet-*`: SDK crates for constants, simulation, tx-cache, types, zenith contract
44-
- `alloy`: Ethereum interaction (providers, signers, EIP-4844)
45-
- `trevm`: EVM simulator with concurrent-db
46-
- `tokio`: Async runtime
111+
### Testing
47112

48-
## Configuration
113+
- Tests panic, never return `Result`. Use `unwrap()` directly.
114+
- Use `setup_test_config()` from `test_utils` to initialize the global config.
115+
- Unit tests in `mod tests` at file bottom. Integration tests in `tests/`.
49116

50-
Required environment variables: `HOST_RPC_URL`, `ROLLUP_RPC_URL`, `QUINCEY_URL`, `TX_POOL_URL`, `BUILDER_KEY`, `BUILDER_REWARDS_ADDRESS`, `BUILDER_PORT`, `BLOCK_QUERY_CUTOFF_BUFFER`, plus OAuth settings (`OAUTH_CLIENT_ID`, `OAUTH_CLIENT_SECRET`, `OAUTH_AUTHENTICATE_URL`, `OAUTH_TOKEN_URL`, `AUTH_TOKEN_REFRESH_INTERVAL`).
117+
### Rustdoc
51118

52-
Optional: `SEQUENCER_KEY` for local signing instead of remote Quincey, `CONCURRENCY_LIMIT` for parallel simulation threads.
119+
- Doc all public items. Include usage examples in rustdoc.
120+
- Hide scaffolding with `#`. Keep examples concise.
121+
- Traits must include an implementation guide.
53122

54-
## Rust Version
123+
### GitHub
55124

56-
Minimum: 1.88, Edition: 2024
125+
- Fresh branches off `main` for PRs. Descriptive branch names.
126+
- AI-authored GitHub comments must include `**[Claude Code]**` header.
57127

58128
## Local Development
59129

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,5 @@ target/
2424
.vscode/launch.json
2525

2626
.claude/*.local.*
27+
.claude/settings.json
2728
CLAUDE.local.md

0 commit comments

Comments
 (0)