カバー画像

[nostr] 虚無リレー始めませんか?

この記事は Nostrアドベントカレンダー2023第一会場 5日目の記事です。4日目は小牧りらさんの『日本人ユーザーの多様性から生まれるオフ会で知らない世界への扉が開かれた話』でした。


みなさんは「虚無リレー」というものをご存知だろうか。知っています🙋 という人は、おそらく知ったかぶりのブルルッチモに違いない。なぜなら私が適当に作った言葉だから。

「虚無」という言葉はひとまず置いて、ここでいうリレーというのは分散SNS用プロトコルの Nostr における通信の根幹を支えるサーバのことだ。Nostr のユーザはすべての通信をリレーを介して行っている。ユーザがデータを保存したくなったらクライアントからリレーにデータを送り、保存したデータを欲しくなったらリレーに問い合わせをする。

このようなクライアントからの要求に一切応えないのが、虚無リレーである。

虚無リレーは、クライアントから EVENT (保存リクエスト) が送られてきたら、データを保存せずに OK とだけ返す。クライアントから REQ (取得リクエスト) が送られてきたら、データを探しもせずに EOSE を返す。やることはこれだけ。

ここで虚無リレーの実装を見てみよう。

以下は deno (ディーノ) で実装された虚無リレーだ。わずか28行。プログラミングに精通してない人が見ても、真ん中らへんで EVENTREQ が出てきて OKEOSE をなんやかんやしているのがわかると思う。

Deno.serve({
  port: 8080,
  handler: async (request) => {
    if (request.headers.get("upgrade") !== "websocket") {
      return;
    }

    const { socket, response } = Deno.upgradeWebSocket(request);

    socket.onopen = () => {
      console.log("CONNECTED");
    };
    socket.onmessage = (event) => {
      try {
        const payload = JSON.parse(event.data);
        if (payload[0] === 'EVENT') {
          ws.send(`["OK","${payload[1].id}",true,""]`);
        } else if (payload[0] === 'REQ') {
          ws.send(`["EOSE","${payload[1]}"]`);
        }
      } catch (e) {}
    };
    socket.onclose = () => console.log("DISCONNECTED");
    socket.onerror = (error) => console.error("ERROR:", error);

    return response;
  },
});

さて、こんなものを実装して何がうれしいのだろうか?

第一に作って動かせることそのものが楽しい。

Nostr がいかにシンプルなプロトコルといっても、一通りの機能が揃ったリレーをイチから開発するのは難しい。しかし、クライアントに虚無リレーのURLを設定すれば、ひとまずは「正常な」リレーとして認識してくれる。つまり、Nostr のネットワークを構成する一員に自作リレーで参加することができる。

第二にプロトコルとしての Nostr の理解の役にたつ。 

クライアントとリレー間のデータのやりとりを規定しているのが、Nostr の仕様を定めている NIPs (Nostr Implementation Possibilities) NIP-01 で、「 EVENT を受け取ったら OK を返す」「 REQ を受け取ったら EOSE を返す」というのもすべてここに書かれている。このやりとりは Nostr のあらゆる通信で行われていることなので、虚無リレーを実装することはプロトコルとしての Nostr を理解することと換言しても過言ではない (本当?)。しかしながら、クライアント開発においては nostr-tools といったライブラリによって隠蔽されてしまっている部分でもある。

第三にサーバサイドプログラミングの勉強として良い題材である。

虚無リレーは実装にかかる時間やコード量が少ないため、さまざまな言語を効率よく試すことができる。同時に、HTTP (WebSocket) サーバ、非同期処理、JSONのシリアライズ/デシリアライズといった、Webバックエンド開発に最低限必要な技術に触れることもできる。

ここまで読んだ方はもれなく全員虚無リレーが作りたくなってきているのではないだろうか? プログラミングが苦手な方も安心して欲しい。以下のリポジトリにはさまざまな言語で書かれた虚無リレーが揃っているため、きっとあなたの参考になるはずだ。

もともとは、 mocrelaynoxir といった自作リレーブームに乗っかろうと考えた際に、プログラミング言語やランタイム間のパフォーマンス比較をしてみようと思ったのが虚無リレーの開発のきっかけだった。もちろんその用途としても役立ってはいるが、今となっては TodoMVC のような存在になるポテンシャルを感じている。知らんけど。

この虚無リレーが、のす本の演習こと『手を動かして学ぶ Nostrプロトコル』、つまりクライアント開発入門の対となり、リレー開発入門としてプロトコル理解の助けとなってくれることを願っている。


6日目の記事はocknamoさんの『nosskeyってなに』です。楽しみですね!