|
| 1 | +# Launch bal-devnet-2 (Erigon + Lighthouse) |
| 2 | + |
| 3 | +Run Erigon and Lighthouse for the bal-devnet-2 ethpandaops devnet (EIP-7928 Block Access Lists). |
| 4 | + |
| 5 | +## Quick Start |
| 6 | + |
| 7 | +```bash |
| 8 | +# 1. Build erigon from bal-devnet-2 branch |
| 9 | +cd ~/mark/hive/clients/erigon/erigon && make erigon |
| 10 | + |
| 11 | +# 2. Initialize (IMPORTANT: --datadir must come BEFORE genesis file) |
| 12 | +./build/bin/erigon init --datadir ~/mark/bal-devnet-2/erigon-data ~/mark/bal-devnet-2/genesis.json |
| 13 | + |
| 14 | +# 3. Start erigon first (creates JWT secret) |
| 15 | +bash ~/mark/bal-devnet-2/start-erigon.sh |
| 16 | + |
| 17 | +# 4. Start lighthouse second (reads JWT from erigon) |
| 18 | +bash ~/mark/bal-devnet-2/start-lighthouse.sh |
| 19 | +``` |
| 20 | + |
| 21 | +## Reinitializing (Clean Restart) |
| 22 | + |
| 23 | +When you need to wipe the datadir and start fresh: |
| 24 | + |
| 25 | +```bash |
| 26 | +# Stop both |
| 27 | +pkill -f "erigon.*bal-devnet-2"; docker stop bal-devnet-2-lighthouse |
| 28 | + |
| 29 | +# Clean EVERYTHING in the datadir except jwt.hex and nodekey |
| 30 | +rm -rf ~/mark/bal-devnet-2/erigon-data/{chaindata,snapshots,txpool,nodes,temp,bal,caplin,migrations,downloader,LOCK,logs} |
| 31 | + |
| 32 | +# CRITICAL: --datadir flag MUST come BEFORE the genesis file path! |
| 33 | +# Wrong: erigon init genesis.json --datadir=path (silently uses default path!) |
| 34 | +# Right: erigon init --datadir path genesis.json |
| 35 | +./build/bin/erigon init --datadir ~/mark/bal-devnet-2/erigon-data ~/mark/bal-devnet-2/genesis.json |
| 36 | + |
| 37 | +# Verify init output says "Writing custom genesis block" (NOT "Writing main-net genesis block") |
| 38 | +# Verify chain config shows ChainID: 7033429093 and Glamsterdam on startup |
| 39 | +``` |
| 40 | + |
| 41 | +### Salt files |
| 42 | + |
| 43 | +After a clean wipe, the `snapshots/salt-state.txt` and `snapshots/salt-blocks.txt` files are |
| 44 | +recreated automatically by `erigon init`. If erigon errors with "salt not found on ReloadSalt", |
| 45 | +create them manually: |
| 46 | + |
| 47 | +```bash |
| 48 | +python3 -c "import os; open('$HOME/mark/bal-devnet-2/erigon-data/snapshots/salt-state.txt', 'wb').write(os.urandom(4))" |
| 49 | +python3 -c "import os; open('$HOME/mark/bal-devnet-2/erigon-data/snapshots/salt-blocks.txt', 'wb').write(os.urandom(4))" |
| 50 | +``` |
| 51 | + |
| 52 | +## Stopping |
| 53 | + |
| 54 | +```bash |
| 55 | +pkill -f "erigon.*bal-devnet-2" |
| 56 | +docker stop bal-devnet-2-lighthouse |
| 57 | +``` |
| 58 | + |
| 59 | +## Checking Status |
| 60 | + |
| 61 | +```bash |
| 62 | +# Erigon block number |
| 63 | +curl -s http://127.0.0.1:8645 -X POST -H "Content-Type: application/json" \ |
| 64 | + -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' |
| 65 | + |
| 66 | +# Lighthouse head slot |
| 67 | +curl -s http://127.0.0.1:5152/eth/v1/beacon/headers/head | python3 -c \ |
| 68 | + "import json,sys; d=json.load(sys.stdin); print('Head slot:', d['data']['header']['message']['slot'])" |
| 69 | + |
| 70 | +# Check erigon logs for errors |
| 71 | +grep -E "WARN|ERR" ~/mark/bal-devnet-2/erigon-data/logs/erigon.log | tail -20 |
| 72 | + |
| 73 | +# Check for gas or BAL mismatches |
| 74 | +grep -E "gas mismatch|BAL mismatch" ~/mark/bal-devnet-2/erigon-data/logs/erigon.log | tail -10 |
| 75 | +``` |
| 76 | + |
| 77 | +## Port Assignments (offset to avoid conflicts) |
| 78 | + |
| 79 | +| Service | Port | Flag | |
| 80 | +|---------|------|------| |
| 81 | +| Erigon HTTP RPC | 8645 | `--http.port` | |
| 82 | +| Erigon Auth RPC | 8651 | `--authrpc.port` | |
| 83 | +| Erigon WebSocket | 8646 | `--ws.port` | |
| 84 | +| Erigon P2P | 30403 | `--port` | |
| 85 | +| Erigon gRPC | 9190 | `--private.api.addr` | |
| 86 | +| Erigon Torrent | 42169 | `--torrent.port` | |
| 87 | +| Erigon pprof | 6160 | `--pprof.port` | |
| 88 | +| Erigon metrics | 6161 | `--metrics.port` | |
| 89 | +| Erigon MCP | 8653 | `--mcp.port` | |
| 90 | +| Lighthouse HTTP | 5152 | `--http-port` | |
| 91 | +| Lighthouse P2P | 9100 | `--port` | |
| 92 | +| Lighthouse metrics | 5264 | `--metrics-port` | |
| 93 | + |
| 94 | +## Network Details |
| 95 | + |
| 96 | +| Parameter | Value | |
| 97 | +|-----------|-------| |
| 98 | +| Chain ID | 7033429093 | |
| 99 | +| Genesis timestamp | 1770388190 | |
| 100 | +| Amsterdam timestamp | 1770400508 (epoch 32) | |
| 101 | +| Seconds per slot | 12 | |
| 102 | +| Gas limit | 60,000,000 | |
| 103 | +| Lighthouse image | `ethpandaops/lighthouse:bal-devnet-2-65bb283` | |
| 104 | +| RPC endpoint | https://rpc.bal-devnet-2.ethpandaops.io | |
| 105 | +| Checkpoint sync | https://checkpoint-sync.bal-devnet-2.ethpandaops.io | |
| 106 | +| Explorer | https://explorer.bal-devnet-2.ethpandaops.io | |
| 107 | +| Faucet | https://faucet.bal-devnet-2.ethpandaops.io | |
| 108 | + |
| 109 | +## Environment Variables |
| 110 | + |
| 111 | +```bash |
| 112 | +ERIGON_EXEC3_PARALLEL=true # Enable parallel execution |
| 113 | +ERIGON_ASSERT=true # Enable assertions |
| 114 | +ERIGON_EXEC3_WORKERS=12 # Number of parallel workers |
| 115 | +LOG_HASH_MISMATCH_REASON=true # Detailed hash mismatch logging |
| 116 | +``` |
| 117 | + |
| 118 | +## Troubleshooting |
| 119 | + |
| 120 | +### "Unsupported fork" errors from engine API |
| 121 | +This means the chain config is wrong. Verify: |
| 122 | +1. The erigon init wrote to the CORRECT datadir (check `Opening Database label=chaindata path=...` in init output) |
| 123 | +2. The chain config shows `Glamsterdam: 2026-02-06` (not mainnet dates) |
| 124 | +3. If wrong, re-init with `--datadir` flag BEFORE the genesis file path |
| 125 | + |
| 126 | +### No P2P peers |
| 127 | +The devnet nodes may be at max peer capacity. Wait or restart; peer slots open periodically. Check with: |
| 128 | +```bash |
| 129 | +grep "GoodPeers\|peers=" ~/mark/bal-devnet-2/erigon-data/logs/erigon.log | tail -5 |
| 130 | +``` |
| 131 | + |
| 132 | +### Gas mismatch at block N (parallel execution) |
| 133 | +Past bugs fixed: |
| 134 | +- **Block 214**: Fixed in versionedio.go (caching all paths except CodePath when readStorage=nil) |
| 135 | +- **Block 8177**: Fixed in versionedio.go (StoragePath MVReadResultNone checks IncarnationPath) |
| 136 | +- **Block 10113**: Fixed in intra_block_state.go (Empty() was calling accountRead(&emptyAccount) for non-existent accounts, overwriting the nil recorded by versionedRead, causing createObject to be skipped for SELFDESTRUCT beneficiaries) |
| 137 | + |
| 138 | +If a new gas mismatch appears, check the erigon logs for the specific block/tx causing it. The root cause is typically a missing version map write that causes stale reads during parallel validation. |
| 139 | + |
| 140 | +## Config Files |
| 141 | + |
| 142 | +All in `~/mark/bal-devnet-2/`: |
| 143 | +- `genesis.json` - EL genesis (from ethpandaops) |
| 144 | +- `testnet-config/config.yaml` - CL beacon config |
| 145 | +- `testnet-config/genesis.ssz` - CL genesis state |
| 146 | +- `start-erigon.sh` - Erigon start script |
| 147 | +- `start-lighthouse.sh` - Lighthouse start script (Docker) |
| 148 | +- `erigon-data/` - Erigon datadir |
| 149 | +- `lighthouse-data/` - Lighthouse datadir (Docker volume) |
| 150 | + |
| 151 | +## Geth Reference Implementation |
| 152 | + |
| 153 | +The geth bal-devnet-2 source is at: https://github.com/ethereum/go-ethereum/tree/bal-devnet-2 |
| 154 | + |
| 155 | +Key EIP-7928 implementation files in geth: |
| 156 | +- `core/block_access_list_tracer.go` - BAL tracer hooks |
| 157 | +- `core/types/bal/bal.go` - BAL builder and types |
| 158 | +- `core/state_processor.go` - BAL integration in block processing |
| 159 | +- `core/state/bal_reader.go` - BAL reader for parallel execution |
| 160 | + |
| 161 | +Key differences from erigon: |
| 162 | +- Geth uses `receipt.GasUsed = MaxUsedGas` (pre-refund) for Amsterdam blocks |
| 163 | +- Erigon uses `receipt.GasUsed = ReceiptGasUsed` (post-refund) - potential mismatch |
| 164 | +- Both use pre-refund gas for block header GasUsed (EIP-7778) |
0 commit comments