-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathMakefile
More file actions
214 lines (198 loc) · 10.5 KB
/
Copy pathMakefile
File metadata and controls
214 lines (198 loc) · 10.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# Operator workflow wrapper for nodes.quip.network.
#
# Two main entry points:
# make testnet -> join the live Quip Testnet
# make localdev -> self-contained single-validator dev chain
#
# Run `make help` for the full target list.
PROFILE ?= cpu
SUDO_KEY ?= //Alice
DATA ?= data
# Host pipe directory for the NVIDIA MPS control daemon (PROFILE=cuda only).
# Matches the path the cuda service bind-mounts in docker-compose.yml.
MPS_PIPE_DIR := /tmp/nvidia-mps
# Plain `docker compose ...` defaults to live Quip Testnet — only
# docker-compose.yml is auto-loaded now that the localdev override was
# renamed off the magic `docker-compose.override.yml` filename.
COMPOSE := docker compose
# Opt-in stack with the dev-chain override layered on top. Runs under its own
# `-p quip-localdev` project so its namespaced containers/volumes (see the
# container_name/volume overrides in docker-compose.localdev.yml) never collide
# with a live `make testnet` stack over the fixed global names in the base file.
COMPOSE_LOCALDEV := docker compose -p quip-localdev -f docker-compose.yml -f docker-compose.localdev.yml
# Localdev resolves the newest published tag per image at run time. CI does not
# move `latest` for rc builds, so tracking it silently holds localdev on an old
# build. `make testnet` deliberately keeps `latest` — a release pointer is what
# a production stack wants.
TAGS_ENV := data/localdev.tags.env
# --env-file replaces compose's default .env loading, so pass both: .env first
# for operator settings, the resolved tags second. A QUIP_*_TAG pinned in .env
# is echoed back unchanged by the resolver, so an explicit pin still wins.
COMPOSE_TAGGED := $(COMPOSE_LOCALDEV) --env-file .env --env-file $(TAGS_ENV)
.DEFAULT_GOAL := help
.PHONY: help testnet localdev pull down logs clean clean-chain require-env require-mps updateconfig updateconfig-docker show-channel
help:
@echo "nodes.quip.network — operator targets"
@echo ""
@echo " make testnet Pull + bring up stack against live Quip Testnet"
@echo " (PROFILE=cuda also starts the host NVIDIA MPS daemon)"
@echo " make localdev Wipe chain, bring up self-contained dev stack"
@echo " (validator on --chain=dev, faucet, seeded topology,"
@echo " registered miner, dashboard, caddy)"
@echo " make updateconfig Convert a v0.1 data/config.toml to the v0.2 [miner]"
@echo " schema (backs up originals to data/.v0.1_backup/)."
@echo " Override the dir with DATA=/path/to/data."
@echo " make updateconfig-docker Same as above but inside python:3.12-alpine"
@echo " (use when the host has Python < 3.11)."
@echo " make pull Pull images for PROFILE"
@echo " make down Tear down both profile sets"
@echo " make logs Tail merged stack log (data/logs/quip-node.log)"
@echo " make clean-chain Wipe data/aglais-chain-db/chains"
@echo " make clean Full reset: down + wipe chain, pgdata volume, dashboard-data"
@echo ""
@echo "Variables (override on cmdline):"
@echo " PROFILE=$(PROFILE) compose profile (cpu | cuda; faucet layers additively)"
@echo " SUDO_KEY=$(SUDO_KEY) dev URI used for localdev seeding"
@echo " DATA=$(DATA) data dir converted by updateconfig"
require-env:
@test -f .env || { \
echo "error: .env not found. Create it with:"; \
echo " cp env.example .env"; \
echo " printf 'PUID=%s\\nPGID=%s\\n' \"\$$(id -u)\" \"\$$(id -g)\" >> .env"; \
exit 1; \
}
# Ensure the host NVIDIA MPS control daemon is running before a GPU miner
# starts, so the cuda container's ipc:host + /tmp/nvidia-mps bind-mount actually
# enable hardware SM sharing instead of the software-nonce fallback. No-op
# unless PROFILE=cuda. Best-effort: a missing nvidia-cuda-mps-control, an
# unsupported host (WSL2/Docker Desktop), or a failed start only warns — the
# miner still runs (degraded), it doesn't block boot.
require-mps:
ifeq ($(PROFILE),cuda)
@command -v nvidia-cuda-mps-control >/dev/null 2>&1 || { \
echo "warning: nvidia-cuda-mps-control not found on host."; \
echo " GPU miner will fall back to software nonce reduction."; \
echo " Install the NVIDIA driver's MPS utilities to enable SM sharing."; \
exit 0; \
}
@mkdir -p "$(MPS_PIPE_DIR)" 2>/dev/null || true
@if pgrep -f nvidia-cuda-mps-control >/dev/null 2>&1; then \
echo "MPS control daemon already running (pipe dir: $(MPS_PIPE_DIR))."; \
else \
echo "starting NVIDIA MPS control daemon (pipe dir: $(MPS_PIPE_DIR))..."; \
if CUDA_MPS_PIPE_DIRECTORY="$(MPS_PIPE_DIR)" nvidia-cuda-mps-control -d; then \
echo "MPS control daemon started."; \
else \
echo "warning: failed to start MPS daemon (may need root, or host is WSL2/Docker Desktop)."; \
echo " Miner will fall back to software nonce reduction."; \
fi; \
fi
endif
# Live Quip Testnet. Plain `docker compose` is testnet now (the localdev
# override is opt-in via -f docker-compose.localdev.yml, not auto-loaded).
# PROFILE=cuda also starts the host MPS daemon first (require-mps).
testnet: require-env require-mps
$(COMPOSE) --profile $(PROFILE) pull
$(COMPOSE) --profile $(PROFILE) up -d
@echo ""
@echo "testnet stack up. tail logs: make logs"
# Self-contained dev chain. Layers docker-compose.localdev.yml on top of the
# base docker-compose.yml to flip the validator to --chain=dev and pull
# quip-faucet into the cpu/cuda profiles. Order matters: validator+faucet
# must produce blocks before sudo seeding; seeding must complete before the
# miner bootstraps (so DefaultTopology + the difficulty are live when the
# miner queries them).
localdev: require-env down clean-chain
# Localdev is config-driven: replace data/config.toml with the dev
# variant (colocated faucet) before the miner boots. The localdev
# stack is self-contained, so clobbering the config is by design.
mkdir -p data
cp config/localdev.$(PROFILE).toml data/config.toml
# Ask the registry which tag is newest per image. Any QUIP_*_TAG already
# set in .env or the environment is passed through, not overridden. The
# script writes the file itself rather than taking a `>` redirect, so it can
# read the previous run's tags and reuse them when the registry is down.
python3 scripts/newest-tags.py $(TAGS_ENV)
@echo "localdev image tags:"
@cat $(TAGS_ENV)
$(COMPOSE_TAGGED) --profile $(PROFILE) pull
$(COMPOSE_TAGGED) --profile $(PROFILE) up -d quip-validator quip-faucet
@echo "waiting for validator to produce blocks..."
@sleep 12
$(COMPOSE_TAGGED) --profile $(PROFILE) run --rm \
--entrypoint quip-coordinator $(PROFILE) seed-chain \
--validator ws://quip-validator:9944 --sudo-key $(SUDO_KEY)
# The cpu/cuda miner self-bootstraps (register + fund) on startup.
# Topology must already be seeded above, otherwise the miner's
# self-bootstrap fails inside its retry loop.
$(COMPOSE_TAGGED) --profile $(PROFILE) up -d
@echo ""
@echo "localdev stack up. tail logs: tail -F data/logs-localdev/quip-node.log"
@echo ""
@echo " dashboard : http://localhost:20049/"
@echo " miner REST (v1) : http://localhost:20049/api/v1/"
@echo " faucet (POST) : http://localhost:20049/api/faucet/request"
@echo " substrate RPC : http://localhost:20049/rpc (HTTP + WS)"
# v0.1 → v0.2 config converter. Renames [global] → [miner], drops P2P/TLS
# keys that no longer have a consumer (substrate validator owns p2p now),
# and preserves the backend tables ([cpu], [gpu], [cuda.N], [qpu], [dwave],
# ...) verbatim. The original data/ contents are moved into
# data/.v0.1_backup/ so nothing is lost. Idempotent on already-v0.2 dirs.
updateconfig:
@test -d "$(DATA)" || { echo "error: $(DATA) is not a directory. Override with DATA=path/to/data."; exit 1; }
python3 scripts/upgrade-config.py "$(DATA)"
# Docker fallback for hosts on Python < 3.11 (e.g. Ubuntu 22.04, which ships
# 3.10 and so doesn't have stdlib `tomllib`). python:3.12-alpine is ~20MB
# and ships tomllib — no pip install needed because the script is stdlib-only.
updateconfig-docker:
@test -d "$(DATA)" || { echo "error: $(DATA) is not a directory. Override with DATA=path/to/data."; exit 1; }
docker run --rm \
-v "$(abspath $(DATA)):/data" \
-v "$(CURDIR)/scripts/upgrade-config.py:/upgrade-config.py:ro" \
python:3.12-alpine \
python3 /upgrade-config.py /data
pull: require-env
$(COMPOSE) --profile $(PROFILE) pull
# Tear down BOTH stacks. testnet (default project) and localdev
# (-p quip-localdev) now live in separate project namespaces, so each must be
# torn down on its own. Harmless on hosts that only ran one of them — compose
# no-ops on a project with nothing running.
down:
$(COMPOSE) --profile $(PROFILE) --profile faucet down
$(COMPOSE_LOCALDEV) --profile $(PROFILE) --profile faucet down
logs:
@if [ -f data/logs/quip-node.log ]; then \
tail -F -n 200 data/logs/quip-node.log; \
else \
echo "data/logs/quip-node.log not present yet; falling back to compose logs"; \
$(COMPOSE) logs -f --tail=50; \
fi
# `trash` keeps wiped chains recoverable via macOS Trash per global preference;
# the rm fallback covers Linux/CI hosts without `trash` installed.
clean-chain:
@if command -v trash >/dev/null 2>&1; then \
trash data/aglais-chain-db/chains 2>/dev/null || true; \
else \
rm -rf data/aglais-chain-db/chains; \
fi
# Full reset. Tears the stack down, wipes the chain, removes the postgres
# data volume (fixes the cross-project `aglais-pgdata` mismatch that breaks
# the dashboard migration with "password authentication failed"), and
# clears dashboard-data so the indexer re-syncs from scratch alongside the
# fresh DB. Destructive — do not run on a production node without a dump.
clean: down clean-chain
-docker volume rm aglais-pgdata quip-localdev-pgdata 2>/dev/null
@if command -v trash >/dev/null 2>&1; then \
trash dashboard-data 2>/dev/null || true; \
else \
rm -rf dashboard-data; \
fi
# Answer "what will I actually pull" in one command. CHANNEL names a moving
# tag, so the reference alone does not say which build it resolves to. Honors
# CHANNEL and any QUIP_*_TAG pin exactly as `up` would, because it asks compose
# rather than reimplementing the rules.
show-channel:
@echo "CHANNEL=$${CHANNEL:-beta} (unset means beta)"
@docker compose --profile cpu --profile cuda --profile faucet config 2>/dev/null \
| grep -E '^[[:space:]]+image: registry' \
| sed 's/^[[:space:]]*image: / /' | sort -u