Skip to content

Commit ae921c1

Browse files
committed
Merge remote-tracking branch 'origin/unstable' into cayman/bls-verifier
2 parents 2a440d9 + 31b0dd0 commit ae921c1

File tree

15 files changed

+1083
-271
lines changed

15 files changed

+1083
-271
lines changed

.claude/README.md

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
# Claude Code Configuration
2+
3+
This directory contains shared [Claude Code](https://code.claude.com/) configuration for the Lodestar project. See also [`AGENTS.md`](../AGENTS.md) at the repo root for project conventions and architecture guidance.
4+
5+
## Structure
6+
7+
```
8+
.claude/
9+
├── settings.json # Shared project settings (permissions allowlist)
10+
├── settings.local.json # Personal settings (gitignored)
11+
├── skills/ # Agent skills — Claude auto-discovers these
12+
│ ├── kurtosis-devnet/ # Multi-client devnet testing
13+
│ ├── release-notes/ # Release note drafting
14+
│ └── local-mainnet-debug/ # Debug with real mainnet peers
15+
└── README.md # This file
16+
```
17+
18+
## Skills
19+
20+
Skills are automatically loaded by Claude Code based on task context. You can also invoke them manually:
21+
22+
| Skill | When to use |
23+
| ----------------------- | -------------------------------------------------------------------------- |
24+
| **kurtosis-devnet** | Spinning up local testnets, cross-client interop testing, fork transitions |
25+
| **release-notes** | Drafting release notes for GitHub and Discord |
26+
| **local-mainnet-debug** | Debugging networking/peer issues against real mainnet peers |
27+
28+
## Shared Plugins
29+
30+
For cross-project Ethereum development resources (consensus specs, client cross-reference), install from the shared marketplace:
31+
32+
```bash
33+
claude plugin marketplace add ChainSafe/lodestar-claude-plugins
34+
claude plugin install ethereum-rnd
35+
claude plugin install consensus-clients
36+
```
37+
38+
## Personal Configuration
39+
40+
Add personal settings to `.claude/settings.local.json` (gitignored). This is useful for:
41+
42+
- Personal API keys or tool preferences
43+
- Local MCP server configurations
44+
- Additional permission rules for your workflow

.claude/settings.json

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
{
2+
"$schema": "https://json.schemastore.org/claude-code-settings.json",
3+
"permissions": {
4+
"allow": [
5+
"Bash(pnpm build)",
6+
"Bash(pnpm --filter * build)",
7+
"Bash(pnpm lint)",
8+
"Bash(pnpm lint:fix)",
9+
"Bash(pnpm check-types)",
10+
"Bash(pnpm --filter * check-types)",
11+
"Bash(pnpm test:unit)",
12+
"Bash(pnpm vitest *)",
13+
"Bash(pnpm download-spec-tests)",
14+
"Bash(pnpm test:spec)",
15+
"Bash(pnpm docs:lint)",
16+
"Bash(pnpm docs:lint:fix)",
17+
"Bash(git status *)",
18+
"Bash(git diff *)",
19+
"Bash(git log *)",
20+
"Bash(git branch *)",
21+
"Bash(git show *)",
22+
"Bash(git fetch *)",
23+
"Bash(gh pr view *)",
24+
"Bash(gh pr list *)",
25+
"Bash(gh pr diff *)",
26+
"Bash(gh pr checks *)",
27+
"Bash(gh issue view *)",
28+
"Bash(gh issue list *)",
29+
"Bash(gh run view *)",
30+
"Bash(gh run list *)",
31+
"Bash(gh search *)",
32+
"Bash(grep *)",
33+
"Bash(cat *)",
34+
"Bash(head *)",
35+
"Bash(tail *)",
36+
"Bash(wc *)",
37+
"Bash(ls *)",
38+
"Bash(curl -s http://localhost:*)"
39+
],
40+
"deny": [
41+
"Bash(rm -rf / *)",
42+
"Bash(sudo *)"
43+
]
44+
},
45+
"enabledPlugins": {
46+
"ethereum-rnd@lodestar-claude-plugins": true,
47+
"consensus-clients@lodestar-claude-plugins": true,
48+
"eth-rnd-archive@lodestar-claude-plugins": true,
49+
"claude-md-management@claude-plugins-official": true,
50+
"code-review@claude-plugins-official": true,
51+
"code-simplifier@claude-plugins-official": true,
52+
"commit-commands@claude-plugins-official": true,
53+
"context7@claude-plugins-official": true,
54+
"feature-dev@claude-plugins-official": true,
55+
"pr-review-toolkit@claude-plugins-official": true,
56+
"superpowers@claude-plugins-official": true,
57+
"typescript-lsp@claude-plugins-official": true
58+
},
59+
"extraKnownMarketplaces": {
60+
"lodestar-claude-plugins": {
61+
"source": {
62+
"source": "github",
63+
"repo": "ChainSafe/lodestar-claude-plugins"
64+
}
65+
}
66+
}
67+
}
Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
---
2+
name: kurtosis-devnet
3+
description: Run Ethereum multi-client devnets using Kurtosis and the ethpandaops/ethereum-package. Use for spinning up local testnets, validating cross-client interop, testing fork transitions, running assertoor checks, debugging CL/EL client interactions, or verifying new feature implementations across multiple consensus and execution clients.
4+
---
5+
6+
# Kurtosis Devnet
7+
8+
Run Ethereum consensus/execution client devnets via [Kurtosis](https://github.com/kurtosis-tech/kurtosis) + [ethereum-package](https://github.com/ethpandaops/ethereum-package).
9+
10+
## Prerequisites
11+
12+
- [Kurtosis CLI](https://docs.kurtosis.com/install/) installed
13+
- Docker running with sufficient resources (8GB+ RAM recommended for multi-client devnets)
14+
15+
## Quick Start
16+
17+
```bash
18+
# Start devnet from config
19+
# Always use --image-download always to ensure external images are up to date
20+
kurtosis run github.com/ethpandaops/ethereum-package \
21+
--enclave <name> \
22+
--args-file network_params.yaml \
23+
--image-download always
24+
25+
# List enclaves
26+
kurtosis enclave ls
27+
28+
# Inspect services
29+
kurtosis enclave inspect <name>
30+
31+
# View logs
32+
kurtosis service logs <enclave> <service-name>
33+
kurtosis service logs <enclave> <service-name> --follow
34+
35+
# Cleanup
36+
kurtosis enclave rm -f <name>
37+
# Or clean all enclaves
38+
kurtosis clean -a
39+
```
40+
41+
## Config File (`network_params.yaml`)
42+
43+
See `references/config-reference.md` for the full config structure.
44+
45+
Key sections:
46+
47+
- `participants`: list of CL+EL client pairs with images, flags, validator counts
48+
- `network_params`: fork epochs, slot time, network-level settings
49+
- `additional_services`: dora (explorer), assertoor (testing), prometheus, grafana
50+
- `assertoor_params`: automated chain health checks
51+
- `port_publisher`: expose CL/EL ports to host
52+
53+
## Building Custom Client Images
54+
55+
When testing local Lodestar branches, build a Docker image first:
56+
57+
```bash
58+
# Fast build (recommended for iteration)
59+
cd ~/lodestar && docker build -t lodestar:custom -f Dockerfile.dev .
60+
61+
# Production build (slower, for final validation only)
62+
cd ~/lodestar && docker build -t lodestar:custom .
63+
64+
# Then reference in config:
65+
# cl_image: lodestar:custom
66+
```
67+
68+
**Always use `Dockerfile.dev` for iterative development.** It caches dependency layers and rebuilds in seconds vs minutes for the production Dockerfile. Only use the production `Dockerfile` for final validation or debugging build issues.
69+
70+
## Service Naming Convention
71+
72+
Kurtosis names services as: `{role}-{index}-{cl_type}-{el_type}`
73+
74+
Examples:
75+
76+
- `cl-1-lodestar-reth` — first CL node (Lodestar with Reth EL)
77+
- `el-1-reth-lodestar` — corresponding EL node
78+
- `vc-1-lodestar-reth` — validator client
79+
80+
## Accessing Services
81+
82+
After `kurtosis enclave inspect <name>`, find mapped ports:
83+
84+
```bash
85+
# CL beacon API (find actual port from inspect output)
86+
curl http://127.0.0.1:<mapped-port>/eth/v1/node/syncing
87+
88+
# Or use port_publisher for predictable ports:
89+
# port_publisher:
90+
# cl:
91+
# enabled: true
92+
# public_port_start: 33000 # cl-1=33000, cl-2=33005, etc.
93+
# el:
94+
# enabled: true
95+
# public_port_start: 32000
96+
```
97+
98+
Port publisher assigns sequential ports (step of 5 per service).
99+
100+
## Assertoor (Automated Testing)
101+
102+
Add to config:
103+
104+
```yaml
105+
additional_services:
106+
- assertoor
107+
108+
assertoor_params:
109+
run_stability_check: true # chain stability, finality, no reorgs
110+
run_block_proposal_check: true # every client pair proposes a block
111+
```
112+
113+
Check results via the assertoor web UI (port shown in `kurtosis enclave inspect`).
114+
115+
## Common Devnet Patterns
116+
117+
### Fork Transition Testing
118+
119+
```yaml
120+
network_params:
121+
electra_fork_epoch: 0
122+
fulu_fork_epoch: 1 # fork at epoch 1 (slot 32)
123+
seconds_per_slot: 6 # faster for testing
124+
```
125+
126+
### Mixed-Client Topology (Cross-Client Interop)
127+
128+
```yaml
129+
participants:
130+
- cl_type: lodestar
131+
el_type: reth
132+
count: 2
133+
validator_count: 128
134+
- cl_type: lighthouse
135+
el_type: geth
136+
count: 2
137+
validator_count: 128
138+
```
139+
140+
### Observer Nodes (No Validators)
141+
142+
```yaml
143+
- cl_type: lodestar
144+
cl_image: lodestar:custom
145+
el_type: reth
146+
count: 1
147+
validator_count: 0 # observer-only
148+
```
149+
150+
### Supernode Mode
151+
152+
Set `supernode: true` to run beacon+validator in a single process (faster startup, simpler topology):
153+
154+
```yaml
155+
- cl_type: lodestar
156+
el_type: reth
157+
supernode: true
158+
validator_count: 128
159+
```
160+
161+
### Extra CL/VC Params
162+
163+
```yaml
164+
cl_extra_params:
165+
- --targetPeers=8
166+
- --logLevel=debug
167+
vc_extra_params:
168+
- --suggestedFeeRecipient=0x...
169+
```
170+
171+
## Monitoring & Debugging
172+
173+
```bash
174+
# Stream logs from a specific service
175+
kurtosis service logs <enclave> cl-1-lodestar-reth --follow
176+
177+
# Save all CL logs for analysis
178+
for svc in $(kurtosis enclave inspect <enclave> 2>/dev/null | grep -oE 'cl-[0-9]+-[^[:space:]]+'); do
179+
kurtosis service logs <enclave> $svc > "/tmp/${svc}.log" 2>&1
180+
done
181+
182+
# Dora explorer (if enabled) — find port via inspect output
183+
184+
# Check chain finality
185+
curl -s http://127.0.0.1:<port>/eth/v1/beacon/states/head/finality_checkpoints | jq
186+
187+
# Check peer count
188+
curl -s http://127.0.0.1:<port>/eth/v1/node/peers | jq '.data | length'
189+
190+
# Check sync status
191+
curl -s http://127.0.0.1:<port>/eth/v1/node/syncing | jq
192+
```
193+
194+
### Wait for Finality
195+
196+
Finality typically takes 2-3 epochs after genesis. With `seconds_per_slot: 6` and 32 slots/epoch:
197+
198+
- 1 epoch ≈ 192s (3.2 min)
199+
- First finalization ≈ epoch 3-4 boundary (≈10-13 min)
200+
201+
Monitor:
202+
203+
```bash
204+
curl -s http://<port>/eth/v1/beacon/states/head/finality_checkpoints | jq '.data.finalized.epoch'
205+
```
206+
207+
### Acceptance Criteria Pattern
208+
209+
For interop validation, define acceptance criteria **before** running the soak test:
210+
211+
```bash
212+
# Example: check for zero errors across all CL nodes
213+
for svc in cl-1-lodestar-reth cl-2-lodestar-reth; do
214+
echo "=== $svc ==="
215+
kurtosis service logs <enclave> $svc 2>&1 | grep -c "ERROR" || echo "0 errors"
216+
done
217+
```
218+
219+
## Troubleshooting
220+
221+
| Issue | Fix |
222+
| ------------------------ | ------------------------------------------------------------------------- |
223+
| Peers not connecting | Increase `--targetPeers`, check `directPeers` config |
224+
| No finality | Need ≥2/3 validators attesting; check VC logs |
225+
| "discv5 has no boot enr" | Harmless startup warning, ignore |
226+
| Port conflicts | Change `public_port_start` or stop conflicting enclaves |
227+
| Image not found | Ensure Docker image is built locally or available in registry |
228+
| Slow startup | Use `Dockerfile.dev` for local builds; reduce validator count |
229+
| Docker bind error | Use non-default port ranges; `kurtosis clean -a` between runs |
230+
| Stale enclave state | Always `kurtosis clean -a` before relaunching (not `docker system prune`) |
231+
232+
## Tips
233+
234+
- **Start small:** 2+2 nodes for iteration, scale up for final validation
235+
- **Test both roles:** Validator nodes show different bugs than observers — always check both
236+
- **Multiple soak passes:** First clean run may miss edge cases. Run extended soaks (hours).
237+
- **`kurtosis clean -a`** between runs — never use `docker system prune` (it can remove Kurtosis engine images)
238+
- **Debug logs:** Set `global_log_level: "debug"` for verbose output from all nodes
239+
- **Per-participant log levels:** Use `cl_log_level` / `el_log_level` on individual entries for targeted debugging
240+
241+
---
242+
243+
## Self-Maintenance
244+
245+
If any commands, file paths, URLs, or configurations in this skill are outdated or no longer work, update this SKILL.md with the correct information after completing your current task. Skills should stay accurate and self-healing — fix what you find broken.

0 commit comments

Comments
 (0)