Hyperledger fabric で始めるブロックチェーンアプリケーション (2/3)

この記事は WESEEK Advent Calendar 2020 3日目の記事です。

# はじめに

前回は Hyperledger fabric についての基礎知識を紹介しました。

今回は Hyperledger fabric 公式のチュートリアルを実際に動かしてみることにします。

1. [基礎知識の紹介](https://qiita.com/tatsurou313/private/ca124beb9d9e06cceb77)
1. サンプルアプリケーションを動かすチュートリアル (この記事)
1. [開発環境の整備](https://qiita.com/tatsurou313/private/ea5b55db19531f74923c)
1. [CIの構築](https://qiita.com/tatsurou313/private/ea5b55db19531f74923c)
1. [SDKを使ったアプリケーションの構築](https://qiita.com/tatsurou313/private/ea5b55db19531f74923c)

# 事前準備

チュートリアルを動作させるために以下のツールが必要です。事前にインストールしてください。

- Docker 17.06.2-CE 以上
- Docker Compose 1.14.0 以上
- Node.js 8.9.4 以上、または 10.15.3 以上 (npm は 5.6.0 推奨)
    - [nvm](https://github.com/nvm-sh/nvm) のような複数バージョンの Node.js をインストールできるツールを利用すると便利です
- (好みで) yarn
- curl (サンプルダウンロード用)

次は、サンプルコードを clone し、fabric 関連ツール及び fabric コンポーネントの Docker image 一式をダウンロードします。

```bash
curl -sSL http://bit.ly/2ysbOFE | bash -s -- 1.4.7 1.4.7
```

<font color="gray">
'20/12/01 現在 Hyperledger fabric の最新 LTS は v2 系ですが、筆者が kubernetes 基盤へデプロイする際に利用した helm chart (stable repo) が Hyperledger fabric v1 のものだけだったため、v1.4.7 でアプリケーションを構築することとなりました。そのため、サンプルも v1.4.7 でチュートリアルを実施することにします。
</font>


# 公式チュートリアル fabcar アプリケーションを実行する

## fabric ネットワークを構築する

[公式チュートリアル fabcar アプリケーション](https://hyperledger-fabric.readthedocs.io/en/release-1.4/write_first_app.html) に従って、Hyperledger fabric が動作する様子を体験してみましょう。

ダウンロードしたコードの中にはいくつかのサンプルアプリケーションがあります。

ここでは、`fabcar` アプリケーションを実行します。
`fabcar` は車の販売店が取り扱う車の情報を台帳で管理するアプリケーションの例です。

```bash
$ ls
fabric-samples
$ cd fabcar
$ ./startFabric.sh javascript
```

以下のようなメッセージが表示されれば正常に起動が完了しています。

```
========= All GOOD, BYFN execution completed ===========                                                                                           


_____   _   _   ____
| ____| | \ | | |  _ \
|  _|   |  \| | | | | |
| |___  | |\  | | |_| |
|_____| |_| \_| |____/
```

このコマンドにより次のようなネットワークが構築され、chaincode `dev-peer0.org1.example.com-fabcar-1.0`, `dev-peer0.org2.example.com-fabcar-1.0` がインスタンス化されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206493/d13b8fa6-4571-2139-a14e-1300e19fc048.png)


Docker container は下のようになります。

```bash
$ docker ps
CONTAINER ID        IMAGE                                                                                                    COMMAND                  CREATED             STATUS              PORTS                                        NAMES
4a4bd830f0a6        dev-peer0.org2.example.com-fabcar-1.0-264b0a1cb5efbecaac5cf8990339c24474dc8435c6e10f10f2be565d555d0e94   "/bin/sh -c 'cd /usr…"   4 minutes ago       Up 4 minutes                                                     dev-peer0.org2.example.com-fabcar-1.0
7129758c892c        dev-peer0.org1.example.com-fabcar-1.0-5c906e402ed29f20260ae42283216aa75549c571e2e380f3615826365d8269ba   "/bin/sh -c 'cd /usr…"   4 minutes ago       Up 4 minutes                                                     dev-peer0.org1.example.com-fabcar-1.0
fc5fcb24773b        hyperledger/fabric-tools:latest                                                                          "/bin/bash"              5 minutes ago       Up 5 minutes                                                     cli
f52409de155a        hyperledger/fabric-peer:latest                                                                           "peer node start"        5 minutes ago       Up 5 minutes        0.0.0.0:9051->9051/tcp                       peer0.org2.example.com
c80dff21f529        hyperledger/fabric-peer:latest                                                                           "peer node start"        5 minutes ago       Up 5 minutes        0.0.0.0:7051->7051/tcp                       peer0.org1.example.com
c470b0dfd851        hyperledger/fabric-peer:latest                                                                           "peer node start"        5 minutes ago       Up 5 minutes        0.0.0.0:8051->8051/tcp                       peer1.org1.example.com
83f703282bc2        hyperledger/fabric-peer:latest                                                                           "peer node start"        5 minutes ago       Up 5 minutes        0.0.0.0:10051->10051/tcp                     peer1.org2.example.com
230cf92ddd76        hyperledger/fabric-ca:latest                                                                             "sh -c 'fabric-ca-se…"   5 minutes ago       Up 5 minutes        0.0.0.0:7054->7054/tcp                       ca_peerOrg1
c5d3fe6eb558        hyperledger/fabric-couchdb                                                                               "tini -- /docker-ent…"   5 minutes ago       Up 5 minutes        4369/tcp, 9100/tcp, 0.0.0.0:6984->5984/tcp   couchdb1
d5d2359b5e18        hyperledger/fabric-orderer:latest                                                                        "orderer"                5 minutes ago       Up 5 minutes        0.0.0.0:7050->7050/tcp                       orderer.example.com
45c17821a25d        hyperledger/fabric-couchdb                                                                               "tini -- /docker-ent…"   5 minutes ago       Up 5 minutes        4369/tcp, 9100/tcp, 0.0.0.0:8984->5984/tcp   couchdb3
9f655933a69d        hyperledger/fabric-couchdb                                                                               "tini -- /docker-ent…"   5 minutes ago       Up 5 minutes        4369/tcp, 9100/tcp, 0.0.0.0:7984->5984/tcp   couchdb2
69a9ee2d0f1e        hyperledger/fabric-ca:latest                                                                             "sh -c 'fabric-ca-se…"   5 minutes ago       Up 5 minutes        7054/tcp, 0.0.0.0:8054->8054/tcp             ca_peerOrg2
6f8e7b766062        hyperledger/fabric-couchdb                                                                               "tini -- /docker-ent…"   5 minutes ago       Up 5 minutes        4369/tcp, 9100/tcp, 0.0.0.0:5984->5984/tcp   couchdb0
```

## fabric アプリケーションを実行する

fabric アプリケーションは Node.js で実装されています。(サンプルには Java, TypeScript を使った例もあります)

一般的な Node.js アプリケーションを実行する要領で実行できます。

まずは依存関係を解決します。

```bash
$ ls
fabric-samples
$ cd fabcar/javascript
$ yarn # or npm install
```

fabcar/javascript ディレクトリ内にはいくつかの Node.js アプリケーションがあります。(サンプルのため機能としては薄い)

- enrollAdmin.js
    - adminユーザーを登録します
- registerUser.js
    - adminユーザーにより、user1を新しく作成＆登録します
- invoke.js
    - chaincode で定義された `createCar` トランザクションを実行します
- query.js
    - chaincode で定義された `queryAllCars` トランザクションを検証します

fabric アプリケーションは fabric ネットワークで識別され、実行する権限があるユーザーがトランザクションを実行することができます。
ユーザーを識別するためには証明書が必要なので、user1 ユーザーがアプリケーションを実行するためには次の手続きが必要です。

0. org1.example.com の管理者ユーザー `admin` を作成する (fabric ネットワーク作成時に既に作成済)
1. `admin` を登録する
2. トランザクション実行用の org1.example.com のメンバーユーザー `user1` を作成＆登録する
3. `user1` の秘密鍵・証明書を使ってトランザクションを実行する

### org1.example.com の管理者ユーザー `admin` を登録する

まずは管理者ユーザーを登録します。
この操作により、まずは実行したローカルファイルシステム上に秘密鍵と公開鍵が作成されます。
次に、作成された公開鍵が CA へ送信され、CA により証明書が発行されます。

Hyperledger はユーザー証明書を含むユーザー情報をウォレットというデータ形式で保持します。(複数ユーザーの情報がウォレット領域にユーザー毎分類されて保存される)

```bash
$ ls wallet
# wallet配下は空

# adminを登録する
$ node enrollAdmin.js
Wallet path: /home/vagrant/work/fabric-samples.1.4.7/fabcar/javascript/wallet
Successfully enrolled admin user "admin" and imported it into the wallet

# adminの公開鍵・秘密鍵が作成され、ウォレットに登録されたことを確認する
$ ls wallet/
admin
$ ls -l wallet/admin/
total 12
-rw-rw-r-- 1 vagrant vagrant 246 Nov 30 19:57 7cafba753580ab2d4d306af5bed61ce5e3aeefd4d54083d2d4f0b37d276670e3-priv # 秘密鍵
-rw-rw-r-- 1 vagrant vagrant 182 Nov 30 19:57 7cafba753580ab2d4d306af5bed61ce5e3aeefd4d54083d2d4f0b37d276670e3-pub  # 公開鍵
-rw-rw-r-- 1 vagrant vagrant 986 Nov 30 19:57 admin                                                                 # ウォレット
$ cat wallet/admin/admin | jq
{
  "name": "admin",
  "mspid": "Org1MSP",
  "roles": null,
  "affiliation": "",
  "enrollmentSecret": "",
  "enrollment": {
    "signingIdentity": "7cafba753580ab2d4d306af5bed61ce5e3aeefd4d54083d2d4f0b37d276670e3",
    "identity": {
      "certificate": "-----BEGIN CERTIFICATE-----\nMIICATCCAaigAwIBAgIURWhPNsHqBR0BJXYTEIkKGE/K2M8wCgYIKoZIzj0EAwIw\nczELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh\nbiBGcmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMT\nE2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMjAxMTMwMTk1MjAwWhcNMjExMTMwMTk1\nNzAwWjAhMQ8wDQYDVQQLEwZjbGllbnQxDjAMBgNVBAMTBWFkbWluMFkwEwYHKoZI\nzj0CAQYIKoZIzj0DAQcDQgAEMsPEEj8hMBrNC4D3gjCA7PgGHYumGQPf3Lj3uikv\n392ps1BjPzgzxB+7y1tQAOlzsSia9taJ3Um0ubYfRw7C9qNsMGowDgYDVR0PAQH/\nBAQDAgeAMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFK/z0HzATs86aQB73aSJUIj3\nDHGKMCsGA1UdIwQkMCKAIKeFc5ZLUOE0kdaM/m4ukEGlzayUGz5AecXS8Rz2ZKJy\nMAoGCCqGSM49BAMCA0cAMEQCIFbQVPlRHfFt0FsrAYJVAvGLBBJxNFDdEdWeC6gA\nCnRsAiAychuZ/+CfG4A0TsydtvEi0K0tDPprdFUK0G1u985feg==\n-----END CERTIFICATE-----\n"
    }
  }
}
```

admin ユーザーの証明書を見てみると次のようになっています。

```bash
$ cat wallet/admin/admin | jq .enrollment.identity.certificate | tr -d '"' | sed -r -e 's/\\n/\n/g' | openssl x509 -noout -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            45:68:4f:36:c1:ea:05:1d:01:25:76:13:10:89:0a:18:4f:ca:d8:cf
        Signature Algorithm: ecdsa-with-SHA256
        Issuer: C = US, ST = California, L = San Francisco, O = org1.example.com, CN = ca.org1.example.com
        Validity
            Not Before: Nov 30 19:52:00 2020 GMT
            Not After : Nov 30 19:57:00 2021 GMT
        Subject: OU = client, CN = admin
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:32:c3:c4:12:3f:21:30:1a:cd:0b:80:f7:82:30:
                    80:ec:f8:06:1d:8b:a6:19:03:df:dc:b8:f7:ba:29:
                    2f:df:dd:a9:b3:50:63:3f:38:33:c4:1f:bb:cb:5b:
                    50:00:e9:73:b1:28:9a:f6:d6:89:dd:49:b4:b9:b6:
                    1f:47:0e:c2:f6
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Key Identifier:
                AF:F3:D0:7C:C0:4E:CF:3A:69:00:7B:DD:A4:89:50:88:F7:0C:71:8A
            X509v3 Authority Key Identifier:
                keyid:A7:85:73:96:4B:50:E1:34:91:D6:8C:FE:6E:2E:90:41:A5:CD:AC:94:1B:3E:40:79:C5:D2:F1:1C:F6:64:A2:72

    Signature Algorithm: ecdsa-with-SHA256
         30:44:02:20:56:d0:54:f9:51:1d:f1:6d:d0:5b:2b:01:82:55:
         02:f1:8b:04:12:71:34:50:dd:11:d5:9e:0b:a8:00:0a:74:6c:
         02:20:32:72:1b:99:ff:e0:9f:1b:80:34:4e:cc:9d:b6:f1:22:
         d0:ad:2d:0c:fa:6b:74:55:0a:d0:6d:6e:f7:ce:5f:7a
```

ここで証明書から次のことが読み取れます。

- `Issuer: ～, CN = ca.org1.example.com` から、認証局が `ca.org1.example.com` であることが読み取れます
- `Subject: OU = client, CN = admin` から、ユーザーID が `admin` であり、fabric クライアント (`client`) であることが読み取れます
    - OU はデフォルトで他に `orderer`, `peer` がある
    - NodeOUs を有効にすることで定義をカスタムできるようです


### トランザクション実行用のユーザーを作成＆登録する

管理ユーザーを登録することができました。
このユーザーを使って、他のユーザの作成や登録を行うことができます。

そこで次に `admin` ユーザの identity を使ってユーザー`user1`を作成＆登録します。

```bash
$ ls wallet/
admin

# user1 を作成＆登録する
$ node registerUser.js
Wallet path: /home/vagrant/work/fabric-samples.1.4.7/fabcar/javascript/wallet
Successfully registered and enrolled admin user "user1" and imported it into the wallet

$ ls wallet/
admin  user1
$ ls -l wallet/user1/
total 12
-rw-rw-r-- 1 vagrant vagrant  246 Nov 30 20:19 edf5c114bbb2c02c2c0c124a9dfa0f32a1769f568ef2ef2952fb0a46c933ac5e-priv
-rw-rw-r-- 1 vagrant vagrant  182 Nov 30 20:19 edf5c114bbb2c02c2c0c124a9dfa0f32a1769f568ef2ef2952fb0a46c933ac5e-pub
-rw-rw-r-- 1 vagrant vagrant 1180 Nov 30 20:19 user1
$ cat wallet/user1/user1 | jq
{
  "name": "user1",
  "mspid": "Org1MSP",
  "roles": null,
  "affiliation": "",
  "enrollmentSecret": "",
  "enrollment": {
    "signingIdentity": "edf5c114bbb2c02c2c0c124a9dfa0f32a1769f568ef2ef2952fb0a46c933ac5e",
    "identity": {
      "certificate": "-----BEGIN CERTIFICATE-----\nMIICjjCCAjWgAwIBAgIUfKQtONFnMS5U6wzquuxFdZy7iEAwCgYIKoZIzj0EAwIw\nczELMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNh\nbiBGcmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMT\nE2NhLm9yZzEuZXhhbXBsZS5jb20wHhcNMjAxMTMwMjAxNTAwWhcNMjExMTMwMjAy\nMDAwWjBCMTAwDQYDVQQLEwZjbGllbnQwCwYDVQQLEwRvcmcxMBIGA1UECxMLZGVw\nYXJ0bWVudDExDjAMBgNVBAMTBXVzZXIxMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcD\nQgAEw3zuvqLwxoInC4EkDoLAU3siTgRXTzlLrWJ9dcQXVSGDv+Hc9dg3ymCmniPg\nDoY95bhZuecjgFIlYZZMkBufaKOB1zCB1DAOBgNVHQ8BAf8EBAMCB4AwDAYDVR0T\nAQH/BAIwADAdBgNVHQ4EFgQUhcfQZ1KzaKj43ppigFqTBVyGP90wKwYDVR0jBCQw\nIoAgp4VzlktQ4TSR1oz+bi6QQaXNrJQbPkB5xdLxHPZkonIwaAYIKgMEBQYHCAEE\nXHsiYXR0cnMiOnsiaGYuQWZmaWxpYXRpb24iOiJvcmcxLmRlcGFydG1lbnQxIiwi\naGYuRW5yb2xsbWVudElEIjoidXNlcjEiLCJoZi5UeXBlIjoiY2xpZW50In19MAoG\nCCqGSM49BAMCA0cAMEQCIH87DJXFL3WM2uCRYHrpp7RGE3QhNant7yVcu0xASv3E\nAiBuIucVQKQefs8yWND74QSyguWl99o6D1n3qP7EkzpMEw==\n-----END CERTIFICATE-----\n"
    }
  }
}
```

今度は user1 の証明書を見てみましょう。

```bash
$ cat wallet/user1/user1 | jq .enrollment.identity.certificate | tr -d '"' | sed -r -e 's/\\n/\n/g' | openssl x509 -noout -text
Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            7c:a4:2d:38:d1:67:31:2e:54:eb:0c:ea:ba:ec:45:75:9c:bb:88:40
        Signature Algorithm: ecdsa-with-SHA256
        Issuer: C = US, ST = California, L = San Francisco, O = org1.example.com, CN = ca.org1.example.com
        Validity
            Not Before: Nov 30 20:15:00 2020 GMT
            Not After : Nov 30 20:20:00 2021 GMT
        Subject: OU = client + OU = org1 + OU = department1, CN = user1
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub:
                    04:c3:7c:ee:be:a2:f0:c6:82:27:0b:81:24:0e:82:
                    c0:53:7b:22:4e:04:57:4f:39:4b:ad:62:7d:75:c4:
                    17:55:21:83:bf:e1:dc:f5:d8:37:ca:60:a6:9e:23:
                    e0:0e:86:3d:e5:b8:59:b9:e7:23:80:52:25:61:96:
                    4c:90:1b:9f:68
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Key Identifier:
                85:C7:D0:67:52:B3:68:A8:F8:DE:9A:62:80:5A:93:05:5C:86:3F:DD
            X509v3 Authority Key Identifier:
                keyid:A7:85:73:96:4B:50:E1:34:91:D6:8C:FE:6E:2E:90:41:A5:CD:AC:94:1B:3E:40:79:C5:D2:F1:1C:F6:64:A2:72

            1.2.3.4.5.6.7.8.1:
                {"attrs":{"hf.Affiliation":"org1.department1","hf.EnrollmentID":"user1","hf.Type":"client"}}
    Signature Algorithm: ecdsa-with-SHA256
         30:44:02:20:7f:3b:0c:95:c5:2f:75:8c:da:e0:91:60:7a:e9:
         a7:b4:46:13:74:21:35:a9:ed:ef:25:5c:bb:4c:40:4a:fd:c4:
         02:20:6e:22:e7:15:40:a4:1e:7e:cf:32:58:d0:fb:e1:04:b2:
         82:e5:a5:f7:da:3a:0f:59:f7:a8:fe:c4:93:3a:4c:13
```

今度は証明書から次のことが読み取れます。

- `Subject: OU = client + OU = org1 + OU = department1, CN = user1` からユーザーID が `user1` である
- Hyperledger fabric 上の権限が `1.2.3.4.5.6.7.8.1` に保存されている
    - 詳細は[Attribute-Based Access Control](https://hyperledger-fabric-ca.readthedocs.io/en/release-1.4/users-guide.html#attribute-based-access-control) に書かれています

### トランザクション実行用のユーザーの秘密鍵・証明書を使ってトランザクションを実行する

トランザクションを実行するユーザが準備できたので、いよいよトランザクションを実行します。

`query.js` には chaincode で定義された `queryAllCars` を検証するコードが記述されています。

`queryAllCars` は台帳に記述された全ての車のデータを返します。

fabric ネットワークを構築した際、initLedger が実行されており、これにより 10 台の車のデータが登録されていました。

そのため、結果は 10 台の車のデータが返ってきます。

```bash
$ node query.js
Wallet path: /home/vagrant/work/fabric-samples.1.4.7/fabcar/javascript/wallet
Transaction has been evaluated, result is: [
{"Key":"CAR0","Record":{"color":"blue","docType":"car","make":"Toyota","model":"Prius","owner":"Tomoko"}},
{"Key":"CAR1","Record":{"color":"red","docType":"car","make":"Ford","model":"Mustang","owner":"Brad"}},
{"Key":"CAR2","Record":{"color":"green","docType":"car","make":"Hyundai","model":"Tucson","owner":"Jin Soo"}},
{"Key":"CAR3","Record":{"color":"yellow","docType":"car","make":"Volkswagen","model":"Passat","owner":"Max"}},
{"Key":"CAR4","Record":{"color":"black","docType":"car","make":"Tesla","model":"S","owner":"Adriana"}},
{"Key":"CAR5","Record":{"color":"purple","docType":"car","make":"Peugeot","model":"205","owner":"Michel"}},
{"Key":"CAR6","Record":{"color":"white","docType":"car","make":"Chery","model":"S22L","owner":"Aarav"}},
{"Key":"CAR7","Record":{"color":"violet","docType":"car","make":"Fiat","model":"Punto","owner":"Pari"}},
{"Key":"CAR8","Record":{"color":"indigo","docType":"car","make":"Tata","model":"Nano","owner":"Valeria"}},
{"Key":"CAR9","Record":{"color":"brown","docType":"car","make":"Holden","model":"Barina","owner":"Shotaro"}}]
```

コマンドだけ見ると実感は少ないと思いますが、これはブロックチェーンの台帳を読み取った結果です。

次に、台帳へ書き込みを行ってみます。

`invoke.js` には chaincode で定義された `createCar` を実行するコードが記述されています。

実行した後、再度 `query.js` を実行すると `CAR12` が追加されていることが分かります。

```bash
$ node invoke.js
Wallet path: /home/vagrant/work/fabric-samples.1.4.7/fabcar/javascript/wallet
Transaction has been submitted

# $ node query.js
Wallet path: /home/vagrant/work/fabric-samples.1.4.7/fabcar/javascript/wallet
Transaction has been evaluated, result is: [
{"Key":"CAR0","Record":{"color":"blue","docType":"car","make":"Toyota","model":"Prius","owner":"Tomoko"}},
{"Key":"CAR1","Record":{"color":"red","docType":"car","make":"Ford","model":"Mustang","owner":"Brad"}},
{"Key":"CAR12","Record":{"color":"Black","docType":"car","make":"Honda","model":"Accord","owner":"Tom"}},
{"Key":"CAR2","Record":{"color":"green","docType":"car","make":"Hyundai","model":"Tucson","owner":"Jin Soo"}},
{"Key":"CAR3","Record":{"color":"yellow","docType":"car","make":"Volkswagen","model":"Passat","owner":"Max"}},
{"Key":"CAR4","Record":{"color":"black","docType":"car","make":"Tesla","model":"S","owner":"Adriana"}},
{"Key":"CAR5","Record":{"color":"purple","docType":"car","make":"Peugeot","model":"205","owner":"Michel"}},
{"Key":"CAR6","Record":{"color":"white","docType":"car","make":"Chery","model":"S22L","owner":"Aarav"}},
{"Key":"CAR7","Record":{"color":"violet","docType":"car","make":"Fiat","model":"Punto","owner":"Pari"}},
{"Key":"CAR8","Record":{"color":"indigo","docType":"car","make":"Tata","model":"Nano","owner":"Valeria"}},
{"Key":"CAR9","Record":{"color":"brown","docType":"car","make":"Holden","model":"Barina","owner":"Shotaro"}}]
```

`invoke.js` にはトランザクションを実行することだけが記述されていますが、内部では Hyperledger fabric におけるトランザクションの検証やコミットやブロックのブロードキャストなどの処理が行われ、その結果台帳が更新されたため `query.js` が更新されています。

# まとめ

Hyperledger fabric 公式のチュートリアルを実際に動かした結果を紹介しました。

Hyperledger fabric におけるユーザーを作成し、作成したユーザーの identity を使ってトランザクションを実行し、台帳を読み書きすることでシステム動作を体験しました。

次は、chaincode を実装する開発環境を構築する方法について紹介したいと思います。

※この記事は [WESEEK Tips wiki](https://tips.weseek.co.jp/) に 2020/12/02 に投稿された記事の転載です。
Tips wiki では、IT企業の技術的な情報やプロジェクトの情報を公開可能な範囲で公開してます。