#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/
にアクセス。(初回はチェーンがないので必須)
ログイン画面になり、アクセストークンの入力を求められるので、
上記でメモしたアクセストークンを入力してログイン。
##プログラムからアクセス
###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";//とりあえず動かしてログで確認したかっただけで、別に意味はないです
}
}