Rubyからブロックチェーン(Ethereum)に接続する

# この記事について
rubyからブロックチェーンのプラットフォームである[Ethereum](https://www.ethereum.org/)に接続するためのライブラリである、[ethereum.rb](https://github.com/EthWorks/ethereum.rb)を触ってみたので、個人メモを残しておきます。

# Ethereumについて
Ethereumとは一言で言えば、ブロックチェーンのためのプラットフォームですが、スマートコントラクトと呼ばれる、オブジェクト指向プログラミングにおけるクラスのように、データと振る舞いがセットになったインスタンス (コントラクト・コード)をブロックチェーン上に記録し、振る舞いを実行させることが可能になっています。
詳しくはこちらを参照ください。
https://book.ethereum-jp.net/what_is_ethereum/

# ethereum.rbについて
[ethereum.rb](https://github.com/EthWorks/ethereum.rb)はrubyから簡単にEthereum上のコントラクトにアクセスし、コントラクト・コードを実行させることのできるライブラリです。

# 事前準備
この事前準備はethereum.rbを使うためと言うより、Ethereum(geth)の設定なので、既に設定されている方はスキップしてください。
このメモでは簡単な説明しかしないので、詳しくは以下の入門マニュアルが非常にわかりやすいです。
https://book.ethereum-jp.net/

## Ethereumのテスト環境(プライベート・ネット)の起動

### gethのインストール
Ethereumはもちろん本番環境への接続もできますが、テスト用の個人用のネットワークを立ち上げることが出来ます。
そのためには、Gethと呼ばれる、Ethereumクライアントが必要になります。

gethのMacへのインストールは以下を参照ください
https://github.com/ethereum/go-ethereum/wiki/Installation-Instructions-for-Mac

### Genesisファイルの作成
Genesisファイルとは、ネットワークでやり取りされるブロックチェーンの最初のブロックとなる情報を記載したファイルです。
詳しい手順は以下を参照ください。
https://book.ethereum-jp.net/first_use/connect_to_private_net.html

### プライベートネットの起動
インストールしたgethを用いて、プライベートネットを起動するためには以下のコマンドを実行します。
ethereum.rbは、要はGethが提供するJSON RPC APIを叩くためのAdapter Libraryであるため、`---rpc`オプションによって、RPCでの通信を有効にしておきます。

```bash
geth --networkid "10" --nodiscover --datadir "/some/directory/eth_private_net" --rpc --rpcapi="db,eth,net,web3" console 2>> /some/directory/eth_private_net/geth_err.log
```
このコマンドを叩くとEthereumに対してコマンド実行するための、コンソールが起動します。

### アカウントの作成、マイニングの開始
ブロックチェーンに接続するためのアカウント情報を作成し、トランザクションが適切に処理されるようにするため、マイニングを開始します。
詳しい手順は割愛しますが、以下のサイトに非常に良くまとまっているので、こちらを参照しながら設定してみていただければと思います。
https://book.ethereum-jp.net/first_use/mining_ether.html

### アカウントのアンロック（Ethereumへのログイン処理）
Ethereum上でコントラクトコードのデプロイや、ブロックチェーンへの書き込みを行うためには、アカウントをアンロックする必要があります。
作成したアカウントを用いてアンロックするため、上記で起動したコンソール上で、以下のコマンドを叩きます。

```bash
personal.unlockAccount(eth.accounts[0])
```
上記のコマンドを実行するとパスワードの入力が求められるので、パスワードを入力します。
これで、作成したアカウントに対してのアンロックが完了しました。

## コントラクト・コードの作成
ethereum.rbを使用するためには、当然ながら、コントラクトコードを用意する必要があります。
コントラクトは、　スマートコントラクト記述言語である、[Solidity](https://solidity.readthedocs.io/en/develop/)を用いて作成します。
SolidityはJavascriptに少し似ている記述言語であり、非常にわかりやすいシンタックスであるため、普通のスキルを持ったWebエンジニアであれば、1週間くらいあれば習得可能と思います。

今回はethereum.rbの使い方がシンプルにわかれば良いので、に以下のように非常に簡単な、インスタンスにある値を設定し、取得するという簡素なaccessor methodのみを持ったクラスを定義しました。

```
pragma solidity ^0.4.2;

contract SingleNumRegister {
    uint storedData;
    function set(uint x) public {
        storedData = x;
    }
    function get() public constant returns (uint retVal) {
    return storedData;
    }
}
```

# ethereum.rbからのEthereumへの接続

さて、いよいよ、ethereum.rbから立ち上げたEthereumのプライベートネットに接続するための流れとなります。
当然ながら、[ethereum.rb](https://github.com/EthWorks/ethereum.rb)の手順にある通り、ethereum.rbのgemをinstallします。

## 接続用HTTPクライアントの起動

まずは、起動したgethのJSON RPC APIに接続するためのクライアントのオブジェクトを起動します。

```ruby
require 'ethereum'
client = Ethereum::HttpClient.new('http://localhost:8545')
```

## コントラクトコードのデプロイ
次に、作成したコントラクトコードを用いて、コントラクトを、ブロックチェーン上にデプロイを行います。
デプロイとは、オブジェクト指向言語で言うところの、インスタンス生成(`new`)と同じような意味合いです。
デプロイに成功すると、addressというオブジェクトを参照するためのポインタのようなものが発行されます。
(ここで、gethコンソール上で、マイニングを開始しておかないと、deployが出来ませんので、gethコンソール上で`miner.start()`を実行しておいてください。)

```ruby
contract = Ethereum::Contract.create(file: 'single_num_register.sol', client: client)
address = contract.deploy_and_wait()
```

## 生成したコントラクトに対してのメソッド呼び出し
コントラクトのデプロイに成功すると、アドレスと、コントラクト・コードを用いて、以下のメソッドを用いて、メソッド呼び出しが可能になります。
最初に `Ethereum::Contract.create`を呼び出して、ブロックチェーン上に記録された、コントラクトを取得します。
コントラクトを取得すると、`contract.transact_and_wait.hogehoge` or `contract.call.hogehoge`と言った形で、コントラクトコードに定義したメソッドをCallできます。
`transact_and_wait`メソッドの方はトランザクション処理が走り、実行が完了するまで待つメソッドなので、ブロックチェーン上への書き込み処理を呼び出す場合に用い、一方で`call`メソッドは値を取得するなど、読み取り専用メソッドを呼び出す際に用います。

```ruby
# fileにはコントラクトコードを指定し、addressにはデプロイ時に発行されたaddress、clientにはHTTPClientのオブジェクトを指定
# こうすることでブロックチェーン上に記録された、contractオブジェクトが取得できる
contract = Ethereum::Contract.create(file: "single_num_register.sol", address: address, client: client)

# 取得したオブジェクトを用いて、メソッドが発行できる。
contract.transact_and_wait.set(10)

# 設定した値を取得する　（この場合、設定した１０の値が返る）
puts contract.call.get()
```

# 最後に
ここで書いたとおりに、簡単にrubyからEthereumに接続することができました。
Ethereumは、仮想通貨だけにとどまらず、コントラクトコードによって、任意の取引におけるオートマトンを定義できるので、多くの分野に活用できるプラットフォームだと思っています。
このライブラリと組み合わせれば、通常のrailsのActiveRecordと同じように振る舞いを持ったモデルを定義でき、RDBと同じ感覚で、データの永続化ができるので、railsなどと組み合わせて、気軽にブロックチェーンを使ったWebアプリケーションを構築してみるのも良いかと思います。