Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Compact Block Filter

Compact Block Filter

GBEC動画解説コンテンツのスライドです。
https://goblockchain.network/2019/09/compact_block_filter/

shigeyuki azuchi

September 09, 2019
Tweet

More Decks by shigeyuki azuchi

Other Decks in Technology

Transcript

  1. 1 Compact Block Filter
 軽量クライアント向けに現在のBloom Filterに変わる新しいフィルター仕様
 
 • BIP-158 Compact

    Block Filter
 Bloom Filterのようにクライアント毎にフィルタを作成する代わりに、
 ブロック毎に生成するゴロム・ライス符号で圧縮した
 Compact Block Filterを定義
 https://github.com/bitcoin/bips/blob/master/bip-0158.mediawiki
 
 • BIP-157 Client Side Block Filtering
 フルノードではなく、クライアントサイドで関連トランザクションの
 フィルタリングをするため、Compact Block Filterを配信する
 新しいP2Pメッセージを定義。
 https://github.com/bitcoin/bips/blob/master/bip-0157.mediawiki

  2. ・・・
 ③ 接続中のフルノードから
 新しいブロックを受信
 2 Bloom Filterを使ったフィルタリング
 軽量ノード
 フルノード
 wallet


    ① ウォレット内の自身が所持する
 コインの公開鍵やそのハッシュ、OutPointな どからBloom Filterを作成
 filter
 ② filterloadメッセージを使って、
 作成したBloom Filterをフルノードに送信
 filter
 フルノード
 Block
 ④ ブロック内の各Txの要素について
 filterにかけ関連するTxをピックアップ
 Block
 Tx
 Tx
 Tx
 Tx
 filter
 ⑤ filterにマッチするTxがあれば、
 merkleblockメッセージを送信
 ⑥ 関連するTxをTxメッセージで送信
 Tx
 ⑦ merkleblockメッセージから部分
 マークルツリーを復元し以下を検証
 • BlockHeaderが正しいか
 • 対象のTxがブロックに含まれ
 ているか
 
 ⑧ 検証をパスすると受信したTxと
 合わせてウォレットの状態を更新
 wallet

  3. 3 現状のフィルタの問題点
 • プライバシー
 Bloom Filterの偽陽性率とリモートピアにリークされる情報のバランスを
 とるものの、フルノードに自身の情報がリークするのは避けられない。
 https://eprint.iacr.org/2014/763.pdf
 • 悪意あるノードとの接続によるデータの欠落


    リモートピアが悪意のあるノードで、実際はフィルタにマッチするTxが
 あるにも関わらずそれを通知しない。正しいデータを受け取れるよう、
 複数のノードに接続する必要がある。(LNクライアントなど特定のオンチェーン 
 イベントに対応する必要があるクライアントにとっては重要) 
 • フルノードの負荷
 フルノードは接続された軽量ノード毎に個別のフィルタを処理する
 必要がある。個別に多数のBloom Filterを処理するフルノードの
 リソース(IOやCPUなど)負荷が大きくなる。

  4. 4 Compact Block Filter
 現状のフィルタの仕組みに代わり、ブロック毎にフィルタを作成する
 
 Basic Block Filterの作り方
 


    1. ブロック内の全Txから以下を抽出してフィルタ要素とする。
 a. Coinbaseを除く全てのTxのインプットが参照する前のTxの
 アウトプットスクリプト
 b. 全Txの各アウトプットスクリプト(OP_RETURNは除く)
 (重複する要素は除外する)
 2. 抽出したフィルタ要素を使ってGCS(Colomb-code set)フィルタを
 構築する。

  5. 5 GCSフィルタの作り方
 1. 各要素について、要素の数を N個とするフィルタの偽陽性パラメータ M(784931)と
 あわせて0〜N*Mの数値の範囲内にマッピングする。 
 a. SipHashを使って要素のハッシュ値を計算

    
 ※SipHashは、128bitの鍵と可変長データを入力として取り64bitのランダムな値を出力するハッシュ関数。
 SipHashの128bitの鍵は、ブロックハッシュの(ビッグエンディアンで)先頭16バイトを使用
 b. 計算したハッシュ値に F=N*Mを乗算し、その上位64bitを取得 
 (結果がある範囲に一様に分布、かつ高速に計算するためにこの方法を採用) 
 c. 全要素分計算し、その結果を昇順にソートする 
 
 2. 昇順の整数のセットに対して、連続する整数の差分をフィルタに登録する。 
 a. 前後の要素の差分を計算 
 b. 差分をゴロム・ライス符号でエンコードする
 c. エンコードしたデータを BitStreamに追記する
 Bitstreamは追記型のbit型ストリームで、指定bit分データをバッファに書き込み、
 バッファのデータが8bitになったらそれをストリームに書き込む
 d. Bitstreamをビット列に変換し、先頭に要素数を CompactSizeでエンコードしものを 
 付加したらBasicタイプのGCSフィルタの完成
 ハッシュをそのままフィルタに 
 登録すると巨大なフィルタに 
 なるので圧縮する
 セット内に存在しない要素が 
 マッチする確率は1/M 
 差分は幾何分布に似るとされており、ゴロム ・ライス符号は幾何分布に従う整数を最適に 符号化できる

  6. 6 GCSフィルタで要素の検索
 軽量クライアントはブロック毎に作成されたGCSフィルタを使って、
 ブロック内に自身に関連するTxが存在するか確認する
 
 1. GCSフィルタをパースし、要素数Nとフィルタのペイロードを取得
 2. 自身が所有する鍵に対応するscriptPubkeyについて、フィルタの登録と
 同様、SipHashを使ってハッシュ値を計算し、0〜N*Mの範囲内の数値に


    変換し、昇順にソート。
 3. N回、以下を繰り返す。
 a. ゴロム・ライス符号でエンコードされたデータをデコードし、
 その差分を加算する。
 b. 加算した値が昇順にソートした要素の整数値と一致するか検証する。
 4. 3の中で1つでも一致したら、そのブロックに関連するTxが存在するので、
 別途ブロックを要求する。

  7. 7 フィルタヘッダ
 ブロックヘッダと同様に、フィルタもチェーンを形成する
 Block Header
 Block Header
 Block Header
 Block

    Header
 Filter Header
 Filter Header
 Filter Header
 Filter Header
 ブロックヘッダは前のブロックの 
 ブロックヘッダのハッシュを参照する 
 ことでチェーンを形成する。 
 各ブロックヘッダには、そのブロック内の 全Txから計算されたマークルツリーのマー クルートが含まれる。 
 Version
 4 bytes
 前のブロックヘッダのハッシュ
 32 bytes
 Merkle Root
 32 bytes
 Timestamp
 4 bytes
 Difficulty 
 4 bytes
 Nonce
 4 bytes
 double-SHA256(GCSFilter)
 32 bytes
 前のフィルタヘッダ
 32 bytes
 double-SHA256
 ブロックヘッダと同じように、 
 前のフィルタヘッダを参照する 
 フィルタチェーンを形成する。 

  8. 8 フィルタの同期
 軽量ノード
 フルノード
 ① 最初にブロックヘッダを同期しておく。
 ※ Compact Block Filterを


     サポートするノードは
  その旨service bitsで通知
 ③ cfheadersメッセージを使って、
 要求された1つ前のFilter Headerと
 その後に続くフィルタのフィルタ
 ハッシュのリストを返す。
 Filter Header
 ② getcfheadersメッセージを使って、
   フィルタヘッダを要求する。
 filter Hash
 filter Hash
 filter Hash
 filter Hash
 ④ 受信したフィルタハッシュを
 使って各フィルタのFilter Headerを計算 し、格納する。
 Filter Header
 Filter Header
 Filter Header
 複数のピアが異なる Filter Headerを送ってき た場合、別途ブロックを要求し、ブロックから 正しいフィルタおよび Filter Headerを計算し、 不正な動作をするリモートピアを特定& BAN する。
 軽量ノードは、代わりに getcfcheckptsメッ セージを使って1000ブロック間隔で Filter Headerをフェッチするのも可能 
 ⑤ Filter Headerの同期が終わると、getcfilters メッセージを使ってフィルタを要求する。
 filter
 ⑥ cfiltersメッセージを使って1つずつフィルタ を送信する。
 filter
 Block
 filter
 ※フィルタをサポートするフルノードは
 ジェネシスブロックから続く、
 ブロック毎のフィルタを生成・保存し、
 軽量ノードに提供する。

  9. 9 フィルタリング
 軽量ノード
 フルノード
 Block
 ② ウォレット内の要素とフィルタが一致する とgetdataメッセージで対象の
 ブロックを要求する。
 ①

    ウォレット内の自分が所有する秘密鍵やス クリプトに対応するscriptPubkeyを
 抽出し、それらがフィルタに含まれているか検 証する。
 ③ blockメッセージを使って要求された
 ブロックを送信する。
 filter
 filter
 filter
 wallet
 ④ ブロック内のTxをチェックし、
 関係するTxを見つけ、ウォレットを更新する。

  10. 10 まとめ
 • Compact Block Filterは軽量クライアントのプライバシーを確保し、
 フルノードの負荷を軽減する新しいフィルタアーキテクチャ
 
 • フィルタで合致する要素が見つかった場合、ブロックを丸ごと


    ダウンロードする必要があるため、クライアントの帯域幅使用は増える。
 そのため、ビッグブロックを採用するチェーンには不向き。
 
 • BIP-158のGCS Filterの仕組みは既にBitcoin Coreにマージ済み。
 https://github.com/bitcoin/bitcoin/pull/12254
 bitcoinrbでも実装してるよ(https://github.com/chaintope/bitcoinrb/blob/master/lib/bitcoin/gcs_filter.rb)
 • BIP-157のメッセージレイヤーはまだマージされていない。