fabcar サンプルで学ぶ、Hyperledger Fabric Node.js クライアントSDK (v1.4対応版)

# この文書の status

3.2. (a) 以外は完成

# 概要

Hyperledger Fabric (以下、Fabric) のサンプルである `fabcar` については以前 [こんな記事](https://qiita.com/yoshihiro-nnnn/items/a9db142f59f606977b11) の技術監修を担当した。
v1.4になってクライアントの種類が増えたりといろいろ変わったのでここに動作方法を記す。なお、fabcarサンプルは手でコードを書き換えながら試すチュートリアルになっているが、面倒くさいので一気に試すテストスクリプトを用意した。

本記事は公式ドキュメントにあるチュートリアル、[Writing Your First Application](https://hyperledger-fabric.readthedocs.io/en/release-1.4/write_first_app.html) にある手順を試すものである。クライアントSDKの詳細についてはまた今度。

> ちなみに、fabcar に関してはもうひとつ説明ドキュメントが存在する。これは [Understanding the Fabcar Network](https://hyperledger-fabric.readthedocs.io/en/release-1.4/understand_fabcar_network.html) という、ナビゲーションバーからは到達できないと思われるページである。このページはクライアントが呼ぶAPIの説明がちょっと古いので注意すること。

# 前提条件

[以前書いた記事の第1回](https://qiita.com/miki110/items/7f4ef59b43c63aa7b754) の内容にしたがって、次の作業が実施済みであること。

- Dockerイメージのpull
- Platform-specific binariesのダウンロード
- fabric-samplesのクローン

(2019年11月修正) なお、このサンプルを動かすには **Node.js v8.x もしくは v10.x** が必要である。 ~~gRPCのバージョンとの関係で、v9以降では動かないことは確認済みである。~~ v8.11で動くことを確認済みである。また、gRPCモジュールのビルドに **Python 2.x** が必要である。

# 1. `fabcar` ディレクトリに移動


`fabcar` ディレクトリに移動する。

```bash
~/fabric-140$ cd fabric-samples/fabcar
~/fabric-140/fabric-samples/fabcar$
```


# 2. すでにコンテナが動いているなら止め、余分なイメージは削除する

Dockerは名前空間がないので、他のアプリケーション用にFabricを動かしていると上手くいかないので止める必要がある。また、チェーンコードのdockerイメージが残っている場合も悪さをすることがあるので、できれば `docker image rm` などで消しておく。

なお、下記の 3.1 で `startFabric.sh` すると `first-network` の `byfn.sh down` をやってから `byfn.sh up` するので、直前に動かしていたデモが `first-network` または `fabcar` なら明示的に止める必要はない。
もし明示的に止めたいなら例えばこうする。以下のコマンドを実行するとチェーンコードイメージの削除も含めてやってくれる。

```text:直前に動かしていたのが first-network か fabcar の場合の止め方
~/fabric-140/fabric-samples/fabcar$ (cd ../first-network/ && ./byfn.sh down && docker system prune -f)
```

このサンプルにかかわらず、日頃から作業を始める前はこれをやっておくとよい。

# 3. 動かす

下記「Fabricネットワーク起動」までは共通。「クライアントを起動」は (a) か (b) を選んで試してほしい。

## 3.1. Fabricネットワーク起動

`startFabric.sh javascript` を実行する。前述のように `first-network` のネットワーク down → up の順に進む。ノード群を立ち上げてチェーンコードをデプロイしている。
v1.4になって使用するチェーンコード言語の種類が増えた。本記事の著者はNode.jsチェーンコードで動作確認した。

```text:Node.jsチェーンコード、本記事で使用
~/fabric-140/fabric-samples/fabcar$ ./startFabric.sh javascript
```

```text:Goチェーンコードの場合
~/fabric-140/fabric-samples/fabcar$ ./startFabric.sh
もしくは
~/fabric-140/fabric-samples/fabcar$ ./startFabric.sh golang
```

```bash:Typescriptチェーンコードの場合
~/fabric-140/fabric-samples/fabcar$ ./startFabric.sh typescript
```

【動作確認】なんか長々とメッセージが出たら成功。クライアントコードの起動方法が書かれている。

## 3.2. クライアントを起動

以下、(a) か (b) のどちらかを選んで試してほしい。

### (a) オリジナルのやり方で試す


_以下 to be written_

### (b) 手抜きして一気にテストする (JavaScript版)

`javascript/` に移動、パッケージをインポートする。

```
~/fabric-140/fabric-samples/fabcar$ cd javascript
~/fabric-140/fabric-samples/fabcar/javascript$ npm install
(ログが出る)
```

さらに私が使い慣れた `ava` と、ディレクトリを削除するパッケージ `rimraf` をインストールする。

```
npm install -D ava rimraf
(ログが出る)
```

テストスクリプトを https://gist.github.com/shinsa82/b05ed46c9ff8ee4e104b321d7572e2e8 から持ってきて上記 `javascript` ディレクトリ内に置く。手動でやるか、以下のコマンドを実行する。

```
curl -O https://gist.githubusercontent.com/shinsa82/b05ed46c9ff8ee4e104b321d7572e2e8/raw/2c2baad6f702c811d8ae54b1b2744851cf0c9a6f/test.js
```

テストする。テストを実行すると鍵などが含まれている `wallet` ディレクトリを削除するので注意すること。
**このテストはFabric起動直後にしか通らないので注意。再び実行するとユーザ `user1` がすでに存在するというエラーが出る。**

```
~/fabric-140/fabric-samples/fabcar/javascript$ npx ava -v

    delete wallet
    ℹ delete wallet directory: .../fabric-140/fabric-samples/fabcar/javascript/wallet
2019-03-05T11:06:34.365Z - info: [TransactionEventHandler]: _strategySuccess: strategy success for transaction "adb5bfd0a800a3fabeb48404deb266bee111988332fb4b573694967955fc0675"
2019-03-05T11:06:36.479Z - info: [TransactionEventHandler]: _strategySuccess: strategy success for transaction "90466c13d06c419fb95ffc9bb6f473c6e4f9f498508fc8eed586b2cdb8f21e0b"
  ✔ e2e test (6.2s)
    ℹ load connection profile for basic-network
    ℹ get wallet
    ℹ get admin's certificate
    ℹ get an enrollment
    ℹ register @user1
    ℹ   get gateway
    ℹ get user1's certificate
    ℹ get an enrollment
    ℹ connect gateway as @user1
    ℹ call queryAllCars
    ℹ call queryCar
    ℹ call createCar
    ℹ call changeCarOwner
    ℹ shutdown gateway

  1 test passed
```

【動作確認】`1 test passed` と出たら成功。もとのチュートリアルに含まれているコードの書き換えに対応する呼び出しも全て行い、結果が期待通りになることをチェックしているので安心してほしい。