Solidityホットリロード
ある日の朝、社内掲示板にて。
社長「キター!」
俺「?」
…という事で何がキタのか調べるべく「Solidity Hot Reloading Using ZepKit」の記事内容を試してみました。
Hot Reloading って何?
どうやらようやくsolidity界隈にも Hot Reloading 機能が実装されたようです。
ホットリロードとは「ファイルの変更をトリガにリアルタイムで変更を反映してくれる」機能の事です。
(こちらからの引用)
この記事のGIF画像が分かり易いです ↓
※右のソースコードを書き換える → 左のブラウザ画面が自動的に更新される → 便利!
Solidityのホットリロードって何?
では、Solidityのホットリロードとは何なのでしょうか。
"引用"
Hot Reloading watches the .sol files you’re using. Once there’s a change, it compiles them, updates the local blockchain using ZeppelinOS, and refreshes your app in the browser while preserving your blockchain state.
(ホットリロードは、使用している.solファイルを監視します。 変更があると、それらをコンパイルし、ZeppelinOSを使用してローカルブロックチェーンを更新し、ブロックチェーンの状態を維持しながらブラウザでアプリケーションを更新します。)
じゃあ、ホットリロードを使って何が嬉しいのでしょうか?
"引用"
Avoiding endless cycles of building and reloading your project whenever you make a change saves time and focus.
(変更を加えるたびにプロジェクトを構築して再ロードするという無限のサイクルを回避することで、時間と集中力を節約できます。)
これって大切ですね。
チームで開発していると、意外とこういったルーチンワークが、生産性向上を阻害するボトルネックになっていたりするものだと思います。
″引用”
Yet in the world of blockchain development, we’re 10 years behind.
ブロックチェーン開発の世界では、10年遅れています。
Solidity Hot Reloading を使えば、10年の遅れを巻き返す事が出来るのか。
さっそく見て行きましょう。
How to start?
「Solidity Hot Reloading Using ZepKit」の真ん中あたりからチュートリアルは始まります。
ここでは、分かり辛い部分に補足を加えて解説していきたいと思います。
なお今回は、Windows10 node.js 環境、Windows Power Shell + Chrome + MetaMask で動作を確認しました。
Install requirements
まず、必要なnpmパッケージをインストールします。
npm install --g zos@2.2.0 ganache-cli@6.3.0 truffle@5.0.2
zos … ZeppelinOS Command-Line Interface. Hot Reloadingで必要です。
ganache-cli … このチュートリアルは、ganache-cli をテストネットとして使います。
truffle … unboxに必要なだけ(おそらく)。
Unbox Zepkit
truffleのunboxコマンドを使い、zepkitをクローンします。
なお、unbox するといきなりファイル・フォルダが展開されるので、作業用フォルダを作成してから行いましょう。
mkdir zepkittest
cd zepkittest
truffle unbox zeppelinos/zepkit
Run the local blockchain
ganache-cliを起動します。
コンソールをもう一つ開いて、コマンドを実行します。
ganache-cli --secure -u 0 -u 1 -u 2 -d
PS C:\Users\tobisako> ganache-cli --secure -u 0 -u 1 -u 2 -d
Ganache CLI v6.3.0 (ganache-core: 2.4.0)
Available Accounts
==================
(0) 0x90f8bf6a479f320ead074411a4b0e7944ea8c9c1 (~100 ETH)
(1) 0xffcf8fdee72ac11b5c542428b35eef5769c409f0 (~100 ETH)
(2) 0x22d491bde2303f2f43325b2108d26f1eaba1e32b (~100 ETH)
(3) 0xe11ba2b4d45eaed5996cd0823791e0c93114882d (~100 ETH) 🔒
(4) 0xd03ea8624c8c5987235048901fb614fdca89b117 (~100 ETH) 🔒
(5) 0x95ced938f7991cd0dfcb48f0a06a40fa1af46ebc (~100 ETH) 🔒
(6) 0x3e5e9111ae8eb78fe1cc3bb8915d5d461f3ef9a9 (~100 ETH) 🔒
(7) 0x28a8746e75304c0780e011bed21c72cd78cd535e (~100 ETH) 🔒
(8) 0xaca94ef8bd5ffee41947b4585a84bda5a3d3da6e (~100 ETH) 🔒
(9) 0x1df62f291b2e969fb0849d99d9ce41e2f137006e (~100 ETH) 🔒
:
「--secure」オプションは、
ganache-cliが用意するテストアカウント(全て)をロック状態にします。
(※このチュートリアルでは不要かもです。)
「-u」オプションは、
逆に指定アカウントをアンロック状態にします。
「-u 0 -u 1 -u 2」と書く事で、アカウント「(0)」「(1)」「(2)」がアンロックされます。
(実行結果では、(0)・(1)・(2)に鍵アイコンが無くアンロックされている事が分かります。)
このチュートリアルでは、後述の「zos session」で、アカウント「(2)」がアンロックされている必要があります(※このチュートリアルでは3つもアンロックしなくても…です)。
「-d」オプションは、
ganache-cliが用意するテストアカウントを生成する際のニーモニック(MNEMONIC)を指定するものです。
1・指定無しの場合は、ganache-cli起動毎にテストアカウントのアドレスが変わります(不便かもです)。
2・「-d」のみ指定すると、常に同じテストアカウントが生成されます。
3・「-d -db [PATH]」と指定する事で、ニーモニックをファイル指定する事も出来る様です。
上記「2」で生成されるテストアカウントのアドレスは、別環境でも常に同じです。
(Windows10 と Ubuntu(Cloud9) で試したが同じだった)
このチュートリアルでは、後述の「zos session」でアカウント「(2)」のアドレスが直指定されており、
ここで「-d」を指定する事で整合性が取れています。(なんだかアクロバティックですね)
※ganache-cliのコマンドライン引数の解説はgithubで確認して下さい。
※ニーモニックについては、HD Wallet
でググッって見てください。
Initialize the ZeppelinOS project
「truffle unbox zeppelinos/zepkit」で取得したチュートリアル・サンプルソースを設定していきましょう。
zos init zepkit
すると、ファイル zos.json が生成されます。
{
"zosversion": "2.2",
"name": "zepkit",
"version": "0.1.0",
"contracts": {}
}
Add the Counter contract to your project
Hot Reloading で監視するコントラクトを設定します。
zos add Counter
すると、下記の様に soliddity ソースファイルがコンパイルされ、zos.json が更新されます。
ファイル zos.json の "contracts" に、 Counter が書き加えられました。
{
"zosversion": "2.2",
"name": "zepkit",
"version": "0.1.0",
"contracts": {
"Counter": "Counter"
}
}
Connect with your local blockchain by opening a session
次に、Hot Reloading で使用するセッション管理情報を保存します。
zos session --network development --from 0x22d491bde2303f2f43325b2108d26f1eaba1e32b --expires 3600
すると、ファイル .zos.session が生成されます。
{
"network": "development",
"from": "0x22d491bde2303f2f43325b2108d26f1eaba1e32b",
"expires": "2019-05-18T15:32:43.175Z"
}
Let’s compile the Counter contract
まだまだ準備は続きます。以下のコマンドを実行し、セッション情報をブロックチェーンにプッシュします。
zos push --deploy-dependencies
このコマンドを実行したら、ganache-cli の表示にも注目しましょう。
We create an instance of our contract and deploy it
次のコマンドで、ようやくコントラクトがデプロイされインスタンスが生成されます。
zos create Counter --init initialize --args 2
※「--args 2」を指定する事で、Counter.sol
のコンストラクタに引数 2 を渡しています。
Open another terminal in the client
folder and run
このチュートリアルでは、MetaMask を ganache-cli に接続して使用するので、まず先に MetaMask のネットワークを「Localhost 8545」に切り替えます。
次に、クライアントweb画面を起動します。
チュートリアルでは別Windowsを開くと書いていますが、ここではそのままコマンドを実行します。
「truffle unbox zeppelinos/zepkit」で取得したフォルダ「client」にパスを移動して、コマンドを実行します。
cd client
npm run start
するとブラウザが起動し、暫くするとweb画面が表示されます。
(コンパイル後に表示されるので、少し時間がかかります)
このタイミングで MetaMask の確認画面が出てくるので、「Connect]ボタンを押して許可しておきましょう。
では、web画面を確認したら、そっと閉じて次のURLを開きましょう。
http://localhost:3000/counter
さて、ホットリロードを確認する前に、以下をチェックしておきましょう。
「Increase Counter by 1」ボタンはアクティブですが、
「Decrease Counter by 1」ボタンは非アクティブで押せない状態になっています。
ここで使用されているSolidityファイルの覗いてみましょう。
:
contract Counter is Initializable {
:
//and it can add to a count
function increaseCounter(uint256 amount) public {
count = count + amount;
}
//We'll upgrade the contract with this function after deploying it
//Function to decrease the counter
// function decreaseCounter(uint256 amount) public returns (bool) {
// require(count > amount, "Cannot be lower than 0");
// count = count - amount;
// return true;
// }
}
※関数「increaseCounter()」と「decreaseCounter()」がありますが、後者はコメントアウトされています。
次に、webクライアント側のソースファイル index.js を覗いてみましょう。
:
<div className={styles.buttons}>
<Button
onClick={() => this.props.increase(1)}
size="small">Increase Counter by 1</Button>
<Button
onClick={() => this.props.decrease(1)}
disabled={!contract.methods.decreaseCounter} size="small">Decrease Counter by 1</Button>
</div>
:
※「disabled={!contract.methods.decreaseCounter}」で、コンパイルされたSolidityソースにメソッド「decreaseCounter()」が含まれているかを確認し、ボタンのアクティブ・非アクティブを切り替えている事がわかります。
今回のお題は「ホット・リローディング」ですので、
Counter.sol の関数「decreaseCounter()」コメントを外し有効にして、ファイルを保存する事で自動的にホット・リロードすれば成功、という事になります。
それでは、やってみましょう。
下記の様に、「Counter.sol」の関数「decreaseCounter()」のコメントを外します。
:
contract Counter is Initializable {
:
//and it can add to a count
function increaseCounter(uint256 amount) public {
count = count + amount;
}
//We'll upgrade the contract with this function after deploying it
//Function to decrease the counter
function decreaseCounter(uint256 amount) public returns (bool) {
require(count > amount, "Cannot be lower than 0");
count = count - amount;
return true;
}
}
そして、内容に変更があった場合のみ、自動的にデプロイが行われます。
(今回は関数「decreaseCounter()」が新たに加わった)
さらに、web画面も自動的に更新され、
ソースファイルを保存しただけで、
上記の様に「Decrease Counter by 1」ボタンがアクティブとなり、押せる様になりました。
これで、Solidity の Hot Reloading がうまく動作した事が確認できました。
失敗するケース
サクサクやらないと失敗するかもしれません。以下の点に注意しましょう。
・1時間(3600秒)以内に終わらせる。
・失敗したら、ganache-cli を一度再起動して、「zos init zepkit」からやり直す。
・たまに「zos.json」(およびzos-dev-xxxx.json)を手動で消さないとやり直し出来ない事がある。
せっかくなのでボタンを押してみよう
ここからはチュートリアルには無いオマケです。
ボタンを押すと、コントラクト関数を呼び出して、カウンターを増やしたり減らしたり出来る筈ですが、
関数呼び出しには gas が必要です。
もし ether 残高が足りないと、MetaMask で「残高不足」となってしまいます。
ganache-cli を使ったテストネットなので、MetaMask で TEST-ether を使う必要があります。
1・使用している MetaMask に ether を送ってやる
2・MetaMask にテストアカウントをインポートしてやる
MetaMask にテストアカウントを追加するのはちょっとアレな感じなので、
ここでは「1」の方法で、geth コンソールを起動して、ganache-cliテストネットに接続し、MetaMask のアカウントに ether を送金しましょう。
geth attach http://127.0.0.1:8545
ganache-cli に geth コンソールで接続出来たら、下記の送金コマンドを実行します。
(「to:」のアドレスは、自分の MetaMask アカウントに置き換えてください。)
eth.sendTransaction({from:eth.accounts[0],
to:"0xd7436A5d7AabaDE2cdBA5FA9489Afd15af2E86EA",
value:1000000000000000000})
※ganache-cli は最初から10個のテストアカウントが作成され、それぞれ 100 ether ずつ入っています。
※上記コマンドでは、アカウント0番→自分の MetaMask アカウントへ 1 ether を送金しています。
これで準備OKです。
さっそく「Increase Counter by 1」ボタンを押してみましょう。
ボタンを押すと、MetaMask のポップアップが表示され、今度はちゃんと押す事が出来ます。「確認」ボタンを押しましょう。
感想
コントラクトの自動デプロイは便利でした。ただ、色々触っているとMetaMaskとの連携でエラーが出たり、ganache-cliを停止させると整合性が保てなくなる等、まだまだ使い勝手としては向上の余地があるのかなと思いました。zosの今後の進歩に期待です。
FLOCブロックチェーン大学校
FLOCブロックチェーン大学校・スマートコントラクト開発課は、solidity・truffleを学ぶ事が出来るカリキュラムです。web受講の他に教室受講オプションがあり、講師に直接質問出来て身に付きやすいです。短期集中で ethereum 開発ノウハウを獲得するならおススメです。
ちょっと嬉しいと思った事
5月下旬からの回では、講師・講師補助メンバーとして関わって下さる方々が増えるのですが、
エンジニア同士でカリキュラムの進め方についてあーだこーだ議論出来るのが嬉しいです(*´Д`)
きっと違った目線からより面白いワークショップが生まれるんじゃないかと思うと今から楽しみです。
乞うご期待!