Open10
Nostr リレー開発
Nostr リレーの開発に必要な情報の調査。
要件
- WebSocket が動くサーバー
- NIP の実装 (wss)
- 認証
- NIP-42
- pubkey ホワイトリスト
- p タグに含まれる場合も許可
- pubkey ホワイトリスト
- NIP-42
- レートリミット
- スパム対策
- タグが大量に含まれる場合は弾く
- kind 3, NIP-51 が弾かれてしまうのでなし
- タグが大量に含まれる場合は弾く
- NIP-11 の実装 (https, application/nostr+json)
- フロントエンド (https)
- トップページ
- 利用規約
- ステータスページ
- ダッシュボード(管理画面)
- スパム報告一覧
- BAN
- データ削除
- ブロック
- pubkey
- IP アドレス
- テスト
- あるといいかも?
- Webhook
- プッシュ通知
規約
利用規約
このサービスはいかなる種類の保証もなく現状のまま提供されます。
管理者は一切の責任を負いません。
利用規約は、将来予告なしにいつでも変更される可能性があります。
BOT は kind 0 に bot: true
を設定してください。設定されていない場合はブロックされることがあります。
管理者の判断で削除およびブロックされることがあります。
例:
- 違法なコンテンツ
- スパム行為
- その他
プライバシーポリシー
送信されたデータおよび送信元の IP アドレスを保存します。
送信されたデータはすべて公開されます。(暗号化されている場合は暗号化後のデータのみ)
IP アドレスは公開されませんが必要に応じて警察などへ提供される場合があります。
参考
ルーティング
-
example.com
-
/
: トップページ- リレーの説明
- 登録
- 利用規約、プライバシーポリシー
- ユーザー数などの情報
-
/
+Accept: application/nostr+json
: NIP-11 -
/
(wss): WebSocket -
/register
: ユーザー登録
-
-
status.example.com
-
/
: ステータス
-
-
portal.example.com
-
/
: 管理画面
-
Hono
npm create hono@latest
Cloudflare
データベース設計
要件
REQ フィルターは可変のため事前に TL を構築することができない。
DB 全体からデータを効率よく取得する必要がある。
メタデータ
- IP アドレス
- 受信日時
- 登録情報
選定
Durable Objects SQL Storage, D1, KV, TimescaleDB, その他から選択。
D1 + KV にするのが良さそう。後々他の選択肢も選べるようになるとベター。
Durable Objects は GUI がないのでデータ見るときに大変そう。
設計
D1 にすべてを保存すると容量(上限 10GB)的に厳しいのとおそらく肥大化したときにパフォーマンスが出ない。
イベントは KV (上限なし)に保存しつつ REQ に必要なデータだけ D1 に保存するのが良さそう。
id
, pubkey
などの SHA256 データは CHAR(64)
ではなく BINARY(32)
で保存した方がよさそう。
events
KV
- id => event
D1
[events]
- id BLOB (32 bytes)
- pubkey BLOB (32 bytes)
- kind INTEGER
- tags TEXT
- created_at INTEGER
[tags をテーブル分ける場合]
- id BLOB
- name TEXT
- value TEXT
- created_at INTEGER
SELECT id FROM tags WHERE name = ? AND value = ?;
SELECT * FROM events WHERE pubkey = ?
AND id IN (SELECT id FROM tags WHERE name = ? AND value = ?) -- #t
AND id IN (SELECT id FROM tags WHERE name = ? AND value = ?) -- #p
SELECT * FROM events WHERE pubkey = ?
INNER JOIN tags ON events.id = tags.id AND name = ? AND value = ? -- #t
INNER JOIN tags ON events.id = tags.id AND name = ? AND value = ? -- #p
connections
KV or D1
- connection_id TEXT (challenge を使える?)
- ip_address
- pubkey
registrations
KV or D1
- pubkey
Cloudflare D1