EOSIOによるスマートコントラクト開発環境の構築

# この文書は何？
- イーサリアムに取って代わると期待されているDApp基盤であるEOSIOプラットフォームについて簡単にまとめる
- プライベートのブロックチェーンネットワークを立ち上げ、簡単なスマートコントラクト(Hello World!的なもの)を実装する

※筆者は2週間前からブロックチェーンの勉強を始めた初心者なので色々と間違いがある可能性があります


# EOSIOとは
本家：https://eos.io/
Wikipedia：https://en.wikipedia.org/wiki/EOS.IO
参考になる記事：https://cryptobriefing.com/eos-ethereum-smart-contract-war-winner/

- EOSIOはブロックチェーン及びスマートコントラクトプラットフォームであり、イーサリアムと直接競合する
- EOSIOではC++で実装したマルチスレッド処理に加えてDelegated Proof of Stake (DPoS)による高速なトランザクション処理を実現
- イーサリアムではトランザクションをマイナーに処理してもらうには手数料(gas)が必要となるので、DAppを使いたい場合は事前に仮想通貨であるEtherを入手しないといけない
- 一方EOSIOでは、トランザクションを処理したブロック作成者のEOSトークンがインフレーションするため、DAppのユーザーは仮想通貨を所有する必要がない (この辺の仕組みはあまり理解できてない。。。とにかくユーザーの手数料は不要。)
- 以上の理由から、EOSIOはイーサリアムに取って代わりうるプラットフォームと期待されている
- イーサリアムと異なり、まだあまり普及していないため日本語の資料はほとんどない
- イーサリアムをベースにして開発されていた(?)ためかイーサリアムと仕組みが似ているところが多いので、イーサリアムでHello world!くらいやっておくとスムーズに理解できる。

# EOSIOの主要コンポーネント
- `nodeos` (node + eos = nodeos) 
    - コアとなるノードデーモン。ブロック生成やAPIエンドポイントの提供。
- `cleos` (cli + eos = cleos) 
    - ウォレットとブロックチェーンを扱うためのコマンドラインツール
- `keosd` (key + eos = keosd) 
    - EOSIOのウォレットを管理する仕組み
- `eosio-cpp`
    - C++のコードからWeb Assemblyファイル(wast)とアプリケーションバイナリインターフェイス(ABI)を生成するコンパイラ

# 開発環境の構築
以下、基本的には公式ドキュメントに沿っていく ( https://developers.eos.io/eosio-home/docs/introduction )
## 1.1 Introduction
C++を使う。IDE使うなら用意する。
Windowsで開発はできない。  

## 1.2 Before You Begin
プレビルドしたバイナリはまだない。
ソースからEOSIOをビルドするのはつらいので、必要なものを入れたDockerイメージがある。
バイナリが準備できるまでDockerイメージを使う。
ローカルに作業用ディレクトリを作る。

```
mkdir <ローカルの作業用ディレクトリの絶対パス>
cd <ローカルの作業用ディレクトリの絶対パス>
```

## 1.3 Your Development Environment
Dockerをインストールしてなければインストールする。
まずはEOSIOのDockerイメージを持ってくる。

```
$ docker pull eosio/eos
```
コンテナを作成。

```
docker run --name eosio \
  --publish 7777:7777 \
  --publish 127.0.0.1:5555:5555 \
  --volume <ローカルの作業用ディレクトリの絶対パス>:<コンテナで作業用ディレクトリにするパス> \
  --detach \
  eosio/eos \
  /bin/bash -c \
  "keosd --http-server-address=0.0.0.0:5555 & exec nodeos -e -p eosio --plugin eosio::producer_plugin --plugin eosio::history_plugin --plugin eosio::chain_api_plugin --plugin eosio::history_plugin --plugin eosio::history_api_plugin --plugin eosio::http_plugin -d /mnt/dev/data --config-dir /mnt/dev/config --http-server-address=0.0.0.0:7777 --access-control-allow-origin=* --contracts-console --http-validate-host=false --filter-on='*'"
```
ブロック生成を確認。

```
$ docker logs --tail 10 eosio
2018-09-29T02:14:46.502 thread-0   producer_plugin.cpp:1419      produce_block        ] Produced block 00004c9052d9f062... #19600 @ 2018-09-29T02:14:46.500 signed by eosio [trxs: 0, lib: 19599, confirmed: 0]
2018-09-29T02:14:47.001 thread-0   producer_plugin.cpp:1419      produce_block        ] Produced block 00004c918d50b2b0... #19601 @ 2018-09-29T02:14:47.000 signed by eosio [trxs: 0, lib: 19600, confirmed: 0]
2018-09-29T02:14:47.503 thread-0   producer_plugin.cpp:1419      produce_block        ] Produced block 00004c92efc6073d... #19602 @ 2018-09-29T02:14:47.500 signed by eosio [trxs: 0, lib: 19601, confirmed: 0]
2018-09-29T02:14:48.004 thread-0   producer_plugin.cpp:1419      produce_block        ] Produced block 00004c93e2bdb939... #19603 @ 2018-09-29T02:14:48.000 signed by eosio [trxs: 0, lib: 19602, confirmed: 0]
2018-09-29T02:14:48.501 thread-0   producer_plugin.cpp:1419      produce_block        ] Produced block 00004c940696ac0c... #19604 @ 2018-09-29T02:14:48.500 signed by eosio [trxs: 0, lib: 19603, confirmed: 0]
2018-09-29T02:14:49.003 thread-0   producer_plugin.cpp:1419      produce_block        ] Produced block 00004c952e9582b9... #19605 @ 2018-09-29T02:14:49.000 signed by eosio [trxs: 0, lib: 19604, confirmed: 0]
2018-09-29T02:14:49.503 thread-0   producer_plugin.cpp:1419      produce_block        ] Produced block 00004c96cc7d5521... #19606 @ 2018-09-29T02:14:49.500 signed by eosio [trxs: 0, lib: 19605, confirmed: 0]
2018-09-29T02:14:50.003 thread-0   producer_plugin.cpp:1419      produce_block        ] Produced block 00004c97a9f60e81... #19607 @ 2018-09-29T02:14:50.000 signed by eosio [trxs: 0, lib: 19606, confirmed: 0]
2018-09-29T02:14:50.500 thread-0   producer_plugin.cpp:1419      produce_block        ] Produced block 00004c98e7f46321... #19608 @ 2018-09-29T02:14:50.500 signed by eosio [trxs: 0, lib: 19607, confirmed: 0]
2018-09-29T02:14:51.000 thread-0   producer_plugin.cpp:1419      produce_block        ] Produced block 00004c99eb03e07e... #19609 @ 2018-09-29T02:14:51.000 signed by eosio [trxs: 0, lib: 19608, confirmed: 0]
```
コンテナに入ってシェルを起動する。

```
docker exec -it eosio bash
```
ウォレットの確認を行う。

```
$cleos --wallet-url http://127.0.0.1:5555 wallet list keys
Wallets:
[]
Error 3120006: No available wallet
Ensure that you have created a wallet and have it open
```
まだウオレットを作成していないのでエラーになるが、これで主要コンポーネントである`keosd`の動作が確認された。
コンテナからはexitで出る。

```
exit
```

chain_api_pluginの動作確認をする。ブラウザで`http://localhost:7777/v1/chain/get_info`にアクセスすると以下のようなjson形式のレスポンスがあるはず。これで`nodeos`の動作確認が完了。

```
{"server_version":"0f6695cb","chain_id":"cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f","head_block_num":21158,"last_irreversible_block_num":21157,"last_irreversible_block_id":"000052a50e14738504a3299b28368232759e31e2ff3afdae0a08954268c312f2","head_block_id":"000052a671160e0fbe1c621dd92715c5a18de0cf92072345643bdffc5529eed5","head_block_time":"2018-09-29T02:27:45.500","head_block_producer":"eosio","virtual_block_cpu_limit":200000000,"virtual_block_net_limit":1048576000,"block_cpu_limit":199900,"block_net_limit":1048576,"server_version_string":"v1.3.0"}
```

いちいちコンテナに入って`cleos`を実行するのは面倒なので、以下のaliasを作っておく。これでローカルから`cleos`コマンドを叩くことができる。

```
alias cleos='docker exec -it eosio /opt/eosio/bin/cleos --url http://127.0.0.1:7777 --wallet-url http://127.0.0.1:5555'
```
## 1.4 Tools You'll Be Using
`nodeos`、`cleos`、`kesod`、`eosio-cpp`の説明。

## 1.5 Build the Contract Development Toolkit
EOSIOのContract Development Toolkit(CDT)をビルド・インストールする。
まずは`git clone`

```
git clone --recursive https://github.com/eosio/eosio.cdt
cd eosio.cdt
```
あとは

```
./build.sh SYS
sudo ./install.sh
```
とするだけだが、かなり時間がかかる。

## 1.6 Create Development Wallet
### ウォレット作成

```
cleos wallet create -n <ウォレット名、今回はdefaultにする> --to-console
```
これをやると

```
Creating wallet: default
Save password to use in the future to unlock this wallet.
Without password imported keys will not be retrievable.
"PW5JSjHEBjguXCv.....................jSH4NVvNh6k"
```
みたいな表示がされる。`default`という名前でウォレットが作成され、パスワードが表示される。
パスワードはウォレットをunlockするために使われる。これを無くすと取り戻す手段はない。
これはどこかに保存しておく。

なお今回は`--to-console`というオプションをつけてパスワードがコンソール出力されるようにしたが、通常は`cleos wallet create -n <ウォレット名> -f <ファイル名>`としてパスワードがファイルに出力されるようにする。なおこのファイルのパスはコンテナのものになることに注意。

### ウォレットのopen
ウォレットはopenしなければ使えない。

```
cleos wallet open -n <ウォレット名>
```
これにはパスワードは不要。ウォレットのリストを確認する。

```
$ cleos wallet list
Wallets:
[
  "default"
]
```

### ウォレットのunlock
次にウォレットをunlockする。ウォレットはopenかつunlockでないと利用できない。
openとunlockは違う概念を指している。`kesod`が動いている限り一度openにすればずっとopenだが、unlockは一度unlockしても5分経つと自動で解消されるという違いがある。

```
cleos wallet unlock -n <ウォレット名>
```
unlockされたウォレットは以下のようにアスタリスクがつく。

```
$ cleos wallet list
Wallets:
[
  "default"
]
```

### 鍵の作成
鍵を作成する。

```
cleos wallet create_key
```
ちなみにこのときunlockされたままだと

```
$ cleos wallet create_key
Error 3120003: Locked wallet
Ensure that your wallet is unlocked before using it!
```
というエラーが出る。
うまくいくと

```
Created new private key with a public key of: "EOS5............MB8"
```
と出る。これを保管しておく。

### ウォレットに開発用キーをimportする
全ての新しく作ったEOSIOのブロックチェーンはデフォルトで"eosio"ユーザーが登録されている。これはsudo権限を持ったrootユーザーのようなものである。開発時はこのアカウントを使えると便利なので、このアカウント用の鍵を登録する。

```
cleos wallet import
```
として今回は以下の秘密鍵を登録する。

```
5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3
```
これは絶対にプロダクション環境で登録してはいけない。eosioアカウントへ誰でもアクセスできるようになってしまう。

本番は

```
cleos create key --to-console
```
とすると以下のような公開鍵と秘密鍵のペアができるので、これを使えば良い。

```
Private key: 5K2KNqJ4Eg7Xs1kSSfnNwwvXQsuv7rzFENa45rwtEu9rD716NYd
Public key: EOS6c5GjoRQuq4cGLsrSmc8ZvbnaVPr3zC4ZXyvqfHgREAS65RBUe
```

## 1.7 Create Test Accounts
アカウントはブロックチェーン上で送金者、受領者を特定するものである。今回は`alice`と`bob`というアカウントを作成する。

```
cleos create account eosio alice YOUR_PUBLIC_KEY
cleos create account eosio bob YOUR_PUBLIC_KEY 
```
YOUR_PUBLIC_KEYにはさっき作った公開鍵を登録する。

```
executed transaction: de68efb695ac60860aa6e94cd0ea7f29bd255d5367abb1fca8684f507075c420  200 bytes  325 us
#         eosio <= eosio::newaccount            {"creator":"eosio","name":"alice","owner":{"threshold":1,"keys":[{"key":"EOS5CoPFe5cTUYsbQpN4z2UnMng...
warning: transaction executed locally, but may not be confirmed by the network yet    ]
```
と出たあとアカウントが作成される。
アカウント一覧は

```
cleos get accounts YOUR_PUBLIC_KEY
```
で見ることができる。

ちなみに

```
cleos create account eosio alice <OWNER KEY> <ACTIVE KEY>
```
として公開鍵を２つ登録することもできる。パーミッションのレベルにはデフォルトでは`OWNER`と`ACTIVE`がある。普段使うときは`ACTIVE KEY`の方で、`OWNER KEY`の方はコールドウォレットで保管しておくと、万が一`ACTIVE KEY`が漏洩しても`OWNER KEY`を使えばそのアカウントを掌握できるため、本番では２つの鍵を登録すべきらしい。詳しくは以下のリンク参照。
https://developers.eos.io/eosio-nodeos/docs/accounts-and-permissions

ようやく開発環境が整った。次はHello World!的なスマートコントラクトを実装する。

EOSIOでスマートコントラクトを実装してみる
https://qiita.com/YukiSekiguchi/items/f84afbf35f4fa039859c