はじめに
本記事は、過去にコンセンサス・ベイスが主宰していたオンラインサロンの記事です。記事は2017年~2018年にかけて執筆されたため、一部は、既に古くなっている可能性があります。あらかじめご了承ください。
今回の内容
Plasmaが抱えているこれらの課題を解決するための機構として提案されたのが、本シリーズのテーマであるPlasma Cashです。
次回はいよいよ、Plasma Cashを用いてこれらの問題がどうスマートに解決するかを見ていきたいと思います。
第1章 Plasma Cash
前回解説したPlasmaですが、Plasmaには二つの問題がありました。
一つ目はユーザーが自分が関わっているトランザクション監視するために全ての子階層のPlasmaチェーンをダウンロードする必要があること。
二つ目はPlasmaチェーン上で処理されたトランザクションの状態を更新するためには親チェーンのアカウントの状態もアップデートする必要があるということです。
Plasma Cashはこれらの問題を解決しようとする試みです。
デポジットされたトークンに固有のIDを発行する
PlasmaおよびPlasma CashはUTXOモデルを採用しており、トークンIDを振ることによりトランザクションを全て固有のものと捉えることができます。 (EthereumのメインチェーンではUTXOではなくアカウントモデルが採用されていることに注意してください)
Plasma Cashでは、Plasmaチェーン上にデポジットされた一つ一つのトークンに、それぞれを識別できるようにユニークな識別子(ID)を付与します。
例えばポケットの中にある現金を数える際には、1枚目の千円札、2枚目の千円札、、、というようにそれぞれに頭の中で番号を振りながら数えるかと思います。その場合と同様、Plasma上のトークンにユニークな番号を振ろうというコンセプトです。
これがPlasma Cashと呼ばれる所以ですが、この番号を振るという行為で多くのメリットがもたらされ、Plasmaの課題を解決することができます。
以下、Plasma Cashにおいて、plasmaのチェーン上にデポジットされたトークンに振られるユニークな番号のことを「トークンID」と呼びます。
第2章 ダウンロードサイズの軽量化と恩恵
まずは一つ目の問題を解決するために、トランザクションをどのように管理しているのかを見ていきます。
トランザクションの構造
Plasma Cashチェーンにあるすべてのブロックのルートは、そのルートチェーン上(Ethereumのメインチェーンなど)に公開される必要があります。
このマークル木の中では、トークンIDと各ノードのインデックスが対応するように、順番に整理されています。
トークンが使用されていない状態では、各ノードの値は空となっています。
トークンが使用され、そのトランザクションが正常に処理されると、使用されたトークンIDに対応した位置(インデックス)のノードにトランザクションのデータが保持されます。
図 : Plasmaチェーンのmerkle木
トークンIDがを紐づけられたトークンを消費するトランザクションは、それがマークル木のトークンIDの位置に含まれている場合にのみ有効となります。たとえば、トークンが使用されていないことを示す(二重使用を防ぐ)際には、トークンIDと1対1で関連づけられているインデックスのノードが空であることを示せば良い、ということになります。
Plasmaではユーザーが自分が関わっているトランザクションを監視するために、全ての子階層のPlasmaチェーンをダウンロードする必要がありました。
しかしPlasma Cashでは、トークンIDに対応したノードのみを提示すれば済むので、取得すべきデータ量が削減されます。
そのため、クライアント側の検証作業が簡略化され、トランザクションのスループットを向上させることができます。
なお、トランザクションの形式は次のようになっています。 表1 : トランザクションの構造 [[prev_hash、prev_block、(target_block?)、token_id、new_owner]、signature]
第3章 アカウント状態の更新処理の削減
次に二つ目の問題の解消に関連する、Plasma Cashチェーン上にトークンをデポジットする手順と利用方法について見ていきます。
Plasma Cashのチェーン上にトークンをデポジットする
Plasma Cashのチェーン上にトークンをデポジットするには、メインチェーンで公開されているPlasmaのコントラクトにあるdeposit()関数を呼び出します。
デポジット関数は、呼び出された際に一緒に送られた量のトークンを元に新しいトークンを生成します。
ERC20トークンの場合はdepositToken(address erc20, uint256 denomination)を呼び出します。
この関数は、ERC20コントラクトに対してユーザーが所有するトークンを引き出し、トークンタイプ(ERC20コントラクトのアドレス)とデポジットするトークンの量を記録します。
Plasma Cashの利用
Plasmaチェーンでトークンを利用するユーザーは、利用したい特定のトークンの完全な履歴を送金するユーザーに提供する必要があります。
Plasmaチェーン上にデポジットされたトークンを消費するトランザクションが発行されるたびに、マークル木による証明がなされます。対応するトークンIDの箇所をマークル木からブランチとして取得し、その箇所にトランザクションが入っていれば、それはトークンが利用されたこととなります。 逆にデポジットされたトークンが消費されなかった場合には、対応するトークンIDの箇所にトランザクションが入っていないことを確認します。 次に、送信されたトークンを受け取ったユーザーは、トークンの履歴をチェックします。 正しいトークンIDの箇所にトランザクションが入っているかを確認し、問題がなければ、受信者はトークンを使用できるようになります。
この一連のトークン送信の処理で、トークンを受信したユーザーのみが送られたトークンを利用することができます。
PlasmaおよびPlasma CashはUTXOモデルを採用しているため、トークンIDを振ることによりトランザクションを全て固有のものと捉えることができます。
これにより、二つ目の問題であるPlasmaチェーン上で処理されたトランザクションの状態を更新するために、都度親チェーンのアカウントの状態をアップデートすることなく所有者の移転が可能となります。
第4章 イグジット(離脱)への不正申告
イグジット(Exit)とは、Plasmaのチェーンから親であるイーサリアムのメインチェーンにトークンを戻す行為です。
しかしこのイグジットを悪用して、例えばPlasmaのチェーン上で5Etherしかもっていないのに、それ以上の額(10Etherとか)をメインチェーンに戻そうとするなどの不正行為が行われることがあります。
その対策として、トークンのデータに携わっているすべてのユーザー(ノード)は不正申告を行うことができます。
各イグジットは申告を行ったユーザーのガスコストと不正に対する賞金を含んでおり、不正を告発したユーザーはこの賞金を受け取ることができます。
イグジットに対する不正申告の種類には次の3つのタイプがあります。
消費コインの不正申告
図1 : 消費コインの不正申告
- イグジットするユーザーは3を用いてイグジットしようと試みます。
- 不正申告ユーザーは3への参照を持つ4を用いてイグジットの不正を申告します。
二重消費の不正申告
図2 : 二重消費の不正申告
- イグジットユーザーは4から2への参照を用いて4をイグジットしようと試みます。
- 不正申告ユーザーは2への参照がある3を用いてイグジットの不正を申告します。
無効な履歴の不正申告
図3 : 無効な履歴の不正申告
- イグジットするユーザーは5と4を用いてイグジットしようと試みます。
- 申告者は最後の有効な2と1を用いて不正申告をします。
- イグジットするユーザーは有効な2の次の有効なトランザクションを答える必要があり、存在しない場合にはイグジットがキャンセルされます。これは不正なブロックが保留されている場合でも動作します。
今後の研究課題
Plasma Cashにより、Plasmaの課題を幾分解決することができましたが、さらに改善する余地は残っています。
今後の研究課題として残っているものとして以下の要素があります
部分的な支出
トークンIDは分割不可能なため、トークンを分割して支払うことができません。
これに対する簡単な解決策としては、トークンIDが小数点をサポートすることが考えられます。Plasmaで完結するための理想的な手法としては、Plasma上でトークンを分割し、分割されたものを一つのトークンにまとめあげてイグジットする手法がありますが、仕様がまだ決定していません。
履歴閲覧の省力化
実装によっては、トークンの履歴を検証する作業コストが大きくなる可能性があります。将来的にゼロ知識証明を利用したzkSTARKの技術を用いるなどして、高速にトークンの履歴チェックを行うようなアイデアが提案されています。
効率的なイグジット
イグジットの処理を簡潔にすることが求められます。
無効なトランザクションの後は、すべてのサブトランザクションが無効であると仮定します。そうすると、無効なトランザクションが含まれる直前にイグジットできるユーザーは、そのトークンの持ち主である、と言うことができます。
実際にはトランザクションの検証をしているので、無効なトランザクションがあったとしても問題にはならないのですが、イグジットのロジックが複雑になってしまいます。
Block Withholding
Block withholdingの説明ですが、まずノードの中で、とあるブロックがブロードキャストされていない状態を想像してください。
そのブロックのトランザクションを考慮しない状態では、一連のトランザクション群は正常であるといえるのですが、その隠されたブロックがブロードキャストされ、そのトランザクションを考慮すると、二重消費などの不正が起きてしまう問題です。
この問題に対処する方法が必要とされます。
また、blocktime以上にblockがholdされた際、それが悪意を持った攻撃なのか、何らかのミスやトラブル、単なる遅延なのかを判断するのが難しく、規定時間を過ぎたブロックを単純にスキップしてもいいのか?という部分の判断もさらなる議論が必要です。
まとめ
今回は、Plasmaチェーンの問題を回避するためのPlasma Cashがどのように問題を解決するのかを見てきました。
Plasma Cashはまだ実装がなく、今後技術的な変更がなされる可能性があります。
今回、3回にわたって解説したPlasmaは、イーサリアムのスケーリングを解決する手法として今後とも多く注目を集めていくであろう技術です。
とはいえ、まだ完成形ではなくEthereum Researchでは日々議論がなされています。興味を持った方はそちらもウォッチしてみてください。
参考資料
- https://karl.tech/plasma-cash-simple-spec/
- https://ethresear.ch/t/plasma-cash-plasma-with-much-less-per-user-data-checking/1298
- https://zoom-blc.com/what-is-plasma-cash