Ethereum
SmartContract
LLL
EthereumDay 15

LLLで環境構築から初期化コードをコンパイルするまで

More than 1 year has passed since last update.

この記事はEthereum Advent Calendar 2017の15日目の記事です。

Qiitaで記事を書くのは初めてなので、拙い部分が多いと思われますが誰かの役に立てれば幸いです。
今回はSolidityの代わりにLLLでコントラクタをコンパイルするところまでやってみます。

参考:https://media.consensys.net/the-structure-of-an-lll-contract-5adfd322be2

LLLでスマートコントラクタを書く理由

Ethereumのコントラクトは、EVM(Ethereum Virtual Machine)という仮想環境上で実行されます。SolidityやLLLで書かれたコードはバイトコードにコンパイルされてからEVMにデプロイして、初めて実行できるようになるわけですが、Ethereumにはトランザクションにgasを支払う必要があります。デプロイもトランザクションの一種なので当然gasを支払う必要が出てきます。

このgasというのは言ってしまえば手数料となりますが、当然トランザクションデータ長、デプロイする場合はバイトコード長が短い方が安く済みます。

Solidityは書きやすい反面、レイヤーが高く抽象化されています。そのためバイトコードは意図してるよりも長くなりがちです。
一方でLLLは手間がかかる一方で、アセンブラコードが容易に想像できる構造をしているので、出力されるバイトコードの長さもある程度想像できるものになります。

LLLはそういった点で優れており、またEVMやコントラクトの理解につながると思います。

環境設定

環境

Mac OS X High sierra 10.13.1

LLLコンパイラのビルドとインストール

LLLのコンパイラ(lllc)のインストールを行なっていきます
まず作業用のディレクトリにgit cloneしましょう
$ git clone --recursive https://github.com/ethereum/solidity.git
solidityディレクトリに移動します。
$ cd solidity

ビルドようのディレクトリを作成します。
$ mkdir build & cd build

solidityフォルダを指定してcmakeを実行します。
$ cmake ..

インストール
$ make install

$lllc --version
LLLC, the Lovely Little Language Compiler
Version: 0.4.20-develop.2017.12.4+commit.4cad0b22.Darwin.appleclang

と表示されればインストール完了です。
次からは実際にLLLでコントラクトを書いていきます。

LLLで何もしないコントラクタを書いてみる

とりあえず、何もしない、支払いを受け付けないコードを見ていきましょう。
solidityではpayableは関数の有無で自動で判別されているので、当然バイトコード化した時にもコストを払っていることになっていますが、LLLでは判別から書いていくことでコスト削減につながります。

とりあえず、コードを見ていきましょう。

(seq
  (when (callvalue) (panic))
  (codecopy 0x00 (bytecodesize) 32))
  (sstore 0x00 (mload 0x00)))

seqは中括弧{}に相当するもので、これでスコープを指定します。

(when (callvalue) (panic)) の行を見ていきます。
(when PRED BODY)はPREDの値が0以外の時にBODYを実行することになっています。
callvalueはcall時の引数なので何か引数があったらpanicで実行を終了します。

続いてメモリ上にコントラクタを読み込んでいきましょう。
codecopyではコントラクタの場所と長さを指定することでメモリ上にコピーされます。
sstoreはメモリからストレージ上にコピーするためのものでコントラクタが永続的に機能するためのものです。mloadでメモリからコピーしてからsstore最後でEVMのメモリ上にコピーされました。

コンパイル

lllc your_file_name.lll --hex
3415600657fe5b60206014600039600051600055

これでメモリ上に支払い不可の何もしないコントラクタがコンパイルされてバイトコードが出力されました。
ABIは何もしていないコードなので空のままです。

おわりに

ここから先に実際にコントラクタ部分を書いていく場合、情報が少ないのでLLLのリファレンスとgithubのコードを追いかけながら書いていくことがメインとなるでしょう。

またgithub上にlll-stdlibを公開してくれている方がいるので、リファレンスと併用しながら書いていくといいと思います。

https://github.com/zigguratt/lll-stdlib

LLLのLispライクな見た目とは異なってアセンブラ単位でコードを書いていくので学習コストが思ったより高かったのですが、変更点のあまりないような細々したコントラクタをいくつか作らないといけない時にはsolidityよりもLLLの方が適しているとも感じました。
触ってみるとEVMの挙動が少しづつ理解できるので、実用レベルに到達しないまでも実際に使ってみるのも悪くないと感じました。