NIP-45は、clientが一致するイベント本体を転送せずに、filterに一致するイベント数をrelayへ問い合わせる方法を定義します。NIP-01のfilter syntaxを再利用するため、clientは既存のREQを、同じfilterを使うCOUNT requestへ変換できることがよくあります。

仕組み

clientは、subscription IDとfilterを含むCOUNT requestを送ります。

["COUNT", "<subscription_id>", {"kinds": [7], "#e": ["<event_id>"]}]

relayはcountを返します。

["COUNT", "<subscription_id>", {"count": 238}]

これにより、単に数字を表示するためだけに何百何千ものイベントをダウンロードせずに済みます。1つのCOUNT requestに複数filterがある場合、relayは複数REQ filterがORされるのと同様に、それらを1つの結果へ集約します。

HyperLogLog approximate counting

2026年2月時点で、NIP-45はHyperLogLog(HLL)によるapproximate countingをサポートしています(PR #1561)。relayは結果を近似値として示せ、cross-relay deduplicationのためにcountと一緒に256個のHLL registerも返せます。

["COUNT", "<subscription_id>", {"count": 4527, "hll": "<512-char hex string>"}]

HLLは根本的な問題を解決します。複数relayにまたがるdistinct eventの数え上げです。relay Aが50件のreaction、relay Bが40件を返しても、合計は90ではありません。多くのイベントが両方に存在するからです。clientはregister位置ごとに最大値を取ってHLL値をmergeし、生イベントをダウンロードせずにnetwork-wideな推定値を得ます。

仕様は、相互運用性のためregister数を256へ固定しています。これによりpayloadは小さく保たれ、同じ対象filterに対してすべてのrelayが同じregister layoutを計算するので、relay側cacheも実用的になります。

相互運用メモ

HLLはtag属性を持つfilterに対してのみ定義されています。register構築に使うoffsetが、filter内で最初に出るtagged valueから導出されるためです。仕様は、reaction、repost、quote、reply、comment、follower countなどのcanonical queryも挙げています。これらはrelayが事前計算やcacheをしやすいcountです。

なぜ重要か

follower count、reaction count、reply countが主な用途です。NIP-45がなければ、clientは1つのrelayの局所的な見え方を信じるか、一致する全イベントをダウンロードして自力でdeduplicateするしかありません。NIP-45はcountingをrelay内に保ち、HLLによって1つのrelayを権威にせずmulti-relay countを現実的にします。


Implementations

  • nostreamPR #522COUNT supportを追加し、clientがイベント本体を取得せずに一致数だけ問い合わせられるようにしました。

Primary sources:

Mentioned in:

See also: