【Hyperledger Fabric v1.4.11】Marbles Demo を動作させる①

# やりたいこと
Hyperledger Fabric ネットワーク上で簡単なデモアプリケーション（Marbles Demo）を動作させます。
思ったよりボリュームが増えたので、本ページでは、初期設定を完了させるところまでを記載しています。


# Marbles Demo とは？
* Hyperledger Fabric ネットワーク上で“Marbles”資産（＝ビー玉）の取引を行う簡単なデモアプリケーション
* GitHub上で公開されている（ https://github.com/IBM-Blockchain-Archive/marbles ）


# Marbles Demo のインストール

## 環境
以下の手順に従って Hyperledger Fabric v1.4.11 を構築した環境を想定しています。

https://qiita.com/kbys7367/items/53793c7077171b8e3673

## Marbles Demo のダウンロード
```
~$ cd fabric/fabric-samples/
~/fabric/fabric-samples$ git clone https://github.com/IBM-Blockchain/marbles.git --depth 1
Cloning into 'marbles'...
remote: Enumerating objects: 187, done.
remote: Counting objects: 100% (187/187), done.
remote: Compressing objects: 100% (178/178), done.
remote: Total 187 (delta 4), reused 92 (delta 0), pack-reused 0
Receiving objects: 100% (187/187), 4.26 MiB | 0 bytes/s, done.
Resolving deltas: 100% (4/4), done.
Checking connectivity... done.

~/fabric/fabric-samples$ cd marbles/
```

## Marbles Demo のセットアップ
```
~/fabric/fabric-samples/marbles$ sudo npm install gulp -g
npm WARN deprecated chokidar@2.1.8: Chokidar 2 will break on node v14+. Upgrade to chokidar 3 with 15x less dependencies.
（中略）
+ gulp@4.0.2
added 323 packages from 220 contributors in 51.402s

~/fabric/fabric-samples/marbles$ npm install
npm WARN deprecated node-pre-gyp@0.7.0: Please upgrade to @mapbox/node-pre-gyp: the non-scoped node-pre-gyp package is deprecated and only the @mapbox scoped package will recieve updates in the future
npm WARN deprecated request@2.83.0: request has been deprecated, see https://github.com/request/request/issues/3142
（中略）
found 60 vulnerabilities (23 low, 8 moderate, 29 high)
  run `npm audit fix` to fix them, or `npm audit` for details
```

**注）Node.js のバージョンは v10.24.1 でしたが、「npm install」で以下のエラーになったため、v8.17.0にダウングレードしました。**

```
> grpc@1.10.1 install /home/vagrant/fabric/fabric-samples/marbles/node_modules/grpc
> node-pre-gyp install --fallback-to-build --library=static_library

node-pre-gyp ERR! Tried to download(403): https://storage.googleapis.com/grpc-precompiled-binaries/node/grpc/v1.10.1/node-v64-linux-x64-glibc.tar.gz
node-pre-gyp ERR! Pre-built binaries not found for grpc@1.10.1 and node@10.24.1 (node-v64 ABI, glibc) (falling back to source compile with node-gyp)
node-pre-gyp ERR! Pre-built binaries not installable for grpc@1.10.1 and node@10.24.1 (node-v64 ABI, glibc) (falling back to source compile with node-gyp)
node-pre-gyp ERR! Hit error Connection closed while downloading tarball file
（以降略）
```


## ゲスト OS のポートフォワーディング設定
Marbles Demo はWebアプリケーションのため、ホストOS上のWebブラウザからアクセスできるようにします。

### ゲストOSのシャットダウン
```
~/fabric/fabric-samples/marbles$ exit
logout
Connection to 127.0.0.1 closed.

$ vagrant halt
==> default: Attempting graceful shutdown of VM...
```

### ポートフォワーディング設定
ゲストOSの3001番ポートをホストOSの3001番ポートにフォワーディングするよう、Vagrangfile を修正します。
```config.vm.network "forwarded_port", guest: 3001, host: 3001```を追加します。


```
  # Create a forwarded port mapping which allows access to a specific port
  # within the machine from a port on the host machine. In the example below,
  # accessing "localhost:8080" will access port 80 on the guest machine.
  # NOTE: This will enable public access to the opened port
  # config.vm.network "forwarded_port", guest: 80, host: 8080
  config.vm.network "forwarded_port", guest: 3001, host: 3001
```

ゲストOSの起動ログでポートフォワーディング設定が反映されていることを確認できます。

```
$ vagrant up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Clearing any previously set forwarded ports...
==> default: Clearing any previously set network interfaces...
==> default: Preparing network interfaces based on configuration...
    default: Adapter 1: nat
==> default: Forwarding ports...
    default: 3001 (guest) => 3001 (host) (adapter 1)
    default: 22 (guest) => 2222 (host) (adapter 1)
（以降略）
```

# Marbles Demo の実行

## 作業ステップ
* ステップ① Marbles Demo 用のブロックチェーンネットワーク起動
* ステップ② Marbles Demo のチェーンコード配備
* ステップ③ Marbles Demo の起動
* ステップ④ Marbles Demo へWebブラウザでアクセス
* ステップ⑤ Marbles Demo の初期設定（初回ログイン時のみ）


## ステップ① Marbles Demo 用のブロックチェーンネットワーク起動
basic-network に付属するブロックチェーンネットワーク起動スクリプト「start.sh」を使用します。
起動前にキーストアを初期化（再作成）しています。

```
~$ cd fabric/fabric-samples/basic-network/
~/fabric/fabric-samples/basic-network$ rm -rf ~/.hfc-key-store
~/fabric/fabric-samples/basic-network$ mkdir ~/.hfc-key-store

~/fabric/fabric-samples/basic-network$ ./start.sh

# don't rewrite paths for Windows Git Bash users
export MSYS_NO_PATHCONV=1
（中略）
/Admin@org1.example.com/msp" peer0.org1.example.com peer channel join -b mychannel.block
2021-04-15 14:14:45.394 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-04-15 14:14:45.599 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel

~/fabric/fabric-samples/marbles/scripts$ docker ps
CONTAINER ID   IMAGE                        COMMAND                  CREATED         STATUS         PORTS                                                                                  NAMES
327e8c060cc3   hyperledger/fabric-peer      "peer node start"        2 minutes ago   Up 2 minutes   0.0.0.0:7051->7051/tcp, :::7051->7051/tcp, 0.0.0.0:7053->7053/tcp, :::7053->7053/tcp   peer0.org1.example.com
f665568a9257   hyperledger/fabric-ca        "sh -c 'fabric-ca-se…"   2 minutes ago   Up 2 minutes   0.0.0.0:7054->7054/tcp, :::7054->7054/tcp                                              ca.example.com
8d83a288d7c9   hyperledger/fabric-couchdb   "tini -- /docker-ent…"   2 minutes ago   Up 2 minutes   4369/tcp, 9100/tcp, 0.0.0.0:5984->5984/tcp, :::5984->5984/tcp                          couchdb
b1ccdbce5478   hyperledger/fabric-orderer   "orderer"                2 minutes ago   Up 2 minutes   0.0.0.0:7050->7050/tcp, :::7050->7050/tcp                                              orderer.example.com
```

## ステップ② Marbles Demo のチェーンコード配備
起動したチェーンネットワークに、Marbles Demo  のチェーンコードを配備します。
配備は、Marbles Demo に付属のスクリプトを使用して行います。

### connection_profile_local.json の編集（任意）
Hyperledger Fabric のインストール先に応じて、"path"の値を変更します（3か所）
今回は、```/$HOME/fabric```配下にインストールした場合になります。

* 変更前：/$HOME/fabric-samples/…
* 変更後：/$HOME/fabric/fabric-samples/…

```
~$ cp -p fabric/fabric-samples/marbles/config/connection_profile_local.json fabric/fabric-samples/marbles/config/connection_profile_local.json.bak

~$ vi fabric//fabric-samples/marbles/config/connection_profile_local.json

~$ diff fabric/fabric-samples/marbles/config/connection_profile_local.json.bak fabric/fabric-samples/marbles/config/connection_profile_local.json
10c10
<                       "path": "/$HOME/fabric-samples/fabcar/hfc-key-store"
---
>                       "path": "/$HOME/fabric/fabric-samples/fabcar/hfc-key-store"
39c39
<                               "path": "/$HOME/fabric-samples/basic-network/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/admincerts/Admin@org1.example.com-cert.pem"
---
>                               "path": "/$HOME/fabric/fabric-samples/basic-network/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/admincerts/Admin@org1.example.com-cert.pem"
42c42
<                               "path": "/$HOME/fabric-samples/basic-network/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/"
---
>                               "path": "/$HOME/fabric/fabric-samples/basic-network/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/keystore/"
```

変更しなかった場合、スクリプトを実行後、以下のようなエラーが発生します。

```
info: First we enroll
/home/vagrant/fabric/fabric-samples/marbles/utils/connection_profile_lib/parts/org.js:102
                throw new Error('Cannot find org.', orgName);
                ^

Error: Cannot find org.
    at Object.helper.getAdminPrivateKeyPEM (/home/vagrant/fabric/fabric-samples/marbles/utils/connection_profile_lib/parts/org.js:102:9)
    at Object.cp.makeEnrollmentOptionsUsingCert (/home/vagrant/fabric/fabric-samples/marbles/utils/connection_profile_lib/index.js:238:22)
（以降略）
```

### スクリプトの実行（チェーンコードの配備とインスタンス化）
「install_chaincode.js」を使用して、チェーンコードを配備します。

```
~$ cd fabric/fabric-samples/marbles/scripts/
~/fabric/fabric-samples/marbles/scripts$ node install_chaincode.js
info: Loaded config file /home/vagrant/fabric/fabric-samples/marbles/config/marbles_local.json
info: Loaded connection profile file /home/vagrant/fabric/fabric-samples/marbles/config/connection_profile_local.json
（中略）
info: [packager/Golang.js]: packaging GOLANG from marbles
debug: [fcw] Successfully obtained transaction endorsement
---------------------------------------
info: Install done. Errors: nope
---------------------------------------
```

「instantiate_chaincode.js」を使用して、チェーンコードをインスタンス化します。

```
~/fabric/fabric-samples/marbles/scripts$ node instantiate_chaincode.js
info: Loaded config file /home/vagrant/fabric/fabric-samples/marbles/config/marbles_local.json
info: Loaded connection profile file /home/vagrant/fabric/fabric-samples/marbles/config/connection_profile_local.json
（中略）
debug: [fcw] Successfully obtained transaction endorsement
debug: [fcw] Successfully ordered instantiate endorsement.
---------------------------------------
info: Instantiate done. Errors: nope
---------------------------------------
```

インスタンス化が成功すると、コンテナが起動します（CONTAINER ID が"50ff019b359c"）。

```
~/fabric/fabric-samples/marbles/scripts$ docker ps
CONTAINER ID   IMAGE                                                                                                    COMMAND                  CREATED          STATUS          PORTS                                                                                  NAMES
50ff019b359c   dev-peer0.org1.example.com-marbles-v4-f704f1411b52539123b5920f0c3d59dc4c88aa255a82cd002be690a5a6a8150e   "chaincode -peer.add…"   32 seconds ago   Up 31 seconds                                                                                          dev-peer0.org1.example.com-marbles-v4
327e8c060cc3   hyperledger/fabric-peer                                                                                  "peer node start"        4 minutes ago    Up 4 minutes    0.0.0.0:7051->7051/tcp, :::7051->7051/tcp, 0.0.0.0:7053->7053/tcp, :::7053->7053/tcp   peer0.org1.example.com
f665568a9257   hyperledger/fabric-ca                                                                                    "sh -c 'fabric-ca-se…"   4 minutes ago    Up 4 minutes    0.0.0.0:7054->7054/tcp, :::7054->7054/tcp                                              ca.example.com
8d83a288d7c9   hyperledger/fabric-couchdb                                                                               "tini -- /docker-ent…"   4 minutes ago    Up 4 minutes    4369/tcp, 9100/tcp, 0.0.0.0:5984->5984/tcp, :::5984->5984/tcp                          couchdb
b1ccdbce5478   hyperledger/fabric-orderer                                                                               "orderer"                4 minutes ago    Up 4 minutes    0.0.0.0:7050->7050/tcp, :::7050->7050/tcp                                              orderer.example.com
```

## ステップ③ Marbles Demo の起動
gulpコマンドに"marbles_local"ターゲットを指定して実行します。

```
~$ cd fabric/fabric-samples/marbles/

~/fabric/fabric-samples/marbles$ gulp marbles_local
[08:50:23] Using gulpfile ~/fabric/fabric-samples/marbles/gulpfile.js
[08:50:23] Starting 'env_local'...
（中略）
----------------------------------- Server Up - localhost:3001 -----------------------------------
Welcome aboard:  United Marbles
Channel:         mychannel
Org:             Org1MSP
CA:              fabric-ca
Orderer:         fabric-orderer
Peer:            fabric-peer-org1
Chaincode ID:    marbles
Chaincode Version:  v4
（中略）
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
info: Detected that we have NOT launched successfully yet
debug: Open your browser to http://localhost:3001 and login as "admin" to initiate startup
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
```


### gulp コマンドの実行でエラーになった場合

最初、gulp コマンドを実行すると以下のエラーが発生しました。

```
~/fabric/fabric-samples/marbles$ gulp marbles_local
~/fabric/fabric-samples/marbles$ { Error: ENOENT: no such file or directory, scandir '/home/vagrant/fabric/fabric-samples/marbles/node_modules/node-sass/vendor'
    at Object.fs.readdirSync (fs.js:904:18)
    at Object.getInstalledBinaries (/home/vagrant/fabric/fabric-samples/marbles/node_modules/node-sass/lib/extensions.js:133:13)
    at foundBinariesList (/home/vagrant/fabric/fabric-samples/marbles/node_modules/node-sass/lib/errors.js:20:15)
    at foundBinaries (/home/vagrant/fabric/fabric-samples/marbles/node_modules/node-sass/lib/errors.js:15:5)
    at Object.module.exports.missingBinary (/home/vagrant/fabric/fabric-samples/marbles/node_modules/node-sass/lib/errors.js:45:5)
    at module.exports (/home/vagrant/fabric/fabric-samples/marbles/node_modules/node-sass/lib/binding.js:15:30)
    at Object.<anonymous> (/home/vagrant/fabric/fabric-samples/marbles/node_modules/node-sass/lib/index.js:14:35)
    at Module._compile (module.js:653:30)
    at Object.Module._extensions..js (module.js:664:10)
    at Module.load (module.js:566:32)
  errno: -2,
  code: 'ENOENT',
  syscall: 'scandir',
  path: '/home/vagrant/fabric/fabric-samples/marbles/node_modules/node-sass/vendor' }
```

```marbles/node_modules/node-sass/``` 配下に、```vendor```ディレクトリが存在しないってエラーなのですが、以下の手順で解決しました（参考：https://qiita.com/master-of-sugar/items/e755bbbdf7112538eb7e ）。

```
$ cd fabric/fabric-samples/marbles/node_modules/node-sass/
~/fabric/fabric-samples/marbles/node_modules/node-sass$ ls
bin          CHANGELOG.md  LICENSE       package.json  scripts  test
binding.gyp  lib           node_modules  README.md     src

~/fabric/fabric-samples/marbles/node_modules/node-sass$ npm install
（出力メッセージは省略）
~/fabric/fabric-samples/marbles/node_modules/node-sass$ npm rebuild node-saas
（出力メッセージは省略）

~/fabric/fabric-samples/marbles/node_modules/node-sass$ ls
bin          CHANGELOG.md  LICENSE       package.json       README.md  src   vendor
binding.gyp  lib           node_modules  package-lock.json  scripts    test
```

## ステップ④ Marbles Demo へWebブラウザでアクセス

Marbles Demo の起動成功後に出力されるアクセス用のURL（ http://localhost:3001 ）へ、Webブラウザでアクセスします。
以下の画面が表示されたら成功です。

![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283970/d9a75355-3f92-eac4-a4bd-e1292306c5a8.png)



## ステップ⑤ Marbles Demo の初期設定（初回ログイン時のみ）

ここでは、[Express]のボタンをクリックします。
デフォルトの設定で自動的に初期設定が行われます。
初期設定が完了すると、以下の状態で台帳が初期化されます。

* "Any"、"Alice"、"Ava"の3ユーザが作られる。
* 大小3つのMarbles資産を各自が持つ。

![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283970/ffdb0fec-ca83-05ac-acf6-0ec252ef6a00.png)

メイン画面上部の「Settings」をクリックすると、"Story Mode"の設定を確認できます。
"Story Mode"は、Hyperledger Fabric における処理の流れを視覚化してくれるので、"Disable"になっている場合は"Enable"へ変更します。
「Story mode is **on**」になっていることを確認してください。

![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283970/9ab10a70-6aaf-7411-9505-8ab4de29fbdb.png)

# Marbles Demo を動かしてみる
以下に続きます。

https://qiita.com/kbys7367/items/847500735a7c4d927163


# 参考文献

https://github.com/IBM-Blockchain-Archive/marbles/blob/v5.0/README-ja.md