可視化ツール Hyperledger Explorer で Hyperledger Fabric ブロックチェーンを見てみよう（v1.2.1対応版)

# 概要
ブロックチェーンを可視化するツール「[Hyperledger Explorer](https://github.com/hyperledger/blockchain-explorer)」をインストールして [Hyperledger Fabric](https://www.hyperledger.org/projects/fabric) のブロックチェーンを見てみたので備忘録を兼ねて共有したいと思います。

（参照）Hyperledger Explorerとは？ -> [Hyperledger Explorer（v0.3.7版）で確認できる情報](https://qiita.com/fhoshi/items/6da01b7aa6f9b0c6b059)

本記事では[Hyperledger Fabric](https://www.hyperledger.org/projects/fabric)のバージョン [v1.2.1](https://hyperledger-fabric.readthedocs.io/en/release-1.2/) を利用しました（執筆中にリリースされたHLF v1.3でも同様手順で問題ないことは確認済）。また、[Hyperledger Explorer](https://github.com/hyperledger/blockchain-explorer)は開発中の [release-3.8](https://github.com/hyperledger/blockchain-explorer/tree/release-3.8) ブランチを利用しました。

このほか、Hyperledger Fabricや公式サンプルの導入方法は他記事としてまとめています。
こちらのリンクから各記事に遷移できますので、ご興味があれば。

参考
[Hyperledger Fabric 1.2.1を動かして、ブロックチェーンの動作を確認・検証しよう](https://qiita.com/kyoko7tam/items/6e0eea28ac8340f6897e)

# Hyperledger Explorer のインストール
[公式サイトの手順(non-Docker版)](https://github.com/hyperledger/blockchain-explorer#hyperledger-explorer)を参考にしました。
（このほかにも[Docker版](https://github.com/hyperledger/blockchain-explorer#Run-Hyperledger-Explorer-using-Docker)も追加されたようなのでまたの機会にでも）。

# 前提ソフトウェアのインストール
- Hyperledger Fabric v1.2 (執筆時点最新 1.2.1)
- Hyperledger Fabric 公式サンプル "fabric-samples"（fabcar サンプルを含む）
- Docker CE 17.06.2-ce / Docker compose 1.14.0 以上
- nodejs 8.11.x 以上 (v9.xは未サポート)
- PostgreSQL 9.5 以上
- jq (https://stedolan.github.io/jq/)
- OSは [Ubuntu Linux 18.04 LTS](http://releases.ubuntu.com/18.04/) を使用(筆者は macOS + Vagrant/VirtualBox + [ubuntu/bionic64](https://app.vagrantup.com/ubuntu) を利用） 

参考
- [面倒なのでVagrantfileやセットアップ手順をscript化したもの（メモ）](https://gist.github.com/hi5san/794d5409544aee315a66c4461187578d)(gistリンク）
-  [Dockerイメージ](https://hub.docker.com/r/hi5san/fabric-quickstart-explorer/)

### Hyperledger Fabric と 公式サンプル
まずは今回利用するHyperledger Fabric v1.2 (curr: 1.2.1) と公式サンプルをインストールします。

参考
[Hyperledger Fabricを動かしてみよう](https://qiita.com/miki110/items/7f4ef59b43c63aa7b754)

### Docker CE および Docker compose
Hyperledger Fabric の前提ツールなので上で一緒にインストールされます。

### nodejs v8.11.x 以上（v9.xはNG）
Hyperledger Explorer は [Hyperledger Fabric Node SDK](https://fabric-sdk-node.github.io) などを使用して実装されている Node.js アプリケーションです。

Node.js ランタイムのインストールは Hyperledger Fabric 公式サンプルの前提ソフトウェアとしてインストール済ですが、注意点として、公式手順に従って対応バージョンにしておかないと`npm install`が正常に動作しないなどしてハマることがあるようです（ハマりました）。

公式手順に従って対応バージョンをインストールする：

```shell
sudo npm install npm@5.6.0 -g
```

このほか`Ubuntu 18.04 LTS`ではさらに[ハマることがある（あった？）](https://github.com/grpc/grpc-node/issues/341)らしい。`npm install`の際に`undefined symbol: SSL_library_init`が出て失敗するというもの：

```
node_modules/grpc/src/node/extension_binary/node-v57-linux-x64-glibc/grpc_node.node: undefined symbol: SSL_library_init
```

この問題は執筆中に[公式に対応された](https://github.com/grpc/grpc-node/issues/341#issuecomment-424817179)ようなのでもはや不要かもしれません。が、一応解決方法をメモしておきます。


メモ：nodesourceから入れ直せば解決する

```shell
sudo apt -y purge nodejs
curl -sL https://deb.nodesource.com/setup_8.x | sudo bash - 
sudo apt -y install nodejs
```
nodesource経由だと、執筆時点では v8.12.0 がインストールされました。

```shell
$ node -v; npm -v
v8.12.0
6.4.1
```

### postgreSQL
Hyperledger Explorer は Fabric に定期的に問い合わせしたりイベント通知を受けて情報をローカルDB(postgreSQL DB)に蓄えるらしい（何に使われているかはよくわかってない）。

```shell
sudo apt -y install locate postgresql
sudo systemctl enable postgresql
sudo service postgresql start
```

### jq (コマンドライン JSON パーサー)
Hyperledger Explorer のセットアップスクリプトなどで使用されている [jq](https://stedolan.github.io/jq/) をインストールします。このツール JSON string を扱うのにものすごくパワフルですよね（下記手順でも活用してます）。

```shell
sudo apt -y install jq
```

確認。

```shell
$ jq --version
jq-1.5-1-a5b5cbe
```
終わり。

## Hyperledger Explorerのダウンロードと初期設定
### ダウンロード
本記事で利用する [release-3.8](https://github.com/hyperledger/blockchain-explorer/tree/release-3.8) ブランチの執筆時点の`commit hash`は`e450fa3790116e9ebc4b8e49d3534a9c8e1587ba`。

```shell
$ git clone https://github.com/hyperledger/blockchain-explorer.git
Cloning into 'blockchain-explorer'...
```
念のため利用バージョンを`checkout`しておきます。

```shell
$ cd ~/blockchain-explorer
$ git checkout release-3.8
```
### 初期セットアップ
後は公式手順通り初期セットアップを行うだけなのですが、確認用のユニットテストがすんなり通らず意外とハマった(ただし、Ubuntu固有？）のでその辺りもメモっておきます。

### データベースの初期化

```shell
$ cd ~/blockchain-explorer/app/persistence/fabric/postgreSQL/db
$ ./createdb.sh
```

確認：fabricexplorer データベースができていれば成功。

```shell
$ sudo -u postgres psql -l |grep fab
 fabricexplorer | hppoc    | UTF8     | en_US.UTF-8 | en_US.UTF-8 | 
```

### 初期設定
```shell
$ cd ~/blockchain-explorer
$ npm install
```

```shell
$ cd ~/blockchain-explorer/app/test
$ npm install
$ npm run test 
```

ここのユニットテストで次のようなエラーが出ました。

```shell
(node:18469) UnhandledPromiseRejectionWarning: error: password authentication failed for user "postgres"
    at Connection.parseE (/home/vagrant/blockchain-explorer/app/test/node_modules/pg/lib/connection.js:553:11)
    at Connection.parseMessage (/home/vagrant/blockchain-explorer/app/test/node_modules/pg/lib/connection.js:378:19)
    at Socket.<anonymous> (/home/vagrant/blockchain-explorer/app/test/node_modules/pg/lib/connection.js:119:22)
    at emitOne (events.js:116:13)
    at Socket.emit (events.js:211:7)
    at addChunk (_stream_readable.js:263:12)
    at readableAddChunk (_stream_readable.js:250:11)
    at Socket.Readable.push (_stream_readable.js:208:10)
    at TCP.onread (net.js:601:20)
(node:18469) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:18469) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
```

＃ユニットテストなので無視すればいいのかもしれませんが、、なんだか気持ち悪いのでpassさせます。

Node/NPM + pg module で MD5認証がうまくいかないという件っぽいですが、ネットにある情報で解消できなかったので、とりあえず trust 設定にして誤魔化します。

```shell
$ sudo sed -i.bak '/^host.*md5/ s/md5/trust/' /etc/postgresql/*/main/pg_hba.conf
$ sudo service postgresql restart
$ npm run test
（略）
1..54
# tests 54
# pass  54
```

続き。

```shell
$ cd ~/blockchain-explorer/client
$ npm install
$ npm test -- -u --coverage
```

こんどはここで下記のように *Test failed*・・（どうなってるんだ？）。

```shell
 RUNS  src/components/View/LandingPage.spec.js
/home/vagrant/blockchain-explorer/client/node_modules/react-scripts/scripts/test.js:20
  throw err;
  ^

TypeError: getBlockActivity is not a function
    at LandingPage.componentDidMount (/home/vagrant/blockchain-explorer/client/src/components/View/LandingPage.js:136:5)
    at <anonymous>
npm ERR! Test failed.  See above for more details.
```

＃こちらもユニットテストなので無視すればいいのでしょう、、でもやはり気持ち悪いのでpassさせときます。

（`getBlockActivity`関数を追加した際のテスト定義更新もれ？）`spec`ファイルの問題？ とりあえず、下記のようにして解決・・っと。

```shell
$ sed -i.bak '/getTransactionByOrg:/i \    getBlockActivity: jest.fn(),' src/components/View/LandingPage.spec.js
$ npm test -- -u --coverage
```

Failしていた`LandingPage`テストも突破して下記のようなメッセージ（最後のcoverage表も）が出れば成功（多分）。

```
Test Suites: 26 passed, 26 total
Tests:       171 passed, 171 total
Snapshots:   0 total
Time:        12.221s
Ran all test suites.
...
```

続き。

```shell
$ npm run build
...
Creating an optimized production build...
Compiled successfully.
```
> 注意: `Vagrant/VirtualBox`を使用しているとここでメモリー不足で`"API fatal error handler returned after process out of memory"`エラーになることがあった。デフォルト`1GB`程度だと足りないようでその場合は`4GB`などにして再実行すれば解決する。

終わり。

# Hyperledger Explorer を動かしてみる
可視化したい対象のブロックチェーンネットワークに合わせてアプリ(Hyperledger Explorer）の設定ファイルを修正します。

アプリの設定ファイルは`blockchain-explorer/app/platform/fabric/config.json`。

デフォルトはBYFNに接続するサンプルになっているので、手っ取り早く動かすにはそれを利用するのが良さそうです。

## BYFN ブロックチェーンネットワークの可視化
というわけで、手っ取り早くサンプルの byfn に接続してみます。

### アプリ設定ファイルの修正(byfn)
設定ファイルの`fabric-path`を BYFN （というか fabric-samples ）のインストールディレクトリに合わせて修正します。

例えば `$HOME/fabric/fabric-samples/first-network` にある場合:

```shell
$ cd ~/blockchain-explorer
$ sed -i.bak s@fabric-path@$HOME/fabric@ app/platform/fabric/config.json
```

参考：[編集済のファイル](https://gist.githubusercontent.com/hi5san/fa3aaaa4b0f85dbedcf23dcdb1569109/) (gistリンク)

### BYFN の起動
BYFNブロックチェーンネットワークを起動します。これは公式サンプル手順通り：

```shell
$ cd ~/fabric/fabric-samples/first-network
$ ./byfn.sh up
Starting for channel 'mychannel' with CLI timeout of '10' seconds and CLI delay of '3' seconds
Continue? [Y/n] Y
...
========= All GOOD, BYFN execution completed =========== 

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

### Hyperledger Explorer の起動
Hyperledger Explorer を起動します。

```shell
$ cd ~/blockchain-explorer
$ ./start.sh
************************************************************************************
**************************** Hyperledger Explorer **********************************
************************************************************************************
***** Please check the log [logs/console/console-2018-10-02.log] for any error *****
************************************************************************************
```

バックグラウンドで実行されるので、アプリの動作ログ`logs/app/app.log`を例えば`tail`して観察します。

```shell
$ tail -f logs/app/app.log
...
```

### Hyperledger Explorer の画面を開く
[http://localhost:8080](http://localhost:8080/) をブラウザで開き、下のような画面が見えれば成功です。

参考：[Hyperledger Explorer（v0.3.7版）で確認できる情報](https://qiita.com/fhoshi/items/6da01b7aa6f9b0c6b059)
![Hyperledger Explorer(byfn) screenshot](https://qiita-image-store.s3.amazonaws.com/0/123276/2675d3c8-a38d-04d6-7bbd-523b6ae3a3e5.png "Hyperledger Explorer - byfn")

Well done!

> 注意：ここの手順でDB関連のエラーで起動ができないことがあった：（`logs/console/console-YYYY-MM-DD.log` に `"Error :  [ 'Explorer is closing due to channel name [%s] is already exist in DB',  'mychannel' ]"` というエラーメッセージが残される）。その場合は`(cd ~/blockchain-explorer/app/persistence/fabric/postgreSQL/db; ./createdb.sh)` を実行してDBを作りなおせば解決するので、ブラウザで画面が表示されない場合には確認すると良いかもしれません。

### Hyperledger Explorerの停止、BYFNの消去
やめるときには `stop.sh` を実行します。

```shell
^C
$ ./stop.sh
$ cd ~/fabric/fabric-samples/first-network
$ ./byfn.sh down
Stopping for channel 'mychannel' with CLI timeout of '10' seconds and CLI delay of '3' seconds
Continue? [Y/n] y
...
```

ついでにDBを初期化し直しておきます（上記「注意」を回避するため）。

```shell
$ (cd ~/blockchain-explorer/app/persistence/fabric/postgreSQL/db/; ./createdb.sh)
```

## fabcar ブロックチェーンネットワークの可視化
デフォルト以外のブロックチェーンにも繋いでみてみたいので、続けて fabcar サンプルに接続してみました。

参考
[Fabcarサンプルで学ぶHyperledger Fabric Node.js SDK](https://qiita.com/yoshihiro-nnnn/items/a9db142f59f606977b11)

### アプリ設定ファイルの修正(fabcar/basic-network)
fabcarサンプルは basic-network サンプルのブロックチェーンネットワークを使って動作するアプリなので`fabric-path`などを basic-network に設定します。また、byfn と違い、basic-network は non-TLS モードで動作するのでそのあたりも合わせこむ必要があります。具体的には下記の通りです。

#### config.json の修正①
まずは簡単なところから。
例えば `$HOME/fabric/fabric-samples/basic-network` にある場合:
- `fabric-path`  -> `$HOME/fabric`
- サンプルの`first-network`を`basic-network`に書き換え

続けて non-TLS の設定：
- tlsEnable を false に設定
- grpcs -> grpc

面倒なので以上を行う sed one-liner を実行します:

```shell
$ cd ~/blockchain-explorer
$ sed -i.bak -e s@fabric-path@$HOME/fabric@ -e s@first-network@basic-network@ -e '/tlsEnable/ s/true/false/' -e s@grpcs@grpc@ app/platform/fabric/config.json
```

#### config.json の修正②
次に basic-network に不要な`Org`や`Peer`の設定を削除します：
- Organization を Org1 のみにする（他のOrg設定は削除）
- peers を peer0.org1.example.com のみにする（他のピア定義を削除）
- non-TLS 接続のため tlsCACerts 定義を削除

面倒なので以上を行う jq one-liner（もっと効率的な書き方ありそう。とりあえずベタに羅列）を実行します:

```shell
$ cp app/platform/fabric/config.json app/platform/fabric/config.json.org
$ jq '. | del(."network-configs"."network-1"."organizations"."Org2MSP") | del(."network-configs"."network-1"."peers"."peer0.org2.example.com",."network-configs"."network-1"."peers"."peer1.org2.example.com",."network-configs"."network-1"."peers"."peer1.org1.example.com",."network-configs"."network-1"."peers"."peer0.org1.example.com"."tlsCACerts")' app/platform/fabric/config.json.org > app/platform/fabric/config/config.json
```

参考：[編集済のファイル](https://gist.githubusercontent.com/hi5san/3d1c7b1278149a8f997887c8ac34b3d0/) (gistリンク)

#### basic-network - docker-compose.ymlの修正
初めて試した時にはHyperledger Explorerの画面でブロックやノード情報が何も表示されずハマりました。調べた結果、最新の Hyperledger Explorer は Fabric v1.2 で追加された [Service Discovery](https://hyperledger-fabric.readthedocs.io/en/release-1.2/discovery-overview.html) を利用してノード情報を取得しているようで、これが basic-networkで構成されていないことが原因のようでした。

参考：[v1.2 Service Discovery](https://hyperledger-fabric.readthedocs.io/en/release-1.2/discovery-overview.html) 

この機能を basic-network で利用できるようにするためには docker-compose.yml を修正して、`CORE_PEER_GOSSIP_EXTERNAL_ENDPOINT`と`CORE_PEER_GOSSIP_BOOTSTRAP`環境変数の設定を追加します。具体的には下記の箇所になります（`# For using v1.2 Service Discovery from app`以下3行を追加）:

```yaml:docker-compose.yml
peer0.org1.example.com:
    container_name: peer0.org1.example.com
    image: hyperledger/fabric-peer
    environment:
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      - CORE_PEER_ID=peer0.org1.example.com
      - CORE_LOGGING_PEER=info
      - CORE_CHAINCODE_LOGGING_LEVEL=info
      - CORE_PEER_LOCALMSPID=Org1MSP
      - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/msp/peer/
      - CORE_PEER_ADDRESS=peer0.org1.example.com:7051
      # For using v1.2 Service Discovery from app
      - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.example.com:7051 
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051
```

（後者の環境変数だけで良いかもしれないが、とりあえず両方つけておいた）

参考：Stack Overflow [CORE_PEER_GOSSIP_EXTERNAL_ENDPOINT/CORE_PEER_GOSSIP_BOOTSTRAP環境変数の解説（英語)](https://stackoverflow.com/questions/51377474/hyperledger-fabric-gossip-bootstrap-gossip-externalendpoints)

参考：[編集済のファイル](https://gist.githubusercontent.com/hi5san/9b853953300ff937ed9da395205f29f9/) (gistリンク)

### fabcar(basic-network) の起動と初期設定
basic-networkのブロックチェーンネットワークを起動します。これは公式サンプル手順通り：

```shell
$ cd ~/fabric/fabric-samples/fabcar
$ npm install
$ ./startFabric.sh
$ node enrollAdmin.js
...
Successfully enrolled admin user "admin"
...
$ node registerUser.js
...
User1 was successfully registered and enrolled and is ready to interact with the fabric network
...
```

このあたりで何をしているかなどはこちらに詳しく書いてありますので、ご興味があればご参照ください -> [Fabcarサンプルで学ぶHyperledger Fabric Node.js SDK](https://qiita.com/yoshihiro-nnnn/items/a9db142f59f606977b11)


確認のため query.js を実行してブロックチェーン上の資産（車）の一覧を取得してみます。

```shell
$ node query.js
...
Successfully loaded user1 from persistence
Query has completed, checking results
Response is  [{"Key":"CAR0", "Record":{"colour":"blue","make":"Toyota","model":"Prius","owner":"Tomoko"}},{"Key":"CAR1", "Record":{"colour":"red","make":"Ford","model":"Mustang","owner":"Brad"}},{"Key":"CAR2", "Record":{"colour":"green","make":"Hyundai","model":"Tucson","owner":"Jin Soo"}},{"Key":"CAR3", "Record":{"colour":"yellow","make":"Volkswagen","model":"Passat","owner":"Max"}},{"Key":"CAR4", "Record":{"colour":"black","make":"Tesla","model":"S","owner":"Adriana"}},{"Key":"CAR5", "Record":{"colour":"purple","make":"Peugeot","model":"205","owner":"Michel"}},{"Key":"CAR6", "Record":{"colour":"white","make":"Chery","model":"S22L","owner":"Aarav"}},{"Key":"CAR7", "Record":{"colour":"violet","make":"Fiat","model":"Punto","owner":"Pari"}},{"Key":"CAR8", "Record":{"colour":"indigo","make":"Tata","model":"Nano","owner":"Valeria"}},{"Key":"CAR9", "Record":{"colour":"brown","make":"Holden","model":"Barina","owner":"Shotaro"}}]
```

問題なさそうですね。

### Hyperledger Explorer の起動
BYFN の例（上記）と同じ手順です。

```shell
$ cd ~/blockchain-explorer
$ ./start.sh
************************************************************************************
**************************** Hyperledger Explorer **********************************
************************************************************************************
***** Please check the log [logs/console/console-2018-10-02.log] for any error *****
************************************************************************************
```

バックグラウンドで実行されるので、アプリの動作ログ`logs/app/app.log`を例えば`tail`して観察します。

```shell
$ tail -f logs/app/app.log
...
```

### Hyperledger Explorer の画面を開く
[http://localhost:8080](http://localhost:8080/) をブラウザで開き、下のような画面が見えれば成功です。

参考：[Hyperledger Explorer（v0.3.7版）で確認できる情報](https://qiita.com/fhoshi/items/6da01b7aa6f9b0c6b059)
![Hyperledger Explorer(fabcar) screenshot](https://qiita-image-store.s3.amazonaws.com/0/123276/aa2c072a-00ab-0d3b-68d9-eab2183c8d0d.png "Hyperledger Explorer - fabcar")

Well done!!

### invoke トランザクションを実行してブロックチェーンを追加してみる
初期状態を見るだけなのも少々つまらないので、せっかくなので、トランザクションを起こして Hyperledger Explorer の表示の変化を見てみましょう。

#### invoke.js の修正（fcnとargsの箇所）
fabcar サンプル付属の`invoke.js`スクリプトを修正して、チェーンコードの`createCar`関数を呼び出して`CAR10` (Nissan GTR) 資産を追加するトランザクションを実行してみます。

```javascript:invoke.js
        var request = {
                //targets: let default to the peer assigned to the client
                chaincodeId: 'fabcar',
                fcn: 'createCar',
                args: ['CAR10', 'Nissan', 'GTR', 'Gun Metallic', 'Paul Allen'],
                chainId: 'mychannel',
                txId: tx_id
        };
```

参考：[編集済のファイル](https://gist.githubusercontent.com/hi5san/520ac1adafc6f03580e2a187124d6681/) (gistリンク)

#### invoke.js の実行
```shell
$ cd ~/fabric/fabric-samples/fabcar
$ node invoke.js
...
```
実行が成功し、資産`CAR10`が追加されたはずです。`query.js`を利用して念のため確認します。

```shell
$ node query.js | grep Response | sed -E 's/Response is  (.*)/\1/g' | jq 'map(select(.Key == "CAR10"))[]'
{
  "Key": "CAR10",
  "Record": {
    "colour": "Gun Metallic",
    "make": "Nissan",
    "model": "GTR",
    "owner": "Paul Allen"
  }
}
```

うまくいきました。

#### Hyperledger Explorerの画面にも反映される
Hyperledger Explorer 画面の内容が更新されて、追加されたブロックやトランザクションの内容が確認できるはずです。

![Hyperledger Explorer(fabcar) screenshot after invoke 1](https://qiita-image-store.s3.amazonaws.com/0/123276/983716a0-982c-f916-a1b7-343da995af65.png "Hyperledger Explorer - fabcar - after invoke-1")
![Hyperledger Explorer(fabcar) screenshot after invoke 2](https://qiita-image-store.s3.amazonaws.com/0/123276/f864b9e0-5f43-c341-5847-1d2e95aec495.png "Hyperledger Explorer - fabcar - after invoke-2")

いい感じに見えてますね!

### Hyperledger Explorer の停止、basic-network の消去
最後にクリーンアップして終わります。

```shell
$ cd ~/blockchain-explorer
$ ./stop.sh
$ cd ~/blockchain-explorer/app/persistence/fabric/postgreSQL/db/
$ ./createdb.sh
$ cd ~/fabric/fabric-samples/basic-network
$ ./stop.sh; ./teardown.sh

# Shut down the Docker containers that might be currently running.
...
Untagged: dev-peer0.org1.example.com-fabcar-1.0-5c906e402ed29f20260ae42283216aa75549c571e2e380f3615826365d8269ba:latest
Deleted: sha256:87f02230cf12f7490d02f14f09c60b3a37dd83cf8457177ca0d5af28cd091ec7
Deleted: sha256:41ad9de237e53679ed99e5d286fa6900a2f8bca3c626f3dc96ddb4273dd886e2
Deleted: sha256:91fab37bc2bb1c5175a4432aa45f6c8f9f64862fbe9fed8f35ef22351d67ffe8
Deleted: sha256:ca0492ce9b313c1a273a00c8d5e3d0120ae80ec4994cda092c0e364ae5c5434d
```

（終わり）