自分を攻略していく記録

自分がやりたいことを達成するには何をすればいいのか、その攻略していく過程をつらつらと

EOS上でスマートコントラクトを作成・実行してみる

EOSとは

f:id:ngo275:20180330234850p:plain

EOSBitsharesSteemitを作ったDaniel Larimer氏が新しく作っている、スマートコントラクトを実行できるパブリックなブロックチェーンである。2018年3月時点ではメインネットはリリースされておらず、テストネットでのみスマートコントラクトは実行可能。スマートコントラクトを実行できるプラットフォームという点ではEthereumと同じだが、そのコンセンサスアルゴリズム(EOSはdPoSと言われる)や実装に利用できる言語も C/C++だったりとEthereumのそれとは異なる(後述)。EOSについて調べていても、まず日本語の情報は皆無で、英語でもGitHubがほとんどの情報源でスマートコントラクトを実行してみるという実験も大変だったので書くことにした。ここではdPoS等のEOSの特徴には触れずに、EOS上でスマートコントラクトを実行するところにフォーカスする。この情報もすぐ廃れてしまうと思うが...。

EOSをインストール・ビルドする

f:id:ngo275:20180327232045p:plain

2018年3月時点でのREADME。かなり危険な臭がする。が、とりあえずmasterをビルドしていくことにする。

$ git clone https://github.com/EOSIO/eos.git --recursive
$ cd eos
$ ./eosio_build.sh
$ sudo make install

これで eos/build/programs の中にあるコマンドが実行できるようになる。 ./eosio_build.sh の実行にはマシンのスペックによっては数時間かかるので注意が必要。

EOSを動かしてアカウントを作成してみる

$ vim /path/to/eos/config.ini

##### config.ini #####

# Load the testnet genesis state, which creates some initial block producers with the default key
genesis-json = genesis.json
 # Enable production on a stale chain, since a single-node test chain is pretty much always stale
enable-stale-production = true
# Enable block production with the testnet producers
producer-name = inita
producer-name = initb
producer-name = initc
producer-name = initd
producer-name = inite
producer-name = initf
producer-name = initg
producer-name = inith
producer-name = initi
producer-name = initj
producer-name = initk
producer-name = initl
producer-name = initm
producer-name = initn
producer-name = inito
producer-name = initp
producer-name = initq
producer-name = initr
producer-name = inits
producer-name = initt
producer-name = initu
producer-name = eosio
# Load the block producer plugin, so you can produce blocks
plugin = eosio::producer_plugin
# Wallet plugin
plugin = eosio::wallet_api_plugin
# As well as API and HTTP plugins
plugin = eosio::chain_api_plugin
plugin = eosio::http_plugin

##### EOF #####

$ nodeos --config-dir /path/to/eos/

これでデーモンが起動するので、 cleos でEOSのコマンドを実行できるようになる。 cleos でEOSをいじってみる。

# ローカルにあるwalletの一覧を確認できる
$ cleos wallet list
# 名前を指定せずに以下のコマンドを実行するとdefaultという名前でwalletが生成される
$ cleos wallet create
# *がついていると、walletがアンロックされている状態を示す
$ cleos wallet list

# keyを作成する
$ cleos create key
Private key: 5K1daHdwBkN6LoCv8SmQipn9tu439k2U2txTWc7xLFmKUCo7TYb
Public key: EOS5reEGNsCNcG6JSFRPtRnaP62KX8BjYRy5CHJki9MQ9yMqGitgh

# 上で生成した鍵を先程作成したwalletにインポートする(人によってimportに続く文字列は変わるので注意)
$ cleos wallet import 5K1daHdwBkN6LoCv8SmQipn9tu439k2U2txTWc7xLFmKUCo7TYb
imported private key for: EOS5reEGNsCNcG6JSFRPtRnaP62KX8BjYRy5CHJki9MQ9yMqGitgh

# もう一つこのprivate keyもインポートする(これはこの値でコピペで良い)
$ cleos wallet import 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3
imported private key for: EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV

# cleos create account eosio アカウント名 PUBLIC_KEY_1 PUBLIC_KEY_2 でアカウント作成する
$ cleos create account eosio sample EOS5reEGNsCNcG6JSFRPtRnaP62KX8BjYRy5CHJki9MQ9yMqGitgh EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV

これでアカウントがブロックチェーンに刻まれる。余談だが、アカウント名は13文字未満、利用可能な文字列は .12345abcdefghijklmnopqrstuvwxyz のみで重複不可なため名前空間が非常に狭い。また、スマートコントラクトも1つのアカウントとして扱われるのでアカウント名はスマートコントラクト名になる。

以下、このアカウントを利用するのでデーモンを切らずに進めていく。一旦デーモンを止めると再び開くとwalletが空になる。困ったら rm /usr/local/var/lib/eosio/node_00/./default.wallet で削除してあげればリセットできる。

スマートコントラクトを書いていく(作成する)

EOSはWebAssenblyコンパイルしたものを動かすことができ、現状では C/C++/Rust で書いたコードがスマートコントラクトとして実行することができる。したがってEthereumのSolidityのように独自の言語で書く必要はない。.abiファイルと、.wastファイルをEOS上にブロードキャストしてスマートコントラクトのデプロイが完了する。

今回はC++で進めていくが、EOS側が簡単な雛形作成コマンドを準備してくれているので特に独自の実装はしない。

# EOSのインストールしたディレクトリとは関係なく好きな場所で以下のコマンドを実行して良い. スマートコントラクトの雛形が生成される.
$ eosiocpp -n hello-world
$ cd hello-world
$ ls
hello-world.abi hello-world.cpp hello-world.hpp

# .wastを生成する
$ eosiocpp -o hello-world.wast hello-world.cpp
$ ls
hello-world.abi     hello-world.cpp     hello-world.hpp     hello-world.wast

スマートコントラクトをデプロイ、実行する

ここではlocalのtestnetのデプロイしてみる。publicのtestnetで試してみようにもREADMEには The master branch is no longer compatible with the dawn-2.x public testnet. To run on the public testnet, please see DAWN-2018-02-14/eos/README.md とあり、少々手間なのでここではlocalのみにフォーカスする。上の手順で、nodeosを動かしたままaccountを作成したあとに、以下の手順を実行する。

# スマートコントラクトをデプロイする
# cleos set contract アカウント名(=コントラクト名) hoge.wast hoge.abi
$ cleos set contract sample /path/to/hello-world/hello.wast /path/to/hello-world/hello.abi

# hello-worldで定義してあるtransferを実行する. parameterはfrom/to/amount.
$ cleos push action sample transfer '{"from":"currency","to":"eosio","amount":"1"}' --permission sample@active

f:id:ngo275:20180330231018p:plain

雑感

開発は盛んでPRも比較的すぐマージされる印象を受けた(issueはめちゃくちゃ多いけど)。しかしながら、Ethereumに比べると圧倒的にドキュメントが少ないし、masterが激しく変化するので不安定すぎる。コマンドがVersion2から大きく変更していることにも注意が必要そうだ。はじめEOSを入れたときはドキュメント通りに動かしても、エラーばかりだったが数日後にリトライしたらREADMEが大幅に変わっていてエラーの数が減った(が、それでも間違っていたのでそっとPRを出しておいた)。

f:id:ngo275:20180327234936p:plain

EOSはロードマップ上では今年の7月頃にメインネットが始動するとのことだが、今後の動向に注目しておきたい。