Intmax
0. プロジェクトの目標
1. EthereumがDAの限界を超えてスケールアップすること
2. Dappsだけでなく、Webアプリケーション/Webサイトも含めたソフトウェア所有の形態を刷新する
3. あらゆる地域のネット市民の財産権をバックアップする。
バックエンドの監査可能性とユーザプライバシーの提供ってのが面白そう。Aztec的な?
最終的に事業の機会を分散化する。→イグジット市場を解放する
1. 既存のZKRとの比較
そもそもZKRのデメリットは
L1への資金投入時に、ユーザーごとにクライアント側のzkp計算が必要
EVMとの互換性が難しい
operatorsやトランザクタがtxcalldataを使用するため、依然としてコストがかかる。この制限は、単にユーザが資金のMerkle proofを生成できないように、取引の結果である状態を復元する必要があるためである。
Rollupsのほとんどの仕様では、operatorsはすべての取引履歴データをL1上のtxcalldataにダンプすることが要求されている。
この取引履歴データの透明化は、txcalldataのガスコストを増加させるだけでなく、取引のプライバシーを阻害する要因にもなっている。逆にいうと取引履歴データのアキュムレータは、効率問題とプライバシー問題の両方を解決することができると推測される。intmaxではこの推測をもとにソリューションが提供される。
このような背景から、Intmax Rollupの要点を挙げると
まず、operatorsが最終状態のdiffを直接txcalldataに書き込むzkRollupを構築する。
この時、取引履歴はzkpの回路のprivate inputになる。
次に、txcalldataから最終状態diffを削除し、shared storageとuser state storageを分離する。
これにより、非包含証明によるユーザの退出が可能となる。
semaphore的な?
ユーザは自分のuser state storageを保持し、そのMerkle Rootのみを公開する。
ユーザーはルート遷移をzkpで証明し、スマートコントラクトのよく使うストレージを更新することができる。
しかし、通信が何段階もあるため、通信レイテンシーがデメリットとなる。
つまり、Txをオンチェーンに保存する代わりに、状態の差分(共通に使うストレージ)をオンチェーンにのみ保存する、というアイデア
txcalldataを使用して状態を完全に復元する2つの方法
1. すべてのトランザクション履歴をtxcalldataに記録する
2. ブロック(バッチ)内のトランザクションの結果としての最終状態の差分を記録する
2.では、取引なしという同じ結果を持つ数百万件の取引は、txcalldataに記録するものがないため、txcalldataの使用には0ガスを使用する。Merkleルート遷移の健全性はzkpによって保証される。
上記2.は、バッチ/ブロック内のトランザクションがコントラクト内の同じ貯蔵値を変更する場合、より少ないガスコストとなる
しかし、そのような共通部分が少ない場合はあまり効率的と言えない
このような共通に共有され変更される値は、ERC20の総供給量やスワッププロトコルの総プール量などのようなものである。
また、このようなストレージはすべてのアセットホルダーに影響し、このようなデータの損失はzkRollupのlivenessの喪失につながる。一方、共通に共有・変更されることのないその他のデータは、ほとんどが個々のアセットデータである。この種のデータの損失は、直接的には所有者の資金の損失を意味する。このリスクは分離され、他の人の資金には影響を与えない。
そこで、ユーザーのステートを分離し、operatorsがユーザーの状態データとその証明をレシートとして渡すことで、大量のガスのコストカットする
ステップ
(1) A transactor send a transaction to the operator
(2) The operator make the merle proof of her user state as a receipt of the transaction
(3) The transactor sign the receipt
(4) Only transaction data with the signed receipt is accepted in the circuit
あるユーザが取引を行い、複数のユーザの残高が変更され、それらの残高とMerkle証明を含む状態を知っている場合、そのうちの誰かが、最後の状態であることを証明するzkpによって、いつでも彼女の資金を終了させることができる。
この最後の状態であることの証明は、各バッチごとに変更された状態の所有者の各アカウントリストのnon-incrusiuon proofによって行うことができる。
このとき、変更された状態の所有者のアカウントリストのSMTを用いると、効率よく証明できる。
変更された状態の所有者に最後の変更を知らせる2つの方法
オンラインであれば、operatorが最後の差分を送り、その差分を署名して受け取り、それをzkp回路の入力に入れる
もし彼らがオンラインでなければ、operatorはそれをtxcalldataかオフチェーンのshared storageにポストする
このように状態を分離することで、オペレータは最終状態のdiffすらtxcalldataに置く必要がなくなり、ユーザは自分のアカウントの状態が出口まで十分に安全であり、shared storageを失うことはオペレータがzkRollupのMerkle Rootを更新できないことを意味するだけなので、単にサービスを停止することになる。
そうすれば、shared storageもuser state storage]もオフチェーンで分散できる。txcalldataには、バッチごとに変更された状態の所有者のアカウントリストだけを記録すればよい。
(1) The user sends a transaction to the operator.
(2) The operator returns the diff of balance and the updated common shared storage.
(3) The user makes zkp proof of the updated Merkle root of her user state and common shared storage.
この機構はrecursive-zkを必要とする。
user state storageは、saftyではなく、livnessのために必要
2.アーキテクチャ
トランザクション履歴はそもそもデータベースの結果を再現するために使うもの。データベースの結果自体を書き込めば要らなくなる。
取引履歴データを必要としないzk-Rollupの鍵となるコンセプトは以下の三つ
(1) stateの分離によるsafetyとlivenessの独立
(2) stateの無更新を証明することによる古いmerkle proofの利用
(3) zkpとの通信を証明することで、tx結果のmerkle proofの即時返却とtx履歴データの削除を実現
大きく以下の 3 つのコンポーネントから構成される
1. zkRollup Aggregator Module:Ethereum securityで実行される監査可能なレイヤ 2 モジュール
2. zkRollup User Module:ユーザ側のデータの保存とAggregatorとの通信を管理するモジュール
3. External Distributed Storage Validation Module:静的Webページ、コントラクトデータ、ユーザデータをZKPでバックアップするための分散ストレージを検証・管理するモジュール
3.に関してはIPFSとか?
セキュリティを維持したまま取引履歴データを保存する方法
https://scrapbox.io/files/62fced921333fa001d68dc50.png
1. Aggregatorは、zkRollupのMerkle Rootに含まれることの証明とともに、バッチ内のすべてのTxの結果としての状態差分を、関連するすべてのユーザに通知する。
2. ユーザーはこれに署名してAggregatorに返却し、Aggregatorはバッチ回路を満足させる。
ユーザはAggregatorから受け取ったデータを(1)で保存する。
この署名がない場合、Aggregatorは分散型ストレージにこれらのデータを出力する必要があり、Aggregatorとユーザーの両方にコストがかかる。
そこで、彼らは署名を提出することで、このコストを回避する。
3. Aggregatorは各バッチの後、取引元のアドレスリスト全体をオンチェーンに公開する。
4. Ethereum Layer1 に出金する際、1. で aggregator が配布した L1 上の zkRollup Merkle Root に対してinclusion proof を提出する。この証明の検証は、スマートコントラクト上で実行することができる。
5. 4.に加え、Aggregatorがproofを渡した後に自分の資産状態が変化していないことを証明するため、引き出し者は自分のアドレスをアドレスリストにinclusion proof を提出する。
この処理では、取引データを calldata に書き込む必要はない。ユーザー側には取引結果とその証明のみが存在し、いつでもオンチェーンで証明することができる。
この問題、前章で述べたzkRollupにトランザクションデータを載せる必要がある理由は、zkp回路で兄弟が直接ユーザに渡ったことをアグリゲータに証明させることで解決している。つまり、Aggregator側のZKP回路において、該当ユーザへの状態差分の通知やMerkle証明の配布に失敗がないことを制約条件とするのである。
Commonly Shared Storage
通常のEthereum型スマートコントラクトでは、ユーザーのプライベートアセットの情報(User Asset Storage)の他に、全ユーザーが共有するコントラクトデータ(Commonly Shared Storage)があるが、これらはユーザー側だけでなくネットワーク全体でも共有する必要がある。
すべてのノードが Commonly Shared Storage を失えば、ユーザは資産をレイヤ 1 に移動することができるので、この Commonly Shared Storage を calldata に書く必要がない
この場合、その後のコントラクトの使用/トランザクションは不可能となる。
Commonly Shared Storageが偽造された場合、Aggregator側のzkp回路の制約を満たさなくなり、更新ができなくなる。
唯一の例外は、スマートコントラクトが所有するアセット/バランスデータ(CA Asset Storage)
これをcalldataに書き込む必要があり、このデータを変更するのはコストがかかる
公開されたスマートコントラクトがL1に抜けることでその資産を確保するためのデータを保存する信頼できるエンティティが存在しない
スケーラビリティのために、ユーザーがスマートコントラクトにアセットを預けるとき、コードはそのスマートコントラクト上のアセットに対する負債として、ユーザーにトークンを管理させる必要があります。
別のスマートコントラクトは、このようなデットトークンを持つことはできない。
このzkRollup上のUniswapの例では、Uniswapコントラクトの2つのERC20残高は1バッチ後に2つの最終値としてcalldataに書き込まれる。一方、ユーザーはERC20の資産を請求するためにLPトークンの残高データを保存するので、これらの残高をcalldataに書き込む必要はない。他のスマートコントラクトは、このコントラクトの請求権としてLPトークンの保有者になることはで木ない
前述の通信処理に加え、スマートコントラクトに必要なデータはユーザー側のUser Asset Storageに格納されるため、スマートコントラクトの実行に必要な変数データが何かをAggregator側に提示してもらう必要がある。これはコントラクトアドレスと変数インデックスで指定でき、ユーザーはUser Asset Storage(UAS)からデータを取得し、そのマークアップ証明でトランザクションの入力とする。
zk
最速Plonky2とガスコストが安いintmaxを組み合わせたら最強
zkEVMはまだまだ先の話
Proto-danksharding
shared storageを実装するためにEIP4844(proto-danksharding)が使われる。
肝は一定期間データを保管して消せるので、ストレージを圧縮しないStateless Clientを実現できる.
厳密にはオンラインユーザーに直でデータ渡すかProto-Dankshardingで安価一時保存するかを選択でき仕組み。
LivenessとSafetyは切り離されるので、shared storageが死んでも、ユーザーのアセットは常時Layer1にExit可能
Secret SC on zkRollup
Intmax zkRollupデフォルトの設定として取引に関わった人のアドレスを秘匿する。
機密保持の構成は以下の通りである。
(1) Aggregatorに取引を送信する際、ユーザは取引に必要なユーザ資産保管庫の資産データの包含証明と、nonceと秘密鍵から生成されるワンタイムアドレスを提出する。この包含証明は、ZKPでメルクル証明の兄弟を隠し、アドレスを明らかにしないようにする。
(2) (1)のトランザクションデータを受け取ったAggregatorは、トランザクションを実行し、実行結果としてのUser Asset Storageのdiffのプルーフを公開する。この差分データは、公開される際にワンタイムアドレスにバインドされる。
(3) ユーザーは、自分のアドレスのUser Asset Storageに、いつでも上記のdiffをマージすることができる。ユーザは、マージして更新したUser Asset StorageのMerkle rootを、クライアント側のzkpが真であることを保証してAggregatorに送信する。Aggregatorは、このUser Asset StorageのMerkle rootの変更を受け入れ、zkRollup全体のMerkleツリーを更新する。
注意すべき点
(1) 5-4-1の出口でセキュリティ機構として使用したアドレスリストは、アドレスが機密であるため、有効ではなくなった。その代わり、Aggregatorはcalldataにワンタイムアドレスのリストを書き込む。Aggregatorから証明書を渡された後、自分の資産状態が変化していないことを証明するために、最後のnonce+1で生成したワンタイムアドレスがオンチェーン上のワンタイムアドレスリストに含まれていないことを証明する。
(2) アドレス隠しに起因する二重支払いについても、上記と同様に防止することができる。ユーザは、前回の nonce で生成されたワンタイムアドレスがリストにあること、および nonce+1 で生成された今回の取引のワンタイムアドレスがリストにないことを証明する。
質問
Q1. shared storageとuser state storageを分離し、stateのdiffを管理することがキモだと思うのですが、基本的にどちらのストレージもIntmax Rollupのノードにのみ保持される(IPFSなど外部に頼らない)という認識であってますか?
>user state storageはユーザーサイドの保管ですね。
shared storageはEIP4844かIPFS/Filecoinです。
shared storageは死んでも、ユーザーのアセットはLayer1にExit可能です
Q2. barry氏との会話で挙げられていたexit blockの間隔は具体的にどのくらいになると思われますか?
また、ここで議論されていない潜在的な懸念点があればお聞きしたいです。
おそらく6時間ですね。Preconsensusと組み合わせるので。
Q3. WPの中ではマークル木しか言及されていませんでしたが、クライアント実装はVerkle Treeの使用が前提でしょうか?たまたまVerkle Treeのレポジトリを見つけました
Verkle Treeを考えてます。zkの計算量との相談ですね。
Q4. 具体的なZKPプリミティブは何を使うのですか?
Ultra plonkです。もしかしたStark使うかもですが。
参考文献