Help us understand the problem. What is going on with this article?

Ethereum のスマートコントラクト実行環境を整える

More than 1 year has passed since last update.

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" という文字列を返します。

HelloWorld.sol
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

下記のようなサンプルのコントラクトとそのテストコードが設置されるので、これを実行します。

contracts/Greeter.sol
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;
    }
}
tests/test_greeter.py
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 テストネットワークやメインネットワークでもデプロイできるようです。

参考文献

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away