Plasma MVP を理解しよう!その2

flada
LOGICA Tech Blog
Published in
15 min readDec 12, 2018

この記事は、Plasma や Plasma MVP について聞いたことはあるがよく理解していないという読者を対象に、コードや仕様からは掴みづらいような背景・考え方なども理解できるような Plasma MVP の解説を目指すシリーズの第二弾です。

第一弾の Plasma MVP を理解しよう!その1 の知識を前提にしますので、まず目を通していただくことをお勧めします。この第二弾ではより詳細に Plasma MVP を見ていきますが、仕様レベルでは ethresearch の vitalik の投稿 を、実装レベルでは omisego/plasma-mvp の実装にのっとる形で進みますので適宜参照してみてください。ただし、omisego/plasma-mvp は元から PoC 的なリポジトリであること、さらに現在ではすでに omisego/plasma-contractsomisego/elixir-omg のリポジトリに開発の手は移っており、それほどアクティブなリポジトリではないことにも注意してください。

Plasma MVP の詳細

下の図は、シーケンス図のような形で Plasma MVP の全体像を示したものです。順を追ってこの図の内容を説明していきたいと思います。

Plasma MVP の全体像

登場人物

まずは図中に登場する人物・システムの紹介です。

Plasma Chain は単独ないし複数の許可されたオペレータによって運用されることを想定した sidechain です。そのような決まりがある訳ではありませんが、処理の高速化のために単独のオペレータによって運用される前提で語られることが多いです。omisego/plasma-mvp では 簡易的なサーバとして実装されていますが、もう少し踏み込んだプロジェクトでは Tendermint や Cosmos SDK を利用して実稼働を目指しているものもあります。

ユーザ は Plasma Chain を利用したいユーザです。Contract とやり取りする EOA(Externally Owned Account) とも言えます。

Contract は mainchain である Ethereum と sidechain である Plasma Chain をつなぐ役割を担う mainchain 上の smart contract であり、オペレータによってデプロイされます。omisego/plasma-mvp における実装は こちら です。

それでは、ひとつずつ手続きを見ていきましょう。図では一番左の列の吹き出しが対応しています。

deposit

全ての始まりとして Plasma Chain へ Ethereum 上の資産を移動させるために、ユーザが Contract の deposit() という関数を実行するトランザクションを作成・送信します。このトランザクションに Plasma Chain 上に持ち込みたい額の ETH を持たせておきます。

呼び出された Contract はトランザクションによって送金された額に等しい額の UTXO(unspent transaction output: 未使用なトランザクションのこと) のみを持つブロックを作成・記録し、emit Deposit(…) を実行することで event を発火させます。この event の発火を Plasma Chain は監視しており、発火したらすぐに Plasma Chain にも UTXO を 1 つだけ持つ内容のブロックを作成します。

Ethereum では Contract と外部のシステムを連携させたいときに、Contract の event 発火を外部から監視するという手法が一般的です。もし馴染みがなければ https://solidity.readthedocs.io/en/v0.5.0/contracts.html#events を参照してみてください。

これで Plasma Chain 上に資産が移動されて、off-chain でトランザクションを処理する準備ができたことになります。

deposit の流れ

send transaction

Plasma Chain 上に作成された UTXO を使って送金を行うにはトランザクションを作成して署名したのち Plasma Chain に送信します。Bitcoin のような UTXO モデルの blockchain と同じです。

また、Plasma MVP には Ethereum のように smart contract をデプロイするような機能は考えられていません。シンプルに deposit で作成された UTXO を別のユーザに送信できるだけです。Plasma の種類によってはこれを実現させようとするものもあります。

Plasma Chain だけで処理が完結するので、対応する Contract の関数などはありません。

submit block

ブロックの作成はオペレータの仕事です。ブロックを構成するトランザクションを確定させたら、まずはそれらのトランザクションから merkle tree を構築して merkle root を得ます。ブロック、トランザクション、merkle root の情報を Plasma Chain に記録しつつ、Contract の submitBlock(...) という関数を実行することで merkle root を Contract に記録します。merkle tree や merkle proof ってなに?という方は Cryptography: How does a Merkle proof actually work? を参照してみてください。

Plasma Chain はオペレータによって運用されているので、オペレータが作為的に不正確なブロックやトランザクションについての情報を公開することもできますが、もし Plasma Chain と Contract 双方の merkle root が一致しなければ、何らかの不正が行われたであろうことがすぐに確認できます。そして Contract に merkle root を記録することで Plasma Chain を利用しながら mainchain のセキュリティにあやかることができるという訳です。これは第一弾で state commitment として紹介しました。

send transaction submit block の流れ

exit

Plasma Chain から Ethereum へ資産を戻すためには exit と呼ばれる手続きを Contract の startExit() という関数を呼び出すことで実行します。Plasma Chain 上で所有している資産が確かに存在する事をトランザクションの merkle proof の形で提出し、それが有効と認められれば、その UTXO を Plasma Chain 上で消滅させた上で Contract からユーザに対して同額の ETH が送金されます。

ただし、この手続きはリアルタイムに処理されるわけではありません。なぜかというと、前述したようにある UTXO の merkle proof を提出するだけで資産を引き出すことが出来てしまえば、その UTXO が本当に 未使用(unspent) であるかを確認していないことになりますが、実際に Plasma MVP の構造では Contract が持つ情報から unspent であるかどうかを自動的に判定することができないのです。

そこで、challenge exit(あるいは単に challenge) と呼ばれる手続きを用意し、その受付期間の間は exit を完了させずに保留することにします。

challenge exit

challenge exit とはすでに消費された UTXO を対象とする exit の不正を告発する手続きで、challenge 期間中の exit に対して誰でも行うことができます。必要なものは exit されようとしている UTXO を input に持つトランザクションのデータ(つまり使用済みのトランザクションであり UTXO ではないということ)とその merkle proof です。これらを Contract の challengeExit() という関数に渡すことでその exit は自動的に却下されます。

また、omisego/plasma-mvp では exit に際して EXIT_BOND という変数名で定義された数量の保証金が必要になっています。challenge が成功した場合はこれを没収して challenge を成功させた人に渡すことで、challenge を行う動機になるように考えられています。

exit と challenge

ユーザは全てのトランザクションを監視する必要がある

しかし、実際には自分の UTXO が不正に exit されるかもしれないという状況が常に起こり得るのに、保証金を得るという自己の利益のために行動する第三者を期待するだけでは安心できないとユーザは考えるでしょう。

つけ加えて、Contract に deposit された ETH は1つの同じ資産のプールから皆が引き出すという形になるため、たとえ関係ない第三者の UTXO に対する不正な exit であったとしても、それが1件でも発生するのを許してしまえばすべてのユーザのすべての UTXO の exit に対応する原資を失っている、つまり、自身が損を被る可能性が発生することになります(このような状況を指して fractional reserve と言われていたりします)。

これらの理由から Plasma MVP では利用者自身が全てのトランザクションに目を光らせ、いち早く不正に気づいて challenge をする必要があると言われています。

さらなる不正の余地 - オペレータによる不正への対策

exit とその制約からくる不正の対策である challenge について触れました。これでユーザによる不正については対策ができましたが、もう一方の登場人物であるオペレータはその立場上、様々な不正を行えるであろうことも考慮しなければなりません。

challenge 期間の詳細と exit priority

例えば、オペレータはブロック作成の役割を担っているので、input が存在しないトランザクションのような明らかに不正なトランザクションでもブロックに含めることが出来てしまうと考えられます。

もちろん、そういった不正なブロックのデータが公開されたならばユーザもすぐに気づくことはできますが、ここで問題になるのはブロックに一度トランザクションが含まれてしまえば、通常のそれと変わらず正常に exit できてしまうということです。

exit するには対象の UTXO の存在の証明だけが必要ですが、これは不正なブロックに確かに含まれているので証明できてしまう。かつ、challenge で告発するには使用済みであるトランザクションという証拠が必要ですが、存在しないはずなので対抗する術がありません。

不正を直接・自動的に止めることはできなくても、その状況下でさえユーザが資産を Ethereum 上に引き出せることが保証されていれば、オペレータがわざわざリスクを犯してまで不正を働く動機が無くなるとも考えられます。
exit はリアルタイムに処理される訳ではないと前述しましたが、実は exit は exit priority と呼ばれる UTXO 作成時点の時間順で古い方から処理されており、ユーザはオペレータの不正に気づいたあとに新しいトランザクションの送信をせず直ちに exit の申請を行うかぎり、必ず先に exit できるため資産を失わずにすむのです。

少しややこしいので、exit が challenge 期間を過ぎて finalize するまでのロジックを箇条書きにしてみました。

  1. 作成から 7 日間以上経過している UTXO の exit は、exit の申請時点から 7 日間の challenge 期間
  2. 作成から 7 日間未満しか経過していない UTXO の exit は、UTXO 作成時点から 14 日間の challenge 期間
  3. Contract の finalizeExit() が実行されることで、実行時点で challenge 期間を過ぎている exit が UTXO position の小さい順で処理される
  4. UTXO position は block number * 1,000,000,000 + transaction index * 10,000 + output index で計算される

これらを前提に、以下のようなシナリオが想定されています。

  1. オペレータが不正なトランザクションをブロックに含めてすぐに exit したとすると、前提の 2. に該当するので UTXO 作成時点から 14 日間の challenge 期間が設定される
  2. 前提の 1. に該当するユーザの UTXO は exit 申請から 7 日間の challenge 期間となり、不正なトランザクション作成から 7 日間経過する前に exit 申請をするならば先に exit できる
  3. 前提の 2. に該当するユーザの UTXO は UTXO 作成時点から 14 日間の challenge 期間となり、不正なトランザクション作成後に作成したものでないかぎり先に exit できる

これらのシナリオから分かる通り、不正なトランザクションがブロックに含まれてからは一切新しいトランザクションを送信せず迅速に exit しなければならず、これもユーザ自身が全てのトランザクションを監視しなければならない理由になっています。

さて、オペレータの不正なトランザクションより 前に 作成された UTXO は問題なく守られることがわかりましたが、オペレータがこれから発行しようとするブロック内のトランザクションを作為的に自分の不正なトランザクションの 後に ユーザのトランザクションが来るように入れ替えてしまったらどうなるでしょう?

この場合、ブロックが同じなので作成時点が一緒となり不正なトランザクションと同じ challenge 期間が設定される、かつ、UTXO position に従って処理される結果として不正なトランザクションより後に exit されることになってしまいます!

confirm signature

そこで登場するのが confirm signature で、これは送信者がトランザクションを送信してブロックに含まれた後に、不正が無いことを確認して再度トランザクションに署名をすることで、そのトランザクションを有効なトランザクションとみなす仕組みです。

実は exit するために Contract の startExit() を実行するにも confirm signature を渡す必要があります。これによって UTXO position で exit 順序が負けるようなトランザクションがブロックに含まれてしまっても、そのトランザクションには confirm signature を与えずに、input としていた UTXO を exit することでユーザの資産が守られることになります。

まとめ

いったいどれだけ不正の対策が必要なんだ…と思われた方も多いでしょう。ここで振り返っていただきたいのが第一弾の内容です。
簡単にまとめれば、off-chain で高速に処理するために Plasma Chain を運用するオペレータを全面的に信頼することになるが、mainchain である Ethereum を工夫して上手に利用することで、オペレータがどんな不正をしたとしてもユーザの資産を守れるように設計するというのが Plasma MVP です。
MVP という響きとは裏腹に、なかなか理解しづらいところも多く、大切なのは背景を理解して仕様の意味を汲み取る姿勢だと思います。この記事が少しでもその役に立てば幸いです。

実装を交えて紹介するつもりでしたが、ほとんど論理的で浅い紹介のような形になってしまいました。コードを追わないとやはり分からないよという方は コードを用いてPlasma MVPの設計を理解する が非常に参考になるかと思います。

また、これまでに触れてきたいくつかの事由から Plasma MVP の実現性に疑問が投げかけられていることにも触れておきましょう。

  • confirm signature が必須であればユーザからしてみると1つのトランザクションに二度も署名が必要となり使い勝手が悪すぎるのではないか?
  • ユーザが全データを監視するというのは現実的なのか?

これらの問題に対する改善案として MoreVPPlasma Cash などいくつもの仕様が提案・検討されています。それらを調べる上でも Plasma MVP についての知識は活かされるはずです。また、数ある Plasma の仕様の関連について俯瞰したければ Plasma World Map — the hitchhiker’s guide to the plasma が役に立つでしょう。

最後に、ぜひ ethresarch の Plasma MVP のスレ も訪れてみてください。ここでは紹介しきれなかった話もたくさんあります。この記事をきっかけに Plasma に興味を持ち、ethresearch を眺める人が少しでも増え、そんな人と議論を交わすことができるような、そういう記事になればとても嬉しいです!

参考

--

--