Rust
Blockchain
EOS
SmartContract
wasm

Rust でEOSにコントラクトをデプロイ して両方に入門


EOSの概略

EOSは2018年12月現在で最速tps(test:9179tps main:3990tps)を持つスマートコントラクトのプラットフォームである。

名前はEnterprise OSの略だと言われており、契約の実行や透明な企業クラウドを

・コントラクト(AWS lambdaみたいなもの)

・Multi-index table(AWS Dynamoみたいなもの)

の組み合わせで実現する。

エコノミースケールはEthereumに及ばずも、アクティブユーザー数は圧倒的に多い。

https://www.stateofthedapps.com/

コントラクトはWebassembly(WASM)がフォーマットとして指定されているので、これにコンパイル可能な言語は理論上すべて使用可能となるが、おそらく安全性の観点から公式のホワイトペーパーではC++とRust、ポータルではC++が対象とされている。金銭を扱うため、脆弱性に後手対応は許されない事情があるが、多くのプロジェクトが脆弱性を露見させ資産を失っている現状が存在する。


Rustの紹介

Mozillaが開発した言語で、Better C++として期待されている。高速で安全と言われている。言語としてあまり簡単ではないが、脆弱なコードはコンパイラが許さず、高速化と軽量化は言語処理の側でされるため、ある意味初心者にも優しい。

Cのライブラリを利用可能であるが、C++のライブラリは利用不可。WebAssemblyをサポート。

最新Version(Rust 2018)ではJSのような非同期処理もサポートし、並列処理・スレッドをデフォルトで使える低レイヤー言語になる。


Rustのインストール

$ curl https://sh.rustup.rs -sSf | sh

$ rustup target add wasm32-unknown-unknown --toolchain nightly

$ cargo install wasm-gc


Rustのプロジェクト作成

さっきのコマンドでCargoっていうコマンドが勝手に有効になったんですが、CargoはRustの簡略化コマンドだと思って下さい。

Rustには安定版のstable,真ん中くらいのbeta,そして”不安定版”のnightlyがあり、EOS関係(というよりWASM関係?)はnightlyばっかり使うのでよろしくお願いします。ビルドする際にnightlyをコマンドで指定します。



$ cargo +nightly new hello --lib

$ cd hello


Rust on EOS

いきなりですが、ここでEOSのブロックチェーンにデプロイできるHelloWorldコントラクトのWASMを、Rustからコンパイルして作ってみます。

Rustではライブラリにあたるものを「クレート」と呼びます。

EOSIOのRustクレートはもうすでにRust公式で存在しています。

https://docs.rs/eosio/0.2.0/eosio/

現在のversionは0.2.0ですので、これをCargo.tomlファイルのdependenciesで指定します。

Cargo.tomlを開き、下のように上書きをします。

[package]

name = "hello"
version = "0.1.0"
authors = []
edition = "2018"
[lib]
crate-type = ["cdylib"]
[dependencies]
eosio = "0.2"

見たままの内容の設定ファイルになっていますね。

こちらが肝心のコントラクトコード、

$ vi src/lib.rs

などでsrc/lib.rsを以下のように編集します

#![feature(proc_macro_hygiene)]

use eosio::*; //クレートの読み込み

#[eosio_action] // 下をEOSのコントラクト関数にする宣言
fn hi(name: AccountName) {
eosio_print!("Hello, ", name); // Helloと返すだけ
}
eosio_abi!(hi);

「fn」が関数の宣言で、「use」がクレートと以下のスコープの読み込みです。

「#」はattributeと呼ばれますが、コンパイラに指示を出すものなのでプリプロセッサのようなものだと考えると良いかと思います。

「!」がつくものはマクロなので、知らない関数の前に!がついていたら外部で定義されていると考えてよいでしょう。

ここにある「#![feature(」はnightlyの場合に使われる宣言です。たくさんあるので、興味ある方はこちらをどうぞ

https://qiita.com/8pockets/items/0b6bb582a1bfa995559e

ではBUIDLします!

$ cargo +nightly build --release --target=wasm32-unknown-unknown


①EOSのインストール

Dockerイメージがサポート中止になりそうなので、ローカル手動でお願いいたします。Ubuntsuの16以下のバージョンの方や、CentOSの方はこちらを参照下さい。

https://developers.eos.io/eosio-home/docs/setting-up-your-environment


MAC OS-X

EOSIO(ネットワーク参加用)インストール



$brew tap eosio/eosio

$brew install eosio



EOSIO-Contract Developer Toolkit(ローカルでコントラクト作成用)インストール



$ brew tap eosio/eosio.cdt

$ brew install eosio.cdt


Ubuntsu18.04

EOSIO(ネットワーク参加用)インストール



$ wget https://github.com/eosio/eos/releases/download/v1.5.0/eosio_1.5.0-1-ubuntu-18.04_amd64.deb

$ sudo apt install ./eosio_1.5.0-1-ubuntu-18.04_amd64.deb



EOSIO-Contract Developer Toolkit(ローカルでコントラクト作成用)インストール



$ wget https://github.com/eosio/eosio.cdt/releases/download/v1.3.2/eosio.cdt-1.3.2.x86_64.deb

$ sudo apt install ./eosio.cdt-1.3.2.x86_64.deb

他のOSについてや、エラーなどに関してはこちらを参照ください。

https://developers.eos.io/eosio-home/docs/setting-up-your-environment


②EOSの環境構築

KylinテストネットのアカウントをIrexで作り、(せっかくなのでMainネットも)

https://irex.io/ja

秘密鍵を保管します。

active,ownerどちらも保管しますが、以後使うのはactiveです

ウォレット作成

$ keosd &

$ cleos wallet create --to-console

パスワードは保管して下さい。

秘密鍵をインポートします。

$ cleos wallet import -n [12文字のアカウント名] --private-key "[EOSから始まる秘密鍵]"

次にcleos クライアントをKylinテストネット用にaliasしておきます。

alias cleos="cleos --url https://api-kylin.eosasia.one"


EOSテストネットにデプロイ

少し余計に感じますが、ブロックチェーンではおなじみのABIファイルを同じ階層に入れておかなくてはなりません。

$ wget https://github.com/sagan-software/rust-eos/blob/master/examples/hello/hello.abi.json

そして最初に作った1.4MBと大きいサイズになってしまうWASMを最適化で100byteまで減らします。

$ wasm-gc target/wasm32-unknown-unknown/release/hello.wasm hello_gc.wasm

ここでwasm-optをインストール

git clone https://github.com/WebAssembly/binaryen

cd binaryen

cmake . && make

でmakeした後に、WASMファイルの圧縮を行います。

$ wasm-opt hello_gc.wasm --output hello_gc_opt.wasm -Oz

ではDEPLOYします!

$ cleos set abi hello hello.abi.json

$ cleos set code hello /mnt/dev/project/hello_gc_opt.wasm

これでデプロイまで一式できることになりますが、

詰まった場合は以下を参照すると良いと思います。

クレートがあるレポジトリでEOSのCppモジュールの多くがRustに置き換わっていることも確認できます。

https://github.com/sagan-software/rust-eos