Cashとは、Karl氏やvitalik氏、Dan氏を中心に提案されたイーサリアムのレイヤー2におけるスケーリングソリューションです。従来のPlasmaを改善することでさらなるスケーリング効果が期待できるとされています。Cashのメリットや課題点について解説していきます。Plasmaの基本的な内容を前提として解説していくので、以下のPlasma解説記事も併せて参考にしてください。Cashの説明の前に、Plasmaの概念について見ていきましょう。Plasmaとは下図のようにイーサリアムのブロックチェーンをメインチェーンとして階層上にPlasmaチェーンが成り立つ構造となっています。Plasma)Plasmaがない通常の場合は、全てのトランザクションの処理をメインチェーンのみで行い、そこにデータを書き込んでいました。Plasmaではそれぞれの子チェーンにおいてトランザクションを送信し、データの書き込みを行います。それぞれの子チェーンのブロックが追加されるごとにトランザクションのマークル木ルートを親チェーンに記録します。この親チェーンのブロックが承認されて初めて子チェーンに新たに追加されたブロックは承認されることになるのです。これを上図のように階層上に繰り返すことで、多くの子チェーンで実行されたトランザクションがイーサリアムのメインチェーンにまとめてハッシュ値として記録されるのでかなりのスケーリング効果が期待できるのです。プラズマシステムを大規模にすればするのほどプラズマチェーンの数が水平方向にも垂直方向にも増え、それぞれのチェーンで並列的に実行できるトランザクションの数も増加します。(メインチェーンに書き込むデータサイズや書き込む頻度はプラズマシステムをどれだけ大きくしても変わりません。)要は、Plasmaを実装することでトランザクションの処理に対するメインチェーンの負担を大幅に軽減することができるということです。攻撃に対するセキュリティまずPlasmaの前提として、子チェーンはネットワーク参加者がオンラインで監視され続ける必要があります。下図のようにアリスやボブが一番下層の子チェーンにトークンを保持している場合は、アリスやボブはその子チェーンから遡る全ての親チェーンを監視する必要があります。Plasma)もしアリスやボブが自分で監視していない場合は、その子チェーンは攻撃者によって不正にトークンを引き出されたりしても、気づくことができません。Proofs)することができるので攻撃成功を回避することができます。アリスやボブが自分で監視していなくても他の誰かによって子チェーンが監視されていれば、攻撃されたときに誰かが代わりに不正行為を申告してくれるはずです。100%のセキュリティを維持するためには自分自身で自分が利用している子チェーンは監視するべきでしょう。Plasmaにおける具体的な攻撃としては以下のようなことがあげられます。アリスが子チェーンに5ETHしかデポジットしないはずなのに10ETHを引き出そうとする攻撃です。この場合、子チェーンを監視しているノードによって不正行為が申告され、攻撃は成功しません。本当にアリスが10ETHを子チェーンにデポジットしているのであれば後述するように「その子チェーンに10ETHを保持している」という証明を行えるはずですが、この証明ができないのであれば不正を行なっている、ということで攻撃は失敗します。Deposit)をデポジットしなければなりません。不正を行なっておらず、無事引き出しが完了した場合はこの保証金はユーザーの元に返金されます。不正を行なっていた場合は、この保証金はユーザーの元には返金されず、その不正行為を申告した申告者に報酬金として渡されます。この報酬金が子チェーンを監視し不正行為を申告することのインセンティブになっているのです。子チェーンで任意のトークンを作る攻撃ブロック生成者であるチャーリーが不正なブロックを作り、子チェーンで実際には保持していないはずの100,000ETHを不正に作る攻撃です。この場合も、上述したようにその子チェーンを監視しているユーザーによって不正行為が申告されるはずなので攻撃を成功させることはできません。プラズマでは親チェーンに対してその子チェーンにデポジットされているトークン量の総量が記録されるデザインになっています。下図のようにメインチェーンにおいてその子チェーンには5ETHしかデポジットされていないのであれば、チャーリーが不正に作った100,000ETHは存在しないはずなのです。Plasma)このような場合は、不正行為が申告されていなくでも仕様上、攻撃自体をすることができません。5ETH以下であればチャーリーはトークンを不正に作成する攻撃ができてしまいます。このケースでは、前述したように不正行為の申告による攻撃からの保護や後述するExitプロセスで親チェーンへ資産の移動が行われます。子チェーンのブロック生成者がユーザーのトランザクションをブロックに含めなかったり、トランザクションを書き換えてしまう攻撃です。ブロック生成者が自身に有利なトランザクションのみをブロックに記録するような攻撃となります。子チェーンのコンセンサスアルゴリズムでPoAが採用されていた場合、少数の決められた管理者によってブロックの生成が行われます。(ちなみに、子チェーンはファイナリティが必要なので、PoWではなくPoAやPoSが原則前提となっています。)このPoAの場合、不正なブロックが生成されるチャンスは高くなります。このような攻撃が行われた場合、その子チェーンに参加するユーザーは攻撃が実現する以前のスナップショットを元に自身の資金を親チェーンに戻すことができます。Cashにおける資金を引き出す具体的なプロセスは後述します。Cashとは以上のような仕組みで成り立っているPlasmaにもいくつかの解決しなければ大きな課題があります。そのうちのひとつに、ユーザーが子チェーンのデータを全てダウンロードしなければならない、ということがあげられます。これは、ユーザーの二重支払いやブロック生成者の不正なブロック生成などの攻撃を防ぐためです。ユーザーが送金をするときにはある特定の子チェーンの特定のブロック高において送金額以上の残高を保持し、かつそのUTXOが複数の受け手に対して送信されていないことを証明する必要があります。(子チェーンはイーサリアムブロックチェーンのようなアカウントベースではなく、ビットコインのようなUTXOベースです。参考:ビットコインのトランザクションにおける「UTXO」を分かりやすく解説)Plasmaのデザインにおいてこの証明を行うためには、そのトークンの履歴(子チェーンにデポジットされてから、誰から誰に送られてきたか)を参照するために子チェーンのデータを全てダウンロードし、二重支払いを行なっていない証明をする必要があるのです。これではそれぞれのユーザーが大きなサイズのデータをダウンロードする必要があり、子チェーンが大きくなるほどさらに不便になっていきます。Cashでは子チェーンのデータを全てダウンロードする必要はありません。CashではPlasmaと比べて、はるかに小さなデータサイズで有効性の証明ができるようになるのです。これは、プラズマチェーンにデポジットするそれぞれのトークンに対して、特有のTokenIDを与えることにより実現されています。アリスがデポジットした3ETHやボブの5ETHはそれぞれ固有のTokenIDが付与されることになります。プラズマチェーンにデポジットされるトークンはNon-Fungibleになるのです。アリスの3ETHはTokenIDが1であり、ボブの5ETHはTokenIDが2になり、それらはTokenIDで区別されうるのです。このようにデポジットされたトークンに対して、固有のTokenIDを与えることで子チェーンでのトランザクションを保持するデータ構造を変更することできます。従来のプラズマでは、プラズマチェーンにはトランザクションのインデックス順にトランザクションをマークル木構造で整理していていました。Cashではデポジット時に付与したTokenID順にトランザクションをマークル木(あるいはマークル・パトリシア木)で整理しているのです。(ここでいうトランザクションとは通常のイーサリアムトランザクションデータとは異なり、Plasma固有のUTXOに基づいたトランザクションデータであることに注意してください)これにより、ユーザーは自身のTokenIDとマークル木のインデックス番号を照合するだけで、そのトークンは有効であることが証明できるのです。TokenIDが5のトークンが消費された場合、以下のようなマークル木構造において5番目の位置にトランザクションが存在することになります。(消費されていない場合はトランザクションは存在しません)アリスが子チェーンにデポジットしているTokenIDが1の5ETHを送金する例を考えてみましょう。このTokenIDが1のトークンはその子チェーンで複数回送金されてアリスの元に渡っています。上述したように、従来のPlasmaではトランザクションを送信するときこの子チェーンを全てダウンロードする必要がありました。Cashでは、TokenIDが1のマークル・ブランチの履歴を送り手が提示するだけでOKです。他の関係のないTokenIDに関するデータは一切必要ありません。無事トランザクションの処理が完了すると、そのマークル木のTokenIDの位置にはそのトランザクションが保持されます。二重支払いをしていない証明をするためにはそのTokenIDの位置が空データであればいいことになります。Cashのデザインでも子チェーンが伸びてくると証明のためのデータもどんどん大きくなっていきます。長期間運用された子チェーンにおける証明のためのデータが大きくなりすぎないように、1年ごとにスナップショットを取りこのデータサイズを0に戻されます。1年ごとにトークンは引き出され即時に再びデポジットされることになります。CashのユーティリティとしてはDEXのようなハイスループットが求められる環境で非常に有効です。Cashではユーザーは自身のTokenIDの位置にあるマークル・ブランチだけが必要になります。Cashではデポジットしたトークンに固有のTokenIDを与えることがPlasmaとの変更点になります。Cashではどのようなメリットが得られるのか見ていきましょう。Cashの最大のメリットはユーザーが保持する子チェーンに関するデータを大幅に削減できることです。ひとりひとりのユーザーが自身が関わっている全ての子チェーンのデータをダウンロードすることは、実際のアプリケーションでは現実的ではありません。Cashではこの部分が大きく改善されていることになります。残高更新のための確認が不要にPlasmaにおいては子チェーンのセキュリティを保つために以下の2段階の確認作業が必要となります。子チェーンでトランザクションを送信する場合は、その子チェーンでのブロック生成者によってトランザクションのマークル木ルートが親チェーンへトランザクションとして送られます。この確認トランザクションが親チェーンのブロックに取り込まれて初めてプラズマチェーンにおいてそのトランザクションは承認されることになります。従来のプラズマでは、上記のトランザクションが承認された後、両者の残高を更新するためにトランザクションの送り手は受け手に対して確認メッセージを送る必要があります。送り手は親チェーンを監視して、トランザクションが取り込まれたら相手に確認メッセージを送るという確認作業が必要であったのです。プラズマチェーンにおいてアリスがボブに5ETHを送金する場合はアリスはボブに対して確認メッセージを送らなければならなかったのです。ボブがアリスからの確認メッセージを受け取って初めて両者のETH残高は更新され、ボブは受け取ったETHを使うことができるようになります。Cashではこの残高更新のための確認作業は必要なくなります。デポジットされたときに与えられた固有のTokenIDがなければトークンを引き出すことはできないという制限が存在するからです。Cashにおいては確認作業は必要なくなります。Cashの基本的な仕組みとメリットになります。これらを踏まえて実際に、親チェーンから子チェーンにデポジットする行為、子チェーンでトークンを送金する行為、そして子チェーンから親チェーンにトークンを戻す行為をどのように行なっていくのか見ていきましょう。Cashにおいて自身が持っているトークンを子チェーンにデポジットするのは、従来のプラズマとほとんど変わりません。親チェーン(メインチェーン)のプラズマコントラクトを実行することで、誰でも子チェーンにデポジットすることができます。従来のプラズマと違う点は、このときデポジットしたトークンに対して特定のTokenIDが与えられることです。複数のトークンに分割したり、他のトークンと結合させたりすることはできません。デポジットするトークン量が少なすぎるとコントラクトを実行するgasの方が大きくなってしまうのである程度のトークン量は最低限必要になります。上述したように、子チェーンのトランザクションはTokenID順にマークル木形式で整理されており、そのマークル木ルートはメインチェーンに記録されています。ユーザーは保持しているTokenIDのマークル・ブランチのみを追っていることになります。Cashにおいて送金をするときは、受け手はそのTokenIDの情報を一切保持していないことになるので、そのトークンの履歴(以前にどのアドレスからどのアドレスに対して送られてきたか)を相手に提示する必要があります。このトークン履歴はブロックチェーン外のオフラインな方法(例えばWhisperなど)で送信されます。受け手はこのトークン履歴をチェックすることで何か不正がないか確かめることができるのです。具体的には、トークンが送金されていない場合、プラズマチェーンのマークル木においてそのTokenIDの位置が存在し、かつ空データであるか、ということをチェックします。NonExistence)これは、子チェーンで二重支払いを防ぐことにとても役立ちます。二重支払いをしようとしている場合は、マークル木のそのTokenIDの位置に以前のトランザクションが存在してしまうからです。このような設計上、同じブロックにおいて同じTokenIDを持つトークンを2回以上送金することはできないということになります。deposit)が必要になります。全てのノードは、あるユーザーの引き出しを監視し、不正を行なっていると判断した場合はネットワークに対して不正申告を行うことができるのです。アリスはプラズマチェーンに2ETHしかデポジットしていないのに、5ETHをメインチェーンに戻そうとしたときは、他のユーザーがこの不正を申告し、もし本当に不正が行われていた場合はアリスの保証金を手に入れることができます。トークンを親チェーンに戻すときは、そのトークンの過去2つのトランザクションに対するマークル木証明を提示する必要があります。「2つ」なのかというと、例えばユーザーがあるブロックでトランザクションを送信した直後に、ブロック生成者が不正なデータを含めてトークンを引き出してしまうという攻撃が考えられれます。このような攻撃の場合、不正なデータは直近2つのトランザクションの間に含まれるので、ユーザーが子チェーンからトークンを引き出すときは直近2つのトランザクションを提示する必要があるのです。このトークンを親チェーンに引き出す行為に対する不正行為の申告は以下の3つのタイプがあります。提示された2つのトランザクションよりも過去のトランザクションに対する申告いずれのタイプも提示されたトランザクションに対応する申告者が保持しているトランザクションを提示することで申告が行われます。引き出すユーザーのトランザクションと申告者のトランザクションが一致しているのか確認するのです。タイプ1,2の場合を考えていきましょう。ブロック生成者が上述したようにユーザーがトランザクションを送信した直後に、不正なexitをした場合、ブロック生成者はexit時のブロック高以降のデータを保持していないことになるので、正当な証明をすることはできません。タイプ3の場合は、トークン履歴の不正に対する申告になります。申告者はそのTokenIDにおける二重支払いで被害を被ったユーザーであり、そのトークン履歴を保持しているはずなので正しいトランザクションを用いて申告することができます。逆に、自分自身の関係のないTokenIDの不正行為には関与する必要はありません。Cashの設計であれば申告を成功させることができます。以上のように、Plasmaのメカニズムにおいてデポジットされたトークンに固有のIDを割り当てることでUX的にかなり改善がされました。Cashにおいてもいくつかのデメリットや課題点があり、それらを解決策については現在議論が進められています。Cashにおいてはデポジットしたトークンに対して固有のTokenIDが割り当てられ、それらは分割したり結合したりすることはできません。5ETHをデポジットしたときはその「5ETH」をひとつのコインと見なして、2ETHと3ETHに分割したり、他のトークンと合わせて10ETHにしたりすることはできないのです。これは、デポジットした5ETHのうち3ETHのみを送金したい、といったときに不都合になります。このようなトークンの一部送金の実現方法については現在議論されている段階で以下のような解決策が提案されています。新しいTokenIDをつけるユーザーが結合や分割をするときに特定のTokenIDを新しいTokenIDに書き換える”merge/split”トランザクションを定義する方法です。新しいTokenIDに変換されてもトークン量自体は同じであるようにします。MVPのexitトランザクションと同程度のChallenge期間が必要になります。Cashのexitプロセスと同じ状況として扱うことが可能です。欲しい量のトークンを保持している第三者を介して送金を行う例えば、アリスがボブに3ETHを送りたいのに5ETHのコインと少額の0.001ETHのコインしか持っていない場合を考えます。このとき、アリスとボブの間に3ETHと2ETHのコインを持っているチャーリーを介することで実質的にトークンの一部送金が可能になります。具体的な流れを見ていきましょう。アリスはチャーリーに5ETHを送るチャーリーはボブに3ETHを送るチャーリーはアリスに2ETHを送るアリスはチャーリーに手数料のための少額な0.001ETHを送るしかし、このような方法だと特定のコインを持っているユーザーを上手くマッチングすることができるのか、さらにそれぞれの手順で上述したexit時のchallenge期間が必要になるのでかなりの時間がかかってしまう、といった問題があります。分割時にTokenIDをdecimal型に対応させることでそのコインを小さくバラバラできるようにする方法です。この方法の問題点としては、コインを小さくしすぎると引き出し時のgasと比較してそのコインの価値がほとんどなくなってしまうことがあげられます。payments)確率的ペイメントとは、例えばアリスが10ETHのコインしか持っていないときボブに5ETHのコインを送金したい場合、50%の確率で10ETHを送金することで実質的に5ETHのコインを送金していると考える方法です。この方法の問題点は、送金額が確率によって左右されてしまうということです。多額の送金には適していません。マイクロペイメントで役に立つ方法であるとされています。以上のようなさまざまな解決策が提案されていますが理想的には、分割したトークンを子チェーンで送金し、それらの分割されたトークンをひとつにまとめて引き出せるようなトランザクションを定義することです。このトランザクションを実現するために有効な解決策は現段階ではまだ考えれらていません。Exit問題とは、攻撃者が子チェーンから親チェーンにトークンを引き出すリクエストを大量に送る攻撃です。引き出しリクエストは順番に処理されていきますので、攻撃者がこのリクエストを大量に送信してしまうと通常のユーザーはなかなかトークンを引き出すことができなくなってしまいます。Cashでは上述したように引き出しの際は保証金もつけることでこの問題を回避しようとしています。不正行為を見つけることができた場合はこの保証金が申告者に報酬金として与えられるのです。Exit攻撃を防ごうとしているのです。Exit問題は実際はもっと複雑な問題です。攻撃者が引き出しリクエストを大量に送り、トランザクションを詰まらせ、gasを上昇させます。すると、申告者が申告を行うときに送信するトランザクションで消費されるgasが、申告が成功したときに得られる報酬金と比べて大差がなくなってしまったり、より大きくなってしまうことも考えられます。なると、申告者が不正行為を申告するインセンティブ設計が崩れてしまうのです。そのPlasmaチェーンが妨害されてしまうことになります。proofs(TokenIDのポジションにあるマークル・ブランチの履歴)のためのデータサイズは大幅に削減されました。filterやzk-SNARKsの技術を用いることでさらに削減しようとする提案もされています。filterとは、実際にイーサリアムブロックチェーンでログ情報を記録するときにも用いられている技術で、確率的な探索フィルタで欲しいパターンを正確に特定しなくてもパターンを記述できる方法となります。zk-SNARKsとは、秘匿化技術の一種です。以下の記事で詳しく解説しています。上述したようにトークンを子チェーンから引き出すExitプロセスは、セキュリティを維持するために複雑な仕組みとなっています。他の巧妙な攻撃に対するセキュリティ効果やユーザーがより素早くExitできるようなプロセスに改善できるように、さまざまな議論がされています。理論的には不正なトランザクションの履歴があったとしてもExitプロセスは進めて問題ありません。ユーザーはそれぞれのトークン履歴をチェックするので、その不正なトランザクションに対しては無視すればいいだけだからです。巧妙な攻撃に備えてトークン履歴においてトランザクションが有効であるだけでなく、不正なトランザクションがない、ということも証明しなければならない必要性が想定されています。この部分はさらに最適化できることが考えられているのです。