Files
simplexmq/scripts/resolver/README.md
T
2026-06-05 17:43:35 +02:00

155 lines
5.4 KiB
Markdown

# Ethereum stack for SMP names role
Reth (execution) + Nimbus (consensus) on Holesky testnet by default.
## Quickstart
```sh
cd scripts/docker/reth-nimbus
docker compose up -d
docker compose logs -f reth nimbus
```
Sync takes a few hours on Holesky, ~1 day on mainnet. When synced:
```sh
curl -s -X POST http://127.0.0.1:8545 \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}'
```
Point smp-server: `[NAMES] ethereum_endpoint: http://127.0.0.1:8545`.
## How the trust bootstrap works
- **Reth** holds Ethereum state and runs the EVM. It does not decide which fork is canonical.
- **Nimbus** follows the beacon chain and tells Reth which payloads to execute.
- Nimbus needs **one trusted starting point** to break the chicken-and-egg of peer-claims. `--trusted-node-url` fetches that checkpoint once from a public beacon API; from that point on every block is verified locally against the validator set.
- The default `TRUSTED_NODE_URL` is publicnode.com (no API key, no rate limits). Replace with any beacon API you trust — only consulted once on first sync.
## Switching to mainnet
Edit `.env`:
```
NETWORK=mainnet
TRUSTED_NODE_URL=https://ethereum-beacon-api.publicnode.com
```
Then `docker compose down -v && docker compose up -d` (the `-v` wipes state so Nimbus re-bootstraps against the new network). Reth on mainnet needs ~260 GB pruned NVMe.
## Notes
- Reth's RPC is bound to `127.0.0.1:8545` only. For remote access (multiple smp-server hosts → one Reth), put Caddy + Let's Encrypt + Basic auth in front — see `plans/20260522_01_smp_public_namespaces.md` §"Operator deployment".
- Ports 30303/9000 are p2p — open on your firewall for sync.
- `jwt.hex` is generated on first run by the `jwt-init` service and shared between Reth and Nimbus via the `jwt` volume.
- To wipe state and re-sync: `docker compose down -v`.
## SNRC resolver REST API (`snrc-resolve.py`)
The companion script `snrc-resolve.py` exposes the SimpleX Namespace
Registry (SNRC) over a small JSON HTTP API. It talks to the same local
Reth + Nimbus stack described above (set `NETWORK=mainnet` in `.env`),
reading the SNRC contracts directly on Ethereum mainnet.
Install the only runtime dependency (same as `ens-lookup.py`):
```sh
pip install --break-system-packages 'eth-hash[pycryptodome]'
```
### Deployed registries
| TLD | Network | ENSRegistry address |
|------------|------------------|----------------------------------------------|
| `.testing` | Ethereum mainnet | `0x03f438da0bd44da3c6c1d0392f8ba183b8b3a7a6` |
| `.simplex` | — (not deployed) | — |
Each TLD is an independent ENS-shaped deployment with its own
`ENSRegistry`. The resolver dispatches by the queried name's rightmost
label, so a single instance can serve both TLDs concurrently once
`.simplex` launches.
### Running
With Reth bound to `127.0.0.1:8545` (the default Quickstart layout
above), no env vars are required — the script defaults to that RPC and
to the mainnet `.testing` registry:
```sh
./scripts/resolver/snrc-resolve.py
```
Output on startup:
```
snrc-resolve listening on 0.0.0.0:8000
RPC = http://127.0.0.1:8545
Registries:
.testing = 0x03f438da0bd44da3c6c1d0392f8ba183b8b3a7a6
.simplex = (not configured)
GET /resolve/<name> GET /health
```
Override the listen port or bind address with `SNRC_PORT` / `SNRC_BIND`.
### Resolving a name
`foobar.testing` is registered on mainnet with every text and
multicoin record populated (useful as a smoke-test target):
```sh
curl -s http://127.0.0.1:8000/resolve/foobar.testing | jq .
```
```json
{
"name": "foobar.testing",
"nickname": "Foo",
"website": "https://foo.bar",
"location": "",
"simplex.contact": "https://smp16.simplex.im/a#Q_F00BA7",
"simplex.channel": "",
"ETH": null,
"BTC": "bc1qpzht4wp64yg7z6sgl07vvrnepyux740juynfcn",
"XMR": "4ANzdVJFxLtCKcBgNGkFSEA41zJFgrTX93LWt9UR6xpg7YNCsdrSV817cw2xKT8NXeS5euBBqTApS2u8kRTxMhyiDGN3Qgt",
"DOT": "139GgyEsXDyGLhmhBTPmDmGCyTvTVuLad3YjHax2PWLK6p3s",
"owner": "0xd83bb610fbad567fb5d8755ec162881e46d1fbc9",
"resolver": "0x80fa1903e70af03e79c73fb7feae2fb33aebae01"
}
```
Address encoding matches each chain's canonical user-facing form:
EIP-55 mixed-case for ETH, bech32/bech32m for BTC segwit/taproot
(base58check for legacy P2PKH/P2SH), SS58 with Polkadot prefix 0 for
DOT, Monero-base58 for XMR. Unrecognised payloads fall back to
`0x`-prefixed hex.
### Health check
```sh
curl -s http://127.0.0.1:8000/health
# → {"ok": true, "rpc": "http://127.0.0.1:8545", "registries": {"testing": "0x…", "simplex": ""}}
```
### Pointing at multiple deployments
Once `.simplex` deploys, point a single resolver instance at both
registries — requests are dispatched by the rightmost label:
```sh
SNRC_REGISTRY_SIMPLEX=0x...mainnet-simplex-ENSRegistry... \
./scripts/resolver/snrc-resolve.py
```
Queries for a TLD with no registry configured return HTTP 400 with the
list of supported TLDs.
### Error responses
| Status | When |
|--------|-----------------------------------------------------------------------|
| 400 | TLD not configured (`/resolve/foo.simplex` while `.simplex` is empty) or path not a fully-qualified name |
| 404 | Name has no resolver set on the registry (`ENSRegistry.resolver(node)` is zero) |
| 502 | Upstream RPC error / unreachable (Reth not running or not synced) |