Scaling Bitcoin 2019予習シリーズ第5弾は、「ZkVM: zero-knowledge virtual machine for fast confidential smart contracts」。おそらく内容はStellarが開発している↓のZkVMの話だと思われる。
https://github.com/stellar/slingshot/tree/main/zkvm
ZkVMブロックチェーン
ZkVMはTxVMの研究から生まれたゼロ知識仮想マシンで、キーとなる機能はゼロ知識証明を利用したコインやコントラクトの秘匿化だが、その他にもTaprootやUtreexoなど現在Bitcoinの改善案として提案されている新しい技術が導入されている。
ブロックチェーンの構造
ZkVMブロックチェーンの参加ノードはそれぞれがブロックチェーンステートを管理する。このブロックチェーンステートは以下の要素で構成される。
名称 | 定義 |
---|---|
initialheader |
ブロックチェーンの初期ブロックヘッダー |
tipheader |
最新のブロックヘッダー |
utxos |
Utreexoで管理するUTXOのルート |
そしてブロックヘッダーは以下の要素で構成される。
名称 | 定義 |
---|---|
version |
ブロックのバージョンで、現在は1 |
height |
ブロック高 |
previd |
前のブロックのID |
timstamp_ms |
タイムスタンプ |
txroot |
ブロック内のトランザクションのマークルルート |
utxoroot |
Utreexoのルート |
ext |
将来の拡張用でversion 1では空 |
既存のネットワークに参加する場合は、公開されている初期ブロックとブロックの履歴を入手しチェーンを同期する。新しいネットワークを作る場合は自分で任意のtimstamp_ms
とutxos
をセットして初期ブロックを作成するみたい。
各ノードは新しいブロックを受け取ると、ローカルに保持しているブロックチェーンステートを更新する。
トランザクション
ZkVMブロックチェーンはUTXOモデルのブロックチェーンで、トランザクションのインプットが前のトランザクションのアウトプットを参照し、そのコインを新しいトランザクションアウトプットへ移動させる仕組みはBitcoinと同様。
各インプットは前のトランザクションアウトプットを参照する識別子を持ち、暗号署名でそのコインをアンロックする。各アウトプットはコインの新しい宛先。トランザクションの各アウトプットはコントラクトを持ち、コントラクトには値もしくはデータパラメータである任意の数のアイテムが含まれ、Predicateによって保護される。Predicateはこのアウトプットの資産をアンロックするために満たす必要がある条件で、公開鍵やサブプログラムで構成される。
トランザクションは一意のトランザクションIDを生成するのに必要なデータとロジックを含む以下の要素で構成される。
名称 | 定義 |
---|---|
Version |
バージョン |
Time bounds |
最小時間と最大時間の範囲を表す時間制限 |
Program |
ZkVMの命令シーケンスを表す可変長のバイト配列で、スタックベースのZkVMで実行されるプログラム。 |
Signature |
64バイトの署名 |
Proof |
VM実行中にConstraint systemを満たす証明で、可変長の点の配列とスカラー値 |
表から分かるように、実はBitcoinのトランザクションのように明示的にインプットやアウトプットをセットするフィールドは存在しない。ZkVMにはinput
命令やoutput
命令があり、インプットとアウトプットの組み立てもProgram内の命令コードとデータを使って行うようになっている。
ZkVMの実行
ZkVMはトランザクションを検証するためのスタックマシンで、トランザクションのプログラムを実行し、そのトランザクションの有効性を検証し、ブロックチェンステートの更新リストを計算するようになっている。
上述したように、インプットおよびアウトプットの指定もこのProgram内で行われる。例えば、ZkVMがProgramを実行し、その中にinput
命令があれば、スタックからUTXOを識別するprevout
をpopし、そのprevout
に対応するコントラクトを構築しスタックにプッシュし、トランザクションログにインプットエントリーを追加する。output
命令があれば、スタックからPredicateおよびアイテムをpopしContractを作成し、アウトプットエントリーをトランザクションログに追加する。このようにして消費したUTXOと新しいアウトプットの情報はトランザクションの実行結果としてトランザクションアウトプットに記録される。そして最終的にトランザクションログを使ってブロックチェーンステートを更新する仕組みになっている。トランザクションの検証とトランザクションログによるブロックチェーンステートの更新を分離することで並列性を高めるみたい。
秘匿性
↑のZkVMはには、Program、スタック、トランザクションログ以外に、もう1つConstraint systemと呼ばれるものが含まれている。
ZkVMはゼロ知識証明システムの一種であるBulletproofs上に構築されている。コインの量を示す値やデータはデフォルトで暗号化され、Pedersen commitmentとして表現される。
Programの実行中にさまざまな命令がConstraint systemに制約を追加し、VMがProgramの実行を完全に終えると、Bulletproofsプロトコルでトランザクション内に格納された証明の文字列を使ってConstraint systemを検証する。トランザクションにセットする証明を作成するには、トランザクション作成者が最初にVMを証明モードで実行する。するとトランザクションのProgramは検証モードと同じ制約を作成するが、証明をチェックする代わりにConstraint systemを使って証明を生成するようになってるみたい。(この辺のBulletproofsを使った証明の仕組みはもっと掘り下げて別の記事で書きたい。)
Taprootの利用
トランザクションアウトプットに定義されるPredicateは公開鍵やサブプログラムで構成されると書いたが、この時Taprootのコミットメントスキームが利用される。コントラクトのアンロック条件をMASTで構成し、その条件セットをTaprootのスキームを利用して公開鍵にエンコードする。Taprootを利用することでロック時に全てのコントラクトロジックをが明らかになることを回避する。また、コントラクトの全参加者が協力する場合、アウトプットをアンロックする際にコントラクトの条件を公開することもない。
具体的なTaprootの仕組みについては以前書いた↓を参照。
techmedia-think.hatenablog.com
Utreexoを利用したUTXOセットの管理
ZkVMブロックチェーンは、UTXOセットの管理にUtreexoを使用する。現在のBitcoinはUTXOセットの全データをKVSで管理し、その容量は3〜4GBほどになるが、ZkVMブロックチェーンではUTXOセットをUtreexoというハッシュベースのアキュムレータを使って管理する。UtreexoではUTXOのセットで複数のマークルツリーを構成し、そのマークルルートのみを保存するため、UTXOセットの容量は数KBまで圧縮される。Uteexoの具体的な仕組みについては、以前書いた↓を参照。