はじめに
Nostrのプロトコル読もうと思った人のための補助になればと思います。
間違い等あったら編集リクエストください。
なお、発展途上のプロトコルのため、未実装やドラフトが目立ちます。
実際にデータを受信してみると謎のデータが付加されていたりします。
このあたりについては、IssueやPRを読むと謎が解決することが多いです。
関連
非常に有用な解説記事
いじって見たい人はまずnostr-toolsを触ることをお勧めします。ハマらずに済みます。
Nostr
- Nostrの特徴と目的
- TwitterやActivityPub, Scuttlebutt(P2P)との比較と優位性
- どのように既存の問題を解決するかと動作の概略
- 発生しうる問題とそれに対する優位性
- FAQ
- NIPへのリンク
があります。
最初に読むべき文章であり、だいたい懸念される事柄については考察済みであることがわかります。
一方でかなり楽観的に書かれている節があるので、過信は禁物です。
注意
Nostr Assets ProtocolおよびNostrトークンは、Nostrの名前を勝手に使用している無関係の(おそらく詐欺)通貨です。混同しないようにご注意ください。
Nostr Implementation Possibilities
実装の可能性の一覧です。事実上のプロトコル仕様書
オープンなプロトコルであり、IssueやPRも読むことをおすすめします。
このページは目次ですが、下部にイベントやメッセージ、タグとそれに対応するNIPの情報がありますので、データの読み解きに非常に便利です。
日本語コミュニティ訳版はこちら
NIP-01: Basic protocol flow description
最も基本となるプロトコルの基礎部分です。
投稿を読み書きするどころか、すべての通信がこの仕様に基づきます。
- イベントと署名(送信)
- 要求
- フィルター(受信・要求する情報種別)
- 応答
の情報があります。
特にフィルターの内容は重要です。
- kindsが取得する種別
- authorsは発信元の公開鍵
- #eは関連するイベントID
- #pは関連する公開鍵です。
通常単に情報を取得する場合は、sinceとlimitとkindsを設定すれば取れます。
フォローしている人の情報を取る(TL含む)にはauthers
リプライなどは#p、引用等は#e
と言った感じです。
kind:0がメタデータ(プロフィール)
kind:1がテキスト(投稿)
kind:3がフォロー一覧
kind:3だけ指定して他のフィルタを掛けないと、global TLになります。(非推奨)
複数のフィルタを1接続で並行して動かせるので、それでローカルTL見ながら、DM受け取り、リプライも拾ってみたいな感じで、複数のフィルタを動かしていくことになります。
だいたいこれがわかればクライアント作れると思います。
実装サンプル
https://gist.github.com/gpsnmeajp/09f2ff0bd0c9167fb335aed79311cb26
NIP-02: Contact List and Petnames
いわゆる自分のフォロー一覧をリレーに送る・取得するときの形式です。
(フィルタのauthorsに自分の公開鍵をセットしてkind:3を取得します。)
これがないとフォローTLを作成できません。
ここから得られた公開鍵をNIP-01のフィルタのauthorsにセットしてkind:1を取得することでフォローしている人のTLを構築することができます。
逆に、全くセットしてないのがいわゆるglobalになります。
他人がフォローしている一覧もこの形で取得できます。
(フィルタのauthorsに相手の公開鍵をセットしてkind:3を取得します。)
NIP-03: OpenTimestamps Attestations for Events
タイムスタンプ証明の提案
NIP-04: Encrypted Direct Message
暗号化されたダイレクトメッセージ
受信者の公開鍵と送信者の秘密鍵の組み合わせでできたAES256-CBC共通暗号鍵で暗号化されます。
誰が誰に送ったか、いつどのタイミングで何回送ったかは秘匿されません。
上記のような問題があるので論議中。
NIP-05: Mapping Nostr keys to DNS-based internet identifiers
DNSベースの公開鍵マッピング
認証マークをつけるのにNIP-05に基づくファイルをWebサーバーの以下の箇所においたと思います。
https://<domain>/.well-known/nostr.json
この形式の記述と、逆利用したユーザー検索、及び注意点など。
あくまでこれはマッピングを行うものであって証明ではない点に注意してください。
NIP-06: Basic key derivation from mnemonic seed phrase
Bitcoinウォレットのようにキーワードからバイナリシードを導出して決定論的に秘密鍵を生成する提案
NIP-07: window.nostr capability for web browsers
ブラウザやブラウザ拡張によって、署名や公開鍵の取得・暗号化と復号化を行うインターフェースが提供されるときの仕様の定義。
これにより、Webアプリケーションに毎度秘密鍵を渡すことなく安全に利用できる。
すでに以下の実装があることが示されています。
- nos2x
- Alby
- Blockcore
- nos2x-fox
使うとこんな感じ。
ハードウェア署名器との連携にも使えるかもしれません。
実装サンプル
https://gist.github.com/gpsnmeajp/23a2563ec39d4db43f0f922e5f08de87
NIP-08: Handling Mentions
メンション(リプライ)の処理方法
メンションは公開鍵をpタグに追加しなければならない。
文中のメンションは#[0]のような形でタグを参照しなければならない
これはユーザのみならず、イベントへ(投稿)の言及も同様。
(いわゆる引用がこれだと思われる)
受け取ったクライアントは、リンクにしたりコンテンツのプレビューを行う。
NIP-09: Event Deletion
削除を定義
eタグで指定した投稿は削除したことになる。
(なおオプションであり、必ず消えるわけではない)
NIP-10: Conventions for clients' use of e and p tags in text events.
テキスト投稿におけるeタグとpタグの使い方
返信時の単一eタグの位置に依る意味付け(非推奨)
返信時の複合eタグによる意味付け(推奨)
返信に関与しているユーザを表すpタグ
NIP-11: Relay Information Document
リレー自身のメタ情報の定義
Websocket接続時に返される。
ここでリレーの管理者の連絡先等の他、リレーが何の機能に対応しているかのNIPリストが返されます。
NIP-12: Generic Tag Queries
汎用タグクエリ
フィルタに1文字の要素がある場合、それを購読できるようにする仕組み(標準のe,pタグ以外も)
例示で以下のものが挙げられている
URL(r) : Webページに対するコメントシステム
ハッシュタグ(t): ハッシュタグ
ジオハッシュ(g): ジオハッシュで物理位置に紐づけ
NIP-13: Proof of Work
Proof of Workを用いたスパム対策の提案
なお、PoWは現在においてはビットコインで有名ですが、元々1993年にメールのスパム対策として提案されていたので先祖返りに近いです。
NIP-14: Subject tag in text events.
投稿に件名を付けられるようにする提案
NIP-15: End of Stored Events Notice
リレーから保存済み情報の終わり(ここから先はストリーミング)である旨を通知する仕組み。
EOSE
クライアント作成しているとこれの有無は結構重要です。(取得完了がわかるため)
NIP-16: Event Treatment
一時的なイベント(入力インジケーターや、ステータスなど保存が不要だったり複数保存する必要がない情報)を扱うための提案
NIP-18
廃止された仕様(Repost)
NIP-19: bech32-encoded entities
bech32について。
公開鍵や秘密鍵、投稿IDの不思議な文字列や接頭辞の定義です。
リレー情報やその他メタデータを含んだ長い形式も定義されています。
bech32mではない
参考
NIP-20: Command Results
リレーからの結果応答とその詳細(エラー等含む)の定義です。
正常、IPアドレスフィルタによる失敗、公開鍵Block、課金必要、レート制限、時刻異常、PoW不足による失敗などの例が挙げられています。
クライアントが識別するための接頭辞と、ユーザーが読むための文が含まれます。
NIP-21: nostr: URL scheme
URLスキームを定義しています。
NIP-22: Event created_at Limits
遠い未来や遠い過去からの投稿が発生しないように、受け入れるタイムスタンプに制限をかけることができる提案です。
NIP-25: Reactions
kind:7で、リアクション(いいねや+1)を投稿することができます。
これに関しては、反応対象をeタグ、相手をpタグで指定する必要があります。
+でlike, -でdislikeですが、絵文字を送信することも可能です。
(絵文字の解釈あるいは表示はクライアントに任されます。)
NIP-26: Delegated Event Signing
委任キーを作成する提案です。
これにより、ルート秘密鍵ではなく、クライアントごとに鍵ペアを作成してそちらに委任して使用するといった方法を提供します。
delegationタグに、委任元の公開鍵と委任期間と権限範囲、そしてこれらに対する委任元の署名がつくことで、委任を証明します。
(多分投稿専用でフォローはできないとか、そういう制限がかけられる。またDMは仕組み上読み書きできないかもしれません)
NIP-28: Public Chat
公開チャットチャネルを作成し、そこで会話することができます。
チャネルには名前や説明・画像を設定でき、その説明を更新したりできます。
投稿に対する非表示やミュートを実施した場合、その旨が発信されるため、
クライアントによっては複数人が非表示にした投稿は非表示にするといった機能を実装することができます。
NIP-33: Parameterized Replaceable Events
NIP-16 (一時イベント)の拡張で、kindのみによる置き換えではなく、kindとタグdが一致するものを置き換えるようにする(?)
NIP-36: Sensitive Content
センシティブなコンテンツありの投稿に対し、非表示と理由を提供する。
NIP-40: Expiration Timestamp
対応するリレーに期限付きメッセージを送るときの形式の提案
NIP-42: Authentication of clients to relays
リレーからクライアントに対するチャレンジ&レスポンス認証の要求
ホワイトリストリレーや有料リレー、より保護されたDMを実装するなどの用途に使用できる。
NIP-50: Keywords filter
リレーによる検索機能を利用するための提案
スパムフィルタをオフにして検索できることが要求されている
その他参考情報