diff --git a/Makefile b/Makefile index 7fcd0dc..42682a5 100644 --- a/Makefile +++ b/Makefile @@ -2,6 +2,10 @@ ENCLAVE_NAME?=localnet PARAMS_FILE?=params.yaml SSV_NODE_COUNT?=4 SSV_COMMIT?=stage +# Minimum free disk (GiB) in the Docker VM before a run. Geth self-terminates below its +# ~1.62GiB low-disk safety threshold, which freezes the chain mid-run (EL gone → CL gets no +# payloads). Guarded with headroom by check-deps; override for tiny/large runs. +MIN_DISK_GIB?=10 default: run @@ -15,6 +19,17 @@ check-deps: @command -v docker >/dev/null 2>&1 || { echo "Error: docker not found. Install: https://docs.docker.com/get-docker/"; exit 1; } @command -v kurtosis >/dev/null 2>&1 || { echo "Error: kurtosis not found. Install: https://docs.kurtosis.com/install"; exit 1; } @docker info >/dev/null 2>&1 || { echo "Error: Docker daemon not running. Start Docker/OrbStack first."; exit 1; } +# Approximate free space in the Docker storage backend: the alpine overlay and Kurtosis volumes +# (where geth's chaindata lives) share the VM data-root on Docker Desktop/OrbStack, so this is a +# good proxy rather than an exact volume measurement. Fails open — if `docker run` can't execute +# (offline, registry/proxy blocked) avail is empty and the check is skipped, not failed. + @avail=$$(docker run --rm alpine df -P / 2>/dev/null | awk 'NR==2{printf "%d", $$4/1024/1024}'); \ + if [ -n "$$avail" ] && [ "$$avail" -lt "$(MIN_DISK_GIB)" ]; then \ + echo "Error: Docker storage backend has only ~$${avail}GiB free (need >= $(MIN_DISK_GIB)GiB)."; \ + echo " Geth self-terminates below ~1.62GiB free (low-disk safety), freezing the chain mid-run."; \ + echo " Free space: docker builder prune -af && docker system prune -f (or raise Docker Desktop's disk image size)."; \ + exit 1; \ + fi .PHONY: run run: check-deps ensure-keys @@ -185,6 +200,7 @@ help: @echo "Network scenarios:" @echo " make run Default: Fulu (all forks active)" @echo " make run-boole Boole fork at epoch 3, Fulu at epoch 5" + @echo " make run-gloas Gloas/ePBS fork at epoch 2 (devnet-5 images)" @echo " make run PARAMS_FILE=custom.yaml Custom params" @echo "" @echo "Configuration:" @@ -199,10 +215,15 @@ help: # ── Network scenarios ──────────────────────────────────────────────── .PHONY: run-boole -run-boole: ensure-keys +run-boole: check-deps ensure-keys @echo "──── Starting SSV testnet (Boole fork at epoch 3) ────" kurtosis run --enclave $(ENCLAVE_NAME) --args-file params-boole.yaml . +.PHONY: run-gloas +run-gloas: check-deps ensure-keys + @echo "──── Starting SSV testnet (Gloas/ePBS fork at epoch 2) ────" + kurtosis run --enclave $(ENCLAVE_NAME) --args-file params-gloas.yaml . + # ── Tests ──────────────────────────────────────────────────────────── .PHONY: test-faulty-el diff --git a/README.md b/README.md index 182947b..4e5fc82 100644 --- a/README.md +++ b/README.md @@ -55,6 +55,7 @@ make help |---------|-------------| | `make run` | Start testnet (default: Fulu, all forks active) | | `make run-boole` | Start with Boole fork at epoch 3, Fulu at epoch 5 | +| `make run-gloas` | Start with Gloas/ePBS (EIP-7732) fork at epoch 2 (devnet-5 images) | | `make reset` | Clean + restart from genesis | | `make show` | Show running services and ports | | `make logs` | Tail ssv-node-0 logs (`SERVICE=ssv-node-1` for others) | @@ -99,6 +100,7 @@ use_static_keys: true # false = regenerate keys at runtime (~40s slower) Pre-built configs: - `params.yaml` — Fulu at genesis (default) - `params-boole.yaml` — Electra→Boole→Fulu fork transitions +- `params-gloas.yaml` — Fulu→Gloas (ePBS/EIP-7732) transition; needs `SSV_COMMIT=epbs-gloas make prepare` and ethpandaops glamsterdam-devnet-5 client images (monitor/E2M disabled — can't parse Gloas) ```bash make run PARAMS_FILE=params-boole.yaml diff --git a/params-gloas.yaml b/params-gloas.yaml new file mode 100644 index 0000000..83884aa --- /dev/null +++ b/params-gloas.yaml @@ -0,0 +1,75 @@ +# Gloas / ePBS (EIP-7732) fork-transition test: genesis on Fulu, forks into Gloas at epoch 2. +# Usage: SSV_COMMIT=epbs-gloas make prepare && make run-gloas +# (or: make run PARAMS_FILE=params-gloas.yaml) +# +# Clients: ethpandaops glamsterdam-devnet-5 builds — the stock geth/lighthouse releases used by +# params.yaml do NOT implement EIP-7732. The genesis generator is pinned to a Gloas-aware build +# (the ethereum-package@6.1.0 default, 5.3.5, predates Gloas). +# +# Heads-up — the devnet image tags below (glamsterdam-devnet-5 for geth/lighthouse, dora master-*) +# are MOVING targets that ethpandaops re-pushes as the devnet advances; they're left unpinned on +# purpose to track devnet-5. If a future run breaks genesis or the transition, a re-pushed image is +# a prime suspect — refresh the tags, or pin a @sha256: digest once devnet-5 stabilizes. +# +# Gloas is purely beacon-driven on the SSV side: the node reads GLOAS_FORK_EPOCH from the beacon +# node's /config/spec at runtime, so no SSV-side fork knob is needed. Boole (the SSV protocol fork +# ePBS builds on) must be active, though — hence boole_epoch: 0 (default is disabled). +# +# Monitor (E2M) is disabled: the ethereum2-monitor image cannot parse Fulu/Gloas beacon blocks +# (it decodes via go-eth2-client, which has no Gloas types). Observe ePBS via the SSV node logs +# and dora. Re-enable once E2M gains Gloas support. + +network: + participants: + - el_type: geth + el_image: ethpandaops/geth:glamsterdam-devnet-5 + cl_type: lighthouse + cl_image: ethpandaops/lighthouse:glamsterdam-devnet-5 + validator_count: 32 + count: 2 + supernode: true + + additional_services: + - dora + + # dora's default image can't render Gloas blocks; pin the devnet-5 build. + dora_params: + image: ethpandaops/dora:master-0e63023 + + # 6.1.0's default generator (5.3.5) predates Gloas; pin the devnet-5 build. + ethereum_genesis_generator_params: + image: ethpandaops/ethereum-genesis-generator:6.0.8 + + network_params: + network_id: "3151908" + deneb_fork_epoch: 0 + electra_fork_epoch: 0 + fulu_fork_epoch: 0 # Fulu must precede Gloas — activate at genesis + gloas_fork_epoch: 2 # ePBS fork; small so the transition lands a few minutes in (tune freely) + perfect_peerdas_enabled: false + preregistered_validator_count: 74 + + port_publisher: + cl: + enabled: true + +use_static_keys: true + +monitor: + enabled: false + +boole_epoch: 0 # SSV Boole fork active from genesis (ePBS builds on Boole); default is disabled + +nodes: + ssv: + count: 4 + anchor: + count: 0 + +images: + ssv: "node/ssv" + anchor: "sigp/anchor:v1.2.0" + monitor: "monitor" + redis: "redis:7.4.2" + postgres: "postgres:15" + deployer: "localssv/ssv-network"