Nullifiers
概要
ZCashやTornadocash,Semaphoreなどで使われる仕組みで、zkpを使ったアプリケーションでは多く使われている。
「同じメッセージを2度使用することを禁ずる」ために使用でき、二重支払いや二重投票を防ぐことができる。
基本的には、秘密の値(乱数)kをメッセージmと一緒にハッシュ関数の入力とする。
Nullfier= Hash (k, m)
通常、Nullifierにはその対となるCommitmentが付属している
そのためNullifier-Commitment schemeと呼ばれたりする
Commitmentは公開された秘密のハッシュであり、誰が有効なNullifierを作成できるかを決定する。
その結果Commitment hashとnullifier hashは、zk proverがその有効性を相互検証できるように、そのpre imageにおいて共通のデータフィールドを共有する。
ZCash
シールドされた支払いを送信するために、送信者は暗号化されたNoteをNullifierとともに公開する。
フルノードは、二重支払いを検出できるように、公開されたすべての Nullifier を追跡する。
Nullifierは送信者のspending keyと変数rhoのハッシュであり、以下のように定義される。
Nullifier = HASH(spending key, rho)
ちなみに、ZCashはSprout, Sapling, Orchardの三つのバージョンが存在し、それぞれでNullifierの仕様が異なる。
Sproutでは、rhoは単なるノートの一意識別子である一方、Saplingでは、rhoは一意識別子とNoteのハッシュを入力させる。
OrchardはSaplingと同様同様。
Nullifierのpre imageは、コミットメントとノートID rhoを共有する。
Tornadocash
Tornado キャッシュからお金を引き出そうとするとき、ユーザーは、public nullifierHash がprivate nullifier のハッシュであることを検証するwitdraw circuitの zkpを提供する。Tornado contractは、nullifierHash が以前に設定されていないことをチェックし、引き出し成功時に送信されたことをマークする。
nullifierHash = HASH(nullifier)
ユーザーはお金を入金し、"nullifier "という名前の秘密をコミットする。zkpは、Commitment hashとnullifier hashを検証することで、ユーザーが以前に入金したことがあることをシステムに納得させる。
Semaphore
nullifiers_hash = HASH(identity_nullifier, external_nullifier, identity_path_index)
semaphore contractも、以前に公開されたnullifiers_hashを追跡するマッピングnullifierHashHistoryを持っている。
アプリケーション設計者は、external_nullifierを利用することで、ユーザーのアクションを特定のトピックに1回だけ制限したり、ユーザーのアクションを3回、または5分に1回に制限したりすることができる
ユーザーがシステムに登録され、"identity nullifier "という名前の秘密データをコミットすることを要求する。
そのため、登録されたユーザーだけが有効なnullifier hashを作成できる。
参考資料