Cointime

Download App
iOS & Android

トルネード キャッシュの原則を振り返る: 規制当局の厄介な問題だが、最も精巧な ZK アプリケーション

著者:ファウスト、オタクウェブ3

はじめに: 最近、Vitalik と一部の学者が共同で新しい論文を発表しました。この論文では、Tornado Cash がどのようにして反 xi マネー ソリューションを実装できるかについて言及しています (実際、これにより引き出し者は自分の預金記録がブラック マネーを含まないコレクションに属していることを証明できます) ) と書かれていますが、この記事ではトルネード キャッシュについての理解が不足しており、キャッシュのビジネス ロジックや原則が詳細に解釈されているため、理解できているようで理解できていないことがわかります。

さらに、Tornado に代表されるプライバシー プロジェクトは、ZK-SNARK アルゴリズムのゼロ知識の性質を実際に使用しているのに対し、ZK のバナーの下にあるほとんどのロールアップは ZK-SNARK の単純性のみを使用していることにも言及する価値があります。多くの場合、人々は Validity Proof と ZK の違いを混同する傾向がありますが、Tornado は ZK アプリケーションを理解するための優れた事例となります。

この記事の著者は、たまたま 2022 年の Web3Caff Research に Tornado の原理に関する記事を書いていました。今日は、誰もが Tornado Cash を体系的に理解できるように、その一部の段落を抜粋および拡張して文書にまとめました。

元のリンク:

https://research.web3caff.com/zh/archives/2663?ref=157

「竜巻」の原理

Tornado Cashはゼロ知識証明を利用したコインミキサープロトコルで、旧バージョンは2019年に運用が開始され、新バージョンは2021年末にベータ版が開始されました。 Tornado の古いバージョンは基本的に分散型です。チェーン上のコントラクトはオープンソースであり、マルチ署名制御はありません。フロントエンド コードはオープンソースで、IPFS ネットワークにバックアップされています。 Tornado は旧バージョンの方が全体の構造がシンプルで分かりやすいため、この記事では旧バージョンについて説明します。

Tornado の主なアイデアは、多数の入金と出金を一緒に混合することです。入金者が Tornado にトークンを入金した後、入金を行ったことを証明するために ZK プルーフを表示し、その後、お金を引き出すための新しいアドレスにより、入金アドレスと引き出しアドレスが遮断されます。

より具体的に言うと、トルネードはガラスの箱のようなもので、たくさんの人から集めたコインが混ざっています。誰がコインを置いたかはわかりますが、これらのコインは均質性が高く、見知らぬ人がガラス箱からコインを取り出した場合、誰が最初に置いたコインなのかを知ることは困難です。

より具体的に言うと、トルネードはガラスの箱のようなもので、たくさんの人から集めたコインが混ざっています。誰がコインを置いたかはわかりますが、これらのコインは均質性が高く、見知らぬ人がガラス箱からコインを取り出した場合、誰が最初に置いたコインなのかを知ることは困難です。

このシナリオはよくあるようです。Uniswap プールからいくつかの ETH を SWAP するとき、Uniswap に流動性を提供した人が多すぎるため、削除された ETH を誰が提供したかを知る方法がありません。しかし、違いは、Uniswap を使用してトークンを転送するたびに、同等のコストとして他のトークンを使用する必要があり、資金を「個人的に」他人に転送することはできないのに対し、通貨ミキサーは引き出し者に預金証明書の提示を要求するだけであることです。 . .

入金と出金のアクションを均一に見せるために、Tornado プールの入金アドレスによって入金された資金と出金アドレスによって出金された資金は毎回一貫しています (たとえば、特定のプールの入金者 100 名と引き出し者 100 名)。 、それらは互いに関連性がないようで、各人の入金額と出金金額は同じです。この際、国民を混乱させ、入出金額から相関関係を判断できなくすることで資金移動の痕跡を遮断することが可能であり、当然のことながら金儲けの行為に利便性を与えるものであることは明らかである。

しかし、重要な疑問があります。引き出し者は、お金を引き出すときに、自分がお金を入金したことをどのように証明できるのでしょうか?ミキサーからの出金を開始するアドレスは入金アドレスとは関係がありません。では、出金資格をどのように判断するのでしょうか?最も直接的な方法は、引き出し者がどのような入金記録を行ったかを直接開示することだと思われますが、これでは本人性が直接明らかになります。ここでゼロ知識証明が役に立ちます。

引き出し者は、Tornado 契約に入金記録があり、デポジットが引き出しられていないことを証明する ZK プルーフを発行することで引き出しを正常に開始できます。ゼロ知識証明そのものはプライバシー保護を実現するものであり、外部の世界は引き出し者が実際に資金プールに入金したことだけを知っており、引き出し者がどの入金者に該当するかは分からない。

「トルネード資金プールにお金を入金した」ことを証明するには、「私の入金記録はトルネード契約に記載されている」に変換できます。 Cn が入金記録を表すために使用される場合、問題は次のように要約できます。

Tornado の入金レコード セットは {C1, C2,...C100...} であることが知られています。引き出し者のボブは、手持ちのキーを使用して入金レコードに特定の Cn を生成したことを証明しますが、ZK は証明しません。 Cn がどれであるかを明らかにします。

ここでは、Merkle Proof の特殊な特性が使用されます。 Tornado のすべてのデポジット記録は、最下位のリーフ ノードとしてチェーン上に構築された MerkleTree に保存され、リーフの総数は約 2 の 20 乗 > 100 万であるため、それらのほとんどは空白の状態です (初期値が与えられた場合)。価値)。新しいデポジットが発生するたびに、コントラクトは対応する特性値 Commitment をリーフに書き込み、マークル ツリーのルートを更新します。

たとえば、Bob の入金操作が Tornado 履歴の 10,000 番目のトランザクションである場合、この入金に関連付けられた特性値 Cn がマークル ツリーの 10,000 番目のリーフ ノードに書き込まれます (C10000 = Cn)。その後、コントラクトは新しいルートを自動的に計算して更新します。 (追記: 計算量を節約するために、Tornado コントラクトは、変更されたノードの前のバッチ (以下の図の Fs1、Fs2、Fs0 など) のデータをキャッシュします)

MerkleProof 自体は非常にシンプルかつ軽量であり、検索/ソース追跡プロセスでツリー データ構造の単純さを利用しています。あるトランザクション TD が MerkleTree に存在することを外部に証明したい場合は、Root (下図の右部分) に対応する MerkleProof を与えるだけでよく、非常に簡単です。マークル ツリーが非常に大きく、下の葉が 2 の 20 乗である場合、つまり 100 万件の預金レコードが含まれる場合、マークル プルーフには 21 ノードの値が含まれるだけでよく、これは非常に短いです。

特定のトランザクション H3 が実際にマークル ツリーに含まれていることを証明したい場合は、H3 とマークル ツリー上のその他の部分データを使用してルートが生成できること、およびルートの生成に必要なデータの一部 (含む) を証明してください。 Td) はマークルプルーフを構成します。

ボブがお金を引き出すとき、彼は自分が所有する証明書がマークル ツリーに記録された特定の預金ハッシュ Cn に対応していることを証明する必要があります。言い換えれば、彼は次の 2 つのことを証明したいと考えています。

・チェーン上のトルネードコントラクトのマークルツリーにはCnが存在しており、具体的にはCnを含むマークルプルーフを構築できる。

・Cnはボブの手元にある預金証書に関係しています。

Tornadoのビジネスロジックの詳細説明

Tornadoのビジネスロジックの詳細説明

Tornado ユーザー インターフェイスのフロントエンド コードには多くの機能があらかじめ実装されており、入金者が TornadoCash Web ページを開いて入金ボタンをクリックすると、フロントエンド コードに付加されたプログラムがローカルで 2 つの乱数 K と r を生成します。 、そして Cn=Hash を計算します (K, r) の値が Tornado コントラクトに渡され、Cn (下図のコミットメント) が後者によって記録されたマークル ツリーに挿入されます。端的に言えば、K と r は秘密鍵に相当します。これらは重要なので、ユーザーはそれらを適切に保存するように求められます。 K と r は、後でお金を引き出すときにも使用されます。

上記の作業はすべてオフチェーンで行われることは注目に値します。つまり、Tornado コントラクトも外部の観察者も K と r を知りません。 K と r が漏洩すると、ウォレットの秘密鍵が盗まれるのと同様になります。

Tornado コントラクトがユーザーのデポジットを受け取り、ユーザーが送信した Cn=Hash(K, r) を受け取った後、Cn を新しいリーフ ノードとしてマークル ツリーの最下層に挿入し、Root の値を更新します。したがって、Cn はユーザーの入金アクションと 1 対 1 に関連付けられており、外部の世界は、各 Cn がどのユーザーに対応するか、誰がミキサーにトークンを入金したか、および各入金者に対応する入金記録を知ることができます。

出金ステップでは、出金者はフロントエンド Web ページに証明書/秘密キー (入金時に生成された乱数 K と r) を入力します。TornadoCash フロントエンド コードのプログラムは K と r を使用します。Cn=Hash( K、r)、Cn 対応するマークル プルーフは、Cn がマークル ツリー上に存在する特定のデポジット レコードであり、K と r が Cn に対応する証明書であることを証明する ZK プルーフを生成するための入力パラメータとして使用されます。

このステップは、「マークル ツリーに記録された特定の預金記録に対応するキーを知っている」ことを証明することに相当します。 ZK Proof を Tornado 契約に提出すると、上記 4 つのパラメータは隠蔽され、外部 (Tornado 契約を含む) に知られることがなくなり、プライバシーが確保されます。

ZKProof の生成に関係するその他のパラメーターには、出金時の Tornado コントラクトのマークル ツリーのルート、カスタマイズされた支払いアドレス A、およびリプレイ攻撃 (後述) を防ぐための識別子 nf が含まれます。これら 3 つのパラメーターはチェーン上で公開され、外部の世界に知られる可能性がありますが、プライバシーは影響を受けません。

ここには詳細があります。つまり、入金操作で Cn が生成されるとき、1 つの乱数ではなく 2 つの乱数 K と r が Cn の生成に使用されます。これは、単一の乱数では安全性が十分ではなく、一定の衝突確率が存在するためであり、たとえば、単一の乱数を使用すると、2 人の異なる預金者が偶然同じ乱数を使用し、生成された Cn が衝突する可能性があります。

ここには詳細があります。つまり、入金操作で Cn が生成されるとき、1 つの乱数ではなく 2 つの乱数 K と r が Cn の生成に使用されます。これは、単一の乱数では安全性が十分ではなく、一定の衝突確率が存在するためであり、たとえば、単一の乱数を使用すると、2 人の異なる預金者が偶然同じ乱数を使用し、生成された Cn が衝突する可能性があります。

上の図の A は、引き出しを受け取るためのアドレスを表しており、引き出し者が記入します。 nf はリプレイ攻撃を防ぐための識別子で、その値 nf = ハッシュ (K)、K は Cn をデポジットするステップで使用される 2 つの乱数 (K と r) の 1 つです。このように、nf と Cn が対応付けられており、各 Cn には対応する nf があり、両者は 1 つずつ関連付けられます。

なぜリプレイ攻撃を防ぐのでしょうか?コインミキサーの設計上の特性により、お金を引き出す際、ユーザーが引き出したコインがマークルツリーのどのリーフ Cn に対応するかは不明です。したがって、引き出し者がどの預金者に関係しているか、または何人の預金者に関係しているかはわかりません。引き出し者が行った入金。2回目の支払い。引き出し者はこの機能を使用して、資金を頻繁に引き出し、リプレイ攻撃を開始し、資金プールがなくなるまでミキサー プールからトークンを複数回取得することができます。

ここで、nf 識別子の役割は、各イーサリアム アドレスが持つトランザクション カウンタ ナンスに似ており、特定のトランザクションがリプレイされないようにするために設定されます。引き出しが発生した場合、引き出し者は nf を送信して、nf が使用された (記録された) かどうかを確認する必要があります。使用されている (記録されている) 場合、引き出しは無効です。そうでない場合は、nf が使用されていないことを意味し、引き出しは有効であり、対応する nf が記録されます。次回誰かがこの nf を送信すると、対応する出金アクションは無効であると直接判断されます。

契約書に記載されていないnfを誰かがランダムに生成しても大丈夫でしょうか?もちろんそうではありません。引き出し者が ZK プルーフを生成するとき、nf = ハッシュ (K) であり、乱数 K がデポジット レコード Cn に関連付けられていることを確認する必要があるからです。つまり、nf は特定の記録されたデポジットに関連付けられています。 Cn.任意に nf を作成し、この nf が入金記録内のすべての入金と一致しない場合、有効な ZK プルーフがスムーズに生成されず、その後の作業がスムーズに完了せず、出金操作が成功しません。

「NF なしでも可能ですか?」と疑問に思う人もいるかもしれません。引き出し者は、お金を引き出すときに、自分が特定の Cn と関係があることを証明するために ZK 証明を提出する必要があるため、引き出しが発生するたびに、対応する ZK 証明がチェーンに提出されているかどうかを確認するだけで十分ではないでしょうか。

しかし、実際には、これを行うコストは非常に高くなります。Tornado 現金契約では、過去に提出された ZK Proof が永久に保管されず、保管スペースが大幅に浪費されるためです。チェーンに送信された新しい ZKProof がそれぞれ既存の Proof と一致するかどうかを比較するよりも、小さな領域を占有する識別子 nf を設定し、それを永続的に保存する方がコスト効率が高くなります。

出金関数のコード例によると、必要なパラメータとビジネス ロジックは次のとおりです。

ユーザーは、ZKProof、nf (NullifierHash) = Hash (K) を送信し、出金を受け取るためのアドレス受信者をカスタマイズします。ZKProof は、Cn、K、および r の値を隠し、外部の世界が取得および取得することを不可能にします。ユーザーの身元を特定します。リージェントは多くの場合、きれいな新しい住所を記入し、個人情報を明らかにしません。

ユーザーは、ZKProof、nf (NullifierHash) = Hash (K) を送信し、出金を受け取るためのアドレス受信者をカスタマイズします。ZKProof は、Cn、K、および r の値を隠し、外部の世界が取得および取得することを不可能にします。ユーザーの身元を特定します。リージェントは多くの場合、きれいな新しい住所を記入し、個人情報を明らかにしません。

しかし、ここには小さな問題があります、それは、ユーザーがお金を引き出すとき、追跡可能性を避けるために、彼らはしばしば新しく適用されたアドレスを使用して引き出しトランザクションを開始します. 現時点では、新しいアドレスにはガスを支払うためのETHがありません手数料。したがって、引き出しアドレスが引き出しを開始する場合、ガス料金を支払う中継者を明示的に宣言する必要があり、その後、ミキサー契約によりユーザーの出金の一部が直接差し引かれ、中継者に返還されます。

まとめると、TornadoCash は出金者と入金者の関係を隠蔽することができ、利用者が多い場合は繁華街のような場所となり、犯罪者が群衆の中に紛れ込むと警察による追跡は困難になります。 。 ZK-SNARKは出金プロセス中に必要であり、隠された証人部分には出金者の重要な情報が含まれており、コインミキサー全体の最も重要なポイントです。現状では、Tornado は ZK に関連する最も独創的なアプリケーション層プロジェクトの 1 つである可能性があります。

コメント

全てのコメント

Recommended for you