Rollupは、ブロックチェーンレイヤー2のスケーリングソリューションのカテゴリーです。Rollupスキームでは、プロジェクトのオペレーターが拡張されたメインチェーン(つまり、レイヤー1)の下に比較的独立したレイヤー2プラットフォームを運営します。ユーザーは、レイヤー2プラットフォーム上で契約を実行したりトークンを転送したりすることができます。
Layer 2プラットフォームのセキュリティは、それが依存するLayer 1ブロックチェーンによって保証されています。Layer 2で新しいブロックが生成されると、Layer 2ブロックからのトランザクション情報とLayer 2のポストトランザクションステートルートがRollupトランザクションとして束ねられ、Layer 1チェーンに公開されます。実際のトランザクションの実行とステートの変更は、メインチェーンの下のLayer 2プラットフォームで処理され、Layer 1は単にLayer 2のステート遷移の正当性を検証する必要があります。ステート遷移の正当性を検証するコストはLayer 1でこれらのトランザクションを実行するコストよりもはるかに低いため、Layer 2はLayer 1プラットフォームの拡張を実現できます。Layer 2プラットフォームは、同等のセキュリティを維持しながら、Layer 1に比べてより高いトランザクションスループットと低いトランザクションコストを提供することができます。
他のオフチェーン取引スキームと比べて、Rollupsには2つの特徴があります:
メインチェーンによるLayer 2状態の更新の検証方法に基づいて、現在、2つの主要なRollup技術ソリューションがあります。1つはオプティミスティックRollupです。このタイプのスキームでは、メインチェーン契約はLayer 2によって提出された新しい状態を直接検証しません。代わりに、各新しい状態に対してチャレンジ期間が準備されます。Rollupはすべての取引情報をメインチェーンに提出し、公開しますので、誰でも状態の更新を検証できます(特に更新が自分のウォレットに関わる場合)。新しい状態が不正確な場合、検証者はその誤った状態に対する詐欺証拠を生成し、チャレンジ期間内に提出することで、不正確な状態更新を無効にすることができます。
別の種類のRollupソリューションはzk Rollupです。この種のスキームでは、レイヤー2の状態更新を実行した後、レイヤー2のオペレーターは状態更新の正当性のゼロ知識証明を提供し、状態更新と共にメインチェーンに提出しなければなりません。メインチェーン上の契約は、状態更新の正当性を決定するために証明を検証します。
Optimistic Rollupスキームと比較すると、zk RollupはLayer 2トランザクションを最終的に確認するための長いチャレンジ期間を必要としません。さらに、zk Rollupは、ネットワークにいつも正直な検証者がいて、不正が発生したときに適時に不正証拠を提出するという前提に依存しません。ただし、同時に、zk Rollupもゼロ知識証明技術の高い計算コスト、複雑さ、開発の難しさなどの問題に直面しており、これらがRollupsにおけるzk Rollup技術の実用的な実装を妨げています。過去2年間でゼロ知識証明技術のさらなる発展により、これらの障害は徐々に克服されつつあります。zk Rollup技術は、Layer 2市場のますます大きなシェアを占め始めています。
下の図に示すように、Rollupレイヤー2のスケーリングフィールド内では、zkRollupが既に領土の半分以上を占め、急速に開発が進んでいます。
データ取得日:2024年1月18日
開発過程で、zkRollupは主に2つの段階を経てきました。最初のタイプは一般的でないzkRollupであり、2番目のタイプはチューリング完全な任意の契約を実行できる一般的なzkRollupです。
これら2種類のzkRollup技術の違いは、主に、Layer 2プラットフォームがプラットフォーム提供者によって書かれた限られた専門ロジックを実行するか、取引でユーザーによって書かれた任意のスマートコントラクトロジックを実行するかにあります。
一般的でないzkRollupプロジェクト(上図の8位にランクインするzkSync Liteなど)では、ユーザーはFT(代替トークン)の送金、支払い、スワップ、NFT(代替不可能トークン)の送金など、ごく一部の種類の取引操作のみを行うことができます。これらの操作の取引ロジックは、プロジェクト所有者によってのみ定義および実装されることができます。
このようなzkRollupプロジェクトを通じて、イーサリアムメインネットワークと比較して、はるかに低い手数料で送金し、より高い取引スループットを得ることができます。ただし、チェーン上でいくつかの興味深い契約を試したい場合、それはできません。
なぜ専門のzkRollupsを使用者に自分自身のスマートコントラクトを展開して使用させることができないのでしょうか?これはzkRollupそのものの証明アーキテクチャに遡ることになります。
L2の状態遷移が正確かつ信頼できるようにするには、zkRollupでは、すべてのL2の状態遷移ロジックをゼロ知識証明回路として記述し、L1の契約によって検証する必要があります。検証に合格した状態のみがL1によって受け入れられ、最終的にRollupを完了します。このプロセスでは、zkRollupプラットフォームのすべてのトランザクション実行ロジックがゼロ知識証明回路で検証される必要があります。ただし、ゼロ知識証明回路で任意の契約ロジックの実行をサポートすることは難しい課題です(この難しさの理由は後述のテキストで説明されます)。その結果、初期のzkRollupプロジェクトでは、比較的簡単な取引のみがサポートされていました。
固定数の単純なトランザクションのみを実行できることは、明らかに zkRollup に対する私たちの期待には添いません。幸いなことに、zkVM(Zero-Knowledge Virtual Machine)技術は、ゼロ知識証明回路内で任意のチューリング完全コードの実行を証明する難しさを解決し、一般的な zkRollup プラットフォームを可能にしました。次に、この記事では zkVM の実装原則を紹介し、一般的な zkRollup 技術の最も核心部分がどのように動作するかについて読者に理解させます。
zkVMの原則を紹介する前に、まずゼロ知識証明技術について簡単に紹介します。ここでは、ゼロ知識証明の基本的な数学的原理を詳しく理解する必要はありません。ゼロ知識証明が何をするか、どのように使用されるか、および専門的な証明回路によって課せられる制約を理解することが十分です。
zkRollup内のゼロ知識証明は、レイヤー2のトランザクションが正しく実行され、レイヤー2の状態が正しく更新されたことを証明するために役立ちます。
この目的を達成するために、zkVM回路は、レイヤー2に展開された任意のスマートコントラクトが正しく実行されたことを証明する必要があります。zkVMの原則を紹介する前に、ゼロ知識証明の役割とその動作方法について最初に議論する必要があります。
なぜゼロ知識証明が必要なのか
ゼロ知識証明は、証明者が追認者に追加情報を明かさずに、ある文が正しいことを確信させる暗号プリミティブです。
ゼロ知識証明には3つの核心的な特性があります:
ゼロ知識証明の完成度が高まると、証明者が複雑な計算を完了すると、入力データから得られた出力データが実行者によって提供された結果であることを検証者に納得させる証明を生成できます。ゼロ知識証明の妥当性により、実行者が間違った結果を提供すると、有効な証明を生成することができません。
そのため、ゼロ知識証明の完全性と健全性を持っているため、これらの複雑な計算を他者に外部委託し、比較的簡単な検証プロセスを通じて計算が正しいかどうかを自信を持って検証することができます。外部委託された側を信頼する必要はありません。
ゼロ知識証明の3つの核心的な特性に加えて、広く使用されているzk-SNARKスキームには、簡潔さという特性もあります。これは、ゼロ知識証明を使用して証明された複雑な論理に対して、生成される証明のサイズと検証にかかる時間が両方とも固定されて比較的小さいということを意味します。これにより、zk-Rollupは状態更新の計算をオフチェーンにオフロードし、チェーン上での操作の正確性のみを検証することが可能になり、スケーリングソリューションが実現可能となります。
ゼロ知識証明のプロセス
次に、この記事では、ゼロ知識証明のプロセスを説明するために、以下の簡単な計算例を使用します。
c=a²+b+5
ゼロ知識証明のゼロ知識側面を説明するために、このゼロ知識証明の公開値として変数aとcを設定し、bを証明者のみが知っている秘密入力とします。私たちの計算が非常に単純であるため、検証者は公開値から秘密入力の値を簡単に推測することができます。これは、検証者が証明プロセスから秘密入力に関する情報を取得できないことを保証するだけであり、ゼロ知識証明方法自体のゼロ知識性質に影響を与えません。
証明を行う際、証明者はまず入力としてそれぞれaとbの値を選択し、cの値を計算します。ここでは、a = 3、b = 2と設定し、その結果としてc = 16となります。すべての計算が完了した後、証明者はこれらの値と操作に対するゼロ知識証明を生成することができます。
証明を完了した後、証明者は検証者に証明の公開入力(すなわち、aとcの値)とゼロ知識証明を提供します。
証明を受け取ると、検証者は、ゼロ知識証明を検証することによって、証明者が秘密の入力 b を使用していることを納得させられます。これにより、a = 3 および c = 16 (つまり、公開入力値) のときに上記の式が真であることができ、公開入力 (a = 3、c = 16) を超えた情報を入手することはできません。
記事の次の部分では、具体的な証明プロセスについて紹介します。ゼロ知識証明法を使用して計算を証明する必要がある場合、最初にゼロ知識証明アルゴリズムが受け入れる算術回路の形式で計算を表現する必要があります。算術回路は、計算のチューリング完全表現です。その名前が示すように、算術回路は算術演算を行うゲートから構成された計算回路です。この例では、変換結果が図に示されています。私たちが言及した公開入力aとcと秘密入力bに加えて、計算プロセスで使用されるdとeという2つの追加の値があることに気づくかもしれません。これらは計算プロセスで使用される中間変数です。
算術回路内の各ワイヤを値と考えることができます。これは公開入力、秘密入力、または中間変数である可能性があります。算術回路に計算を展開した後、各中間変数はその場所を持ち、証明プロセスで使用されます。入力との唯一の違いは、彼らの値が証明者によって直接入力されるのではなく、算術回路内の他の入力値によって決定されることです。
算術回路は2つの部分として見ることができます:1つは回路に現れるすべての数値、もう1つはこれらの値の間の関係(制約条件)です。通常、回路内の公開入力は文(この例ではaとc)として参照され、秘密入力(b)や中間変数(dとe)を含む他のすべての値は証人として扱われます。
回路の論理によると、公開入力を記述とし、秘密入力を証人とすると、回路内のすべての証人値を計算できます。
したがって、算術回路のゲート回路は以下の形で表すこともできます。
ステートメント:
a、c
証人:
b,d,e
制約:
d = a * a
e = b + 5
c = d + e
回路を証明するためにアリスメタイズされた後、ゼロ知識証明アルゴリズムは回路の制約を処理し、証明の生成と検証に必要な形式に変換する必要があります。処理後、回路は回路のサイズとは無関係な固定長のVK(検証キー)を生成します。検証者は検証キーを使用して対応する回路のゼロ知識証明を検証できます。検証キーは、回路へのコミットメントにいくぶん似ています。制約に変更が加わると、それに対応する検証キーも変更されます。
実際の応用では、ゼロ知識証明のユーザーは、必要なロジックをzk回路のソースコードに記述し、審査を通じて対応するVKを生成する必要があります。このVKは検証者に引き渡されます。証明者によって証明された公開入力と生成された証拠と共に、検証者はこれらの公開入力が制約条件を満たしているかどうかを検証できます。この例では、証明者はa、b、cの値で証明を生成できます。検証者は、この操作を実行せずにa2 + bがCと等しいかどうかを検証できます。
ゼロ知識証明回路の制約
zk回路はチューリング完全であり、任意の計算を表現できますが、計算を算術回路の特殊表現形式に変換する必要があるため、算術回路を記述する際にいくつかの追加制限があります。
コンピュータプログラムでは、if-else文を使用してプログラム実行のブランチを制御できます。プログラムで選択したブランチのみが実行されます。しかし、ゼロ知識証明プロセスでは、計算が回路に平坦化され、実行パスや制御フローの概念はありません。そのため、算術回路で特定のブランチを選択して実行することはできません。
もちろん、これは回路で枝や選択肢を使用できないことを意味するものではありません。それは単に、回路では選択されたかどうかに関係なく、すべての枝が実行され、証明の生成に寄与することを意味します。枝の選択は、次の変数に出力される枝の結果にのみ影響します。
次の操作を例として取る:
if (flag) {
c = x + x
} else {
c = x * x
}
この操作を算術回路に変換すると、以下に示す制約に変換されます。明らかに、回路にはtemp1とtemp2という2つの新しい証人が追加されます。さらに、x+xの値とx*xの値が両方とも計算されます。
つまり、zk回路では、実行されるかどうかに関係なく、すべての枝やロジックが計算されます。
temp1 = x + x
temp2 = x * x
c = フラッグtemp1 + (1-flag)temp2
これらの制限のため、ゼロ知識証明回路での条件付き選択をサポートすることは非常に難しいです。ゼロ知識証明でスマートコントラクトロジックの実行パスを証明する方法は、zk仮想マシンの主要な課題の1つです。
私たちは、VMを普遍的な状態機械のモデルを通じて説明します。VMは、命令が処理されるときに状態を遷移する状態機械です。仮想マシンがゼロ知識回路で証明される方法を、非常にシンプルな状態機械の例で説明しましょう。
我々は、この普遍的な状態機械に汎用レジスタ(AとB)を持ち、さらに、現在の命令番号を格納するプログラムカウンタレジスタを持つと仮定します。
実行命令前のレジスタの状態
下の図は、ZK仮想マシンの証明回路の基本的なワークフローを示しています。
State 0は、実行前のこの仮想マシンの初期状態と見なすことができます。合計m命令を実行した後の初期状態は、最終状態mに到達します。初期状態に加えて、この仮想マシンには2つの通常の入力テーブルがあります。
図では、n番目の命令の実行プロセスが抽象化され、左側に表示されます。 状態機械の状態、状態nは、n番目の命令の実行後に状態n+1に遷移します。 同じ回路はm回の反復の後、vmでm個の命令の実行を達成します。
ここには2つの問題があります。
Oneは、固定回路内で異なる命令を実行する方法ですか?契約バイトコードを実行する際、実行されるnth命令を特定することはできませんので、ここでの実際の回路ロジックは決定できません。
2番目の質問は、実行する命令の数がmでないことをどのように証明するかですか?
最初の質問に対する解決策は、回路内のすべての可能な命令に対するロジックを実装することです。次に、命令に基づいてセレクターを使用して、前述の専門回路のif-elseと同様に、そのうちの1つを次の状態として選択します。
第2の質問について、回路内の命令数を直接変更することはできません。なぜなら、回路内の各命令には独立した回路セグメントが必要だからです。命令数が増減すると、回路が変化し、対応する検証キーも変化します。これにより、固定された回路内の任意のロジックを検証する要件を満たすことが不可能になります。
この問題を解決するために、状態を変更しないnoop命令を命令セットに追加することができます。したがって、各固定回路が実行できる命令の数には上限があります。zkVMの回路は、固定数の命令スロットを持つコンテナと見なすことができます。必要な命令がさらに必要な場合は、より大きな回路が必要です。実際の証明では、必要に応じて適切なサイズの回路が選択されます。
基本指示の証明
基本的な計算命令の例として、回路内の基本的な命令がどのように証明されるかを示します。
図は、指示証明回路のフローチャートを示しています。以下の数式は、証明のための回路制約です。
これらの2つの制約は、右上隅にリストされた汎用レジスタAとBの基本的な命令をいくつか証明できます。これらの証明により、入力テーブルから値をロードしたり、即値を命令からレジスタに読み込んだり、レジスタAおよびBの値を加算してレジスタに書き戻したりすることができます。
この図から、状態変化の制約を構築するために、回路はいくつかの補助制御状態を導入していることがわかります。
これらの補助レジスタと汎用レジスタ間の計算論理は、以下の数式によって実装されています。興味のある読者は、対応する値を制約式に代入して検証することができます。これらの2つの制約があることで、基本的な算術加算命令を実装することができることがわかります。より多くの操作が必要な場合は、より多くの命令制約を追加する必要があります。
基本的なプロセスダイアグラムに戻ると、このセクションの計算回路は、全体のプロセスにおける命令と見なすことができます。セレクタは、その出力が状態マシンによって採用される次の状態かどうかを選択します。このセクションの回路に必要な補助的な状態は、PCレジスタが指す命令によって生成されます。
インストラクションの取得は、専用のルックアップ回路によって実装されており、インデックスを通じて固定テーブルからデータセグメントの取得を証明することができます。したがって、zkVM回路はPCによって指定された仮想マシンによって実行された状態遷移を証明することができます。
条件付き判断と制御フローのジャンプの証明
状態マシンの複雑なロジックを実行する能力は、条件付きおよびジャンプ命令に依存しています。実際の契約では、条件に基づいて実行パスを変更するロジックを扱う必要があるため、そのような回路が必要です。
ここで注記すべきは、zkVM回路は実際に契約ロジックを実行し結果を計算するモジュールではないということです。zkVM回路が実際に行うのは、契約ロジックの計算過程を証明することです。したがって、証明する際には、実際に実行された命令のシーケンス過程を回路に記入し、このジャンプの条件が満たされているかどうかを回路で検証し、そして実行された命令フローが正しいジャンプを行ったことを証明することが必要です。
最初に、条件判定の証明を紹介します:
i番目の命令のオペランドがゼロと等しいかどうかの判断を例に取る。判断結果のisZeroのための補助状態を追加します。判断された値が0の場合、補助状態isZeroの値は1となります。判断された値が0以外の値である場合、isZeroは0となります。
このプロセスは、図中の2つの式によって制約されています。
この制約の妥当性は、ゼロ知識証明で使用される楕円曲線の数学的性質に関連しています。ゼロ知識証明回路内のすべての値は、楕円曲線上の有限体内の要素です。その値が0でない場合、逆要素が存在し、それを自身と乗算すると1になります。この性質を使って、図中の2つの制約とともに、ある値がゼロかどうかを検証し、それを補助状態に変換することが可能です。
このisZero条件補助状態があると、条件付きジャンプ命令の証明に進むことができます。
基本的なプロセス図に戻ると、現在の命令が条件付きジャンプ命令である場合。まずisZeroチェックを実行し、ジャンプ条件が満たされているかどうかを判定し、その後PCの値を変更します。PCの値を更新した後、次の命令の実行はまずPCを基にルックアップしてジャンプ後の命令を見つけることに関与します。
I/Oと複雑な操作
一般的な状態機械証明回路を使用する場合、状態遷移を正しく処理するためには、単一の状態遷移中にサポートされる各命令に対応する制御状態と制約を追加する必要があります。これらの状態値と制約の数は、zkVMがサポートする命令の数によっても乗算する必要があります。zkVMによってサポートされる命令の数が増えるにつれて、これらの状態値と制約の数も増えます。実際にzkVMによって実行されるプログラムで操作が行われない場合(すべてNOP)、これらの状態値と制約のチェックを省略することはできません。
したがって、この記事の前半で一般状態機械回路を使用して複雑な計算を実行することは非常に効率的ではありません。これらの方法を使用して複雑な計算を実装すると、そのパフォーマンスは受け入れがたいです。さらに、一般状態機械回路が複雑な命令を実行したり、直接外部とやり取りすることは困難です。
この問題を解決するため、zkVMの実際の実装では、一般的な状態マシン回路と専門の証明回路の組み合わせを使用して、プログラムの一部を別々に証明し、その後証明を一つの解決策に集約することが一般的です。
左側の図は、Scrollプロジェクトの回路アーキテクチャであり、右下隅の図はPolygonの回路アーキテクチャです。両方とも、右上隅の図に示されているように、類似したアプローチを採用しています。
一般的なステートマシンは、プログラムの実行ロジックの制御を証明する責任があります。ほとんどの契約では、このロジックの一部の実際の実行時間は非常に短いため、非効率な一般的なステートマシンでそれを証明することは、効率的な観点からはまだ許容されています。
より多くの固定複雑な計算、例えばハッシュ、MPTツリー操作、外部入力データなどは、専用回路によって証明されています。
一般的な状態機械と特殊な証明回路は、ルックアップテーブルを使用して相互作用します。状態機械回路がこれらの操作を呼び出すたびに、証明のための証人を生成するモジュールは、呼び出しパラメータと計算結果をルックアップテーブルに書き込みます。したがって、状態機械回路でこれらの操作を呼び出す際は、ルックアップ操作に簡素化されます。
ルックアップテーブル内の各呼び出しと戻り値の正確性は、専門の回路によって制約され、証明されています。
最終的に、回路内のコピー制約は、ステートマシン回路、専用回路、およびルックアップテーブルを接続し、ルックアップテーブル内の各アイテムが対応する専用回路によって証明されているかどうかをチェックし、最終的に完全なブロックの証明を生成します。
L1契約は、この集計証明を確認するだけで、仮想マシンの実行プロセス全体の正確性を確認する必要があります。
ゼロ知識証明技術により、計算を簡単かつ迅速に証明することが可能になり、信頼性のない環境で計算プロセスを外部委託する扉が開かれました。この技術は、ブロックチェーンで使用されると、実行をチェーンから解放し、メインブロックチェーンが分散化およびセキュリティの問題に焦点を当てることを可能にします。ただし、専門のゼロ知識証明回路の特性により、固定ロジックのみを実行することが制限され、これにより初期のzkRollupの能力が一部のトランザクションの種類に制限されています。
しかし、zk仮想マシンの開発と成熟により、任意のスマートコントラクトのチューリング完全な実行をサポートすることが可能になりました。zkRollupの可能性は本当に解き放たれ、ブロックチェーントライレンマを破るというビジョンが実現されるでしょう。
Rollupは、ブロックチェーンレイヤー2のスケーリングソリューションのカテゴリーです。Rollupスキームでは、プロジェクトのオペレーターが拡張されたメインチェーン(つまり、レイヤー1)の下に比較的独立したレイヤー2プラットフォームを運営します。ユーザーは、レイヤー2プラットフォーム上で契約を実行したりトークンを転送したりすることができます。
Layer 2プラットフォームのセキュリティは、それが依存するLayer 1ブロックチェーンによって保証されています。Layer 2で新しいブロックが生成されると、Layer 2ブロックからのトランザクション情報とLayer 2のポストトランザクションステートルートがRollupトランザクションとして束ねられ、Layer 1チェーンに公開されます。実際のトランザクションの実行とステートの変更は、メインチェーンの下のLayer 2プラットフォームで処理され、Layer 1は単にLayer 2のステート遷移の正当性を検証する必要があります。ステート遷移の正当性を検証するコストはLayer 1でこれらのトランザクションを実行するコストよりもはるかに低いため、Layer 2はLayer 1プラットフォームの拡張を実現できます。Layer 2プラットフォームは、同等のセキュリティを維持しながら、Layer 1に比べてより高いトランザクションスループットと低いトランザクションコストを提供することができます。
他のオフチェーン取引スキームと比べて、Rollupsには2つの特徴があります:
メインチェーンによるLayer 2状態の更新の検証方法に基づいて、現在、2つの主要なRollup技術ソリューションがあります。1つはオプティミスティックRollupです。このタイプのスキームでは、メインチェーン契約はLayer 2によって提出された新しい状態を直接検証しません。代わりに、各新しい状態に対してチャレンジ期間が準備されます。Rollupはすべての取引情報をメインチェーンに提出し、公開しますので、誰でも状態の更新を検証できます(特に更新が自分のウォレットに関わる場合)。新しい状態が不正確な場合、検証者はその誤った状態に対する詐欺証拠を生成し、チャレンジ期間内に提出することで、不正確な状態更新を無効にすることができます。
別の種類のRollupソリューションはzk Rollupです。この種のスキームでは、レイヤー2の状態更新を実行した後、レイヤー2のオペレーターは状態更新の正当性のゼロ知識証明を提供し、状態更新と共にメインチェーンに提出しなければなりません。メインチェーン上の契約は、状態更新の正当性を決定するために証明を検証します。
Optimistic Rollupスキームと比較すると、zk RollupはLayer 2トランザクションを最終的に確認するための長いチャレンジ期間を必要としません。さらに、zk Rollupは、ネットワークにいつも正直な検証者がいて、不正が発生したときに適時に不正証拠を提出するという前提に依存しません。ただし、同時に、zk Rollupもゼロ知識証明技術の高い計算コスト、複雑さ、開発の難しさなどの問題に直面しており、これらがRollupsにおけるzk Rollup技術の実用的な実装を妨げています。過去2年間でゼロ知識証明技術のさらなる発展により、これらの障害は徐々に克服されつつあります。zk Rollup技術は、Layer 2市場のますます大きなシェアを占め始めています。
下の図に示すように、Rollupレイヤー2のスケーリングフィールド内では、zkRollupが既に領土の半分以上を占め、急速に開発が進んでいます。
データ取得日:2024年1月18日
開発過程で、zkRollupは主に2つの段階を経てきました。最初のタイプは一般的でないzkRollupであり、2番目のタイプはチューリング完全な任意の契約を実行できる一般的なzkRollupです。
これら2種類のzkRollup技術の違いは、主に、Layer 2プラットフォームがプラットフォーム提供者によって書かれた限られた専門ロジックを実行するか、取引でユーザーによって書かれた任意のスマートコントラクトロジックを実行するかにあります。
一般的でないzkRollupプロジェクト(上図の8位にランクインするzkSync Liteなど)では、ユーザーはFT(代替トークン)の送金、支払い、スワップ、NFT(代替不可能トークン)の送金など、ごく一部の種類の取引操作のみを行うことができます。これらの操作の取引ロジックは、プロジェクト所有者によってのみ定義および実装されることができます。
このようなzkRollupプロジェクトを通じて、イーサリアムメインネットワークと比較して、はるかに低い手数料で送金し、より高い取引スループットを得ることができます。ただし、チェーン上でいくつかの興味深い契約を試したい場合、それはできません。
なぜ専門のzkRollupsを使用者に自分自身のスマートコントラクトを展開して使用させることができないのでしょうか?これはzkRollupそのものの証明アーキテクチャに遡ることになります。
L2の状態遷移が正確かつ信頼できるようにするには、zkRollupでは、すべてのL2の状態遷移ロジックをゼロ知識証明回路として記述し、L1の契約によって検証する必要があります。検証に合格した状態のみがL1によって受け入れられ、最終的にRollupを完了します。このプロセスでは、zkRollupプラットフォームのすべてのトランザクション実行ロジックがゼロ知識証明回路で検証される必要があります。ただし、ゼロ知識証明回路で任意の契約ロジックの実行をサポートすることは難しい課題です(この難しさの理由は後述のテキストで説明されます)。その結果、初期のzkRollupプロジェクトでは、比較的簡単な取引のみがサポートされていました。
固定数の単純なトランザクションのみを実行できることは、明らかに zkRollup に対する私たちの期待には添いません。幸いなことに、zkVM(Zero-Knowledge Virtual Machine)技術は、ゼロ知識証明回路内で任意のチューリング完全コードの実行を証明する難しさを解決し、一般的な zkRollup プラットフォームを可能にしました。次に、この記事では zkVM の実装原則を紹介し、一般的な zkRollup 技術の最も核心部分がどのように動作するかについて読者に理解させます。
zkVMの原則を紹介する前に、まずゼロ知識証明技術について簡単に紹介します。ここでは、ゼロ知識証明の基本的な数学的原理を詳しく理解する必要はありません。ゼロ知識証明が何をするか、どのように使用されるか、および専門的な証明回路によって課せられる制約を理解することが十分です。
zkRollup内のゼロ知識証明は、レイヤー2のトランザクションが正しく実行され、レイヤー2の状態が正しく更新されたことを証明するために役立ちます。
この目的を達成するために、zkVM回路は、レイヤー2に展開された任意のスマートコントラクトが正しく実行されたことを証明する必要があります。zkVMの原則を紹介する前に、ゼロ知識証明の役割とその動作方法について最初に議論する必要があります。
なぜゼロ知識証明が必要なのか
ゼロ知識証明は、証明者が追認者に追加情報を明かさずに、ある文が正しいことを確信させる暗号プリミティブです。
ゼロ知識証明には3つの核心的な特性があります:
ゼロ知識証明の完成度が高まると、証明者が複雑な計算を完了すると、入力データから得られた出力データが実行者によって提供された結果であることを検証者に納得させる証明を生成できます。ゼロ知識証明の妥当性により、実行者が間違った結果を提供すると、有効な証明を生成することができません。
そのため、ゼロ知識証明の完全性と健全性を持っているため、これらの複雑な計算を他者に外部委託し、比較的簡単な検証プロセスを通じて計算が正しいかどうかを自信を持って検証することができます。外部委託された側を信頼する必要はありません。
ゼロ知識証明の3つの核心的な特性に加えて、広く使用されているzk-SNARKスキームには、簡潔さという特性もあります。これは、ゼロ知識証明を使用して証明された複雑な論理に対して、生成される証明のサイズと検証にかかる時間が両方とも固定されて比較的小さいということを意味します。これにより、zk-Rollupは状態更新の計算をオフチェーンにオフロードし、チェーン上での操作の正確性のみを検証することが可能になり、スケーリングソリューションが実現可能となります。
ゼロ知識証明のプロセス
次に、この記事では、ゼロ知識証明のプロセスを説明するために、以下の簡単な計算例を使用します。
c=a²+b+5
ゼロ知識証明のゼロ知識側面を説明するために、このゼロ知識証明の公開値として変数aとcを設定し、bを証明者のみが知っている秘密入力とします。私たちの計算が非常に単純であるため、検証者は公開値から秘密入力の値を簡単に推測することができます。これは、検証者が証明プロセスから秘密入力に関する情報を取得できないことを保証するだけであり、ゼロ知識証明方法自体のゼロ知識性質に影響を与えません。
証明を行う際、証明者はまず入力としてそれぞれaとbの値を選択し、cの値を計算します。ここでは、a = 3、b = 2と設定し、その結果としてc = 16となります。すべての計算が完了した後、証明者はこれらの値と操作に対するゼロ知識証明を生成することができます。
証明を完了した後、証明者は検証者に証明の公開入力(すなわち、aとcの値)とゼロ知識証明を提供します。
証明を受け取ると、検証者は、ゼロ知識証明を検証することによって、証明者が秘密の入力 b を使用していることを納得させられます。これにより、a = 3 および c = 16 (つまり、公開入力値) のときに上記の式が真であることができ、公開入力 (a = 3、c = 16) を超えた情報を入手することはできません。
記事の次の部分では、具体的な証明プロセスについて紹介します。ゼロ知識証明法を使用して計算を証明する必要がある場合、最初にゼロ知識証明アルゴリズムが受け入れる算術回路の形式で計算を表現する必要があります。算術回路は、計算のチューリング完全表現です。その名前が示すように、算術回路は算術演算を行うゲートから構成された計算回路です。この例では、変換結果が図に示されています。私たちが言及した公開入力aとcと秘密入力bに加えて、計算プロセスで使用されるdとeという2つの追加の値があることに気づくかもしれません。これらは計算プロセスで使用される中間変数です。
算術回路内の各ワイヤを値と考えることができます。これは公開入力、秘密入力、または中間変数である可能性があります。算術回路に計算を展開した後、各中間変数はその場所を持ち、証明プロセスで使用されます。入力との唯一の違いは、彼らの値が証明者によって直接入力されるのではなく、算術回路内の他の入力値によって決定されることです。
算術回路は2つの部分として見ることができます:1つは回路に現れるすべての数値、もう1つはこれらの値の間の関係(制約条件)です。通常、回路内の公開入力は文(この例ではaとc)として参照され、秘密入力(b)や中間変数(dとe)を含む他のすべての値は証人として扱われます。
回路の論理によると、公開入力を記述とし、秘密入力を証人とすると、回路内のすべての証人値を計算できます。
したがって、算術回路のゲート回路は以下の形で表すこともできます。
ステートメント:
a、c
証人:
b,d,e
制約:
d = a * a
e = b + 5
c = d + e
回路を証明するためにアリスメタイズされた後、ゼロ知識証明アルゴリズムは回路の制約を処理し、証明の生成と検証に必要な形式に変換する必要があります。処理後、回路は回路のサイズとは無関係な固定長のVK(検証キー)を生成します。検証者は検証キーを使用して対応する回路のゼロ知識証明を検証できます。検証キーは、回路へのコミットメントにいくぶん似ています。制約に変更が加わると、それに対応する検証キーも変更されます。
実際の応用では、ゼロ知識証明のユーザーは、必要なロジックをzk回路のソースコードに記述し、審査を通じて対応するVKを生成する必要があります。このVKは検証者に引き渡されます。証明者によって証明された公開入力と生成された証拠と共に、検証者はこれらの公開入力が制約条件を満たしているかどうかを検証できます。この例では、証明者はa、b、cの値で証明を生成できます。検証者は、この操作を実行せずにa2 + bがCと等しいかどうかを検証できます。
ゼロ知識証明回路の制約
zk回路はチューリング完全であり、任意の計算を表現できますが、計算を算術回路の特殊表現形式に変換する必要があるため、算術回路を記述する際にいくつかの追加制限があります。
コンピュータプログラムでは、if-else文を使用してプログラム実行のブランチを制御できます。プログラムで選択したブランチのみが実行されます。しかし、ゼロ知識証明プロセスでは、計算が回路に平坦化され、実行パスや制御フローの概念はありません。そのため、算術回路で特定のブランチを選択して実行することはできません。
もちろん、これは回路で枝や選択肢を使用できないことを意味するものではありません。それは単に、回路では選択されたかどうかに関係なく、すべての枝が実行され、証明の生成に寄与することを意味します。枝の選択は、次の変数に出力される枝の結果にのみ影響します。
次の操作を例として取る:
if (flag) {
c = x + x
} else {
c = x * x
}
この操作を算術回路に変換すると、以下に示す制約に変換されます。明らかに、回路にはtemp1とtemp2という2つの新しい証人が追加されます。さらに、x+xの値とx*xの値が両方とも計算されます。
つまり、zk回路では、実行されるかどうかに関係なく、すべての枝やロジックが計算されます。
temp1 = x + x
temp2 = x * x
c = フラッグtemp1 + (1-flag)temp2
これらの制限のため、ゼロ知識証明回路での条件付き選択をサポートすることは非常に難しいです。ゼロ知識証明でスマートコントラクトロジックの実行パスを証明する方法は、zk仮想マシンの主要な課題の1つです。
私たちは、VMを普遍的な状態機械のモデルを通じて説明します。VMは、命令が処理されるときに状態を遷移する状態機械です。仮想マシンがゼロ知識回路で証明される方法を、非常にシンプルな状態機械の例で説明しましょう。
我々は、この普遍的な状態機械に汎用レジスタ(AとB)を持ち、さらに、現在の命令番号を格納するプログラムカウンタレジスタを持つと仮定します。
実行命令前のレジスタの状態
下の図は、ZK仮想マシンの証明回路の基本的なワークフローを示しています。
State 0は、実行前のこの仮想マシンの初期状態と見なすことができます。合計m命令を実行した後の初期状態は、最終状態mに到達します。初期状態に加えて、この仮想マシンには2つの通常の入力テーブルがあります。
図では、n番目の命令の実行プロセスが抽象化され、左側に表示されます。 状態機械の状態、状態nは、n番目の命令の実行後に状態n+1に遷移します。 同じ回路はm回の反復の後、vmでm個の命令の実行を達成します。
ここには2つの問題があります。
Oneは、固定回路内で異なる命令を実行する方法ですか?契約バイトコードを実行する際、実行されるnth命令を特定することはできませんので、ここでの実際の回路ロジックは決定できません。
2番目の質問は、実行する命令の数がmでないことをどのように証明するかですか?
最初の質問に対する解決策は、回路内のすべての可能な命令に対するロジックを実装することです。次に、命令に基づいてセレクターを使用して、前述の専門回路のif-elseと同様に、そのうちの1つを次の状態として選択します。
第2の質問について、回路内の命令数を直接変更することはできません。なぜなら、回路内の各命令には独立した回路セグメントが必要だからです。命令数が増減すると、回路が変化し、対応する検証キーも変化します。これにより、固定された回路内の任意のロジックを検証する要件を満たすことが不可能になります。
この問題を解決するために、状態を変更しないnoop命令を命令セットに追加することができます。したがって、各固定回路が実行できる命令の数には上限があります。zkVMの回路は、固定数の命令スロットを持つコンテナと見なすことができます。必要な命令がさらに必要な場合は、より大きな回路が必要です。実際の証明では、必要に応じて適切なサイズの回路が選択されます。
基本指示の証明
基本的な計算命令の例として、回路内の基本的な命令がどのように証明されるかを示します。
図は、指示証明回路のフローチャートを示しています。以下の数式は、証明のための回路制約です。
これらの2つの制約は、右上隅にリストされた汎用レジスタAとBの基本的な命令をいくつか証明できます。これらの証明により、入力テーブルから値をロードしたり、即値を命令からレジスタに読み込んだり、レジスタAおよびBの値を加算してレジスタに書き戻したりすることができます。
この図から、状態変化の制約を構築するために、回路はいくつかの補助制御状態を導入していることがわかります。
これらの補助レジスタと汎用レジスタ間の計算論理は、以下の数式によって実装されています。興味のある読者は、対応する値を制約式に代入して検証することができます。これらの2つの制約があることで、基本的な算術加算命令を実装することができることがわかります。より多くの操作が必要な場合は、より多くの命令制約を追加する必要があります。
基本的なプロセスダイアグラムに戻ると、このセクションの計算回路は、全体のプロセスにおける命令と見なすことができます。セレクタは、その出力が状態マシンによって採用される次の状態かどうかを選択します。このセクションの回路に必要な補助的な状態は、PCレジスタが指す命令によって生成されます。
インストラクションの取得は、専用のルックアップ回路によって実装されており、インデックスを通じて固定テーブルからデータセグメントの取得を証明することができます。したがって、zkVM回路はPCによって指定された仮想マシンによって実行された状態遷移を証明することができます。
条件付き判断と制御フローのジャンプの証明
状態マシンの複雑なロジックを実行する能力は、条件付きおよびジャンプ命令に依存しています。実際の契約では、条件に基づいて実行パスを変更するロジックを扱う必要があるため、そのような回路が必要です。
ここで注記すべきは、zkVM回路は実際に契約ロジックを実行し結果を計算するモジュールではないということです。zkVM回路が実際に行うのは、契約ロジックの計算過程を証明することです。したがって、証明する際には、実際に実行された命令のシーケンス過程を回路に記入し、このジャンプの条件が満たされているかどうかを回路で検証し、そして実行された命令フローが正しいジャンプを行ったことを証明することが必要です。
最初に、条件判定の証明を紹介します:
i番目の命令のオペランドがゼロと等しいかどうかの判断を例に取る。判断結果のisZeroのための補助状態を追加します。判断された値が0の場合、補助状態isZeroの値は1となります。判断された値が0以外の値である場合、isZeroは0となります。
このプロセスは、図中の2つの式によって制約されています。
この制約の妥当性は、ゼロ知識証明で使用される楕円曲線の数学的性質に関連しています。ゼロ知識証明回路内のすべての値は、楕円曲線上の有限体内の要素です。その値が0でない場合、逆要素が存在し、それを自身と乗算すると1になります。この性質を使って、図中の2つの制約とともに、ある値がゼロかどうかを検証し、それを補助状態に変換することが可能です。
このisZero条件補助状態があると、条件付きジャンプ命令の証明に進むことができます。
基本的なプロセス図に戻ると、現在の命令が条件付きジャンプ命令である場合。まずisZeroチェックを実行し、ジャンプ条件が満たされているかどうかを判定し、その後PCの値を変更します。PCの値を更新した後、次の命令の実行はまずPCを基にルックアップしてジャンプ後の命令を見つけることに関与します。
I/Oと複雑な操作
一般的な状態機械証明回路を使用する場合、状態遷移を正しく処理するためには、単一の状態遷移中にサポートされる各命令に対応する制御状態と制約を追加する必要があります。これらの状態値と制約の数は、zkVMがサポートする命令の数によっても乗算する必要があります。zkVMによってサポートされる命令の数が増えるにつれて、これらの状態値と制約の数も増えます。実際にzkVMによって実行されるプログラムで操作が行われない場合(すべてNOP)、これらの状態値と制約のチェックを省略することはできません。
したがって、この記事の前半で一般状態機械回路を使用して複雑な計算を実行することは非常に効率的ではありません。これらの方法を使用して複雑な計算を実装すると、そのパフォーマンスは受け入れがたいです。さらに、一般状態機械回路が複雑な命令を実行したり、直接外部とやり取りすることは困難です。
この問題を解決するため、zkVMの実際の実装では、一般的な状態マシン回路と専門の証明回路の組み合わせを使用して、プログラムの一部を別々に証明し、その後証明を一つの解決策に集約することが一般的です。
左側の図は、Scrollプロジェクトの回路アーキテクチャであり、右下隅の図はPolygonの回路アーキテクチャです。両方とも、右上隅の図に示されているように、類似したアプローチを採用しています。
一般的なステートマシンは、プログラムの実行ロジックの制御を証明する責任があります。ほとんどの契約では、このロジックの一部の実際の実行時間は非常に短いため、非効率な一般的なステートマシンでそれを証明することは、効率的な観点からはまだ許容されています。
より多くの固定複雑な計算、例えばハッシュ、MPTツリー操作、外部入力データなどは、専用回路によって証明されています。
一般的な状態機械と特殊な証明回路は、ルックアップテーブルを使用して相互作用します。状態機械回路がこれらの操作を呼び出すたびに、証明のための証人を生成するモジュールは、呼び出しパラメータと計算結果をルックアップテーブルに書き込みます。したがって、状態機械回路でこれらの操作を呼び出す際は、ルックアップ操作に簡素化されます。
ルックアップテーブル内の各呼び出しと戻り値の正確性は、専門の回路によって制約され、証明されています。
最終的に、回路内のコピー制約は、ステートマシン回路、専用回路、およびルックアップテーブルを接続し、ルックアップテーブル内の各アイテムが対応する専用回路によって証明されているかどうかをチェックし、最終的に完全なブロックの証明を生成します。
L1契約は、この集計証明を確認するだけで、仮想マシンの実行プロセス全体の正確性を確認する必要があります。
ゼロ知識証明技術により、計算を簡単かつ迅速に証明することが可能になり、信頼性のない環境で計算プロセスを外部委託する扉が開かれました。この技術は、ブロックチェーンで使用されると、実行をチェーンから解放し、メインブロックチェーンが分散化およびセキュリティの問題に焦点を当てることを可能にします。ただし、専門のゼロ知識証明回路の特性により、固定ロジックのみを実行することが制限され、これにより初期のzkRollupの能力が一部のトランザクションの種類に制限されています。
しかし、zk仮想マシンの開発と成熟により、任意のスマートコントラクトのチューリング完全な実行をサポートすることが可能になりました。zkRollupの可能性は本当に解き放たれ、ブロックチェーントライレンマを破るというビジョンが実現されるでしょう。