Ethereumノード+ウェブサーバー+分散型アプリ(DApp)ブラウザ
この記事では、基本的なツールチェーン上でDAppを立ち上げて実行する方法をエンドツーエンドで説明します。ラッパースクリプトを使用するのではなく、Ethereumノード、Webサーバ、DApブラウザを直接操作して、裏で何が起こっているのかを説明します。
既存のSolidity Remix IDE「Donation」チュートリアルをベースに、ツールの現状(2017年6月)に合わせたアップデートを加えて構築します。
必要不可欠なインフラは、Ethereumノード(私たちはethを選びました)、静的ファイルをホストするための標準的なWebサーバー(私たちはpython -m SimpleHTTPServerを使用しました)、そしてDAppブラウザ(私たちはMistを選びました)です。
この種のDAppのアーキテクチャは、DAppブラウザ(Mist)がWebサーバから静的なHTML、JS、CSSファイルを読み込み、標準のDOMに加えて、注入されたweb3.jsオブジェクトを介してEthereumノード(eth)へのアクセスを提供するというものです。基本的にウェブページは、通常のウェブと同様にEthereumブロックチェーンと対話することができます。
開発モードでゲスを開始し、アカウントを作成し、いくつかのブロックを採掘します。
このようにシンプルなDAppの場合、geth --devを実行するだけで、シングルノードのEthereumテストネットワークを設定してくれます。
gethが起動したら、テストアカウントを作成します。
その後、マイナーを起動していくつかのブロックを採掘します。コインベースは自動的にテストアカウントに設定されているので、採掘したイーサはそこに入金されます。eth.coinbaseを実行することで確認できます。
そして数秒後に鉱夫を止める。
では、テスト口座の残高を確認してみましょう。
私たちのテストアカウントには40イーサが入っていますが、これはブロックあたり5イーサで、DAGの生成を含めて、現代のiMacで8秒で8ブロックを採掘したことを意味します。
なお、IPCエンドポイントを指定することで、geth devインスタンスに対してMistブラウザを起動することもできます(IPCであるにもかかわらず、Mistのコマンドラインオプションは--rpcとなっていることに注意してください)。もし、"Looking for peers"で停止した場合は、Mistのスプラッシュ画面で"Launch Application"をクリックする必要があるかもしれません。
Linuxです。
マックです。
テストウォレットに40イーサの残高が表示されています。また、Mistでは左下に「Private-net」という真っ赤なインジケーターが表示され、これが公開されているEthereumネットワークではないことを示しています。
ネットワークの選択肢をテストする
geth devモードの代わりに、プライベートテストネットワークで実行するという選択もありました。Consensus 2017 Hackathon]({{ site.baseurl }}{% link _posts/2017-05-12-daysofblock-03-consensus-hackathon.md %})のときにそれを試してみましたが、いくつかの問題に遭遇しました。
公衆テストネットワークのいずれかで実行することもできますが、その場合、スマートコントラクトをそのネットワークにさらすことになり、さらに公衆テストネットワークに関連したパフォーマンスや容量の影響をすべて受けることになります。
あるいはメインネットワーク上で実行することもできますが、それだと高額になってしまいます(2017年6月:Ethereumの取引コストはそれぞれ約0.30米ドル)。
Geth devモードの説明
その速さに驚きました。プライベートテストネットワーク上で実行するために geth を設定する場合、ジェネシスブロックを作成し、正しいオプションで geth を実行するというプロセスがあります。難易度を低くして素早く採掘できるようにすると、アルゴリズムが素早く調整され、すぐにブロックが数十秒から数分かかるようになります。
geth の場合、コンセンサスアルゴリズムを Proof of Authority に切り替えたり、geth のソースコードをハックしたりすることで回避する方法があります。しかし、gethの開発モードでは、ブロックは常に数秒で採掘されます。
何が起こっているのか、ゲスのソースコードを調べてみることにしました。
flags.goでは、geth --devが他の多くのオプションを設定するトリガーとなっていることがわかります。
基本的にこれはシングルノードネットワークであり、他のノードからのディスカバリは許可されていません。
同じファイルのさらに下の方では、devモードのジェネシスブロックがどこから来ているのかがわかり、デフォルトではガス価格が0に設定されています。
cfg.PowTestの設定は、devモードの作業証明アルゴリズムが設定されていることを示唆しています。このフラグをethash.goに通せば、なぜマイニングに時間がかからず、開発者モードでは難易度が上がらないのかを確認することができます。
コードを読んだだけでは、DAG(キャッシュ)サイズは常に1024/4 = 256 uint32の小さな値に制限されているように見えますが、これはブロックが非常に速く採掘されることを示唆しています。
寄付金DApp
DApp用に作成するファイルは2つあります。
- Donation.solはSolidityのスマートコントラクト
- index.htmlは DApp のウェブページです。
そのリンク先のWebページのソースコードはまばらに見えますが、Mistやその他の最新のブラウザでは問題なく動作します。
index.htmlと同じディレクトリで、Webサーバを起動します。標準のPythonがインストールされていると仮定して、python -m SimpleHTTPServerを実行するだけです。
DAppのテスト
Webブラウザでindex.htmlを開き、「与える」ボタンをクリックします。標準のWebブラウザではweb3.jsライブラリとgethへの接続が存在しないため、何も起こりません。
ここで、Mistブラウザでindex.htmlを開きます。上部のナビゲーションバーをクリックして、https://wallet.ethereum.org と表示されていると思われる場所をクリックし、index.html をローカルのウェブサーバがホストしているindex.html に置き換えます。例えば、http://localhost:8000。
今から「give」をクリックしても何も起こらず、裏でエラーが出ていますが、今回は必須項目が入力されていないことが原因です。MistはChromeブラウザのラッパーにEthereumのサポート(web3.js、gethへのIPC接続など)を追加したものなので、標準の開発者ツールが利用できます。試しにDevelop => 開発者ツールの切り替え => localhost:8000にしてみます。
ブロックチェーン上にスマートコントラクトをロードする
MistにはRemixSolidity IDEも含まれており、これはDevelop => Open Remix IDEからアクセスできます。チュートリアルの次のステップ][mist-deploy-contract]では、Remixを使用してDonation.solのスマートコントラクトをgethのdevノード内のブロックチェーンにデプロイします。
Remix IDEの右上にあるフォルダアイコンをクリックしてDonation.solを開きます。すると、使用されていない変数に関する(意図的な)警告と、pragma文の欠落に関する警告が表示されていることに気づくでしょう。このチュートリアルでは、これらの警告は無視して構いません。
環境は「Injected Web3」となっており、geth devノードへのIPC接続を示しており、アカウントは先ほど作成したテストウォレットであることに注意してください。
右ペインの中央にあるピンク色の「作成」ボタンをクリックすると、スマートコントラクトがブロックチェーン上にロードされます。
トランザクションの送信」をクリックしても何も表示されません。これは、少なくとも1つのブロックが採掘された後、数秒後にminer.start()に続いてminer.stop()を実行する必要があります。
Mistでは、アドレス0xeb4578083c1d0928d634298e84313104f1f8bda2を含む展開された契約の詳細が表示されます。アドレスをコピー」をクリックしてどこかに貼り付けてメモしておきます。
geth ヘルパースクリプト
geth コンソールは、基本的には web3.js が埋め込まれた Javascript の read-eval-print ループです。テストを簡単にするために自動化できることの1つは、トランザクションが保留中の場合にのみマイニングをトリガーすることです。マイナーを起動したり停止したりする必要がなくなり、コンソールと geth dev モードのブロックチェーンデータフォルダが不必要にいっぱいになることもなくなります。
ここでは、私たちが便利だと感じたgeth スクリプトをまとめています。
オンデマンド マイニングを行うには、次の Javascript スニペットをファイルにコピーしてください。miner.stop() がパラメータを取らなくなったことと、現在 StackExchange にあるスクリプトは動作しないため、以下に完全なソースを含めています。
exit と入力して geth を終了し、以下のように再起動してヘルパースクリプトを含めます。
今では、トランザクションが送信されるたびに、鉱夫が自動的に開始して停止し、新しいブロックに含めるようになりました。
スマートコントラクトにトランザクションを送信する
Mistでは、寄付契約フォームの「契約アドレス」の欄に、先ほどコピーしたDonation.solを展開したアドレスを記入します。give」ボタンの左には、「from」にウォレットのアドレスを、「金額」には魏の1イーサを10000000000000と記入します。
give」をクリックし、「Send Transaction」をクリックします。
前のセクションでマイニングヘルパースクリプトを有効にした場合、数秒後にDAppのポップアップでトランザクションが確認されるはずです。gethコンソールには、新しくマイニングされたブロックにトランザクションが追加されたことも表示されます。
トランザクションのデバッグ
Remix IDEでトランザクションをデバッグするためには、トランザクションハッシュが必要となります。あるいは、gethコンソールの"Submitted transaction"行の"fullhash"の値(上図参照)で確認することができます。この例では、0xbbc31070d5c88e510b7e9ec8fafd1df9bbcdff8c55aea71f1c72c7227dd473c1となっています。
Remix IDEで右上の"Debugger"タブをクリックし、"Transaction index or hash"フィールドにトランザクションハッシュ値を貼り付け、再生アイコンをクリックします。ボタンやスライダーを使ってコードをステップスルーすることができます。
デバッガで前にも後ろにも進むことができるのは、Remixがトランザクションの前後のブロックチェーンの状態全体にアクセスできるからです。リアルタイムのデバッグとは対照的に、アイスホッケーのゴールの瞬間的なリプレイのように、すでに起こったことをステップスルーしているのです。
結論
元のチュートリアルが同様に終わったところで、私たちはここで物事を残します。Geth dev modeはテスト用のEthereumブロックチェーンを使って素早く立ち上げて実行するのに最適な方法であり、GethとMistとシンプルなWebサーバーの組み合わせは、基本的なDApp開発のための完全なツールチェーンです。