@toon-protocol/relay 2.0.0 → 2.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -2
- package/dist/{chunk-745ADETR.js → chunk-QZQRHQEQ.js} +354 -108
- package/dist/chunk-QZQRHQEQ.js.map +1 -0
- package/dist/chunk-SMT6G3XD.js +92 -0
- package/dist/chunk-SMT6G3XD.js.map +1 -0
- package/dist/cli.js +58 -5
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +432 -12
- package/dist/index.js +118 -7
- package/dist/index.js.map +1 -1
- package/dist/verify-worker.d.ts +2 -0
- package/dist/verify-worker.js +17 -0
- package/dist/verify-worker.js.map +1 -0
- package/package.json +2 -1
- package/dist/chunk-745ADETR.js.map +0 -1
package/README.md
CHANGED
|
@@ -29,8 +29,39 @@ NOSTR_SECRET_KEY=<64-char-hex> npx @toon-protocol/relay
|
|
|
29
29
|
| `TOON_MNEMONIC` | — | BIP-39 mnemonic (NIP-06 derivation) |
|
|
30
30
|
| `TOON_RELAY_PORT` | `7100` | WebSocket read port |
|
|
31
31
|
| `TOON_BLS_PORT` | `3100` | HTTP write/health port |
|
|
32
|
+
| `TOON_HOST` | `0.0.0.0` | WebSocket bind host |
|
|
33
|
+
| `TOON_WRITE_HOST` | `0.0.0.0` | HTTP write/health bind host (see [write-port exposure](#paid-ephemeral-verify-skip-relay85)) |
|
|
32
34
|
| `TOON_DATA_DIR` | `./data` | SQLite data directory |
|
|
33
35
|
| `TOON_DEV_MODE` | `false` | Skip event-signature verification on `POST /write` |
|
|
36
|
+
| `TOON_VERIFY_EPHEMERAL` | `false` | Run FULL schnorr verification on ephemeral kinds too (see below) |
|
|
37
|
+
| `TOON_VERIFY_WORKERS` | CPUs − 1 | Worker threads for persistent-kind signature verification; `0` = inline on the event loop (automatic on 1-core boxes) |
|
|
38
|
+
| `TOON_MAX_CONNECTIONS` | `4096` | Maximum concurrent WebSocket read connections (each costs one file descriptor — mind `ulimit -n`) |
|
|
39
|
+
|
|
40
|
+
## Paid-ephemeral verify skip (relay#85)
|
|
41
|
+
|
|
42
|
+
By default the relay **skips schnorr verification for ephemeral kinds**
|
|
43
|
+
(NIP-16, `20000 <= kind < 30000`) on `POST /write` and keeps only the SHA-256
|
|
44
|
+
event-id check. This is a deliberate, payment-gated bypass:
|
|
45
|
+
|
|
46
|
+
- **Why it is safe here:** every request reaching `POST /write` has already
|
|
47
|
+
passed the upstream connector's payment claim gate — payment is the
|
|
48
|
+
admission/spam gate. Protocol rule: clients trust the signature chain and
|
|
49
|
+
verify every event themselves, never the relay. Relay-side schnorr on paid
|
|
50
|
+
ephemeral frames buys no additional trust; forging a speaker costs real
|
|
51
|
+
money to emit frames every client discards.
|
|
52
|
+
- **What is still checked:** the SHA-256 id check always runs, so the relay
|
|
53
|
+
never broadcasts bytes that disagree with the event id clients verify by.
|
|
54
|
+
- **When you MUST turn it off:** if your write port is fronted by anything
|
|
55
|
+
other than a payment-gating connector — or you ever add a FREE ephemeral
|
|
56
|
+
write lane — set `TOON_VERIFY_EPHEMERAL=true` (`--verify-ephemeral`,
|
|
57
|
+
`verifyEphemeral: true`). A free lane must NOT reuse this skip.
|
|
58
|
+
- **Exposure guard:** the write port must be reachable only via the
|
|
59
|
+
connector. In docker, never host-publish it (`expose:`, not `ports:` —
|
|
60
|
+
docker-published ports bypass ufw). Outside docker, bind it internally via
|
|
61
|
+
`TOON_WRITE_HOST=127.0.0.1`. At startup the relay logs a prominent warning
|
|
62
|
+
if the write listener binds a non-internal interface while the skip is
|
|
63
|
+
active (warning only — container topologies legitimately bind `0.0.0.0`
|
|
64
|
+
and stay private by not publishing the port).
|
|
34
65
|
|
|
35
66
|
## Run (programmatic)
|
|
36
67
|
|
|
@@ -46,8 +77,9 @@ await relay.stop();
|
|
|
46
77
|
|
|
47
78
|
| Method | Path | Description |
|
|
48
79
|
|--------|------|-------------|
|
|
49
|
-
| `POST` | `/write` | Store an event. Body `{ "event": <NostrEvent> }`. Trusts injected `X-TOON-Payer`/`-Amount`/`-Chain` headers (echoed, not validated); verifies only the event signature. |
|
|
80
|
+
| `POST` | `/write` | Store an event. Body `{ "event": <NostrEvent> }`. Trusts injected `X-TOON-Payer`/`-Amount`/`-Chain` headers (echoed, not validated); verifies only the event signature (ephemeral kinds: id check only by default, see above). |
|
|
50
81
|
| `GET` | `/health` | Liveness, identity (`pubkey`), `capabilities`, and `version`. |
|
|
82
|
+
| `GET` | `/metrics` | JSON telemetry: `eventLoopDelayMs` (mean/p50/p99/max — loop lag is ephemeral-frame tail latency) and `verify` (per-event verify wall time incl. pool queueing, active implementation, worker count). The trigger metrics for scaling decisions (relay#85). |
|
|
51
83
|
|
|
52
84
|
## WebSocket Relay Server
|
|
53
85
|
|
|
@@ -79,7 +111,7 @@ const results = memStore.query([{ kinds: [1], limit: 10 }]);
|
|
|
79
111
|
|
|
80
112
|
## TOON Codec
|
|
81
113
|
|
|
82
|
-
|
|
114
|
+
Vendored in-repo (`src/toon/codec.ts`) so the relay depends only on the lightweight `@toon-format/toon` encoder rather than `@toon-protocol/core`'s full transitive tree. The relay has no runtime dependency on `@toon-protocol/core`.
|
|
83
115
|
|
|
84
116
|
```ts
|
|
85
117
|
import { encodeEventToToon, decodeEventFromToon } from '@toon-protocol/relay';
|