Amazon Managed Blockchain Hands on

# まずはじめに
本内容は、Blockchain@Loftで利用するハンズオン記事になります。
こちらをベースとした内容になっています。
https://github.com/aws-samples/bank-transfer-blockchain-reinvent2019-workshop

## 前提
- AWSアカウントがあり、AWSアカウントにログインできます。
- アカウントには、このワークショップが使用するリソースに対する権限が必要です。 必要なAWSサービスには、Amazon S3、Amazon Managed Blockchain、Amazon Kinesis Data Streams、Amazon Kinesis Data Firehose、Amazon Athenaが必要になります。

## ハンズオンの概要
- Amazon Managed Blockchainを使用して仮の銀行間転送ソリューションを構築していきます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69671/290b58a3-97d1-45bc-92f6-09d1eae7fcff.png)

## ハンズオンの一連の流れ

- Amazon Managed Blockchainの構築
- Cloud9のSetup
- バンキング、通貨換算、銀行間振替を提供する3つのファブリックチェーンコードプログラム
- チェーンコードを実行してシンプルな、オンラインバンキングエクスペリエンスを提供するREST APIとWebアプリ
- ~~チェーンコードのイベントをリッスンし、Amazon Kinesisに送信するイベントリスナー~~
- ~~Amazon Kinesis Analytics、Amazon Athena、Amazon Quicksightを使用したチェーンコードイベントの分析ソリューションの構築~~

## Let's Go!

### Amazon Manged Blockchainの構築
- 次のパラメーターを使用してブロックチェーンネットワークを作成します。
- Hyperledger Fabricバージョン1.2を選択します
- [ネットワーク名]に、「AmazonManagedBlockchainWorkshop」などのネットワークの名前を入力してください
- 「Bank1」などのメンバー名を入力してください
- 管理者名には、「admin」と入力します
- 管理者パスワードは「Admin123」と入力します。 （ **これは後で重要になります。**）
- これで、ネットワークは単一のメンバーでプロビジョニングされます。ネットワークのプロビジョニングには時間がかかる場合があります。
- ノードを作成します。
- ネットワークがプロビジョニングされたら、ネットワークをクリックします。上部のタブで、[メンバー]をクリックします。
- 「自分が所有するメンバー」のステップ1で指定した名前のメンバーをクリックします。
- [ピアノードの作成]ボタンをクリックします。
- ノードインスタンスタイプとして「bc.t3.small」を選択します。
- 「ピアノードの作成」をクリックします
- これで、単一のメンバーとそのメンバーの下の単一のノードでブロックチェーンネットワークがプロビジョニングされました。これで続行できます。

### Cloud9のSetup

- AWSコンソールからCloud9 IDEを起動します。 
- Cloud9コンソールで、[環境の作成]をクリックします。 リージョンに 'ap-northeast-1'を使用する方が簡単です。
- 環境の名前を入力します。
- [その他のインスタンスタイプ]を選択し、t2.mediumを選択して[次のステップ]をクリックします
- 「環境の作成」をクリックします。 Cloud9 IDEを作成するには、通常30〜60秒かかります
- Cloud9ターミナルのホームディレクトリで、このリポジトリのクローンを作成します。

```
cd ~/environment/
git clone https://github.com/aws-samples/bank-transfer-blockchain-reinvent2019-workshop.git 
```
- Cloud9のdisk volumeの拡張
    - 以下のスクリプトを `/home/ec2-user/environment/resize.sh`という名前で用意します。

```
#!/bin/bash

# Specify the desired volume size in GiB as a command-line argument. If not specified, default to 20 GiB.
SIZE=${1:=20}

# Install the jq command-line JSON processor.
sudo yum -y install jq

# Get the ID of the envrionment host Amazon EC2 instance.
INSTANCEID=$(curl http://169.254.169.254/latest/meta-data//instance-id)

# Get the ID of the Amazon EBS volume associated with the instance.
VOLUMEID=$(aws ec2 describe-instances --instance-id $INSTANCEID | jq -r .Reservations[0].Instances[0].BlockDeviceMappings[0].Ebs.VolumeId)

# Resize the EBS volume.
aws ec2 modify-volume --volume-id $VOLUMEID --size $SIZE

# Wait for the resize to finish.
while [ "$(aws ec2 describe-volumes-modifications --volume-id $VOLUMEID --filters Name=modification-state,Values="optimizing","completed" | jq '.VolumesModifications | length')" != "1" ]; do
  sleep 1
done

# Rewrite the partition table so that the partition takes up all the space that it can.
sudo growpart /dev/xvda 1

# Expand the size of the file system.
sudo resize2fs /dev/xvda1
```

- スクリプトを実行する

```
sh resize.sh 20
sudo reboot
```

- setup する際に、sedで置換

```
sed -i 's/us-east-1/ap-northeast-1/g' ~/environment/bank-transfer-blockchain-reinvent2019-workshop/setup/setup_environment.sh 
sed -i 's/us-east-1-amazonaws/ap-northeast-1-amazonaws/g' ~/environment/bank-transfer-blockchain-reinvent2019-workshop/setup/setup_fabric_environment.py 
```

- 最初のスクリプトは、このワークショップに必要な依存関係とツールをすべて備えた環境をダウンロードしてセットアップします。 以下を実行します。

```
cd ~
~/environment/bank-transfer-blockchain-reinvent2019-workshop/setup/setup_environment.sh
```

- 次に、bashプロファイルをインポートして、更新されたパスと変数を取得する必要があります。

```
source ~/.bash_profile
```

- 次に、ブロックチェーンネットワークの環境をセットアップする2番目のスクリプトを実行する必要があります。 次のスクリプトを実行します。

```
cd ~/environment/
./bank-transfer-blockchain-reinvent2019-workshop/setup/setup_fabric_environment.py
```

- 一連の質問が表示されます。 利用可能なネットワーク、メンバー、ノードを選択します。 次に、スクリプトはいくつかの設定を行います。

- 完了後、以下のfileを読み込みます

```
source ~/fabric_exports
```

- Amazon Managed Blockchain ネットワークとCloud9ノートブックがファブリックと対話するように構成されたので、チェーンコードのデプロイを開始できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69671/85a1a1db-bf03-2dec-746f-310eb90fbfdc.png)

### プライベートチャネルにチェーンコードをデプロイする

上記の指示に従って環境をセットアップしてAWSアカウントにログインすると、最初のステップは、ネットワークのメンバー間で共有されるチャネルをプロビジョニングすることです。チャネルは、メンバーのサブセット間のプライベート通信を可能にするHyperledger Fabricの構造です。ネットワーク上の各トランザクションは、チャネル上で実行されます。

この部分では、次のアクションを実行します。

- プライベートチャネルの構成ファイルを作成し、チャネルのブロックチェーンに最初のブロックを作成します。
- Peer nodeとOrder node に、先ほど作成した構成ファイルを使用してチャネルを作成するよう実行します。
- Peer node をチャネルに参加させて、チャネルと対話し、Orderからトランザクションを取得できるようにします。
- 銀行、Foriegn Exchangeプロバイダー（別名Forexプロバイダー）、およびInterbankに転送プロバイダーを表すチャネルにチェーンコード（別名スマートコントラクト）をインストールしてインスタンス化します。
- Bank内にアカウントを作成し、クエリを実行します。
- チェーンコードをアップグレードします。


### Cloud9インスタンスを開いて環境変数を確認する

- 環境が正しく設定されていることを確認します。環境変数にネットワークの詳細が設定されていることを確認します。

```
echo $MEMBERID
echo $NETWORKID
```

- プライベートチャネル構成の作成
  - スペースを含まない一意の名前をチャンネルに付けます。 ネットワークメンバー間で一意である必要があります。

```
export CHANNEL=<UNIQUE CHANNEL NAME>
```

- チャネル構成を更新します。 このファイルは、チャネルの作成方法を構成します。 NameおよびIDフィールドは、Managed BlockchainのメンバーIDで更新する必要があります。

```
cp ~/environment/bank-transfer-blockchain-reinvent2019-workshop/setup/private-configtx.yaml ~/configtx.yaml
sed -i "s|__MEMBERID__|$MEMBERID|g" ~/configtx.yaml
```

- 次のスクリプトを実行して、configtxチャネル構成を生成します。チャネルが作成されると、このチャネル設定がチャネル上の起点ブロック(すなわちブロック0)になります。

```
docker exec cli configtxgen -outputCreateChannelTx /opt/home/$CHANNEL.pb -profile OneOrgChannel -channelID $CHANNEL --configPath /opt/home/
```

- You should see the following output:

```
2019-11-20 23:34:56.190 UTC [common/tools/configtxgen] doOutputChannelCreateTx -> INFO 005 Writing new channel tx
```

- チャンネルを作成する
  - 次のコマンドを実行して、確立した変数と作成したconfigtxピアブロックを使用してチャネルを作成します。

```
docker exec -e "CORE_PEER_TLS_ENABLED=true" \
-e "CORE_PEER_TLS_ROOTCERT_FILE=/opt/home/managedblockchain-tls-chain.pem" \
-e "CORE_PEER_ADDRESS=$PEER" \
-e "CORE_PEER_LOCALMSPID=$MSP" \
-e "CORE_PEER_MSPCONFIGPATH=$MSP_PATH" \
cli peer channel create -c $CHANNEL \
-f /opt/home/$CHANNEL.pb -o $ORDERER \
--cafile /opt/home/managedblockchain-tls-chain.pem --tls
```

- You should see output which resembles the following:

```
2019-11-23 18:58:38.801 UTC [channelCmd] InitCmdFactory -> INFO 01b Endorser and orderer connections initialized
2019-11-23 18:58:39.003 UTC [cli/common] readBlock -> INFO 01c Got status: &{NOT_FOUND}
2019-11-23 18:58:39.014 UTC [channelCmd] InitCmdFactory -> INFO 01d Endorser and orderer connections initialized
2019-11-23 18:58:39.216 UTC [cli/common] readBlock -> INFO 01e Got status: &{NOT_FOUND}
2019-11-23 18:58:39.228 UTC [channelCmd] InitCmdFactory -> INFO 01f Endorser and orderer connections initialized
2019-11-23 18:58:39.430 UTC [cli/common] readBlock -> INFO 020 Got status: &{NOT_FOUND}
2019-11-23 18:58:39.444 UTC [channelCmd] InitCmdFactory -> INFO 021 Endorser and orderer connections initialized
2019-11-23 18:58:39.650 UTC [cli/common] readBlock -> INFO 022 Received block: 0
```

- ピアをチャンネルに参加させる

```
docker exec -e "CORE_PEER_TLS_ENABLED=true" \
-e "CORE_PEER_TLS_ROOTCERT_FILE=/opt/home/managedblockchain-tls-chain.pem" \
-e "CORE_PEER_ADDRESS=$PEER" \
-e "CORE_PEER_LOCALMSPID=$MSP" \
-e "CORE_PEER_MSPCONFIGPATH=$MSP_PATH" \
cli peer channel join -b $CHANNEL.block \
-o $ORDERER --cafile /opt/home/managedblockchain-tls-chain.pem --tls
```
- You should see output resembling the following, which indicates that your peer has joined the channel:

```
2019-11-23 19:11:22.708 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2019-11-23 19:11:22.937 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
```

### チェーンコードのDeploy

チェーンコードは、Go、Node、またはJavaで記述されたプログラムであり、標準インターフェースを実装し、Fabricピアで実行されます。 チェーンコードは台帳内の状態を管理し、外部プロセスから呼び出すことができる関数を公開します。 このワークショップのこの最初の部分では、銀行、銀行口座、外国為替、および送金を管理するための機能を提供する3つのチェーンコードプログラムを展開します。 


- チェーンコードをGOPATHにコピーします
    - 開始するには、リポジトリのchaincode / srcフォルダーからGOPATHにチェーンコードをコピーします。

```
cp -r ~/environment/bank-transfer-blockchain-reinvent2019-workshop/chaincode/* ~/go/
```

- GOPATHへのシンボリックリンクの追加
    - 組み込みのCloud9エディターでファイルを簡単に変更できるようにするには、環境ディレクトリに〜/ goへのシンボリックリンクを作成します。

```
cd ~/environment/
ln -s ~/go
```

Cloud9の左側の環境ファイルリストに〜/ goが表示されます。

- 依存関係をダウンロード
    - チェーンコードの依存関係をダウンロードします。

```
cd ~/go/src/bank
go get -t 
```

- 銀行チェーンコードをDeployする

BankChaincodeにデプロイする最初のチェーンコード。 これは、対話する主要なチェーンコードであり、このワークショップの他の2つのチェーンコードプログラムから関数を呼び出すチェーンコードです。

BANKCHAINCODENAMEを銀行名に設定します
BANKCHAINCODENAME変数を、スペースや大文字を含まない架空の銀行の名前に設定します。 次に、$ FOREXCHAINCODENAMEを設定します。

```
export BANKCHAINCODENAME=<YOUR FICTIONAL BANK NAME>
export FOREXCHAINCODENAME=$BANKCHAINCODENAME-forex
```

- Install the Chaincode on the Peer

```
docker exec -e "CORE_PEER_TLS_ENABLED=true" \
-e "CORE_PEER_TLS_ROOTCERT_FILE=/opt/home/managedblockchain-tls-chain.pem"  \
-e "CORE_PEER_LOCALMSPID=$MSP" \
-e "CORE_PEER_MSPCONFIGPATH=$MSP_PATH"  \
-e "CORE_PEER_ADDRESS=$PEER" \
cli peer chaincode install -n $BANKCHAINCODENAME -v v0 -p bank/cmd  
```

```
2019-11-23 18:54:01.948 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" > 
```

- Instantiate the Bank Chaincode

```
docker exec -e "CORE_PEER_TLS_ENABLED=true" \
-e "CORE_PEER_TLS_ROOTCERT_FILE=/opt/home/managedblockchain-tls-chain.pem"  \
-e "CORE_PEER_LOCALMSPID=$MSP" \
-e "CORE_PEER_MSPCONFIGPATH=$MSP_PATH"  \
-e "CORE_PEER_ADDRESS=$PEER" \
cli peer chaincode instantiate -o $ORDERER -C $CHANNEL -n $BANKCHAINCODENAME -v v0 -c '{"Args":["The Royal Bank of Cloud", "0001", "'$FOREXCHAINCODENAME'"]}' --cafile /opt/home/managedblockchain-tls-chain.pem --tls  
```

- 新しいアカウントを作成する（チェーンコードを呼び出す）

これでチェーンコードがインストールされ、インスタンス化されたので、それを呼び出すことができます。 createAccount関数は4つの引数を取ります。口座所有者の名前、口座番号、口座の残高、および口座で使用される通貨（3文字の通貨記号として）です。 口座番号が0000001、残高が50米ドルの新しい銀行口座を作成してみましょう。

```
docker exec -e "CORE_PEER_TLS_ENABLED=true" \
-e "CORE_PEER_TLS_ROOTCERT_FILE=/opt/home/managedblockchain-tls-chain.pem"  \
-e "CORE_PEER_LOCALMSPID=$MSP" \
-e "CORE_PEER_MSPCONFIGPATH=$MSP_PATH"  \
-e "CORE_PEER_ADDRESS=$PEER" \
cli peer chaincode invoke  -C $CHANNEL -n $BANKCHAINCODENAME -c '{"Args":["createAccount", "zabbio", "0000001", "500000", "USD"]}' --cafile /opt/home/managedblockchain-tls-chain.pem --tls
```
```
2019-11-21 00:21:09.408 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 002 Chaincode invoke successful. result: status:200 
```

- そのアカウントをクエリする（クエリチェーンコード）
次に、そのアカウントにクエリを実行すると、アカウントの詳細が返されます。

```
docker exec -e "CORE_PEER_TLS_ENABLED=true" \
-e "CORE_PEER_TLS_ROOTCERT_FILE=/opt/home/managedblockchain-tls-chain.pem"  \
-e "CORE_PEER_LOCALMSPID=$MSP" \
-e "CORE_PEER_MSPCONFIGPATH=$MSP_PATH"  \
-e "CORE_PEER_ADDRESS=$PEER" \
cli peer chaincode invoke  -C $CHANNEL -n $BANKCHAINCODENAME -c '{"Args":["queryAccount", "0000001"]}' --cafile /opt/home/managedblockchain-tls-chain.pem --tls 
```

- Create a Second Account
Let's create a second account. This time with account number 0000002 and 0 USD balance.

```
docker exec -e "CORE_PEER_TLS_ENABLED=true" \
-e "CORE_PEER_TLS_ROOTCERT_FILE=/opt/home/managedblockchain-tls-chain.pem"  \
-e "CORE_PEER_LOCALMSPID=$MSP" \
-e "CORE_PEER_MSPCONFIGPATH=$MSP_PATH"  \
-e "CORE_PEER_ADDRESS=$PEER" \
cli peer chaincode invoke  -C $CHANNEL -n $BANKCHAINCODENAME -c '{"Args":["createAccount", "kuwano", "0000002", "10", "USD"]}' --cafile /opt/home/managedblockchain-tls-chain.pem --tls  
```

- Transfer Between Accounts

Now, let's perform an intra-bank transfer between accounts

```
docker exec -e "CORE_PEER_TLS_ENABLED=true" \
-e "CORE_PEER_TLS_ROOTCERT_FILE=/opt/home/managedblockchain-tls-chain.pem"  \
-e "CORE_PEER_LOCALMSPID=$MSP" \
-e "CORE_PEER_MSPCONFIGPATH=$MSP_PATH"  \
-e "CORE_PEER_ADDRESS=$PEER" \
cli peer chaincode invoke -C $CHANNEL -n $BANKCHAINCODENAME -c '{"Args":["transfer", "0000001", "0001", "0000002", "10"]}' --cafile /opt/home/managedblockchain-tls-chain.pem --tls  
```

- Query account 0000002 and confirm the transfer was successful

```
docker exec -e "CORE_PEER_TLS_ENABLED=true" \
-e "CORE_PEER_TLS_ROOTCERT_FILE=/opt/home/managedblockchain-tls-chain.pem"  \
-e "CORE_PEER_LOCALMSPID=$MSP" \
-e "CORE_PEER_MSPCONFIGPATH=$MSP_PATH"  \
-e "CORE_PEER_ADDRESS=$PEER" \
cli peer chaincode invoke  -C $CHANNEL -n $BANKCHAINCODENAME -c '{"Args":["queryAccount", "0000002"]}' --cafile /opt/home/managedblockchain-tls-chain.pem --tls  
```

- You should see the following (note the balance is 20 now):

```
2019-11-27 02:06:13.149 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 002 Chaincode invoke successful. result: status:200 payload:"{\"name\":\"kuwano\",\"id\":\"0000002\",\"balance\":\"20\",\"currency\":\"USD\"}" 
```

- アカウントの履歴状態を調べる

振替を実行することにより、各アカウントの新しい残高を保存するように台帳を変更しました。 元帳の履歴状態を調べ、アカウントがどのように変更されたかを調べることができます。 そのためには、getTransactionHistory関数を実行します。

```
docker exec -e "CORE_PEER_TLS_ENABLED=true" \
-e "CORE_PEER_TLS_ROOTCERT_FILE=/opt/home/managedblockchain-tls-chain.pem"  \
-e "CORE_PEER_LOCALMSPID=$MSP" \
-e "CORE_PEER_MSPCONFIGPATH=$MSP_PATH"  \
-e "CORE_PEER_ADDRESS=$PEER" \
cli peer chaincode invoke -C $CHANNEL -n $BANKCHAINCODENAME -c '{"Args":["getTransactionHistory", "0000001"]}' --cafile /opt/home/managedblockchain-tls-chain.pem --tls  
```

### REST APIとWebアプリの構成とデプロイ

前のセクションでは、Fabric CLIを介してチェーンコードを直接操作しました。 手動でチェーンコード関数を呼び出すのは少し面倒であり、定期的にこれを実行することはほとんどありません。 チェーンコードを呼び出すより伝統的なアプリケーションを構築することが望ましいでしょう。 チェーンコードを使用せずにアプリケーションを統合することで、あらゆる方法のワークフローにブロックチェーンを統合できます。 金融サービスのコンテキスト内で、チェーンコードをメッセージキュー、Webアプリ、ミドルウェアと統合する一般的な使用例。 このセクションでは、チェーンコードと相互作用するREST APIをデプロイします。


- Install Dependencies

```
cd ~/environment/bank-transfer-blockchain-reinvent2019-workshop/api
npm install
```

- Generate Connection Profile

```
chmod +x ~/environment/bank-transfer-blockchain-reinvent2019-workshop/api/connection-profile/gen-profile.sh
./connection-profile/gen-profile.sh
```

接続プロファイルが正しく生成されたことを確認します。

```
cat ~/environment/bank-transfer-blockchain-reinvent2019-workshop/tmp/connection-profile/bank-connection-profile.yaml
```

- config fileの編集

Cloud9のエディターを使用して、bank-transfer-blockchain-reinvent2019-workshop/api/config.jsonファイルを編集し、チャネルの名前（ourchannelまたは$ CHANNELのいずれか）と銀行チェーンコードの名前（指定しない場合）を指定します それが何であるかを覚えてない場合は、「echo $ BANKCHAINCODENAME」を実行してください）。

```
echo $CHANNEL
echo $BANKCHAINCODENAME
```

```
vi ~/environment/bank-transfer-blockchain-reinvent2019-workshop/api/config.json
```

- Start the REST API

```
cd ~/environment/bank-transfer-blockchain-reinvent2019-workshop/api/
./start.sh
```

- REST APIを使用して転送を呼び出す
    - Cloud9で、タブの（+）ボタンをクリックして新しいターミナルを開始し、[新しいターミナル]を選択します。 実行：

```
source ~/fabric_exports
```

```
curl http://localhost:8081/account/0000001
curl -s -X POST http://localhost:8081/transfer -H "Content-Type: application/json" -d '{"FromAccNumber":"0000001", "ToBankID": "0001", "ToAccNumber": "0000002", "Amount": "1"}'
curl http://localhost:8081/transactions/0000001
```

### Deploy the Web App

次に、シンプルなAngular UIをデプロイして、Web APIを呼び出します。 実際の環境では、エンドユーザーはブロックチェーンとの直接的なやり取りが最小限であるか、まったくありません。 代わりに、Web UIなどの従来のインターフェースは、基盤となるチェーンコードとインフラストラクチャを抽象化します。 このセクションでは、この概念を示します。

2番目のターミナル（最初のターミナルはwebservicesを実行しています）を使用して、uiディレクトリに移動します。

```
cd ~/environment/bank-transfer-blockchain-reinvent2019-workshop/ui
```


Cloud9エディターを使用して、'ui/src/environments/environment.ts' を編集し、「bank_name」の値を銀行に付けた名前に変更します。 Cloud9インスタンスのパブリックIPアドレスを使用するようにapp_urlを変更します。 次のコマンドを実行して、パブリックIPを見つけることができます。

```
curl ifconfig.moe
vim /home/ec2-user/environment/bank-transfer-blockchain-reinvent2019-workshop/ui/src/environments/environment.ts
```

次に、Webアプリの依存関係をインストールします。

```
npm install -g @angular/cli
npm install
```

install が完了したら、ng serveで起動

```
ng serve --port 8080 --disableHostCheck true --host 0.0.0.0
```

- Webアプリを表示する

ブラウザーでhttp：// public-ip-of-the-cloud-instance：8080に移動します。上記のコマンドを使用して、インスタンスのパブリックIPを見つけることができます。

Webアプリでは、口座番号を使用してログインし、現在の残高、過去の取引を表示して、取引を行うことができます。 アカウントID 0000001を使用してzabbioとしてログインしてみてください。

注：UIにアクセスできない場合は、他のファイアウォールルールがポート8080へのトラフィックを許可していない可能性があります。企業VPNを使用している場合は、切断する必要があります。

または、ポート8080に接続できない場合。「Preview Running App」を選択して組み込みのCloud9 Webブラウザーを使用し、Webアプリケーションに移動します。