プロダクト開発日記(Astar) 2日目 [WASMスマートコントラクトを作成してデプロイする]
Web2のエンジニアであるsekaiがAstar上でプロダクトを開発するまでにどのように学習したか変遷を綴っている記事です。
*筆者はブロックチェーンの業界3ヶ月目、mastering bitcoinを3-4回読んでいるような状況です。
*もし間違いや意見がある場合はぜひ教えてください。 勉強になります。
*筆者のスペックですがweb2エンジニアを6-7年しており、RubyやNode.jsをよく使っています。
今回の記事は2日目の記事になります。
2日目
1日目に ローカルでAstar Networkを立ち上げるチュートリアルを見つけて行う。
を行いました。
そのため今日は Dappを作るためにはEVM、またはWASMがあると聞いたことがあるがそれぞれどのような特徴があり、今回はどちらを選ぶのか決定する
を行います。
ちなみに現在取り組んでいるリストはこちらです。
1日目 ローカルでAstar Networkを立ち上げるチュートリアルを見つけて行う。
2日目 Dappを作るためにはEVM、またはWASMがあると聞いたことがあるがそれぞれどのような特徴があり、今回はどちらを選ぶのか決定する
2日目 上記で決定したものを使って簡単なスマートコントラクを作成するチュートリアルを見つけて行う。
- スマートコントラクトをフロント側で呼び出してみる。(これはweb3.jsのようなものになるはずです。)
早速本題です。
EVMとWASMについて
Astarの話題を追っていると今後「WASM」の時代がくるといった話をよく聞きますが、web3に親しみのないsekaiにとって難しい話です。
WASMはWebAssemblyの略ですが、そもそもこの技術自体も新しくwebエンジニアの方で実際に触っている方は少ないのでしょうか。 今回sekaiが調べたことをまとめていきます。
スマートコントラクトとVMについて
まず最初にスマートコントラクトとVMの関係性を知ることが大切です。
なぜならEVMとWASMのどちらを選ぶかという問いは、スマートコントラクトをどこで実行するかという問いになるからです。
そのためスマートコントラクトとVMの言葉の定義をまとめます。
- スマートコントラクトとは行為Aをするときにどんなプログラムを走らせるのか事前に定義し、行為Aが行われるときにそのプログラムを走らせる仕組みのことです。
- VMは上記のプログラムを実行する環境のことです。
- スマートコントラクトの実行はブロックチェーンに参加している各ノードが実行でき、 結果が正しいか確認できます。各ノードは事前に配布されたVM上でスマートコントラクトを実行できます。
次に言葉の概念を抽象度を高めに理解していきます。
EVMとは
イーサリアム上でSolidityで書いたスマートコントラクトを実行できる環境です。
WASMとは
WebAssemblyのコードを実行できる環境です。
(*EVMの対立項として理解できるように、言葉をかなり無理やり変換しています。)
初めての言葉が出てきたので補足しておくと
WebAssembly = ブラウザ上で動くバイナリコードの新しいフォーマット(仕様)
WASM= バイナリフォーマットです。
になります。(参考: https://qiita.com/ShuntaShirai/items/3ac92412720789576f22 )
要するにWebAssemblyはブラウザでJavaScript以外の言語を実行するための技術で、Rustなどで書いたものをバイナリコードに変換して、ブラウザで実行できる技術です。
このバイナリコードはブラウザ以外でも実行できるみたいなので、 ブロックチェーン上でのWASMとは 各ノードでWebAssemblyのコードを実行できる環境のことを指すのだと抽象的に理解しています。
WASMのバイナリはRust, C/C++, C#, Typescript, Haxe, Kotlinなどで作成することができるため、 既存のweb2エンジニアにとっても参入障壁は少ないかもしれません。
EVMとWASMどちらを選ぶか
仕事で技術選定をするときは、枯れた技術を使うことがセオリーです。 枯れた技術は多くの人が長い期間使用しており、またドキュメントが多いため、習得難易度が低くなります。
EVMで使えるsolidityは2014年8月に提案され1年後にリリース、 WASMのWebAssemblyは2015年に開発が発表され2017年3月にリリースされています。
sekaiからするとsolidityの技術の方が枯れているように感じます。 (wasmでスマートコントラクトを作るドキュメントは少ないですが、Solidityの方が多い気がします。話が脱線しますが、Solidityを勉強するときは https://cryptozombies.io/ が分かりやすかったです。)
しかし、今回は仕事ではなく納期もないプロジェクトなので思想ベースで技術を選択します。 WASMであれば言語を一つに絞ることなく、複数の言語で書くことができるためAstarの思想とも合っていると思いました。(Astarの思想は色々なブロックチェーンと仲良くする+開発者サポートです。)
そのため今後はWASMベースでプロダクトを開発してきます。
おまけ:WebAssemblyに関連するドキュメント
WebAssemblyの特性をもっと理解するために、調べたことを翻訳ツールの力を駆使して書いていきます。
1. まずWebAssemblyでサポートされている言語達:
https://github.com/appcypher/awesome-wasm-langs
2. 以下は、Ink!で記述されている「どうしてスマートコントラクトを作成するのにWebAssemblyを使うのか」の抜粋です。
(https://paritytech.github.io/ink-docs/why-webassembly-for-smart-contracts/。*sekaiが噛み砕いて書いています。)
1.高性能。
2.サイズが小さい。
3.より多くの環境で実行できる。
4.中間コンパイラが効率的。
5.仕様が少なく分かりやすい
6.決定論的実行ができる。
7.Googleなど含む強い団体が開発してきました。
8.多くの言語でWASMを作成できる
9.実行時にPCの環境を汚染することがない。(sandbox環境)
10.LLVMという有名なコンパイラの最適化の恩恵を得られる
正直どのプロジェクトでも謳われそうな文句が入っていますが、 特に大切なのは3と7と8と9だとsekaiは思います。
他にも下記の記事がとても参考になりました。
- 「Web 以外でも期待される WebAssembly – Blockchain との親和性について」
https://engineering.linecorp.com/ja/blog/webassembly-expected-to-be-used-beyond-the-web/
- 「Why we believe in Wasm as the base layer of decentralized application development」
https://www.parity.io/blog/wasm-smart-contract-development/
WASMスマートコントラクトを作成してデプロイする
WASMに決めたので次に行うことは、WASMでスマートコントラクトを作ることです。
そしてスマートコントラクトを1日目に作成したローカルネットワークにデプロイすることです。
WASMのスマートコントラクトをデプロイするための記事を下記で見つけることができました。
https://docs.astar.network/build/smart-contracts/examples/wasm-implement-psp22-with-openbrush
試していきます。
…
試していたのですが、どうやら初見では厳しそうです。(環境構築がうまくいきませんでした。)
なのでとても簡単なWASMコントラクトをローカルネットワークにデプロイします。
今回はink!で作成したスマートコントラクトをデプロイします。
まずいくつか言葉の意味を知る必要があります。
Substrate=ブロックチェーン構築のためのフレームワーク
pallet=関数やメモリアイテムなどを定義しているライブラリのようなもの。
ink!=Substrateで作られたブロックチェーン上のコントラクトを書くためのツール。
と言葉の定義を書いても分かりづらいなので、sekaiが理解したものを噛み砕いてかくと、
ブロックチェーンチェーンを作ることができるSubstrateで作ったブロックチェーンにスマートコントラクトを作成できるのがink!。(ちなみにink!で作成したスマートコントラクトはWebAssemblyにコンパイルできます。ink!のレポジトリはこちら https://github.com/paritytech/ink/ )
ink!で用意された flipperというscaffold(雛形・サンプル)のコントラクトを作成して、 ローカルネットワークにデプロイします。flipperのコントラクト自体はとても簡単で、一つのbooleanの値を保持しており、実行すると現在の値が反転します。
例えばbooleanの値がtrueの時にflipperのコントラクト(flip)を実行するとその値はfalseになります。もう一度実行すると値はtrueになります。
(実際には現在の値を取得するgetも存在します。ソースコードを見たい方はこちらをご覧ください。https://github.com/paritytech/ink/blob/master/examples/flipper/lib.rs))
さてそれでは実際にflipperコントラクトを作っていきましょう。 まずは環境構築からになります。*途中で必要のないコマンドも打っているかもしれません。あしからず
(下記は全てmac上で行なっています。)
まずink!のセットアップから始めます。
https://paritytech.github.io/ink-docs/getting-started/setup
RustとCargoをインストールします。
curl https://sh.rustup.rs -sSf | sh
WebAssemblyのバイトコードを最適化するための binaryenパッケージをインストールします。
brew install binaryen
次にcargo-contractをインストールします。 cargo-contractはink!で作成されたWASMコントラクトをCLIで管理するためのツールです。
cargo install cargo-contract --vers ^0.17 --force --locked
sekaiはM1のmacを使っているため下記を実行します。(M1でない場合は不要です。)
softwareupdate --install-rosetta
そして必要なパッケージをインストールします。
brew install openssl Ink!のチュートリアルに戻り下記を実行します。
rustup component add rust-src --toolchain nightly
rustup target add wasm32-unknown-unknown --toolchain nightly
これでやっとink!に必要なセットアップが終わりました。 それではflipperのコントラクトを作りましょう。 cargo contract new flipper flipperのフォルダができていると思います。
このままだとエラーが起きたので、
cargo.tomlの中身を下記を参考に書き換えてください。
https://zenn.dev/polonity/articles/3c8d0d6a559911
そして
npm i wasm-opt -g
を実行してください。
cargo +nightly build
cargo +nightly test
cargo +nightly contract build
を実行すると target/ink/内に必要なファイルが書き出されます。 このファイルを使ってローカルネットワークにデプロイをします。
これでスマートコントラクトを作成できました。
今度はこのスマートコントラクトをローカルネットワークにデプロイしてみましょう。
1日目の内容を参考に
./target/release/astar-collator --port 30333 --ws-port 9944 --rpc-port 9933 --rpc-cors all --alice --dev
をしてください。
ブラウザからこちらにアクセスしてください。
https://polkadot.js.org/apps/?rpc=ws%3A%2F%2F127.0.0.1%3A9944#/contracts
Upload & deploy codeのボタンを押してください。
ファイルを選択する画面でmetadata.jsonを選択してください。( target/ink/内にあります。)
WASMコントラクトを選択してください。
Nextボタンを押してください。
デプロイボタンを押してください。
Sign and Submitを押してください。
デプロイされたことを確認してください。
スマートコントラクトを実行してみます。
execボタンを実行してください。
Executeボタンを押してください。
Sign and Submitを押してください。
flipされて現在の値が変わったことがわかります。
これでローカルネットワークにWASMベースのスマートコントラクトをデプロイすることができました。
次の目標は
- スマートコントラクトをフロント側で呼び出してみる。
ですが、こちらを取り組む前にどの言語を使ってWASMを作成するのか決めようと思います。(今更ですが。。)
SekaiはRubyに慣れ親しんでいますが、もしかしたらRustを使って開発した方が良いのかと思っています。(ink!がRust製なのと、RustでWASMを作っている人の話を聞いたため。)
SekaiはRustに詳しくないので、Rustを使う場合はRustのチュートリアルを行なっていく予定です。
そのチュートリアルが終わり次第3日目にいきます。
それでは。