Help us understand the problem. What is going on with this article?

EOSをDockerで動かしてトークンで遊んでみる

一年以上前にEOSを試した時に簡単にコントラクトの実行についてメモしたがガラリと変わっているのでEOSのノードをDockerで動かしつつトークンをデプロイするところまでサクッと見ていく。

EOSの公式ドキュメントを参照するとMacOSやUbuntu、CentOSなどいくつかのOSにおけるインストール方法が出てくるが、Dockerを使った方がPCも汚れないし簡単に試すことができるので、Dockerを使ったEOSの立ち上げ方について説明する。Dockerを使っているのはあくまでノードの部分(nodeos)のみ。

*ここではeosstudioが公開しているDockerイメージを利用する。執筆時点での最新Verが1.8.3なのでそれを利用しているが、その時の最新版で書き換えて良い。

EOSのノードのセットアップ

# dockerイメージを落とす
$ docker pull eostudio/eos:v1.8.3
v1.8.3: Pulling from eostudio/eos
5b7339215d1d: Already exists
14ca88e9f672: Already exists
a31c3b1caad4: Already exists
b054a26005b7: Already exists
a677768c3204: Pull complete
a743177c79c8: Pull complete
4dd68c5b6b2c: Pull complete
2a9ecc7eee10: Pull complete
Digest: sha256:725154d672654d09c86dcde6b4d2cbbec48c944b31ad4e765ec0903d63db2533
Status: Downloaded newer image for eostudio/eos:v1.8.3
docker.io/eostudio/eos:v1.8.3

# portは8888を解放。スマートコントラクトを配置するディレクトリは/path/to/contractsとしている。任意で良い。
$ docker run --name nodeos -dit -p 8888:8888 -v /path/to/contracts:/contracts eostudio/eos:v1.8.3
2b62951d170dacfc7d6e106bbfdd68cff419641b6a47ce63d6cf563b648a60b13

# dockerコンテナが動いてるのが確認できる。
$ docker ps -a
CONTAINER ID        IMAGE                 COMMAND             CREATED             STATUS              PORTS                    NAMES
2b62951d170d        eostudio/eos:v1.8.3   "/bin/bash"         20 seconds ago      Up 19 seconds       0.0.0.0:8888->8888/tcp   nodeos

# コンテナの中に入る。
$ docker exec -it nodeos bash
root@2b62951d170d:/#

# コンテナ内でnodeosのコマンドを実行する。
root@2b62951d170d:/# nodeos -e -p eosio --plugin eosio::producer_plugin --plugin eosio::history_plugin --plugin eosio::chain_api_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:8888 --access-control-allow-origin=* --contracts-console --http-validate-host=false --max-transaction-time=1000

以下の画像のようにnodeosが動き出す。

image.png

EOSのブロック情報が以下のように取得できれば成功。

$ curl http://localhost:8888/v1/chain/get_info
{"server_version":"7116e887","chain_id":"cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f","head_block_num":289,"last_irreversible_block_num":288,"last_irreversible_block_id":"0000012068f42c0c021775b7ea90535f3a5a0458d0e7ce345fc11b18ca6727b3","head_block_id":"0000012134461c28c52f92aff0dc20370d4bc5d21ddc9869538a6617267e5fca","head_block_time":"2019-09-20T08:54:33.000","head_block_producer":"eosio","virtual_block_cpu_limit":266624,"virtual_block_net_limit":1398582,"block_cpu_limit":199900,"block_net_limit":1048576,"server_version_string":"v1.8.3","fork_db_head_block_num":289,"fork_db_head_block_id":"0000012134461c28c52f92aff0dc20370d4bc5d21ddc9869538a6617267e5fca"}

EOSのコマンドラインのセットアップ

公式ページに詳しいインストール方法が書いてある。このツールはコントラクトのコンパイル等で利用される。

MacOSだとこんな感じ。

$ brew tap eosio/eosio.cdt
$ brew install eosio.cdt

Ubuntuだとこんな感じ。

$ wget https://github.com/EOSIO/eosio.cdt/releases/download/v1.6.1/eosio.cdt_1.6.1-1_amd64.deb
$ sudo apt install ./eosio.cdt_1.6.1-1_amd64.deb

Walletのセットアップ

# コンテナの中に入った状態で始める。
root@2b62951d170d:/# cleos wallet create --to-console
Creating wallet: default
Save password to use in the future to unlock this wallet.
Without password imported keys will not be retrievable.
"PW5J1GMa6QzUGVAHeiJcBv6ct7nkmAj312xGaYUg7auybF2NvTwcp"

root@2b62951d170d:/# cleos wallet open
Opened: default

root@2b62951d170d:/# cleos wallet list
Wallets:
[
  "default"
]

# 上で発行したパスワード(PW5J1GMa6QzUGVAHeiJcBv6ct7nkmAj312xGaYUg7auybF2NvTwcp)を入力
root@2b62951d170d:/# cleos wallet unlock
password: Unlocked: default

# *印がunlock状態を意味する。
root@2b62951d170d:/# cleos wallet list
Wallets:
[
  "default *"
]

# 新しいキーペアを作成。
root@2b62951d170d:/# cleos wallet create_key
Created new private key with a public key of: "EOS7vURhtJepaqsRSAJVSpPA9bv7U3uyv8RotpRwxLvqL7s2JDnPW"

# eosioの秘密鍵(5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3)を入力する。
root@2b62951d170d:/# cleos wallet import
private key: imported private key for: EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV

# create_keyで作成したキーペアを元にbobというアカウントを作成する。
root@2b62951d170d:/# cleos create account eosio bob EOS7vURhtJepaqsRSAJVSpPA9bv7U3uyv8RotpRwxLvqL7s2JDnPW
executed transaction: d145f646aad4f50baa2c94a1ccabe996e8901d564dd5b66cff5339ca95d67103  200 bytes  231 us
#         eosio <= eosio::newaccount            {"creator":"eosio","name":"bob","owner":{"threshold":1,"keys":[{"key":"EOS7vURhtJepaqsRSAJVSpPA9bv7U...
warning: transaction executed locally, but may not be confirmed by the network yet         ]

# create_keyで作成したキーペアを元にaliceというアカウントを作成する。
root@2b62951d170d:/# cleos create account eosio alice EOS7vURhtJepaqsRSAJVSpPA9bv7U3uyv8RotpRwxLvqL7s2JDnPW
executed transaction: 710cfb8ca86df0e0aebb349378141d1f46c81333d1f228a5329f71fe01641306  200 bytes  219 us
#         eosio <= eosio::newaccount            {"creator":"eosio","name":"alice","owner":{"threshold":1,"keys":[{"key":"EOS7vURhtJepaqsRSAJVSpPA9bv...
warning: transaction executed locally, but may not be confirmed by the network yet         ]

# aliceのaccount情報はこんな感じ。
root@2b62951d170d:/# cleos get account alice
created: 2019-09-20T10:53:06.000
permissions:
     owner     1:    1 EOS7vURhtJepaqsRSAJVSpPA9bv7U3uyv8RotpRwxLvqL7s2JDnPW
        active     1:    1 EOS7vURhtJepaqsRSAJVSpPA9bv7U3uyv8RotpRwxLvqL7s2JDnPW
memory:
     quota:       unlimited  used:      2.66 KiB

net bandwidth:
     used:               unlimited
     available:          unlimited
     limit:              unlimited

cpu bandwidth:
     used:               unlimited
     available:          unlimited
     limit:              unlimited

スマートコントラクトを試す

# /path/to/contractsの階層でhelloディレクトリを作る。
$ mkdir hello
$ cd hello
$ vim hello.cpp

hello.cppを以下のように編集する。実行すると、 Hello, 名前が返ってくるだけのいたってシンプルなEOSスマートコントラクトである。

#include <eosio/eosio.hpp>

using namespace eosio;

class [[eosio::contract]] hello : public contract {
  public:
      using contract::contract;

      [[eosio::action]]
      void hi( name user ) {
         print( "Hello, ", user);
      }
};

このhello.cppをコンパイルする。eosio-cppは先ほどインストールしたeosio.cdtに含まれている。

$ eosio-cpp hello.cpp -o hello.wasm

再びdockerコンテナに戻る。もしwalletがロックされていたら、cleos wallet unlockで最初に発行されたパスワード(本稿ではPW5J1GMa6QzUGVAHeiJcBv6ct7nkmAj312xGaYUg7auybF2NvTwcp)を入力することで再びアンロックできる。

# コントラクト用にhelloというアカウントを作成する。
root@2b62951d170d:/# cleos create account eosio hello EOS7vURhtJepaqsRSAJVSpPA9bv7U3uyv8RotpRwxLvqL7s2JDnPW -p eosio@active
executed transaction: 93f33e70d3108b723bcdcf850e3f12e9f5944f230cadbeee8804d6a397086a1b  200 bytes  244 us
#         eosio <= eosio::newaccount            {"creator":"eosio","name":"hello","owner":{"threshold":1,"keys":[{"key":"EOS7vURhtJepaqsRSAJVSpPA9bv...

# helloアカウントにコントラクトをセットする。
root@2b62951d170d:/# cleos set contract hello contracts/hello -p hello@active
Reading WASM from /contracts/hello/hello.wasm...
Publishing contract...
executed transaction: 07acebc8a0492277db4581eddf7cd09b53cff6725e47a16624a18825488372ac  688 bytes  422 us
#         eosio <= eosio::setcode               {"account":"hello","vmtype":0,"vmversion":0,"code":"0061736d0100000001370b6000017f60027f7f0060037f7f...
#         eosio <= eosio::setabi                {"account":"hello","abi":"0e656f73696f3a3a6162692f312e31000102686900010475736572046e616d650100000000...

# bobアカウントから、コントラクトのメソッドhelloを実行してみる。
root@2b62951d170d:/# cleos push action hello hi '["bob"]' -p bob@active
executed transaction: f8df222edc812552dfaf6f4e72d39c9ed3300cb5ea72bec3988b077e346fa525  104 bytes  460 us
#         hello <= hello::hi                    {"user":"bob"}
>> Hello, bob

# aliceアカウントから、コントラクトのメソッドhelloを実行してみる。
root@2b62951d170d:/# cleos push action hello hi '["bob"]' -p alice@active
executed transaction: fb6ee5f4d6ddcea43ab825867213f743da0637a39946e7e9e82cf9f7072dd872  104 bytes  432 us
#         hello <= hello::hi                    {"user":"bob"}
>> Hello, bob

helloアクションが正常に実行されたのが確認できた。

トークンをデプロイして送金してみる

helloが表示されるだけでは面白くないので、次は、公式で出ているサンプルトークンを試してみる。

# 最初のディレクトリに戻る。
$ cd /path/to/contracts
# cloneする。
$ git clone https://github.com/EOSIO/eosio.contracts --branch v1.7.0 --single-branch
# eosio.tokenディレクトリへ(eosio.tokenとはEthereumでいうところのERC20トークン)。
$ cd eosio.contracts/contracts/eosio.token
# コンパイルする。
$ eosio-cpp -I include -o eosio.token.wasm src/eosio.token.cpp --abigen

再びdockerコンテナに戻る。

# eosのアカウントからトークン用(eosio.token)のアカウントを作成する。
root@2b62951d170d:/# cleos create account eosio eosio.token EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
executed transaction: 0dd3ce0bb9f9cd47869c0d123dc99c205ff318698b2cd4db58a0e80ba7dd1950  200 bytes  183 us
#         eosio <= eosio::newaccount            {"creator":"eosio","name":"eosio.token","owner":{"threshold":1,"keys":[{"key":"EOS6MRyAjQq8ud7hVNYcf...

# eos.tokenアカウントにデプロイする。
root@2b62951d170d:/# cleos set contract eosio.token contracts/eosio.contracts/contracts/eosio.token --abi eosio.token.abi -p eosio.token@active
Reading WASM from /contracts/eosio.contracts/contracts/eosio.token/eosio.token.wasm...
Publishing contract...
executed transaction: 32f940123f30c131f17d828a6e018ac3278725e1a3601e323e05aed8dee55764  6984 bytes  1198 us
#         eosio <= eosio::setcode               {"account":"eosio.token","vmtype":0,"vmversion":0,"code":"0061736d0100000001a0011b60000060017e006002...
#         eosio <= eosio::setabi                {"account":"eosio.token","abi":"0e656f73696f3a3a6162692f312e310008076163636f756e7400010762616c616e63...

# eosio.tokenのcreateアクションを実行する。aliceは 1000000000 SYS分の発行権を獲得する。'SYS'という決まりはなく'JPY'でも問題ない。
root@2b62951d170d:/# cleos push action eosio.token create '[ "alice", "1000000000.0000 SYS"]' -p eosio.token@active
executed transaction: 8c2fdcf0d38ce0220a324a1f92beb92ea416503316f0ccded26f7ad564a07553  120 bytes  1210 us
#   eosio.token <= eosio.token::create          {"issuer":"alice","maximum_supply":"1000000000.0000 SYS"}

# aliceは自分に対して 100 SYS 発行する。createアクションの時点ではaliceの残高は0のまま。
root@2b62951d170d:/# cleos push action eosio.token issue '[ "alice", "100.0000 SYS", "memo" ]' -p alice@active
executed transaction: c2e2717923df4bb07fe2b42e286a2a513342634380684e65a6f89a4684d19c71  128 bytes  2333 us
#   eosio.token <= eosio.token::issue           {"to":"alice","quantity":"100.0000 SYS","memo":"memo"}

# aliceは所有している 100 SYS のうち、 25 SYS をbobに送金する。
root@2b62951d170d:/# cleos push action eosio.token transfer '[ "alice", "bob", "25.0000 SYS", "m" ]' -p alice@active
executed transaction: d5d5c59ad6612aba2ddf52a9ef0b170d1bc8cf32f4e02caeb917f9081dd611b2  128 bytes  2751 us
#   eosio.token <= eosio.token::transfer        {"from":"alice","to":"bob","quantity":"25.0000 SYS","memo":"m"}
#         alice <= eosio.token::transfer        {"from":"alice","to":"bob","quantity":"25.0000 SYS","memo":"m"}
#           bob <= eosio.token::transfer        {"from":"alice","to":"bob","quantity":"25.0000 SYS","memo":"m"}

# bobの所持金を確認すると、 25 SYS になっている。
root@2b62951d170d:/# cleos get currency balance eosio.token bob SYS
25.0000 SYS

# aliceの所持金を確認すると、 75 SYS になっている。
root@2b62951d170d:/# cleos get currency balance eosio.token alice SYS
75.0000 SYS

これでEOSで標準のトークンを発行して送金してみるところまで確認できた。

dockerを閉じる時は、以下のようにすれば良い。

$ docker stop nodeos
$ docker rm nodeos

所感

  • 2018年の2月頭にEOSを初めて触った時は、READMEも嘘ばっかりで地獄の様相を呈していたが、今はドキュメントもかなりまともになっていた。
  • account名やaction名、eosio.tokenのシンボル名等の命名規則が厳しい。
  • EOSはDPoSを採用しており、「DPoSは中央集権的なのでは」という議論もあるが、TPSを考慮しても現時点では現実的な技術なのではないかという感想。

参照

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away