|
| 1 | +--- |
| 2 | +name: test-pr-devnet |
| 3 | +description: Test ethlambda PR changes in multi-client devnet. Use when users want to (1) Test a branch/PR with other Lean clients, (2) Validate BlocksByRoot or P2P protocol changes, (3) Test sync recovery with pause/unpause, (4) Verify cross-client interoperability, (5) Run integration tests before merging. |
| 4 | +disable-model-invocation: true |
| 5 | +--- |
| 6 | + |
| 7 | +# Test PR in Devnet |
| 8 | + |
| 9 | +Test ethlambda branch changes in a multi-client local devnet with zeam (Zig), ream (Rust), qlean (C++), and ethlambda. |
| 10 | + |
| 11 | +## Quick Start |
| 12 | + |
| 13 | +```bash |
| 14 | +# Test current branch (basic interoperability, ~60-90s) |
| 15 | +.claude/skills/test-pr-devnet/scripts/test-branch.sh |
| 16 | + |
| 17 | +# Test with sync recovery (BlocksByRoot validation, ~90-120s) |
| 18 | +.claude/skills/test-pr-devnet/scripts/test-branch.sh --with-sync-test |
| 19 | + |
| 20 | +# Test specific branch |
| 21 | +.claude/skills/test-pr-devnet/scripts/test-branch.sh my-feature-branch |
| 22 | + |
| 23 | +# Check status while running |
| 24 | +.claude/skills/test-pr-devnet/scripts/check-status.sh |
| 25 | + |
| 26 | +# Cleanup when done |
| 27 | +.claude/skills/test-pr-devnet/scripts/cleanup.sh |
| 28 | +``` |
| 29 | + |
| 30 | +## What It Does |
| 31 | + |
| 32 | +1. **Builds branch-specific Docker image** tagged as `ghcr.io/lambdaclass/ethlambda:<branch-name>` |
| 33 | +2. **Updates lean-quickstart config** to use new image (backs up original) |
| 34 | +3. **Starts 4-node devnet** with fresh genesis (zeam, ream, qlean, ethlambda) |
| 35 | +4. **Optionally tests sync recovery** by pausing/unpausing nodes |
| 36 | +5. **Analyzes results** and provides summary |
| 37 | +6. **Leaves devnet running** for manual inspection |
| 38 | + |
| 39 | +## Prerequisites |
| 40 | + |
| 41 | +| Requirement | Location | Check | |
| 42 | +|-------------|----------|-------| |
| 43 | +| lean-quickstart | `/Users/mega/lean_consensus/lean-quickstart` | `ls $LEAN_QUICKSTART` | |
| 44 | +| Docker running | - | `docker ps` | |
| 45 | +| Git repository | ethlambda root | `git branch` | |
| 46 | + |
| 47 | +## Test Scenarios |
| 48 | + |
| 49 | +### Basic Interoperability (~60-90s) |
| 50 | + |
| 51 | +**Goal:** Verify ethlambda produces blocks and reaches consensus with other clients |
| 52 | + |
| 53 | +**Success criteria:** |
| 54 | +- ✅ No errors in ethlambda logs |
| 55 | +- ✅ All 4 nodes at same head slot |
| 56 | +- ✅ Finalization advancing (every 6-12 slots) |
| 57 | +- ✅ Each validator produces blocks for their slots |
| 58 | + |
| 59 | +### Sync Recovery (~90-120s) |
| 60 | + |
| 61 | +**Goal:** Test BlocksByRoot request/response when nodes fall behind |
| 62 | + |
| 63 | +**Usage:** Add `--with-sync-test` flag |
| 64 | + |
| 65 | +**What happens:** |
| 66 | +1. Devnet runs for 10s (~2-3 slots) |
| 67 | +2. Pauses `zeam_0` and `qlean_0` |
| 68 | +3. Network progresses 20s (~5 slots) |
| 69 | +4. Unpauses nodes → nodes sync |
| 70 | + |
| 71 | +**Success criteria:** |
| 72 | +- ✅ Inbound BlocksByRoot requests logged |
| 73 | +- ✅ Successful responses sent |
| 74 | +- ✅ Paused nodes sync to current head |
| 75 | + |
| 76 | +## Configuration Changes |
| 77 | + |
| 78 | +The skill modifies `lean-quickstart/client-cmds/ethlambda-cmd.sh` to use your branch's Docker image. |
| 79 | + |
| 80 | +**Automatic backup:** Creates `ethlambda-cmd.sh.backup` |
| 81 | + |
| 82 | +**Restore methods:** |
| 83 | +```bash |
| 84 | +# 1. Cleanup script (recommended) |
| 85 | +.claude/skills/test-pr-devnet/scripts/cleanup.sh |
| 86 | + |
| 87 | +# 2. Manual restore |
| 88 | +mv $LEAN_QUICKSTART/client-cmds/ethlambda-cmd.sh.backup \ |
| 89 | + $LEAN_QUICKSTART/client-cmds/ethlambda-cmd.sh |
| 90 | + |
| 91 | +# 3. Git restore (if no uncommitted changes) |
| 92 | +cd $LEAN_QUICKSTART && git checkout client-cmds/ethlambda-cmd.sh |
| 93 | +``` |
| 94 | + |
| 95 | +## Manual Workflow (Alternative to Script) |
| 96 | + |
| 97 | +If you need fine-grained control: |
| 98 | + |
| 99 | +### 1. Build Image |
| 100 | + |
| 101 | +```bash |
| 102 | +cd /Users/mega/lean_consensus/ethlambda |
| 103 | +BRANCH=$(git rev-parse --abbrev-ref HEAD) |
| 104 | +docker build \ |
| 105 | + --build-arg GIT_COMMIT=$(git rev-parse HEAD) \ |
| 106 | + --build-arg GIT_BRANCH=$BRANCH \ |
| 107 | + -t ghcr.io/lambdaclass/ethlambda:$BRANCH . |
| 108 | +``` |
| 109 | + |
| 110 | +### 2. Update Configuration |
| 111 | + |
| 112 | +Edit `$LEAN_QUICKSTART/client-cmds/ethlambda-cmd.sh` line 17: |
| 113 | +```bash |
| 114 | +node_docker="ghcr.io/lambdaclass/ethlambda:<your-branch> \ |
| 115 | +``` |
| 116 | +
|
| 117 | +### 3. Start Devnet |
| 118 | +
|
| 119 | +```bash |
| 120 | +cd $LEAN_QUICKSTART |
| 121 | +NETWORK_DIR=local-devnet ./spin-node.sh --node all --generateGenesis --metrics |
| 122 | +``` |
| 123 | +
|
| 124 | +### 4. Test Sync (Optional) |
| 125 | +
|
| 126 | +```bash |
| 127 | +# Create sync gap |
| 128 | +docker pause zeam_0 qlean_0 |
| 129 | +sleep 20 # Network progresses |
| 130 | +
|
| 131 | +# Test recovery |
| 132 | +docker unpause zeam_0 qlean_0 |
| 133 | +sleep 10 # Wait for sync |
| 134 | +``` |
| 135 | +
|
| 136 | +### 5. Check Results |
| 137 | +
|
| 138 | +```bash |
| 139 | +# Quick status |
| 140 | +.claude/skills/test-pr-devnet/scripts/check-status.sh |
| 141 | +
|
| 142 | +# Detailed analysis (use devnet-log-review skill in lean-quickstart) |
| 143 | +cd $LEAN_QUICKSTART |
| 144 | +.claude/skills/devnet-log-review/scripts/analyze-logs.sh |
| 145 | +``` |
| 146 | +
|
| 147 | +## Protocol Compatibility |
| 148 | +
|
| 149 | +| Client | Status | Gossipsub | BlocksByRoot | |
| 150 | +|--------|--------|-----------|--------------| |
| 151 | +| ream | ✅ Full | ✅ Full | ✅ Full | |
| 152 | +| zeam | ✅ Full | ✅ Full | ⚠️ Limited | |
| 153 | +| qlean | ✅ Full | ✅ Full | ⚠️ Limited | |
| 154 | +| ethlambda | ✅ Full | ✅ Full | ✅ Full | |
| 155 | +
|
| 156 | +**Notes:** |
| 157 | +- zeam/qlean BlocksByRoot errors are expected (not a blocker) |
| 158 | +- ream ↔ ethlambda BlocksByRoot should work perfectly |
| 159 | +- All clients use Gossipsub for block propagation |
| 160 | +
|
| 161 | +## Verification Checklist |
| 162 | +
|
| 163 | +| Check | Command | Expected | |
| 164 | +|-------|---------|----------| |
| 165 | +| All nodes running | `docker ps --filter "name=_0"` | 4 containers | |
| 166 | +| Peers connected | `docker logs ethlambda_0 \| grep "Received status request" \| wc -l` | > 10 | |
| 167 | +| Blocks produced | `docker logs ethlambda_0 \| grep "Published block" \| wc -l` | > 0 | |
| 168 | +| No errors | `docker logs ethlambda_0 \| grep ERROR \| wc -l` | 0 | |
| 169 | +
|
| 170 | +## Troubleshooting |
| 171 | +
|
| 172 | +### Build Fails |
| 173 | +```bash |
| 174 | +docker ps # Check Docker running |
| 175 | +docker system prune -a # Clean cache if needed |
| 176 | +``` |
| 177 | +
|
| 178 | +### Nodes Won't Start |
| 179 | +```bash |
| 180 | +# Clean and retry |
| 181 | +docker stop zeam_0 ream_0 qlean_0 ethlambda_0 2>/dev/null |
| 182 | +docker rm zeam_0 ream_0 qlean_0 ethlambda_0 2>/dev/null |
| 183 | +cd $LEAN_QUICKSTART |
| 184 | +NETWORK_DIR=local-devnet ./spin-node.sh --node all --generateGenesis |
| 185 | +``` |
| 186 | +
|
| 187 | +### Genesis Mismatch |
| 188 | +```bash |
| 189 | +cd $LEAN_QUICKSTART |
| 190 | +NETWORK_DIR=local-devnet ./spin-node.sh --node all --cleanData --generateGenesis |
| 191 | +``` |
| 192 | +
|
| 193 | +### Image Tag Not Updated |
| 194 | +```bash |
| 195 | +# Verify the change |
| 196 | +grep "node_docker=" $LEAN_QUICKSTART/client-cmds/ethlambda-cmd.sh |
| 197 | +# Should show your branch name, not :local |
| 198 | +``` |
| 199 | +
|
| 200 | +### Port Already in Use |
| 201 | +```bash |
| 202 | +docker stop $(docker ps -q --filter "name=_0") 2>/dev/null || true |
| 203 | +``` |
| 204 | +
|
| 205 | +## Debugging |
| 206 | +
|
| 207 | +### P2P Request/Response Debugging |
| 208 | +
|
| 209 | +```bash |
| 210 | +# Check inbound BlocksByRoot handling |
| 211 | +docker logs ethlambda_0 2>&1 | grep "Received BlocksByRoot request" |
| 212 | +docker logs ethlambda_0 2>&1 | grep "Responding to BlocksByRoot" |
| 213 | +
|
| 214 | +# Check outbound BlocksByRoot requests |
| 215 | +docker logs ethlambda_0 2>&1 | grep "Sending BlocksByRoot request" |
| 216 | +docker logs ethlambda_0 2>&1 | grep "Received BlocksByRoot response" |
| 217 | +
|
| 218 | +# Check for protocol errors |
| 219 | +docker logs ethlambda_0 2>&1 | grep -E "Outbound request failed|protocol.*not.*support" |
| 220 | +
|
| 221 | +# Count requests/responses |
| 222 | +docker logs ethlambda_0 2>&1 | grep "Received BlocksByRoot request" | wc -l |
| 223 | +``` |
| 224 | +
|
| 225 | +### Devnet Status Checks |
| 226 | +
|
| 227 | +```bash |
| 228 | +# Check all nodes are running |
| 229 | +docker ps --format "{{.Names}}: {{.Status}}" --filter "name=_0" |
| 230 | +
|
| 231 | +# Get current chain status (zeam) |
| 232 | +docker logs zeam_0 2>&1 | tail -100 | grep "CHAIN STATUS" | tail -1 |
| 233 | +
|
| 234 | +# Get fork choice updates (ethlambda) |
| 235 | +docker logs ethlambda_0 2>&1 | grep "Fork choice head updated" | tail -5 |
| 236 | +
|
| 237 | +# Check peer connectivity |
| 238 | +docker logs ethlambda_0 2>&1 | grep "Received status request" | wc -l |
| 239 | +``` |
| 240 | +
|
| 241 | +### Common Investigation Patterns |
| 242 | +
|
| 243 | +```bash |
| 244 | +# Verify ethlambda is proposing blocks |
| 245 | +docker logs ethlambda_0 2>&1 | grep "We are the proposer" |
| 246 | +
|
| 247 | +# Compare finalized slots across clients |
| 248 | +for node in zeam_0 ream_0 ethlambda_0; do |
| 249 | + echo "$node:" |
| 250 | + docker logs "$node" 2>&1 | grep -i "finalized" | tail -1 |
| 251 | +done |
| 252 | +
|
| 253 | +# Check peer discovery |
| 254 | +docker logs ethlambda_0 2>&1 | grep -i "peer\|connection" | head -20 |
| 255 | +``` |
| 256 | +
|
| 257 | +## References |
| 258 | +
|
| 259 | +- **[ethlambda CLAUDE.md](../../CLAUDE.md)** - Development workflow, detailed debugging commands |
| 260 | +- **[lean-quickstart devnet-log-review](../../../lean-quickstart/.claude/skills/devnet-log-review/SKILL.md)** - Comprehensive log analysis |
0 commit comments