アルゴリズムとかオーダーとか

仕事で勉強したことなどをまとめてます

EIP-1679 istanbulで導入候補のEIPを整理する その2

今回も引き続き、福岡ブロックチェーン勉強会#29 エキスパートコースでQ&A形式で発表した、EIP-1679についてまとめていきます。
github.com

本記事は連載記事となっております。よろしければ前回の記事もご覧ください。
y-nakajo.hatenablog.com

このEIP-1679は次のEthereum1.0のアップデートであるIstanbulで導入されるEIPについてまとめたものです。EIP-1679は現在はまだ導入される候補(Proposal)EIPをリストアップしたものであり、この中から期限までに実装可能で十分にテストされたものだけが、最終的にIstanbulとしてEthereumに導入されます。
リストをみてわかる通り、多くのEIPが候補に上がっており、また似たようなEIPも多数含まれています。引き続きこれらのEIPをカテゴライズしながら紹介します。

gasCostを低くする提案

前回の記事では特にPrecompiled Contractの呼び出しに関係するgasCostの値下げ提案についてまとめました。ここではそれ以外のgasCostを値下げする提案について解説します。

EIP-1380:自己召集のためのガス代の削減

Ethereumでは過去に起きたDoS攻撃を緩和するために、EIP-150でいくつかのOPCODEのgasCostが引き上げられました。
github.com
特にこちらの記事で周辺事件も含めて詳しく解説されていますので合わせて参照ください。
ethereum-japan.net

この提案ではEIP-150でgasCostが引き上げられたOPCODEのうち、CALLおよび、DELEGATECALL、STATICCALLを実行する際に、対象のaddressが自分自身である場合はgasCostを700から40に引き下げようという提案です。
gasCostを下げる根拠としては、EIP-150はDoS攻撃緩和のために、ディスクI/Oが発生するOPCODEを引き上げることが目的でした。しかし、自分自身のコントラクトコードを呼ぶ際には、すでにそのコードはメモリにロード済みでありディスクI/Oは発生しないため、gasCostをEIP-150以前の40に戻しても良いのではないか?ということを挙げています。

また、CALL系OPCODEのgasCostを下げる利点としては、内部関数呼び出しをJUMPからCALLに置き換えられる点を挙げています。JUMP命令の代わりにCALLを用いて内部関数を呼び出すと、EVMのコンテキストが新たに生成されるため、解析および、関数呼び出し時のスタック操作がより簡潔になるという利点があります。ただ、内部関数を呼び出す処理をJUMPとCALLのどちらで行う方がより安くなるかはケースバイケースになるため、コンパイラのoptimizationのコストは高くなってしまう点は提案内でも述べられています。

EIP-2028:Calldataのガスコスト削減

この提案はCalldataのゼロでないbyteデータのgascostを現状の68からTBDに引き下げるという提案です。
CalldataとはTransactionのdata部に格納されているデータを指します。コントラクトのある関数をTransactionを介して呼び出す場合はTransactionのdata部に呼び出す関数のIDと必要となる引数のデータが格納されます。このdataに対して1byte毎に値が0の場合と0以外の場合で、以下のようにgasCostがかかるようになっています。

calldata gascost
calldata gascost
(Ethereum Yellow Paper より)

このCalldataのgasCostを引き下げることにより、Transactionに格納できるデータサイズを引き上げ、スケーラビリティーを改善しようというのが提案の動機になります。
Transactionに格納できるデータサイズを引き上げることで以下の利点が生まれます。

  • proofデータサイズの大きな、zk-SNARKsやzk-STARKsの利用可能性が高まる。
  • zkやMerkle Proofを用いたLayer2によるスケーラビリティ改善がより実現しやすくなる。

ただし、欠点としてはブロックのデータサイズ増加に伴うネットワーク遅延を挙げています。

個人的には、下図のchartが示す通り現状のブロックサイズはBitcoinの1MBと比べても小さく(大体30Kb)、2〜3倍程度に引き上げても問題無い様に思います。また、下図2つのBlock Average SizeとBlock Gaslimitのchartが示す通り、ブロックのガスリミットとデータサイズには相関関係がないため、1 Transactionに含まれるデータサイズが大きくなってもブロック全体のサイズが比例して大きくなるとは考えにくく、Transactionサイズの引き上げの影響はそこまで大きくないのでは?と思っています。

Block Average Data Size
https://etherscan.io/chart/blocksizeより - 2019/06/30 2:30 時点
Block Gaslimit Chart
https://etherscan.io/chart/gaslimitより- 2019/06/30 2:30 時点

EIP-2045:EVMオペコードのパーティクルガスコスト

この提案は単純命令形のOPCODE(ADDやMUL、SWAPなど)の価格を引き下げるための提案です。
単純命令形のgasCostを引き下げる理由としては、これらの命令がディスクI/Oを伴う命令(SSTORやSLOAD)に比べて遥かに安価なリソースや処理時間で処理が可能なためです。
また、SSTORなどのストレージ操作系OPCODEのgasCostを引き上げる場合は以下の問題があることを指摘しています。

  • コントラクトをデプロイした当時に算出した経済的なコストが引き上げられてしまう
  • 不変式(現状、EVMにおいて何を不変式とするかにはまだ議論が続いているが。。)の変更による、想定外の影響

上記の動機により、この提案では単純処理系のgasCostを引き下げるように提案していますが、引き下げ方法についても工夫されています。その工夫とはパーティクル(粒度)gasCostという現在のgasに比べて1/10000の尺度を持つ単位を新たに加え、より小さなgasCostを定義可能にするという提案です。
その理由としては、現在、単純処理系のgasCostは3もしくは5が割り当てられており、gasの単位のままであれば、ADD命令などは実質1/5〜1/3程度しかコストを削減できないことになります。新たな尺度を追加することでこの問題を解決し、単純処理系のgasCostを現状の1/10以上削減できるようにします。なお、パーティクルgasCostはEVM処理中にのみ計算され、Transaction処理の際には今までどおりgas単位で計算が行われます。

gasCostを引き上げる提案

これまではgasCostを引き下げる提案を見てきました。次はgasCostを引き上げる2つの提案について解説します。

EIP-1884:トライサイズに依存するオペコードの価格変更

この提案では以下のようにgasCostの引き上げと新しいOPCODEの追加を提案しています。

  • SLOADのgasCostを200から800に引き上げ
  • BALANCE(a.k.a EXTBALANCE、つまり他のaddressのBALANCEを取得する場合)のgasCostを400から700に引き上げ
  • SELFBALANCE OPCODEを追加。このOPCODEのgasCostは5であり、このOPCODEは自分のbalanceを取得するためのもの。

SLOADおよび、BALANCE OPCODEを外部アドレスに対するものと、自身のBALANCEを読み出すものに分離し、外部アドレスのBALANCEを取得するOPCODEのgasCostを引き上げる根拠としては、現状のEthereumを同期する際にかかるOPCODEごとの処理時間に対する実際の分析結果を元にしています。

https://eips.ethereum.org/assets/eip-1884/run3.total-bars-6.png
このグラフは最近(6M〜7M)のブロックを同期する際のOPCODEごとの実行時間を重い順に並べたものです。GASPRICEが一位になっていますが、GASPRICEについては最適化が可能としてここでは除外しています。
このグラフが示す通り、最近ではEthereumが保有するstateデータサイズの増加に伴い、SLOADの処理時間が非常に重くなっています。

https://eips.ethereum.org/assets/eip-1884/BALANCE-run3.png
また、このグラフはBALANCE OPCODEに関する処理時間についてです。2Mブロックあたりで急激に処理時間が増加しているのは過去のDoS攻撃によるものです。6Mブロック付近でも過去のDoS攻撃と同様の処理時間がかかっていることが計測されています。
BALANCE OPCODEはEIP-150にてgasCostが20から400に引き上げられました。その理由としてはディスクI/Oを伴うOPCODEだからです。しかしながら、BALANCEの挙動をより詳細に見ると、実はディスクI/Oを必要としない、自身のbalanceの取得とディスクI/Oを必要とする外部アドレスのbalanceの取得という2つの性質に分けられます。
このことから、この提案では自身のbalanceを取得するOPCODEを新たにSELFBALANCEとして定義し、これは安価な5 gasで呼び出せるように、また、外部アドレスのbalanceを取得するOPCODEを最近の処理時間の増加を鑑みて400から700に引き上げることを提案しています。

EIP-2035:ステートレスクライアント - SLOADとSSTOREをブロックプルーフの代金として再評価

この提案はステートレスクライアントを実現するための準備として、SLOADとSSTOREのgasCostを引き上げるという提案です。
ステートレスクライアントの仕組みについては同提案の中にもリンクがある、下記の記事を参照ください。
medium.com

ステートレスクライアントを簡単に説明すると以下のようなものです。

  • 軽量なデバイスでblock検証を可能にする仕組み
  • BitcoinSPVノードみたいなものを実現するための仕組み
  • ステートレスクライアントでは1つのBlockの中にstateの変更を検証可能な全てのデータも含まれるため、blockを検証するたびに全てのstateを捜査する必要がなくなる。(のでステートレスと呼ばれる)

上記のような仕組みを実現するためにBlockの生成および伝搬について以下の変更が加えられます。

  • Blockの中にこのBlockに含まれるTransactionを処理する際に呼ばれるSLOADとSSTOREに必要となるstateデータが追加される。
  • Blockの中に含まれるstateデータが正しいことを証明するMerkle Proofも追加する。
  • これらのBlock Proof(記事内では上記2つをまとめてBlock proofと呼んでいるのでここでもそれに習う)の作成はminerが行う。

このように、ステートレスクライアントに対応する場合は、SLOADとSSTOREを利用するたびにBlockサイズの増加とminerがBlock Proofを作成するコストが増加します。そのため、この提案ではステートレスクライアントを実装する前準備としてこれらの増加するコストを支払うためにSSTOREとSLOADの価格の引き上げを提案しています。なお、具体的なcostをいくらにするのかについては提案の中では触れられていません。なのでこの提案はあくまで議論を進めるためのものとして提案されているようです。

まとめ

2回目の今回では、Ethereumのエコシステムに直接影響を与える、gasCostの変更に関する提案を解説しました。Ethereumはすでに4年ほどの稼働実績があり、gasCostを変更する提案に関してこれらの実績を元に、実際のデータを分析することで最適な価格が算出可能になっていることがわかりました。特に、2Mブロック付近で起きたDoS攻撃が、ある意味ちょうど良い指標となっているのも興味深いです。

また、ブロックチェーンの根本的な問題として、稼働年月に比例してデータサイズが増加してしまう問題が特にEthereumではディスクI/Oを伴う処理に対して顕著担っていることが、予想だけではなくデータとしてもはっきりと示されていることがわかりました。

次回は、State Rentに関する提案を中心にまとめていきたいと思います。