Chain環境構築

#Chainとは
VISA主導で進められていた、多数企業が参画していたプロジェクトのブロックチェーン技術。
もともとはクローズドソース。
2016年11月時点では、Chain Core Developer Editionというエディションに限りオープンソース化されている。
Enterprise向けEditionは非公開で、Developer Editionとの機能差異が若干ある。
まだオープンソース化されたばかりで情報が少ないが、もともとEnterprise版はJava用のSDKもあり、ドキュメントも比較的充実していたため、そちらが参考になると思われる。
#ドキュメント
###Chain Docs
https://chain.com/docs/core/get-started/introduction
を参考に。
サンプルコードもあげられているため、そちらも参考になる。
オープンソース化された為、今後Web上でも記事が増えてくると期待したい。
#環境構築手順
##centos7での構築
###AWSのEC2にcentos7ベースでインスタンス生成
AWSではなく、ローカルPCに仮想環境でも可。
Windows版はinstallerが用意されている。
ほかのディストリビューションでも可能だと思われる。
###事前準備
```
$ sudo yum update
$ sudo yum upgrade
$ sudo yum install epel-release
$ sudo yum update
```
このへんはお好みで。
###SELinux無効化
```
$ sudo nano /etc/selinux/config
```
SELINUX=disabled
に変更して保存。（使いたい人は飛ばす）
###Dockerインストール
以下URLを参考に。
https://docs.docker.com/engine/installation/linux/centos/

```
$ sudo tee /etc/yum.repos.d/docker.repo <<-'EOF'
[dockerrepo]
name=Docker Repository
baseurl=https://yum.dockerproject.org/repo/main/centos/7/
enabled=1
gpgcheck=1
gpgkey=https://yum.dockerproject.org/gpg
EOF
```
```
$ sudo yum install docker-engine
$ sudo systemctl enable docker.service
$ sudo systemctl start docker
$ sudo docker run --rm hello-world
```
###chaincore起動
```
$ sudo docker run --name firstchain -it -p 1999:1999 chaincore/developer
Initializing Chain Core...
Listening on: http://localhost:1999
Client access token: client:c4b26a66d35d3369028202004d92ddd9747bc2b9ef3700be2a9fffa24f666ed8
Chain Core is online!
```
のように表示され、アクセストークンが発行される。
この部分をメモ。
ここで、
>「client:．．．．．．」の部分

つまり"client:"部分を含んだ文字列がアクセストークン。
再起動する場合はDockerコンテナの再起動で。

```
$ sudo docker restart firstchain 
```


###EC2セキュリティグループで、1999ポート開放
Chainには管理画面があり、起動時に指定したポートでWebアプリケーションが起動している。メニューから初回のチェーンの新規作成やアカウント作成、asset（通貨）定義などもこの管理画面から操作可能。
###管理画面にブラウザアクセス
ローカルPCのブラウザから
http://ec2のIPアドレス:1999/
にアクセス。（初回はチェーンがないので必須）

ログイン画面になり、アクセストークンの入力を求められるので、
上記でメモしたアクセストークンを入力してログイン。
![FireShot Capture 1 - Chain Core Dashboard - http___52.198.35.160_1999_dashboard_.png](https://qiita-image-store.s3.amazonaws.com/0/142538/d6c1d98c-4bb7-fee7-0dd0-f4bd96967f22.png)

３つ並んでいて、左でチェーンを作成できる。
![FireShot Capture 2 - Chain Core Dashboard - http___52.198.35.160_1999_dashboard_configuration.png](https://qiita-image-store.s3.amazonaws.com/0/142538/d564bf23-84aa-e3e5-3004-d694fac2b298.png)

##プログラムからアクセス
###JavaSDKダウンロード
JavaのSDKを下記からダウンロード
https://chain.com/docs/java/chain-sdk-latest.jar

JavaのSDK(chain-sdk-latest.jar)をビルドパスに組み込んだjavaアプリケーションから
APIを実行することでも、通貨定義や送金、通貨ごとの残高確認や、アカウント作成など実行できる。
だいたいメソッドチェーンで書けるようになっているので分かりやすい。

以下、テスト実行用クラスを一部抜粋。
使用できるメソッドやクラスは、公式サイトのサンプルコードを参考に。

```
package com.example.service;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.chain.api.Account;
import com.chain.api.Asset;
import com.chain.api.Balance;
import com.chain.api.MockHsm;
import com.chain.api.Transaction;
import com.chain.exception.ChainException;
import com.chain.http.Client;
import com.chain.signing.HsmSigner;

@Service
public class FirstChainApiService {

	public static final String TARGET_URL = "http://XX.XXX.XXX.XXX:1999/";
	public static final String TOKEN = "client:c4b26a66d35d3369028202004d92ddd9747bc2b9ef3700be2a9fffa24f666ed8";//サーバ起動のたびにかわる

	private static final Logger LOGGER = LoggerFactory.getLogger(FirstChainApiService.class.getName());

	public String checkApi() throws ChainException {
		Client client = new Client(TARGET_URL,TOKEN);
		MockHsm.Key key = MockHsm.Key.create(client);
		HsmSigner.addKey(key, MockHsm.getSignerClient(client));
		//通貨定義
		Asset asset = new Asset.Builder().setAlias("gold").addRootXpub(key.xpub).setQuorum(1)
				.create(client);
		//アカウント作成
		Account alice = new Account.Builder().setAlias("alice").addRootXpub(key.xpub)
				.setQuorum(1).create(client);
		Account bob = new Account.Builder().setAlias("bob").addRootXpub(key.xpub)
				.setQuorum(1).create(client);
		
		//chain上にgoldを100生成し、aliceに100gold設定
		Transaction.Template issuance = new Transaction.Builder()
				.addAction(
						new Transaction.Action.Issue().setAssetAlias("gold")
								.setAmount(100))
				.addAction(
						new Transaction.Action.ControlWithAccount()
								.setAccountAlias("alice").setAssetAlias("gold")
								.setAmount(100)).build(client);

		Transaction.submit(client, HsmSigner.sign(issuance));

		//aliceから10gold出力し、bobに10gold設定
		Transaction.Template spending = new Transaction.Builder()
				.addAction(
						new Transaction.Action.SpendFromAccount()
								.setAccountAlias("alice").setAssetAlias("gold")
								.setAmount(10))
				.addAction(
						new Transaction.Action.ControlWithAccount()
								.setAccountAlias("bob").setAssetAlias("gold")
								.setAmount(10)).build(client);

		Transaction.submit(client, HsmSigner.sign(spending));

		//bobから5gold出力し、5gold破棄
		Transaction.Template retirement = new Transaction.Builder()
				.addAction(
						new Transaction.Action.SpendFromAccount()
								.setAccountAlias("bob").setAssetAlias("gold")
								.setAmount(5))
				.addAction(
						new Transaction.Action.Retire().setAssetAlias("gold")
								.setAmount(5)).build(client);

		Transaction.submit(client, HsmSigner.sign(retirement));

		LOGGER.info("balance before");

		//aliceの残高
		Balance.Items balances = new Balance.QueryBuilder()
		  .setFilter("account_alias=$1")
		  .addFilterParameter("alice")
		  .execute(client);

		LOGGER.info("balance after");

		while (balances.hasNext()) {
		  Balance b = balances.next();
		  LOGGER.info(
		    "Alice's balance of " + b.sumBy.get("asset_alias") +
		    ": " + b.amount
		  );
		}
		return "success";//とりあえず動かしてログで確認したかっただけで、別に意味はないです
	}
}
```