ハンタ読むだけで基礎からPlasmaまでイーサリアムを理解
PlasmaはEthereumの玄人コーダーでも割と挫折するコンセプトですが、BitcoinとEthereumの基本から筋を通すと簡単に理解できます。
以下大学サークル内の教材目的でHUNTER×HUNTERより引用を多用します。当記事は一切の利潤目的はございませんので、ご了承下さい。
#ハンター試験編 〜スマートコントラクト習得〜
(ここはエンジニアの方は飛ばしてくれても構いません)
仮想通貨に興味をもったエンジニアは、だいたい、世の中の中央集権的なクラウド・システムをリセットし、安全で公平なインターネットを作るという目的をもっています。
昔の記事では、ビットコインvs既存金融のような文脈をよく見ますが、近年では、よくサーバー(クラウド)vsブロックチェーンのような記事も多いです。これはご存知のとおり、ブロックチェーンに仮想計算機をつけたイーサリアムなどのスマートコントラクトが、中央集権的なクラウドサーバーに代わってくれるという期待です。
で、エンジニアは仲間と共に苦難を乗り越えて、適性検査に合格し、Solidityというプログラミング言語の特訓を師匠のもとで行うと、スマートコントラクトを作れるようになりました。
スマートコントラクトで「制約と誓約」をインターネットで行えるようになり、晴れて右図のように、中央集権サービスをフラットにするプロジェクト(Dapps)をイーサリアムを武器に始めることができます。
スマートコントラクトでは、個人アカウントであるEOAと、法人アカウントのようなものであるコントラクトアカウントがあり、これらが規則通りにどんどん変化することで、お金のやりとりや計算の約束ができます。コントラクトの状態がイーサリアムやDappsでは唯一の真実のようなものだと思って頂けたら速いです。
アカウント間のやりとりであるトランザクションはそのままブロックに記録され、アカウントの状態はハッシュ値で要約されてブロックに入ります。アカウントの状態はあまりにも膨大なデータであるため、全員でチェーンで共有はしないのです。(この性質を知っているかいないかが後で差がつくとは誰も思っていなかった・・・。)
さて、スマコンという念能力を覚えたにも関わらず、参加人数が多すぎてイーサリアムの手数料(燃料なのでGASと呼ばれます)が高騰し始めます。トランザクション詰まりと言うやつです。
イーサリアムの世界は厳しく、効率的にGASを減らさないエンジニアは次々に淘汰されます。
#クモ前編 〜Plasma発想〜
ここで、他のエンジニアに対し圧倒的効率性を持つ集団が現れます。Plasmanです。
PlasmaというEthereumのスケール方式を聞いたことがある方が多いと思います。子チェーンとよばれる新しいブロックチェーンをコントラクトと同期させるのです。
現状、一部のEthereumエンジニア(Plasman)が熱狂し、一部のEthereumエンジニアは「よく分からない」という感想をもっています。
現在、暗号通貨界ではビットコインのライトニング・ネットワークを筆頭にした「オフチェーン」と呼ばれるブロックチェーン外での暗号の活用による負担の削減方法が沢山登場しています。
Plasmaは確かにオフチェーンによるスケール方式なのですが、他のオフチェーンに比べて明らかに異質で構造的に異なるものです。その点をここで説明します。
さて、Solidityエンジニアは、一番単純なPlasmaであるMinimum Viable Plasmaに挑戦しますが、つかみどころがなく、当然苦戦します。
自分が、Plasmaへの熱狂が理解できない時はこんな理由でした。
①オフチェーンが負担を減らすのは当然で普通だから
②子チェーンという非効率そうな方式が何故いいのか分からないから(State Channelのほうがよさげ)
では、Plasmaの本質とは何か。
Ethereumの解説である先ほどの図をもう一度見てみましょう。
ブロックにトランザクションはそのまま入れ、アカウントの状態はハッシュ化して不可逆に要約します。
つまり、
①最新ブロックだけ取っても、アカウントの状態は分からない
②ブロックを全部ダウンロードしてあるフルノードは、トランザクションから全アカウントの状態を復元することができる
ということが分かります。つまり、フルノードは全アカウントの全情報をもっていて、ブロックチェーンには直接書いてはいないということです。このブロックに刻まれる全アカウント情報の要約をワールドステートと言います。
このハッシュはMerkleハッシュというもので、沢山のアカウント・アドレスの状態を要約し、整合性をチェックするのに非常に便利で、ビットコインにも使われています。非常にブロックチェーンの状態保存に関し、本質的な仕組みと言えるでしょう。
よって以下の図を得ます。
ここで、1つ質問です。
「フルノードが、他のチェーンのワールドステートを持ったら何が起こりますか?」
背筋がゾッとしますね。
これは狂人の発想のようですが、このコントラクト・アカウントの情報を当然もつフルノードが、このチェーンをスマートコントラクトの制限を受けながら管理することになります。
これを知った瞬間エンジニアは鎖野郎(Plasman)になります。
マークルハッシュは逆木構造になっており、一番上がワールドステート、一番下がアカウントの変数(データ)になっています。この変数がワールドステートになることで、大量の処理結果を要約することができます。
このPlasmaという仕組みはビットコインから使われているマークルハッシュの可能性を最大限に利用し、延々と下位チェーンの宇宙を広げるスケール策なのです。
もちろん、この下位チェーンに他の下位チェーンのマークルハッシュ要約を入れられます。
ブロックサイズの限界も、フルノードにのみデータが存在し、ブロックにはハッシュ化された小さいデータしかないので、ほぼ心配ないでしょう。問題はトラストレス性です。
下位チェーンの構造に関係なく、正当なスマートコントラクトの実行がチェーン外で行われなければなりません。
#クモ 後編 〜子チェーン実装〜
これから、メインチェーンの下につくチェーンを子チェーンと呼ぶことにします。
ワールドステートはそうは呼ばれず、ブロックヘッダーと呼ばれますが、この理由は簡単で、子チェーンは1つのコントラクトアカウントの情報しか持たないので、全アカウントの情報を意味するワールドステートとはイメージがちょっと違います。
では、子チェーンのブロックヘッダー(ワールドステート)をコントラクト・アカウントの変数にぶち込むだけでスケールするか?と言われたら、絶対そうではありません。そもそも、例えば子チェーンでEtherを勝手に発行して、メインチェーンに移すことができたら、どうしようもないです。
基本に立ち返れば、資産はすべて、子チェーンを管理するためのコントラクト・アカウント(ChainManager)に置いておく(Deposit)必要があります。逆に、これさえして、ブロックヘッダー(Merkleハッシュ)を矛盾なく作りさえすれば、何をしても良いです。
ここで、子チェーン内のオレオレルールとして、一人が管理コントラクト(ChainManager)にブロックヘッダーを送る役割を担うことになります。オペレーターと呼ばれます。
こんなことをして、怖くないのでしょうか?トラストレス??
実際、悪オペレーターがブロックヘッダーを管理コントラクトに一方的に送るだけの子チェーンではこうなります。
オペレーター監視のためには様々な施策が考えられ、子チェーンの仕様はブロックヘッダーを除いて自由ですので、PoS、DPoS、PoAなど沢山の選択肢があります。しかし、あくまで子チェーン内で悪のオペレータを追い詰めたところで、管理コントラクト・メインチェーンでガバナンスを行わなければ・・・
Exitとは子チェーンからメインチェーンに資産を逃がすことです。
当然トラストレスを保証しているのがメインチェーンであるため、そこが重要です。コントラクトの状態がイーサリアムやDappsでは唯一の真実であることはPlasmaでも変わらないのです。
さて、どうやって管理コントラクトでオペレーターの勝手を許さないようにできるでしょうか?
①オペレーターを訴えて、罰金を食らわせる
②子チェーンからみんな逃げ出したときに、オペレーターが損をするようにする
「いつでも訴えられる・いつでも逃げれる」ということでトラストレスを作っています。よく言う”Trust But Verify”形式とも言えるでしょう。
実際にどうしているのか、ちょっと管理コントラクトのコードを見てみましょう。
https://github.com/ethereum-plasma/plasma/blob/master/contracts/PlasmaChainManager.sol
pragma solidity ^0.4.19;
(中略)
contract PlasmaChainManager {
(中略)
//オペレーターがブロックヘッダを提出するための処理
function submitBlockHeader(bytes header) public returns (bool success) {
//ブロックヘッダ作る
BlockHeader memory newHeader = BlockHeader({ blockNumber: uint8(blockNumber), previousHash: previousHash,
merkleRoot: merkleRoot,
r: sigR,
s: sigS,
v: uint8(sigV),
timeSubmitted: now
});
//ブロックナンバーと組み合わせて記録
headers[uint8(blockNumber)] = newHeader;
}
(中略)//オペレーターを訴える処理
function challengeWithdrawal(
(中略)//訴えが正しいか、トランザクションとマークルハッシュを検証
require(isValidProof(header.merkleRoot, targetTx, proof));
チェーン内では基本は記録するだけで、訴える処理で初めて検証していますね。Gasを減らすためには当然の設計です。子チェーンでは、常にノードたちがおかしくないか計算して監視しています。常々、現実の司法と似てるなと思います。
ここで、重要なのは、子チェーンで行ったEthereumメインの鍵を使った署名は、メインチェーンでも有効になることです。そういった性質を使わなければ、メインチェーンでも有効な資産を子チェーンで持つことはできません。
https://github.com/ethereum-plasma/plasma
このPlasmaライブラリではjsファイルは子チェーンのノードが動かすプログラム、solファイルはチェーン内で動かす管理コントラクトのコードになってます。びっくりするほど読みやすいです。
ただ、最小構成の実装では、トランザクション承認をいちいちしなければならず、ノードの負担が大きすぎると言われ、もっと安心して使える奴にならないかという観点からその後、「More Viable Plasma」の提案が行われました。オペレーターの不正をしにくくするのは大変です。
ここで、個人的な意見を述べさせてもらいますと、トラストとはただの「コストの問題」なのです。セキュリティ対策とは攻撃者のコストを上げることを言いますし、非中央集権とは独裁・不正をするコストを上げるシステムのことを意味すると考えられます。
たとえば、先ほどの承認がいちいち必要なPlasmaに関しても、確かにオペレーターが不正をする可能性はありますが、透明性があるので、不正をしたらバレるわけです。
もし、メンバーが顔を出しているプロジェクトなら、この不正コストは社会的に非常に高いと考えられます。つまり、ある程度のトラストレス性が保証されているとも言えるわけです。
トラストレスにはいくつかの構成要素があります。個人的な分析では
①ルール変更不可能性
②透明性
③改ざん耐性
です。実は②だけでも、中央ノードが社会的信用が高いなら、ルール変更の独断や改ざんの社会的コストが高く、充分なトラストレスになるのです。つまりは、場合によってはプライベート・チェーンはトラストレスだという立場です。
このトラストレスがいくつか構成要素があることを忘れると、コインチェックハック時に有識者が、サードパーティーのみなりん氏による追跡モザイクの発行等を「中央集権でトラストレスではない」という批判をするに至った、あのグチャグチャな議論の流れを生むので避けたいところです。
さて、オペレーターの不正コストを保ちながら、ユーザーに楽させるために、承認者(バリデーター)という役割のノードを導入する提案がされています。
これにおいて、不正をするためには、オペレーターと不特定な監視者バリデーターが談合する必要が生まれ、難しいと考えられます。
もし、多少バリデーターから不正に誘われても、管理コントラクトがあるので、難しいでしょう。
だいたい、これでオペレーターは不正をしにくくなってきたわけですが、各実装に自由度が高すぎるため技術ハードルがまだまだ高いことは言うまでもなさそうです。