Ethereum のスマートコントラクト開発フレームワーク Populus でコンパイル・テスト・デプロイしたときのメモです。
- geth 1.7.3
- solidity 0.4.18
- populus 1.10.1
スマートコントラクトを書いてみる
Ethereum クライアント Geth をインストールする
Ethereum の P2P ネットワークに参加するには、 クライアントソフトウェアが必要となります。
Ethereum クライアントには C++ 実装の cpp-ethereum 、Python 実装の pyethereum などがありますが、現在推奨されているクライアントは Go 実装の Geth になります。("G"o の "Eth"ereum Client ということで Geth だそうです)
Geth がインストールされていれば、Ethereum ネットワークにフルノードとして参加することができ、マイニングやトランザクションの生成、スマートコントラクトの生成などができるようになります。
MacOS での Geth のインストールには、Homebrew を使う方法が一番手軽です。
% brew tap ethereum/ethereum
% brew install ethereum
geth help
コマンドでオプション一覧が表示されれば、無事にインストールが完了しています。
MacOS 以外でのインストール方法はこちら。
Solidity をインストールする
Ethereum では、スマートコントラクトのコードは Ethereum Virtual Machine Code (EVM Code) と呼ばれるバイトコード形式で記述・実行されます。
そのまま人間が記述するには大変なので、Ethereum ではスマートコントラクトの記述に特化したプログラミング言語が開発されています。Solidity はその一つで、JavaScript に似た構文を持つ静的型付け言語です。
Solidity のインストールには、Geth 同様 Homebrew を使用します。
% brew install solidity
solc --version
コマンドを実行するとバージョンを確認できます。
MacOS 以外でのインストール方法はこちら。
Solidity で Hello, World
以下は Solidity でのサンプルコードです。
contract
句で宣言されるコントラクトが基本の構成要素です。コントラクトは Java などのオブジェクト指向言語におけるクラスに似ています。そして、function
に続くのが関数定義です。
このコードでは get
関数が呼ばれると "Hello World" という文字列を返します。
pragma solidity ^0.4.18;
contract HelloWorld {
function get() internal pure returns (string retVal) {
return "Hello World";
}
}
NOTE: 関数定義にて Visibility (可視性)の設定ができます。
external
/public
/internal
/private
から選択でき、もし指定がなければ Warning: No visibility specified. Defaulting to "public".
という警告が出ます。
また、pure
は純粋関数の意味で、状態の読み込みと変更がないことを示します。純粋関数にもかかわらず pure
の記述がないと Warning: Function state mutability can be restricted to pure
という警告が出ます。詳細については公式ドキュメントを参照。
サンプルコードを HelloWorld.sol
として保存し、下記のコマンドを実行するとコンパイルできます。
Binary:
に続く文字列が、コンパイルされたバイトコードである EVM Code です。
% solc --bin hello_world.sol
======= hello_world.sol:HelloWorld =======
Binary:
60606040523415600e57600080fd5b603580601b6000396000f3006060604052600080fd00a165627a7a72305820f80d5060f45e69eba0838f389e99600d64e3bcd7f03288c42af2669d109f628e0029
スマートコントラクトをテストする
ここまででスマートコントラクトを記述し、コンパイルすることができました。
しかしコンパイルしたコントラクトを実行するには、Ethereum ネットワーク上に設置しなければいけません。
Ethereum ネットワークに設置しないとデバッグできないようでは不便なので、Populus というスマートコントラクト開発フレームワークを使用します。
Populus を使うと Python のテストフレームワーク pytest でテストを記述・実行できます。
Populus をインストールする
事前に Python、Solidity と Geth のインストールが必要となります。
依存関係のあるパッケージがいくつかあるので、Homebrew でインストールした後、pip で Populus をインストールします。
% brew install pkg-config libffi autoconf automake libtool openssl
% pip install populus
MacOS 以外の環境でのインストール方法はこちら。
Populus でコンパイル・テスト・デプロイ
適当なディレクトリで populus init
を実行すると、Populus プロジェクトが新規作成されます。
% populus init
下記のようなサンプルのコントラクトとそのテストコードが設置されるので、これを実行します。
pragma solidity ^0.4.0;
contract Greeter {
string public greeting;
function Greeter() {
greeting = 'Hello';
}
function setGreeting(string _greeting) public {
greeting = _greeting;
}
function greet() constant returns (string) {
return greeting;
}
}
def test_greeter(chain):
greeter, _ = chain.provider.get_or_deploy_contract('Greeter')
greeting = greeter.call().greet()
assert greeting == 'Hello'
def test_custom_greeting(chain):
greeter, _ = chain.provider.get_or_deploy_contract('Greeter')
set_txn_hash = greeter.transact().setGreeting('Guten Tag')
chain.wait.for_receipt(set_txn_hash)
greeting = greeter.call().greet()
assert greeting == 'Guten Tag'
Populus ではコンパイルもできます。
% populus compile
> Found 1 contract source files
- contracts/Greeter.sol
> Compiled 1 contracts
- contracts/Greeter.sol:Greeter
> Wrote compiled assets to: build/contracts.json
コンパイル後、テストを実行します。
% py.test
実行結果に 2 passed
が返ってくればテストは通っています。
テストに成功したコードのデプロイも Populus でテストできます。Populus がローカルのメモリ上にテストチェーンを用意し、テストチェーン上にデプロイをしてくれます。
% populus deploy --chain tester --no-wait-for-sync
> Found 1 contract source files
- contracts/Greeter.sol
> Compiled 1 contracts
- contracts/Greeter.sol:Greeter
Please select the desired contract:
0: Greeter
: // 0 を入力して Enter
Beginning contract deployment. Deploying 1 total contracts (1 Specified, 0 because of library dependencies).
Greeter
Deploying Greeter
Deploy Transaction Sent: 0x5e9c682715478ef7984d7621ac63ef4ec0668c6368d69fd0f60c888037cdab50
Waiting for confirmation...
Transaction Mined
=================
Tx Hash : 0x5e9c682715478ef7984d7621ac63ef4ec0668c6368d69fd0f60c888037cdab50
Address : 0xc305c901078781c232a2a521c2af7980f8385ee9
Gas Provided : 466599
Gas Used : 366599
Verified contract bytecode @ 0xc305c901078781c232a2a521c2af7980f8385ee9
Deployment Successful.
これでローカルのテストチェーン上にデプロイできることが確認できました。
テストチェーンなのですぐに終了し、コントラクトが保存されることはありませんが、populus deploy
コマンドの --chain
オプションで、 Ethereum テストネットワークやメインネットワークでもデプロイできるようです。