Запуск Control Plane
Эта страница ведёт от звезды с ролью CP к Control Plane, который находят узлы и клиенты: запустить star, опубликовать эндпоинт и ключ фронта и проверить, что всё работает.
Прежде всего
Заголовок раздела «Прежде всего»Роль CP не выдаётся при регистрации: каждая новая звезда — Node. На стадии теста её выдаёт основатель вручную, а дальше звезда будет получать её, внеся стейк. См. как стать Control Plane.
Эта страница исходит из того, что у вашей звезды роль уже есть.
Всё остальное ничьего согласия не требует: список эндпоинтов открыт, клиенты сами опрашивают его, а чтобы войти в федерацию, разрешение остальных участников не нужно.
Что понадобится
Заголовок раздела «Что понадобится»- То же, что для узла: Linux-сервер, Docker и кошелёк на одну транзакцию.
- Публичное DNS-имя и терминация TLS перед портом gRPC.
- ETH на адресе подписанта Control Plane. В отличие от узла, Control Plane отправляет транзакции: публикует отработанное время и ретранслирует операции без газа, и за то и другое платит горячий подписант.
Шаг 1 — зарегистрировать звезду
Заголовок раздела «Шаг 1 — зарегистрировать звезду»Ровно как для узла — см. запуск узла. На выходе у вас starId с ролью Node.
Шаг 2 — получить роль
Заголовок раздела «Шаг 2 — получить роль»Как только роль появилась, программа переключается сама: читает роль из блокчейна и поднимает gRPC на 0.0.0.0:9090. Перезапуск не нужен.
Шаг 3 — пополнить подписанта
Заголовок раздела «Шаг 3 — пополнить подписанта»Скопируйте адрес подписанта со страницы звезды в Stargate и отправьте на него ETH — но немного. Подписант — горячий ключ на сервере, и всё, что на нём лежит, пропадёт, если сервер взломают.
Транзакция в Arbitrum стоит доли цента. Отправка пачки интервалов в блокчейн тратит примерно от 50 000 до 1 000 000 газа, и при обычной цене газа около 0,02 gwei это не больше 0,00002 ETH. Таких транзакций Control Plane отправляет несколько в день, плюс операции без газа, которые он ретранслирует за клиентов. 0,005 ETH хватает примерно на месяц, даже если все пачки тяжёлые, а обычно дольше. Пополняйте, когда заканчивается, а не держите большой баланс.
Следите за этим балансом: когда он дойдёт до нуля, Control Plane перестанет публиковать отработанное время, и его узлы перестанут зарабатывать.
Шаг 4 — настроить
Заголовок раздела «Шаг 4 — настроить»Почти все значения по умолчанию подходят. Внимания требует одно:
environment: - BLOCKCHAIN_RPC_URL=https://sepolia-rollup.arbitrum.io/rpc - CHAIN_ID=421614 - REVERSE_PROXY=cp.example.com:443REVERSE_PROXY — публичный адрес, который этот Control Plane сообщает соседям по федерации, когда представляется им; в блокчейн он не записывается. Эндпоинт в блокчейне публикует владелец отдельно, на шаге 5. Укажите в обоих местах один и тот же адрес.
Адреса контрактов не настраиваются. При запуске программа читает их все из SingulaProtocol, директории сети, так что передеплоенный контракт доходит до каждого Control Plane через одну запись в блокчейне. Переменная адреса вроде SUBSCRIBER_REGISTRY_ADDRESS, оставшаяся в compose-файле, игнорируется, если директория говорит иначе, и в лог пишется предупреждение. Если директорию прочитать не удалось, программа не запускается: работать на угаданных адресах было бы хуже. SINGULA_PROTOCOL_ADDRESS указывает на другую директорию, а off отключает её для локальной сети — тогда используются переменные адресов.
Стоит знать:
| Переменная | По умолчанию | Что делает |
|---|---|---|
GRPC_ADDRESS | 0.0.0.0:9090 | Где слушают все четыре сервиса |
ATTESTATION_PUSH_INTERVAL | 4ч | Как часто отработанное время уходит в блокчейн |
ACCESS_SWEEP_INTERVAL | 1ч | Как часто этот Control Plane убирает истёкших подписчиков из множества — в блокчейне и за свой газ |
CP_FRONT_ENABLED | true | Фронт |
CP_FRONT_PORT | 8443 | Где слушает фронт; клиенты приходят на 443 через прокси |
REALITY_KEY_VERSION | 1 | Если поднять, ключ фронта сменится |
BADGER_DIR | /var/lib/star/badger | Локальное хранилище |
METRICS_HTTP_PORT | 9101 | Порт /status (JSON) и /metrics (Prometheus); 0 выключает |
METRICS_BIND | 127.0.0.1 | Где он слушает. Расширяйте только за файрволом или паролем |
Правила сети здесь не настраиваются: сколько живут учётные данные, сколько сессия должна передать, чтобы время засчиталось, и ограничения анонимного уровня. Каждый Control Plane читает их из директории. См. ограничения.
Шаг 5 — опубликовать эндпоинт
Заголовок раздела «Шаг 5 — опубликовать эндпоинт»CPEndpointRegistry.setEndpoint(starId, host, port) вызывает владелец, и только пока у звезды роль CP.
В Stargate на карточке Control Plane для этого две кнопки: Set Endpoint, которая принимает host или host:port (без порта сохранится 0, то есть «порт протокола по умолчанию»), и Clear Endpoint.
Когда транзакция пройдёт, вы появитесь в getActiveEndpoints(), и узлы с клиентами подхватят вас при следующем опросе.
Шаг 6 — опубликовать ключ фронта
Заголовок раздела «Шаг 6 — опубликовать ключ фронта»Каждый Control Plane держит фронт: вход по REALITY, который ведёт к его собственному gRPC и больше никуда. Он нужен клиентам из сетей, где эндпоинт заблокирован. Параметры фронта задаёт протокол, поэтому любой клиент доберётся до фронта любого Control Plane с тем, что у него уже есть. Свой у вас только ключ.
Ключ выводится из ключа подписанта и REALITY_KEY_VERSION. Ничего нового хранить не нужно, и при переезде на другую машину ключ сохраняется. Control Plane печатает его при каждом запуске:
REALITY public key (version 1): Vfv6lG2gjLQSbkLJdcH72Eo7zW2LrNRhAyrvU_YPJGQОпубликуйте его действием REALITY key на карточке Control Plane в Stargate или вызовом CPEndpointRegistry.setRealityKey(starId, key) — это 32 байта, в которые декодируется текст base64url. Клиенты читают ключ оттуда. Если подняли версию, опубликуйте новый ключ.
Фронт слушает на CP_FRONT_PORT. Клиенты приходят на порт 443 с именем сервера account.adobe.com, поэтому направьте это имя на фронт, пропуская TLS нетронутым: REALITY должен сам увидеть ClientHello. С Traefik:
labels: - traefik.tcp.routers.cp-front.rule=HostSNI(`account.adobe.com`) - traefik.tcp.routers.cp-front.entrypoints=websecure - traefik.tcp.routers.cp-front.tls.passthrough=true - traefik.tcp.routers.cp-front.service=cp-front - traefik.tcp.services.cp-front.loadbalancer.server.port=8443Этого имени нет среди пресетов узла, поэтому прокси, который делит 443 между Control Plane и узлом, разводит их по имени без конфликтов.
Шаг 7 — проверить
Заголовок раздела «Шаг 7 — проверить»grpcurl <host>:<port> singula.admin.v1.AdminService/GetHealthотвечаетSERVING.- Вы есть в
getActiveEndpoints()в блокчейне. - В Stargate появляются живые сессии и подключённые узлы.
- Через несколько часов работы с трафиком в
EpochAttestationsпоявляются событияPushedот вашего подписанта.
За обратным прокси
Заголовок раздела «За обратным прокси»Программа говорит на обычном gRPC, а TLS завершается перед ней. Прокси общается с ней по HTTP/2 без TLS — это и есть h2c.
cp.example.com { reverse_proxy h2c://127.0.0.1:9090}services: traefik: image: traefik:v3.1 restart: unless-stopped command: - --providers.docker=true - --providers.docker.exposedbydefault=false - --entrypoints.websecure.address=:443 - --entrypoints.web.address=:80 - --certificatesresolvers.le.acme.tlschallenge=true - --certificatesresolvers.le.acme.email=ops@example.com - --certificatesresolvers.le.acme.storage=/letsencrypt/acme.json ports: ["443:443", "80:80"] volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - ./letsencrypt:/letsencrypt
star: image: singulanetwork/star:alpha container_name: singula-cp restart: unless-stopped env_file: .env labels: - traefik.enable=true - traefik.http.routers.cp.rule=Host(`cp.example.com`) - traefik.http.routers.cp.entrypoints=websecure - traefik.http.routers.cp.tls.certresolver=le - traefik.http.services.cp.loadbalancer.server.port=9090 - traefik.http.services.cp.loadbalancer.server.scheme=h2cservices: star: image: singulanetwork/star:alpha container_name: singula-cp restart: unless-stopped env_file: .env expose: ["9090"] networks: [edge]
haproxy: image: haproxy:2.9-alpine restart: unless-stopped depends_on: [star] ports: ["443:443"] volumes: - ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro - ./certs/cp.pem:/etc/ssl/cp.pem:ro # cat fullchain.pem privkey.pem > cp.pem networks: [edge]
networks: edge: {}
# haproxy.cfg# global# log stdout format raw local0# defaults# mode http# timeout connect 5s# timeout client 1h# timeout server 1h# frontend grpc_in# bind *:443 ssl crt /etc/ssl/cp.pem alpn h2# default_backend grpc_cp# backend grpc_cp# server cp star:9090 proto h2Таймауты делайте длинными: потоки клиентов держатся часами.
За чем следить
Заголовок раздела «За чем следить»Control Plane рассказывает о себе по тем же двум адресам, что и узел: /status отдаёт JSON, /metrics — формат Prometheus, оба на METRICS_HTTP_PORT.
curl -s localhost:9101/status | jqВ ответе есть эпоха, сколько узлов подключено и сколько ждут регистрации, сколько открыто клиентских сессий, сколько интервалов ждут отправки и сколько прошло с последней записи в блокчейн, а ещё время работы, процессор и память. Блок info называет адрес подписанта и starId.
Стоит поставить отдельные оповещения:
singula_cp_attestation_pushes_totalравен нулю. Ничего из того, что обслужил этот Control Plane, ни разу не было оплачено.- Баланс ETH у подписанта. На нуле публикация останавливается, и ваши узлы перестают зарабатывать.
- Место на диске под BadgerDB.
- Нет событий
PushedвEpochAttestations, хотя трафик идёт: интервалы отбрасываются, а не отправляются. - Строки
relay errorв логе — см. если что-то не работает.
