概要
LaserStreamはカッコウフィルタを介した圧縮アカウントフィルタリングをサポートしています。subscribeリクエストに明示的なpubkeyリスト(アカウントあたり32バイト)を送信する代わりに、コンパクトな確率的フィルタを送信し、ワイヤー上でアカウントあたり約3〜4バイトかかります。 これにより、単一のストリームで何十万ものアカウントを購読することが実用的になります。接続を分割する必要がなく、大きすぎる購読リクエストもありません。 例えば、50万アカウントを追跡するフィルタは、約2.1 MBにシリアル化されますが、raw pubkeyリストとしては16 MBにもなります — 約7.6倍小さいです。正確な節約量はフィルタの満杯度に依存します。容量に近いほど、アカウントあたりのバイト数が少なくなります。利用可能性
カッコウフィルタを使用する時
一般的な使用例:トークンのすべての保有者の監視、貸付プロトコルのすべてのポジションの追跡、取引または解析システムのための大規模なウォレットセットの監視。
仕組み
- クライアント側でフィルタを作成します。 各追跡pubkeyを
CompressedAccountFilterSetに挿入します。ハッシュシードはフィルタごとにランダム化され、一緒にシリアル化されるため、サーバーはクライアントが使用したのと同じシードを使用して着信アカウントをハッシュします。 - subscribeリクエストに添付します。
insert_into_subscribe_request()はシリアル化されたフィルタを標準のSubscribeRequestのアカウントストリームに配置します。 - サーバーは確率的に一致します。 フィルタは確率的なため、追跡していないアカウントのアップデートをサーバーが配信する場合があります — フルロード時の偽陽性は1%未満に制限されています。偽陰性は決してありません:追跡されたアカウントのすべてのアップデートが配信されます。
- 各更新をローカルで再確認 — このステップは必須です。 処理する前に着信アカウントごとに
set.contains(pubkey)を呼び出します。このチェックは正確(内部ハッシュセットによって裏付けられている)なので、ローカルフィルタリング後には偽陽性はゼロになります。
クイックスタート(Rust)
プロジェクトにSDKを追加します。Cargo.toml
main.rs
rust/examples/cuckoo_account_filter.rs。
クイックスタート(JavaScript/TypeScript)
SDKをインストールします(カッコウサポートにはhelius-laserstream 0.4.0以上が必要です):
javascript/examples/cuckoo-account-sub.ts。
APIリファレンス
CompressedAccountFilterSetは生のカッコウフィルタと正確なハッシュセットを一緒にラップし、操作とメンバーシップチェックが常に安全で正確です。
上記のメソッド名はRustの慣習を使用しています。JavaScript/TypeScript SDKは同じ表面をキャメルケースで公開しています —
new CompressedAccountFilterSet(capacity)はwith_capacityではなく、insertIntoSubscribeRequest、isDirty、takeDirty、toProtoなどを使用しています。JavaScriptではinsertがBoolean(新たに追加された場合はtrue)を返し、フィルタがいっぱいの時にTableFullErrorをスローします。pubkeyはbase58文字列、生の32バイト、またはtoBytes()メソッドを持つ任意のオブジェクトとして渡すことができます。
必ずCompressedAccountFilterSetを使用し、生のCuckooFilterを使用しないでください。生のフィルタのremove()は誤ったアイテムを静かに削除する可能性があります — カッコウフィルタのドキュメント化された注意点です。このラッパーはフィルタを正確なハッシュセットとペアリングしているため、挿入、削除、含有は常に正しいです。
容量のサイズ調整
- フィルタのサイズは、
with_capacity(n)を介して追跡することが期待されるアカウントのピーク数に基づいて調整します。 - 容量を超えて挿入すると、安全に
TableFullErrorが返され、フィルタは破損しません。実際には、テーブルは挿入を拒否する前にわずかなオーバーフィルを許容しますが、その余地に依存しないでください。 - シリアル化されたサイズは、挿入したアカウント数ではなく容量によって決まるため、過剰サイズのフィルタはワイヤーバイトを無駄にします。実際のピークに近い容量を選択してください。
追跡セットの更新
追跡セットが変更された場合(フォローすべき新しいアカウント、削除すべき古いアカウント):insert()/remove()をCompressedAccountFilterSetで呼び出します。- フィルタが最後に送信されて以来変更されたかどうかを確認するために
is_dirty()をチェックします(またはtake_dirty()を使用してフラグを消費します)。 - 変更があれば、
insert_into_subscribe_request()でリクエストを再構築します。JavaScriptでは、stream.write(request)で同じストリームで再送信できます。Rustでは、再構築されたリクエストを使用して再購読します。
FAQ
フィルタ内のアカウントの更新を見逃すことはありますか?
フィルタ内のアカウントの更新を見逃すことはありますか?
いいえ。カッコウフィルタは偽陽性(追跡していないアカウントの追加の更新)を生成しますが、偽陰性はありません。追跡されたアカウントのすべての更新が配信されます。
何件の追加(偽陽性)更新を受け取りますか?
何件の追加(偽陽性)更新を受け取りますか?
フルロード時で1%未満、通常はフィルタが容量以下の場合は少なくなります。ローカルの
contains()呼び出しを各更新に行うことで、正確にフィルタリングします。どのクライアントがカッコウフィルタをサポートしていますか?
どのクライアントがカッコウフィルタをサポートしていますか?
Rust SDK (
helius-laserstream 0.2.0+)、JavaScript/TypeScript SDK (helius-laserstream 0.4.0+)、Yellowstone Rust クライアント (yellowstone-grpc-client 13.1.0+) がサポートしています。Go SDKはまだサポートしていません。利用可能性テーブルを参照してください。明示的なpubkeyリストを利用できますか?
明示的なpubkeyリストを利用できますか?
はい。標準の
account: [...]フィルタは変更なしで機能し、少数のアカウントセット(約10,000アカウントまで)には適した選択のままです。アカウントサブスクリプションガイドを参照してください。関連情報
アカウントサブスクリプション
所有者、サイズ、memcmpフィルタによる標準アカウントフィルタリング。
クライアントとSDK
自動リプレイと再接続を備えたTypeScript、Rust、Go SDK。