トップへ戻る
公開日
2018年5月17日
筆者:Curvegrid
ダニエル・ブリスキン

第一原理からDAppをテストする(2018年5月更新

前回と同様に、Solidity Remix IDEの「Donation」チュートリアルをEthereumのプライベートネット上で実行するために必要な手順を説明します。

はじめに

今回の記事は、前回のブログ記事「Test a DApp from First Principles」を更新したものです。前回と同様に、Solidity Remix IDEの「Donation」チュートリアルをEthereumのプライベートネット上で動作させるために必要な手順を説明します。今回の記事のベースとなるチュートリアルはRemix IDEのReadTheDocsで公開されていますが、yann300さんの許可を得て、必要な2つのファイルをここで公開することにしました。この記事では、DAppが正しく機能するために必要な追加のステップをいくつか紹介します。

このチュートリアルでは、これまでと同じツールセットを使用します。Ethereumノードにはeth、DAppブラウザにはMist、静的ファイル用のWebサーバにはPythonのSimpleHTTPServerを選びました。gethを使うことで、ブロックチェーン上のデータを保存したり、読み込んだりすることができるようになりました。ウェブサーバは、DAppで使用する静的なHTML、CSS、JavaScriptファイルを迅速に提供します。Mistブラウザは、これら2つの情報技術のパラダイムの間の橋渡し役となり、Webサーバから静的ファイルをロードして利用したり、注入されたweb3.jsオブジェクトを介してEthereumノードと通信したりすることができます。

これまでの経験から、開発モードで geth ノードを実行するのが DApp の開発とテストに最適な方法であるという結論に至りました。Ganache のような他の開発プラットフォームもありますが、メインネット上で DApp の動作をシミュレートするには geth dev モードを使って開発するよりも良い方法はないことがわかりました。

今回のチュートリアルでは、新しくリリースされたRemix IDEのスタンドアロン版を使用します。npmやyarnを使ってインストールしてください。


yarn global add remix-ide



このチュートリアルは geth バージョン 1.8.6-stable と Mist バージョン 0.10.0 を使用して書かれています。

セスの初期化

まず、ブロックチェーンデータを保存するフォルダを作成しましょう。


mkdir test-chain-dir


次に、新しく作成したデータディレクトリを指す geth ノードを起動します。gethをdevモードで実行しているので、DAppはシングルノードのプライベートネットにデプロイされ、メインネット上でDAppを構築してテストするという金銭的な負担を避けることができます。


geth --dev --datadir test-chain-dir console


geth ターミナルウィンドウでは、以下のような出力が表示されるはずです。


INFO [05-17|14:32:51] Maximum peer count                       ETH=25 LES=0 total=25INFO [05-17|14:32:52] Using developer account                  address=0xf92EcEa910C31e302699e58B866bD2604527dD1dINFO [05-17|14:32:52] Starting peer-to-peer node               instance=Geth/v1.8.6-stable/darwin-amd64/go1.10.1INFO [05-17|14:32:52] Allocated cache and file handles         database=/Users/danielbriskin/tut/test-chain-dir/geth/chaindata cache=768 handles=1024INFO [05-17|14:32:52] Writing custom genesis blockINFO [05-17|14:32:52] Persisted trie from memory database      nodes=12 size=2.26kB time=54.111µs gcnodes=0 gcsize=0.00B gctime=0s livenodes=1 livesize=0.00BINFO [05-17|14:32:52] Initialised chain configuration          config="{ChainID: 1337 Homestead: 0 DAO:  DAOSupport: false EIP150: 0 EIP155: 0 EIP158.0 ビザンチウム: 0 コンスタンチノープル。  Engine: clique}"INFO [05-17|14:32:52] Ethereumプロトコルのバージョンを初期化する="[63 62]" network=1INFO [05-17|14:32:52] 最新のローカルヘッダ番号=0 hash=4374f1...a3fed1 td=1INFO [05-17|14:32:52] 最新のローカルフルブロック番号=0 hash=4374f1...a3fed1 td=1INFO [05-17|14:32:52] 最新のローカルフルブロック番号=0 hash=4374f1...a3fed1 td=1INFO [05-17|14.32:52] 最新のローカル高速ブロック番号=0 hash=4374f1...a3fed1 td=1INFO [05-17|14:32:52] ローカルトランザクションジャーナルトランザクション=0 accounts=0INFO [05-17|14:32:52] P2Pネットワーキング開始INFO [05-17|14:32:52] whisper v.を起動しました。6.0INFO [05-17|14:32:52] RLPxリスナー up self="enode.//38fb7579853407637b21437c1595a47995a63fd39cb7c0a192d891c68728c0d4ed7d0402517f9b915d924594b0e91441fbc6f7963a91f780f74119ab4db5291b@[::]:49775?discport=0"INFO [05-17|14:32:52] IPCエンドポイントがオープンしました url=/Users/danielbriskin/tut/test-chain-dir/geth.ipcINFO [05-17|14:32:52] トランザクションプール価格閾値更新 price=18000000000INFO [05-17|14:32:52] Etherbase自動設定 address=0xf92EcEcEa910C31e302699e58B866bD2604527dD1dINFO [05-17|14:32:52] マイニング動作開始INFO [05-17|14:32:52] マイニング動作を開始しました。32:52] マイニング作業開始INFO [05-17|14:32:52] 新規マイニング作業のコミット number=1 txs=0 uncles=0 経過=118.067μsWARN [05-17|14:32:52] ブロックシーリングに失敗しました err="トランザクション待ち"


出力の2番目の最後の行は、ノードがブロックのマイニングを開始したことを示しています。しかし、出力の最後の行は、ブロックに含めるべきトランザクションがないため、マイニングが一時停止されたことを示しています。これは、前回のチュートリアルで表示された出力とは異なります。元の記事を書いている時点で、geth --devはProof of WorkからProof of Authorityのマイニングアルゴリズムへと移行しています。これにより、プライベートネットDAppの開発が簡素化され、手動でマイニングツールを起動したり停止したりする必要がなくなりました。マイナーは、含まれるべきトランザクションがある場合にのみブロックをマイニングします。

IPCエンドポイントがオープンされたという行に注目してください。これでMistを起動してプライベートネットに接続できるようになりました。これで、Mistを起動してプライベートネットに接続できます。

Linuxです。


mist --rpc test-chain-dir/geth.ipc


マックです。


$ /Applications/Mist.app/Contents/MacOS/Mist --rpc test-chain-dir/geth.ipc


その後まもなく、Mistのターミナルウィンドウが出力を開始し、そのスプラッシュスクリーンが開くのがわかります。Launch Applicationボタンを押してアプリケーションウィンドウを開きます。以下のようなウィンドウが表示されるはずです。

geth devインスタンスのミストウォレット

スタート時の残高が非常に大きいことに注目してください。Etherを生成するためにブロックを採掘する必要はありません。Etherbaseから個人アカウントにブロックを送信するだけで、Etherbaseウォレットを直接使用することができます。

それはさておき、端末画面に戻って個人アカウントを作成してみましょう。


> personal.newAccount()Passphrase:Repeat passphrase:"0xb1c7a4b22525f920ccb4c43904bb86ca487f07fe"


Mistアプリケーションのウィンドウに戻ると、Ethereum Walletタブに新しいアカウントが表示されます。このアカウントの開始時のイーサの残高はゼロです。また、イーサの残高を確認するには、イーサ端末のウィンドウから確認することができます。


> web3.fromWei(eth.getBalance(personal.listAccounts[1]), "ether")0


また、配列のインデックス値を 1 から 0 に切り替えることで、コマンドラインから Etherbase のバランスを確認することもできます。


> web3.fromWei(eth.getBalance(personal.listAccounts[0]), "ether")1.15792089237316195423570985008687907853269984665640564039457584007913129639927e+59

寄付金DApp

このチュートリアルでは、2つのファイルが必要です。

  • ソリダリティスマートコントラクトファイル

contract Donation {    address owner;    event fundMoved(address _to, uint _amount);    modifier onlyowner { if (msg.sender == owner) _; }    address[] _giver;    uint[] _values;    function Donation() {        owner = msg.sender;    }    function donate() payable {        addGiver(msg.value);    }    function moveFund(address _to, uint _amount) onlyowner {        uint balance = this.balance;        uint amount = _amount;        if (_amount <= this.balance) {            if (_to.send(this.balance)) {                fundMoved(_to, _amount);            } else {                throw;            }        } else {            throw;        }    }    function addGiver(uint _amount) internal {        _giver.push(msg.sender);        _values.push(_amount);    }}


このファイルをDonation.solとして保存します。

  • DApp ウェブページ

寄付金契約










このファイルをindex.htmlとして保存します。

webserverという新しいフォルダを作成し、その中にindex.htmlを移動します。ターミナルウィンドウでフォルダを開き、以下のコマンドを実行します。


python -m SimpleHTTPServer


デフォルトのブラウザを開き、http://localhost:8000 を読み込んでください。開発者コンソールを開いて出力を確認してください。

以下のような画面が表示されます。

Chrome での web3 未定義

コンソールのエラーに注目してください。さすがにChromeはweb3をサポートしていません。 そのため、部分的にMistを使う必要があります。

ここで、Mistで http://localhost:8000 を開きます。そのページを右クリックして開発者コンソールを開きます。同じエラーが表示されるはずです。

ミストでweb3が未定義

web3がまだ定義されていないようです。index.htmlにJavaScriptファイルを入れてみましょう。

Below the closing </div> at line 20, add the following line





Mistでページを更新してください。それでも同じエラーが表示されるはずです。なぜでしょうか?

結局のところ、web3にgethノードを提供することでweb3を初期化する必要があります。これにより、web3.js プラグインが geth に接続できるようになり、JavaScript API を使用してブロックチェーンにデータを読み書きできるようになります。

Add the following code inside the <script> tag containing all the donation functions.




if (typeof web3 !== 'undefined') {
  web3 = new Web3(web3.currentProvider);
} else {
  // set the provider you want from Web3.providers
  web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));
}



Mistでページを更新します。コンソールにエラーが出なくなっているはずです。

HTMLにweb3.jsを入れて、gethノード接続で初期化しなければならないのに、Mistを使う意味があるのかと疑問に思うかもしれません。これはChromeでも同じように動作するのではないでしょうか?

簡単に言うと、MistはEthereumとの統合の他の形態を提供しているということです。例えば、Mistの右上に小さなアイコンがあるはずです。これをクリックすると、Etherウォレットを含むポップアップが表示されます。このモーダルを使用して、DAppsが支払いを行ったり受け取ったりする際に使用するアドレスを制御することができます。従来のウェブブラウザでは、このタイプの統合はサポートされていません。

ブロックチェーンへのDonation.solの展開

フロントエンドが立ち上がったので、Donationスマートコントラクトをプライベートネットブロックチェーンにデプロイする必要があります。

ターミナルウィンドウでRemix IDEを起動してください。スタンドアロンのIDEが利用できるようになったので、Mistに統合されたIDEよりも、スタンドアロンのIDEを使用することを強くお勧めします。


$ remix-ide


Mistブラウザを開き、http://localhost:8080 を読み込みます。以下のような画面が表示されるはずです。

リミックスIDE

デフォルトのballot.solタブを閉じ、左パネル左上のフォルダアイコンを押してDonation.solを開きます。右パネルの「コンパイル」タブを選択し、「コンパイル開始」ボタンを押します。右側のパネルに警告のリストが表示されるはずですが、このチュートリアルの目的上、これらを気にする必要はありません。

右側のパネルで、[実行]タブに切り替えます。パネルの上部にある[環境]ドロップダウンに注意してください。3つのオプションがあります。JavaScript VM、Injected Web3、Web3 Providerです。このドロップダウンでは、スマートコントラクトのデプロイ先を選択できます。

  • JavaScript VM - ブラウザを使って分離されたEthereumノードを実行します。これはスマートコントラクトを素早くテストするのに便利ですが、結果として得られるブロックチェーンは永続的ではなく、ブラウザを閉じると消えてしまいます。
  • Injected Web3 - ブラウザが現在接続しているWeb3プロバイダを使用します。このチュートリアルでは、Mist のインスタンスを実行中の geth dev ノードに既に接続しているので、このオプションを使用します。
  • Web3 Provider - これにより、IDEを手動でWeb3 Providerに指定することができます。例えば、別のマシン上でGethノードを実行している場合、ローカルのRemix IDEインスタンスを接続してリモートのEthereumノードを使用することができます。

環境] ドロップダウンの下に、[アカウント] ドロップダウンがあります。ここでは、スマートコントラクトの展開に資金を供給するために使用するイーサウォレットを選択できます。デフォルトでは、アカウントのドロップダウンは空です。これは、Remix IDEに接続するためのEtherウォレットがまだ認可されていないためです。Mistの右上にあるピクセル化されたトップハットのアイコンをクリックします。すると以下のようなポップアップウィンドウが表示されます。

ミストのアカウント認証

認証するアカウントを選択してください。ここではEtherbaseアカウントを使用します。認証をクリックすると、ブラウザが更新されます。実行タブに戻ると、ドロップダウンに利用可能なアカウントが表示されます。

さて、スマートコントラクトをプライベートネットにデプロイしましょう。実行タブのパネルの2番目のセクションで、ドロップダウンで「寄付」が選択されていることを確認し、その下のサーモン色のデプロイボタンをクリックします。次のウィンドウがポップアップします。

契約書の作成

Ether ウォレットのパスワードを入力します。個人アカウントを使用している場合は、チュートリアルの最初にアカウントを作成したときに入力したものと同じパスワードになります。Etherbase ウォレットのデフォルトのパスワードは空白です。Send Transaction(トランザクションの送信)ボタンをクリックします。

gethターミナルのウィンドウに戻します。以下のような出力が表示されます。


INFO [05-18|11:07:11] 契約書作成完了 fullhash=0xc6e89db6d500cb8cfa8f16ff590f4f866de0cc7fe31d60d84e6f72f43db39327 契約書=0xE6D27720E581b5133EeB9011006A47C750AEa426を送信しました。
INFO [05-18|11:07:11] コミット 新規マイニング作業番号=1 txs=1 uncles=0 経過=2.536ms
INFO [05-18|11:07:11] Successfully sealed new block number=1 hash=c551ee...91cd18.
INFO [05-18|11:07:11]🔨 採掘された可能性のあるブロック番号=1 hash=c551ee...91cd18
INFO [05-18|11:07:11] コミット 新規マイニング作業番号=2 txs=0 uncles=0 経過=1.153ms
WARN [05-18|11:07:11] Block sealing failed err="waiting for transactions"


大成功!当社のスマートコントラクトがブロックチェーンにデプロイされました。出力の最初の行にある契約アドレスに注目してください。このアドレスは、Remix IDEウィンドウの「実行」タブの下部からコピーすることもできます。これがブロックチェーン上のスマートコントラクトのアドレスです。

寄付DAppの使用

今、私たちのフロントエンドは稼働していて web3 を介して geth に接続することができ、スマートコントラクトは私たちのプライベートネットブロックチェーンにデプロイされています。それでは、すべてをまとめてみましょう。

PythonのSimpleHTTPServerを実行している状態で、Mistブラウザでhttp://localhost:8000をロードします。一番上の契約アドレスのフィールドに、前のステップでgethターミナルウィンドウまたはRemixからコピーした契約アドレスを貼り付けます。次の行のフィールドでは、「from」フィールドにイーサウォレットアドレスを、「金額」フィールドに1000000000000000000を貼り付けます。この金額は魏で1イーサです。ここでギブボタンを押すと、取引画面がポップアップします。

契約の実行

イーサウォレットのパスワードを入力し、取引を送信します。しばらくすると、DApのウィンドウは以下のようになります。

契約の成功

geth端末のウィンドウを見て、何が起こったのかを確認してみましょう。


INFO [05-18|11:24:26] Submitted transaction fullhash=0x69c5346dbaf3b5a5415134c181ba16bcda76966bd60b9a42cf646651fc4a517a recipient=0xE6D27720E581b5133EeB9011006A47C750AEa426を送信しました。
INFO [05-18|11:24:26] 新規マイニング作業のコミット number=2 txs=1 uncles=0 経過=801.974µs
INFO [05-18|11:24:26] Successfully sealed new block number=2 hash=f88586...e73ee1.
INFO [05-18|11:24:26]🔨 mined potential block number=2 hash=f88586...e73ee1
INFO [05-18|11:24:26] コミット 新規マイニング作業番号=3 txs=0 uncles=0 経過=514.943µs
WARN [05-18|11:24:26] Block sealing failed err="waiting for transactions"


トランザクションが成功し、イーサがスマートコントラクトのアドレスに送信されました。トランザクションのFullhashをコピーして、何が起こったのかを見てみましょう。

トランザクションのデバッグ

Remix IDEウィンドウの右側パネルにあるデバッガタブに切り替えて、"Transaction index or hash"フィールドにfullhashを貼り付けることで、トランザクションによって実行されたコードをステップスルーすることができます。再生ボタンを押して、ハッシュからトランザクションをロードします。これで、スマートコントラクトの機能の実行中にスライダーや前進・後退ボタンを使って移動することができます。

結論

このチュートリアルでDAppの基本的なアーキテクチャをよりよく理解していただけたのではないでしょうか。Geth dev modeはテスト用のEthereumブロックチェーンを使って素早く立ち上げて実行するのに最適な方法であり、GethとMistとシンプルなWebサーバーの組み合わせは、基本的なDApp開発のための完全なツールチェーンです。