Files
simplexmq/scripts/resolver/docker-compose.yml
T
brenzi-agentandbrenzi-agent 89c8ba9c98 resolver: read .simplex reservations from the name policy (#1993)
* resolver: read .simplex reservations from the name policy

simplex-network/ens-contracts#42 moved reservedNames from SimplexController
to SimplexNamePolicy. SNRC_NAME_POLICY_<TLD> names it; where it is unset the
controller is read as before, as on .testing.

Claude-Session: https://claude.ai/code/session_01BxsKd45qytTbangMqJs93F

* resolver: address review: keep the reserved read's shape, explicit policy in tests, describe contracts by behavior

Claude-Session: https://claude.ai/code/session_01BxsKd45qytTbangMqJs93F

* resolver: address review: pin the name policy in every test that reads reservations, one policy test that fails without the read, note setNamePolicy

Claude-Session: https://claude.ai/code/session_01BxsKd45qytTbangMqJs93F

* resolver: address review: no env pins the suite does not keep elsewhere, no comment repeating the docstring

Claude-Session: https://claude.ai/code/session_01BxsKd45qytTbangMqJs93F

* resolver: address review: name what the .testing controller keeps

Claude-Session: https://claude.ai/code/session_01BxsKd45qytTbangMqJs93F

* resolver: address review: an empty name policy reply is refused too

Claude-Session: https://claude.ai/code/session_01BxsKd45qytTbangMqJs93F

* resolver: read each controller's name policy at startup in place of SNRC_NAME_POLICY_<TLD>

Claude-Session: https://claude.ai/code/session_01BxsKd45qytTbangMqJs93F

* resolver: address review: workers open their own RPC connections, docs of the startup read, test names and docstrings that say what holds

Claude-Session: https://claude.ai/code/session_01BxsKd45qytTbangMqJs93F

* resolver: a controller with no contract behind it stops the startup read, so the container restarts until the node reaches it

Claude-Session: https://claude.ai/code/session_01BxsKd45qytTbangMqJs93F

* resolver: address review: an empty name policy reply falls back again, so a chain without .testing's controller still starts; new functions after the ones they join, compose lines added only

Claude-Session: https://claude.ai/code/session_01BxsKd45qytTbangMqJs93F

* resolver: address review: tests of the workers' own connections, an address without a contract and an unconfigured controller; docs of which TLDs answer 502

Claude-Session: https://claude.ai/code/session_01BxsKd45qytTbangMqJs93F

* resolver: address review: a controller naming no policy is logged as the other fallbacks are, a test of the startup exit, no redundant default

Claude-Session: https://claude.ai/code/session_01BxsKd45qytTbangMqJs93F

* resolver: address review: the startup test above the worker tests' Linux guard, without a controller it does not need

Claude-Session: https://claude.ai/code/session_01BxsKd45qytTbangMqJs93F

* resolver: address review: the startup test runs one worker, a test of an unconfigured controller, the fallbacks described once

Claude-Session: https://claude.ai/code/session_01BxsKd45qytTbangMqJs93F

* resolver: address review: compose names the 502 of a policy the node has not reached, the worker test sets its own reservation, no repeated README clauses

Claude-Session: https://claude.ai/code/session_01BxsKd45qytTbangMqJs93F

* resolver: every worker test reads the name's reservation from the policy, so its answer stays in setUp

Claude-Session: https://claude.ai/code/session_01BxsKd45qytTbangMqJs93F

* resolver: address review: docstrings that say where reservations are read from, no comment that does not hold

Claude-Session: https://claude.ai/code/session_01BxsKd45qytTbangMqJs93F

* resolver: address review: each reservation read picks the policy over the controller itself, no helper for two sites

Claude-Session: https://claude.ai/code/session_01BxsKd45qytTbangMqJs93F

* resolver: address review: the quick start's restart for a TLD with a name policy, the startup read's docstring

Claude-Session: https://claude.ai/code/session_01BxsKd45qytTbangMqJs93F

---------

Co-authored-by: brenzi-agent <346870783+brenzi-agent@users.noreply.github.com>
2026-10-29 12:13:37 +00:00

182 lines
6.5 KiB
YAML

services:
# One-shot setup (runs as root): generates /jwt/jwt.hex and chowns the
# nimbus-data volume to UID 1000 (the user Nimbus runs as inside its image).
# Without this chown Nimbus gets "Permission denied" on its data dir
# because docker creates fresh named volumes owned by root.
init:
image: alpine:latest
volumes:
- jwt:/jwt
- nimbus-data:/nimbus-data
command: >
sh -c '
set -e;
if [ ! -f /jwt/jwt.hex ]; then
apk add --no-cache openssl >/dev/null;
openssl rand -hex 32 | tr -d "\n" > /jwt/jwt.hex;
chmod 644 /jwt/jwt.hex;
echo "Generated /jwt/jwt.hex";
else
echo "jwt.hex already exists";
fi;
chown 1000:1000 /nimbus-data;
echo "Chowned /nimbus-data to 1000:1000";
'
restart: "no"
# One-shot: fetches a recent finalised checkpoint into the Nimbus data dir
# using the trustedNodeSync subcommand. Skipped if the data dir is already
# initialised, so subsequent compose-ups are no-ops.
nimbus-checkpoint-sync:
image: statusim/nimbus-eth2:multiarch-latest
depends_on:
init:
condition: service_completed_successfully
volumes:
- nimbus-data:/home/user/nimbus-eth2/build/data
entrypoint:
- sh
- -c
- |
if [ -d /home/user/nimbus-eth2/build/data/${NETWORK:-mainnet}/db ]; then
echo "Nimbus data dir already initialised — skipping checkpoint sync";
exit 0;
fi;
/home/user/nimbus-eth2/build/nimbus_beacon_node trustedNodeSync \
--network=${NETWORK:-mainnet} \
--data-dir=/home/user/nimbus-eth2/build/data/${NETWORK:-mainnet} \
--trusted-node-url=${TRUSTED_NODE_URL:-https://mainnet-checkpoint-sync.attestant.io} \
--backfill=false
restart: "no"
# One-shot: downloads a pre-synced snapshot from snapshots.reth.rs into the
# Reth data dir. Turns a multi-day from-scratch sync into a ~hour download.
# Skipped if the data dir is already initialised — re-runs are no-ops.
# Privacy note: snapshots.reth.rs sees this download (operator existence).
# Subsequent eth_call traffic stays local.
reth-snapshot-init:
image: ghcr.io/paradigmxyz/reth:latest
depends_on:
init:
condition: service_completed_successfully
volumes:
- reth-data:/data
entrypoint:
- sh
- -c
- |
if [ -f /data/.snapshot-done ] || [ -d /data/db ]; then
echo "Reth data already initialised — skipping snapshot download";
exit 0;
fi;
echo "Downloading Reth ${NETWORK:-mainnet} --minimal snapshot...";
reth download --datadir /data --chain ${NETWORK:-mainnet} --minimal && \
touch /data/.snapshot-done && \
echo "Snapshot download complete"
restart: "no"
reth:
image: ghcr.io/paradigmxyz/reth:latest
depends_on:
reth-snapshot-init:
condition: service_completed_successfully
volumes:
- reth-data:/data
- jwt:/jwt:ro
ports:
# JSON-RPC for smp-server. Bound to loopback — put Caddy in front for remote access.
- "127.0.0.1:8545:8545"
# p2p (Ethereum network). Open these on your firewall for sync.
- "30303:30303/tcp"
- "30303:30303/udp"
command: >
node
--datadir /data
--chain ${NETWORK:-mainnet}
--minimal
--authrpc.jwtsecret /jwt/jwt.hex
--authrpc.addr 0.0.0.0 --authrpc.port 8551
--http
--http.addr 0.0.0.0 --http.port 8545
--http.api eth,net
--rpc.gascap 50000000
--port 30303
--discovery.port 30303
restart: unless-stopped
nimbus:
image: statusim/nimbus-eth2:multiarch-latest
depends_on:
nimbus-checkpoint-sync:
condition: service_completed_successfully
volumes:
- nimbus-data:/home/user/nimbus-eth2/build/data
- jwt:/jwt:ro
ports:
- "9000:9000/tcp"
- "9000:9000/udp"
- "127.0.0.1:5052:5052"
command: >
--network=${NETWORK:-mainnet}
--data-dir=/home/user/nimbus-eth2/build/data/${NETWORK:-mainnet}
--el=http://reth:8551
--jwt-secret=/jwt/jwt.hex
--non-interactive
--rest --rest-address=0.0.0.0 --rest-port=5052
--nat=${NAT:-any}
restart: unless-stopped
# SNRC REST resolver. Talks to reth on the compose-internal network,
# exposes /resolve and /health on 127.0.0.1:8000 by default. The
# smp-server points its [NAMES] resolver_endpoint at this URL.
# To change the host port, edit the LEFT side of the port mapping below.
resolver:
image: snrc-resolve:local
build:
context: ./service
dockerfile: Dockerfile
depends_on:
# reth's `service_started` is sufficient — the resolver tolerates
# eth_call failures gracefully (returns 502 with the error body), so
# starting before reth has finished snapshot replay just yields a few
# 502s until the chain is queryable. The upstream reth image doesn't
# ship a HEALTHCHECK, so we can't gate on healthy.
# The startup read of the name policies is the exception: until reth
# answers, the resolver exits and restarts, and a TLD whose name policy
# reth has not yet reached answers 502 until the resolver restarts
# (README, "Configuring addresses").
reth:
condition: service_started
environment:
SNRC_RPC: http://reth:8545
SNRC_BIND: 0.0.0.0
# Registry addresses cascade through the script's own defaults
# (mainnet `.testing`; `.simplex` unconfigured). Set explicitly here
# only if you're deploying against a different network or contract.
# SNRC_REGISTRY_TESTING: 0x...
# SNRC_REGISTRY_SIMPLEX: 0x...
# Registrar and controller, same cascade. Without the registrar `status`
# is "unknown"; without the controller a reserved name is "unregistered".
# SNRC_REGISTRAR_TESTING: 0x...
# SNRC_REGISTRAR_SIMPLEX: 0x...
# SNRC_CONTROLLER_TESTING: 0x...
# SNRC_CONTROLLER_SIMPLEX: 0x...
# Set in .env (see .env.example); unset or empty means the resolver's default.
SNRC_WORKERS: ${SNRC_WORKERS:-}
SNRC_RPC_TIMEOUT: ${SNRC_RPC_TIMEOUT:-}
SNRC_LOG_FORMAT: ${SNRC_LOG_FORMAT:-}
SNRC_LOG_COLOR: ${SNRC_LOG_COLOR:-}
SNRC_LOG_LEVEL: ${SNRC_LOG_LEVEL:-}
SNRC_TRUSTED_PROXIES: ${SNRC_TRUSTED_PROXIES:-}
ports:
- "127.0.0.1:8000:8000"
# a line per lookup; the local driver keeps 5 rotated files of 20 MB
logging:
driver: local
restart: unless-stopped
volumes:
reth-data:
nimbus-data:
jwt: