Hyperledger Avalonのサンプルをシミュレーションモードで動かしてみる

# はじめに

株式会社日立製作所 研究開発グループ サービスコンピューティング研究部の池川です。
Blockchainに関する研究をしており、特にHyperledgerが管理するOSSを使っています。

本記事では、Hyperledger Avalonの紹介とサンプルを使った実行例について説明します。

## Hyperledger Avalonとは

Hyperledger AvaonはLinux Foundationのブロックチェーン技術推進コミュニティであるHyperledgerが管理するOSSプロジェクトの1つです。

> + [Hyperledger Avalon](https://www.hyperledger.org/use/avalon)
> + [hyperledger/avalon | github](https://github.com/hyperledger/avalon)

Hyperledger AvalonはEnterprise Ethereum Allianceが発表したOff-Chain Trusted Compute Specificationを実現するプロジェクトです。

> + [Enterprise Ethereum Alliance Off-Chain Trusted Compute Specification v1.1](https://entethalliance.org/wp-content/uploads/2019/11/EEA_Off-Chain_Trusted_Compute_Specification_v1.1.pdf)

このプロジェクトには4つの目的があります。

> 1. ブロックチェーン上で相互に信頼できない当事者間のプライベート取引をサポートすることでブロックチェーンへのアクセス権を持つ他の当事者にも取引の詳細を開示することを可能にする。
> 2. ブロックチェーン上の選択された当事者に対して選択された情報の開示し、一方でこれらの同じ選択された当事者からの他の情報の秘密を維持する（選択的プライバシー)。
> 3. 集中的な処理をメインブロックチェーンからオフチェーンのTrusted Computeに移動する 機能を使用することで、スループットとスケーラビリティを向上させることができます。
> 4. 認証されたオラクルのサポート
>
> [引用] "Enterprise Ethereum Alliance Off-Chain Trusted Compute Specification v1.1" (日本語訳)

現状のAvalonでは、これらの目的の中で、1、3、4の開発が進められ機能を体験することができます。
_（2020年12月12日現在では、2に関しての開発も進められているようですが機能を試してみることはまだできないようです。）_

Avalon計算が正しく秘密裏に行われたことを保証するために下記の技術を含みます。

1. Multi-Party Compute (MPC)
2. Zero-Knowledge Proofs (ZKP)
3. __Intel SGX Trusted Execution Environments (TEE)__

現時点ではTEEを用いた実装が最優先で進められています。
_（2020年12月12日現在ではMPCおよびZKPについては未実装です）_

## Trusted Execution Environments (TEE)

[Intel Software Guard Extensions (SGX)](https://www.intel.co.jp/content/www/jp/ja/architecture-and-technology/software-guard-extensions.html)や[ARM TrustZone](https://www.arm.com/ja/why-arm/technologies/trustzone-for-cortex-m)、[AMD Secure Encrypted Virtualization (SEV)](https://developer.amd.com/sev/)などCPUベンダ各社が提供しているセキュリティ技術です。

Hyperledger Avalonでは、Intel SGXを利用した実装が進められています。
Intel SGXはメモリ上に暗号化領域を生成し、そこにプログラムやデータをロードすることでセンシティブなデータを保護しつつプログラムを実行することが可能となるCPUの機能です。
Intel SGXではメモリ上の暗号化領域を __Enclave__ と呼んでいます。

Intel SGXについて、詳しくは下記の記事を参考にしました。

> + [Intel SGX入門 - SGX基礎知識編](https://qiita.com/Cliffford/items/2f155f40a1c3eec288cf)
> + [Intel SGX入門 - SGXプログラミング編](https://qiita.com/Cliffford/items/c6c0c696d4cc6d60d515)

# 前提環境構築

Ubuntu Server 20.04 LTSを搭載したサーバを1台立ち上げます。
なお、筆者はAWS上にm5.4xlargeのEC2インスタンスを立ち上げて作業をしました。

以後、立ち上げたインスタンスにssh接続し構築しました。

## docker, docker-composeのインストール

ホームディレクトリで作業を行います。

```shell
cd ~

# docker, docker-composeのインストール (最新のUbuntu20.04LTSではaptで普通にインストールできます)
sudo apt update
sudo apt install -y docker docker-compose

# sudoなしでdockerコマンドを使えるようにする
sudo usermod -aG docker $(whoami)

# ここで一旦再起動
sudo reboot
```

## GithubからHyperledger Avalonのソースをクローンして初期設定

```shell
cd ~

# Avalonをclone
git clone https://github.com/hyperledger/avalon

# 執筆時点では下記のコミットが最新の状態でした。
# 必要であればあcheckoutしてください。
# git checkout 65853e715d8775360e93c495be6f0f2cb5050870

cd avalon

echo export TCF_HOME=$PWD >> ~/.bashrc
source ~/.bashrc
```

## Hyperledger Avalonの立ち上げ
以下のコマンドを実行してDockerイメージのビルドと立ち上げを行います。
マシンのスペックにもよりますが20分弱かかるので気長に待ちましょう。

```shell
cd $TCF_HOME
sudo docker-compose up -d --build
```

ビルドが完了し下記の4つのコンテナが立ち上がります。

+ avalon-shell
    + 命令を投げるクライアントです。一通りコンテナ全てが立ち上がったらこちらのコンテナから操作を実行します。
+ avalon-enclave-manager
    + Intel SGXより作成された暗号化領域（Enclave）です。こちらに暗号化されたプログラムを配置し実行します。
+ avalon-listener
    + 命令を監視するリスナーです。
+ avalon-lmdb
    + リスナーから一時的に命令を保存するデータベースです。


```shell
ubuntu@test:~/avalon$ docker ps
CONTAINER ID        IMAGE                        COMMAND                   CREATED             STATUS              PORTS                NAMES
c689e7799c3d        avalon-shell-dev             "bash -c 'tail -f /d…"    6 days ago          Up 6 days                                avalon-shell
7e5057954ee8        avalon-enclave-manager-dev   "bash -c '\n  if [ -v…"   6 days ago          Up 6 days           5555/tcp             avalon-enclave-manager
8364d15c21c8        avalon-listener-dev          "bash -c '\n  avalon_…"   6 days ago          Up 6 days           1947/tcp, 5555/tcp   avalon-listener
37505c095909        avalon-lmdb-dev              "bash -c '\n  kv_stor…"   6 days ago          Up 6 days           9090/tcp             avalon-lmdb
```


# 動作確認

avalon-shellコンテナの中に入って操作をします。

```shell
docker exec -it avalon-shell bash
```

## サンプル1：echo-result

avalon-shellコンテナに入り、echo-resultというサンプルを実行してみます。

このプログラムはユーザが指定した任意の文字列をEnclave上のプログラムに渡し、その文字列をそのままユーザに返すプログラムです。
命令を出す側を _Requester_ 、命令を受けて実行するEnclaveを持つ側を _Worker_ と呼んでいます。
本サンプルの動作説明を以下に示します。

1. `echo-result`では、まずRequesterがavalon-shellのgeneric_client.pyを用いて命令を発行します。
2. `generic_client.py`で命令を暗号化し、avalon-listenerに渡します。
3. avalon-listenerは、受けた命令をavalon-lmdbに書き込みます。
4. avalon-enclave-managerはavalon-lmdbの中を監視し、自身のworker_idが指定された命令を復号化して命令を実行します。
     + echo-resultは、Requesterが指定した任意の文字列をそのまま再度暗号化して結果として返すプログラムとなっています。
5. 命令の実行と逆の経路を通り、Requesterが実行したgeneric_client.pyが結果を受け取り復号化した後にコンソールにその結果を出力します。

```shell:コマンド
examples/apps/generic_client/generic_client.py -o --uri "http://avalon-listener:1947" --workload_id "echo-result" --in_data "Hello" --worker_id "singleton-worker-1"
```

+ `examples/apps/generic_client/generic_client.py`はRequesterが命令を発行するクライアントのプログラムとなります。
+ `--uri "http://avalon-listener:1947"`は命令の渡し先になります。今回はBlockchainとの接続はしない単純なモデルの紹介であり、直接avalon-listenerに命令を渡しています。
+ `--workload_id "echo-result"`では、動作するプログラムを選択します。
+ `--in_data "Hello"`で任意の文字列を記入します。
+ `--worker_id "singleton-worker-1"`で、どのWorkerのEnclaveに入っているプログラムを動作させるかを選択します。worker_idはavalon/config/singleton_enclave_config.tomlで変更することができます。

```shell:結果

2020-12-01 02:34:48,894 - INFO - ******* Hyperledger Avalon Generic client *******
2020-12-01 02:34:48,922 - INFO -
 Worker retrieve: worker status 1 details : {
    "workOrderSyncUri": "",
    "workOrderAsyncUri": "",
    "workOrderPullUri": "",
    "workOrderNotifyUri": "",
    "receiptInvocationUri": "",
    "workOrderInvocationAddress": "",
    "receiptInvocationAddress": "",
    "fromAddress": "",
    "hashingAlgorithm": "SHA-256",
    "signingAlgorithm": "SECP256K1",
    "keyEncryptionAlgorithm": "RSA-OAEP-3072",
    "dataEncryptionAlgorithm": "AES-GCM-256",
    "workOrderPayloadFormats": "JSON-RPC",
    "workerTypeData": {
        "verificationKey": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAExPSiZWcSMHc+h2eSgG3gZaNa0xZ4NUMY\n4vnI5vJepYHmKRJhpXaTZuPgUNE2Mtgmp6PlrrsENQMK0x/9Kn9l7A==\n-----END PUBLIC KEY-----\n",
        "extendedMeasurements": [
            "DEADBEEF00000000DEADBEEF0000000000000000000000000000000000000000",
            "D6D43CC49AD5ED1D937D63C8DCC0B428C94FC6490533BE79B145EE3A20473378"
        ],
        "proofDataType": "TEE-SGX-IAS",
        "proofData": "",
        "encryptionKey": "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAzReZDZeM933kQH7bxjYv\n6USaa9U694BOx4gyKF/MrkY/iQKCbC0zq1STT5UcM6DPUH+/YLrm3EKDi3gsO28u\ngWmW0ACYV66vgZP9AN/BLYt4wuPAknQ31ray5P3xRmK+RLS2iRXTLfy8JQ0rHZmF\nxOPOb/fAueQ5s34U2tjgIKSQoBENK5voQ+QC6UOyZ+NGlwCWEt1a4wMOVDIiAwKI\nHlwg8GNdxTZaONOZVGH2/MpLptCkGKXC0giHxp6F+pWKqLISghTduAHQpgAn24Ml\nM3cWBkhjR4afB65pPpo1zuq0Rhi66SVi6YX8ffPyUYYAbMsza/+VSaCW4ATIAbyZ\nPR5iTEa2Yg2c1/OXqx+FUsDZ1mJX9U6y7C0G9REZMAU85INF2l2EiT7fQzJB62O/\nhIutfmE/W+g88Qn4xJQhbMUTbRigThMBUAGP/tIctVSEWpEhsM77vCheSwMeRWpt\n9lY3AG1mrbZKWBpKA7wX4f84wGRTeJD7f7f4CPCGQ7UxAgMBAAE=\n-----END PUBLIC KEY-----\n",
        "encryptionKeySignature": "3044022045B40DB94BD7C034C9584857A5C84D5C109E7D927352272D074685B864BE2EB402201F526F40C28DAC53222CC632A23630AE1219F0ED3C0669EB13BCC574F1D6FE9C"
    }
}

2020-12-01 02:34:48,924 - INFO - *********Updating Worker Details*********
2020-12-01 02:34:48,924 - INFO - Hashing Algorithm : SHA-256
2020-12-01 02:34:48,925 - INFO - Signing Algorithm : SECP256K1
2020-12-01 02:34:48,963 - INFO - Proof data is empty. Skipping verification of attestation report
2020-12-01 02:34:48,963 - INFO - **********Worker details Updated with Worker ID*********
0b03616a46ea9cf574f3f8eedc93a62c691a60dbd3783427c0243bacfe5bba94

2020-12-01 02:34:48,963 - INFO - worker_encrypt_key -----BEGIN PUBLIC KEY-----
MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAzReZDZeM933kQH7bxjYv
6USaa9U694BOx4gyKF/MrkY/iQKCbC0zq1STT5UcM6DPUH+/YLrm3EKDi3gsO28u
gWmW0ACYV66vgZP9AN/BLYt4wuPAknQ31ray5P3xRmK+RLS2iRXTLfy8JQ0rHZmF
xOPOb/fAueQ5s34U2tjgIKSQoBENK5voQ+QC6UOyZ+NGlwCWEt1a4wMOVDIiAwKI
Hlwg8GNdxTZaONOZVGH2/MpLptCkGKXC0giHxp6F+pWKqLISghTduAHQpgAn24Ml
M3cWBkhjR4afB65pPpo1zuq0Rhi66SVi6YX8ffPyUYYAbMsza/+VSaCW4ATIAbyZ
PR5iTEa2Yg2c1/OXqx+FUsDZ1mJX9U6y7C0G9REZMAU85INF2l2EiT7fQzJB62O/
hIutfmE/W+g88Qn4xJQhbMUTbRigThMBUAGP/tIctVSEWpEhsM77vCheSwMeRWpt
9lY3AG1mrbZKWBpKA7wX4f84wGRTeJD7f7f4CPCGQ7UxAgMBAAE=
-----END PUBLIC KEY-----

2020-12-01 02:34:48,977 - INFO -
 Work order sumbit request {
    "jsonrpc": "2.0",
    "method": "WorkOrderSubmit",
    "id": 8330,
    "params": {
        "workOrderId": "b7eedda1e3de2a1af59fd5addc846dd7aa48028d6f6003ebd2f75625a765aefd",
        "responseTimeoutMSecs": 6000,
        "payloadFormat": "JSON-RPC",
        "requesterNonce": "b86f4842f8979c74eef2dd743bc484aa",
        "workloadId": "6563686f2d726573756c74",
        "workerId": "0b03616a46ea9cf574f3f8eedc93a62c691a60dbd3783427c0243bacfe5bba94",
        "requesterId": "34a8fe3fcd5493d7f93004dfd0a50bfce114eb007153d3922860bd82be7bef89",
        "sessionKeyIv": "84EB02939DD062CA798994F0",
        "workerEncryptionKey": "2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d4949426f6a414e42676b71686b6947397730424151454641414f43415938414d49494269674b43415945417a52655a445a654d3933336b51483762786a59760a36555361613955363934424f783467794b462f4d726b592f69514b436243307a71315354543555634d36445055482b2f594c726d33454b44693367734f3238750a67576d573041435956363676675a5039414e2f424c597434777550416b6e51333172617935503378526d4b2b524c5332695258544c6679384a513072485a6d460a784f504f622f6641756551357333345532746a67494b53516f42454e4b35766f512b514336554f795a2b4e476c7743574574316134774d4f5644496941774b490a486c776738474e6478545a614f4e4f5a564748322f4d704c7074436b474b584330676948787036462b70574b714c495367685464754148517067416e32344d6c0a4d336357426b686a523461664236357050706f317a7571305268693636535669365958386666507955595941624d737a612f2b5653614357344154494162795a0a505235695445613259673263312f4f5871782b465573445a316d4a5839553679374330473952455a4d41553835494e46326c324569543766517a4a4236324f2f0a68497574666d452f572b673838516e34784a5168624d55546252696754684d42554147502f7449637456534557704568734d37377643686553774d65525770740a396c59334147316d72625a4b5742704b413777583466383477475254654a443766376634435043475137557841674d424141453d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a",
        "dataEncryptionAlgorithm": "AES-GCM-256",
        "encryptedSessionKey": "43061E5C6C2BA16CA614B8542003A161FCE2AB03B998137D2ACF88F9E5B2BC2CB80C2793B3846BC919A9092B5EA9E2B3351FB702C69B6B964222F658726A6B3B1BF64005259F54504ADCE45BD2DEA6B45E7379FA36EFCD75F52D9B6CFC0632B9FACAAA1D56F9FA3726D8EFAA644D3474FE24A228D989E75D24B4531FC912FAC4F25C807657ABD8941DD856444129F0C228533168D0B491B87BD9CF04C84B788AD76FB21530DCC7A4E6CEC9844DFA00D6DD0D136ACD7CEAB641E8167182B29D516C2006B9903570259C131108B440E6BDA242D8DC8268D6C7237452B716A37C19CE5D1D4A93F106175C5ED97E71FE71E4F177C4F0570149AA03D187FA38F806463C83003A08697603FF4E3CB316BC578BFF3D787FBAE5862C4BFEA373BDCD8E052E8597A953FB18202E245B91F7E082FBE2CF337817FC1AF8E057E4ABF9A2105E7AD096C12D3CC8D7AD640E5550D2F95D618E4722B5616D35627D04562418218EA2179F915781D91B72B5CA3A69E9EDFBFDED0F70375C70DFEC2FBCB9F445F6BE",
        "encryptedRequestHash": "7E1C988308CBC8DEE5CF2E8106927A5EA4A43BBA8871E24FE4794EFE65031503EAD56C08587B39573A504D5371E3A89C",
        "requesterSignature": "",
        "inData": [
            {
                "index": 0,
                "data": "zOZvXt6fJjnwgcNDIxpNOf89EOYb"
            }
        ]
    }
}

2020-12-01 02:34:49,011 - INFO - Work order submit response : {
    "error": {
        "code": 5,
        "message": "Work order is computing. Please query for WorkOrderGetResult to view the result",
        "data": {
            "workOrderId": "b7eedda1e3de2a1af59fd5addc846dd7aa48028d6f6003ebd2f75625a765aefd"
        }
    },
    "id": 8330,
    "jsonrpc": "2.0"
}

2020-12-01 02:34:53,062 - INFO - Work order get result {
    "result": {
        "workOrderId": "b7eedda1e3de2a1af59fd5addc846dd7aa48028d6f6003ebd2f75625a765aefd",
        "workloadId": "6563686f2d726573756c74",
        "workerId": "0b03616a46ea9cf574f3f8eedc93a62c691a60dbd3783427c0243bacfe5bba94",
        "requesterId": "34a8fe3fcd5493d7f93004dfd0a50bfce114eb007153d3922860bd82be7bef89",
        "workerNonce": "d3VyMGn27hTFfjjGN7sQYcusA4Y6dyTln60F6vRfHLY=",
        "workerSignature": "MEQCIHWJyn/XROwhZBawmMu2armAbRVLRPFaeqvX0EdakBJqAiBSDzjLfUkQGzZk+N6tghRewMUpxyducs0gVffGOVgttg==",
        "outData": [
            {
                "index": 0,
                "dataHash": "84EA068A1326A99D02AF62D878FD15A5F2AFA8CF7BAAFADD95DA31165E3B45F1",
                "data": "1sZQZ/2ZQNwL9Pw3G6Fngagy281Tf3E8pS7pJhg=",
                "encryptedDataEncryptionKey": "",
                "iv": ""
            }
        ]
    },
    "id": 5521,
    "jsonrpc": "2.0"
}
2020-12-01 02:34:53,072 - INFO - Signature verification Successful
Decryption result at client - b'RESULT: Hello'
2020-12-01 02:34:53,073 - INFO - Decryption result at client - b'RESULT: Hello'
2020-12-01 02:34:53,074 - INFO -
Decrypted response:
 [{'index': 0, 'dataHash': '84EA068A1326A99D02AF62D878FD15A5F2AFA8CF7BAAFADD95DA31165E3B45F1', 'data': b'RESULT: Hello', 'encryptedDataEncryptionKey': '', 'iv': ''}]
```

## サンプル2：heart-disease-eval

続いて、心臓病リスクを評価をするheart-disease-evalというプログラムを実行してみます。
こちらは心拍データを入力することでenclave領域内の心臓病リスク評価プログラムが動作します。
その結果をユーザに返すプログラムです。

先程のサンプルと同様に、命令を出す側を _Requester_ 、命令を受けて実行するEnclaveを持つ側を _Worker_ と呼んでいます。
基本的なデータフローは先程説明したecho-resultと同様です。
heart-disease-evalでは、Enclave内で入力された心拍データを解析して心臓病の発症リスクを計算し、その結果をRequesterに返します。
命令内容や結果は暗号化されており、さらにEnclave領域内で命令の暗号化、解析、および結果の暗号化が閉じているため、心拍データ(入力データ)と心臓病の発症リスク(解析結果)はRequesterのみが知る情報となります。
Avalonは医療データなどのセンシティブなデータを扱うような場合、患者のデータを隠しながら他の組織が持つ計算資源を利用して解析を行うようなユースケースに適応可能なOSSです。

```shell:コマンド
examples/apps/generic_client/generic_client.py -o --uri "http://avalon-listener:1947" --workload_id "echo-result" --in_data "Hello" --worker_id "singleton-worker-1"
```

+ `examples/apps/generic_client/generic_client.py`はRequesterが命令を発行するクライアントのプログラムとなります。
+ `--uri "http://avalon-listener:1947"`は命令の渡し先になります。今回はBlockchainとの接続はしない単純なモデルの紹介であり、直接avalon-listenerに命令を渡しています。
+ `--workload_id "echo-result"`では、動作するプログラムを選択します。
+ `--in_data "Hello"`で任意の文字列を記入します。
+ `--worker_id "singleton-worker-1"`で、どのWorkerのEnclaveに入っているプログラムを動作させるかを選択します。worker_idはavalon/config/singleton_enclave_config.tomlで変更することができます。






```shell:コマンド
examples/apps/generic_client/generic_client.py -o --uri "http://avalon-listener:1947" --workload_id "heart-disease-eval" --in_data "Data: 25 10 1 67 102 125 1 95 5 10 1 11 36 1" --worker_id "singleton-worker-1"
```

```shell:結果
2020-12-01 03:11:19,544 - INFO - ******* Hyperledger Avalon Generic client *******
2020-12-01 03:11:19,565 - INFO -
 Worker retrieve: worker status 1 details : {
    "workOrderSyncUri": "",
    "workOrderAsyncUri": "",
    "workOrderPullUri": "",
    "workOrderNotifyUri": "",
    "receiptInvocationUri": "",
    "workOrderInvocationAddress": "",
    "receiptInvocationAddress": "",
    "fromAddress": "",
    "hashingAlgorithm": "SHA-256",
    "signingAlgorithm": "SECP256K1",
    "keyEncryptionAlgorithm": "RSA-OAEP-3072",
    "dataEncryptionAlgorithm": "AES-GCM-256",
    "workOrderPayloadFormats": "JSON-RPC",
    "workerTypeData": {
        "verificationKey": "-----BEGIN PUBLIC KEY-----\nMFYwEAYHKoZIzj0CAQYFK4EEAAoDQgAExPSiZWcSMHc+h2eSgG3gZaNa0xZ4NUMY\n4vnI5vJepYHmKRJhpXaTZuPgUNE2Mtgmp6PlrrsENQMK0x/9Kn9l7A==\n-----END PUBLIC KEY-----\n",
        "extendedMeasurements": [
            "DEADBEEF00000000DEADBEEF0000000000000000000000000000000000000000",
            "D6D43CC49AD5ED1D937D63C8DCC0B428C94FC6490533BE79B145EE3A20473378"
        ],
        "proofDataType": "TEE-SGX-IAS",
        "proofData": "",
        "encryptionKey": "-----BEGIN PUBLIC KEY-----\nMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAzReZDZeM933kQH7bxjYv\n6USaa9U694BOx4gyKF/MrkY/iQKCbC0zq1STT5UcM6DPUH+/YLrm3EKDi3gsO28u\ngWmW0ACYV66vgZP9AN/BLYt4wuPAknQ31ray5P3xRmK+RLS2iRXTLfy8JQ0rHZmF\nxOPOb/fAueQ5s34U2tjgIKSQoBENK5voQ+QC6UOyZ+NGlwCWEt1a4wMOVDIiAwKI\nHlwg8GNdxTZaONOZVGH2/MpLptCkGKXC0giHxp6F+pWKqLISghTduAHQpgAn24Ml\nM3cWBkhjR4afB65pPpo1zuq0Rhi66SVi6YX8ffPyUYYAbMsza/+VSaCW4ATIAbyZ\nPR5iTEa2Yg2c1/OXqx+FUsDZ1mJX9U6y7C0G9REZMAU85INF2l2EiT7fQzJB62O/\nhIutfmE/W+g88Qn4xJQhbMUTbRigThMBUAGP/tIctVSEWpEhsM77vCheSwMeRWpt\n9lY3AG1mrbZKWBpKA7wX4f84wGRTeJD7f7f4CPCGQ7UxAgMBAAE=\n-----END PUBLIC KEY-----\n",
        "encryptionKeySignature": "3044022045B40DB94BD7C034C9584857A5C84D5C109E7D927352272D074685B864BE2EB402201F526F40C28DAC53222CC632A23630AE1219F0ED3C0669EB13BCC574F1D6FE9C"
    }
}

2020-12-01 03:11:19,567 - INFO - *********Updating Worker Details*********
2020-12-01 03:11:19,567 - INFO - Hashing Algorithm : SHA-256
2020-12-01 03:11:19,568 - INFO - Signing Algorithm : SECP256K1
2020-12-01 03:11:19,606 - INFO - Proof data is empty. Skipping verification of attestation report
2020-12-01 03:11:19,606 - INFO - **********Worker details Updated with Worker ID*********
0b03616a46ea9cf574f3f8eedc93a62c691a60dbd3783427c0243bacfe5bba94

2020-12-01 03:11:19,606 - INFO - worker_encrypt_key -----BEGIN PUBLIC KEY-----
MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAzReZDZeM933kQH7bxjYv
6USaa9U694BOx4gyKF/MrkY/iQKCbC0zq1STT5UcM6DPUH+/YLrm3EKDi3gsO28u
gWmW0ACYV66vgZP9AN/BLYt4wuPAknQ31ray5P3xRmK+RLS2iRXTLfy8JQ0rHZmF
xOPOb/fAueQ5s34U2tjgIKSQoBENK5voQ+QC6UOyZ+NGlwCWEt1a4wMOVDIiAwKI
Hlwg8GNdxTZaONOZVGH2/MpLptCkGKXC0giHxp6F+pWKqLISghTduAHQpgAn24Ml
M3cWBkhjR4afB65pPpo1zuq0Rhi66SVi6YX8ffPyUYYAbMsza/+VSaCW4ATIAbyZ
PR5iTEa2Yg2c1/OXqx+FUsDZ1mJX9U6y7C0G9REZMAU85INF2l2EiT7fQzJB62O/
hIutfmE/W+g88Qn4xJQhbMUTbRigThMBUAGP/tIctVSEWpEhsM77vCheSwMeRWpt
9lY3AG1mrbZKWBpKA7wX4f84wGRTeJD7f7f4CPCGQ7UxAgMBAAE=
-----END PUBLIC KEY-----

2020-12-01 03:11:19,626 - INFO -
 Work order sumbit request {
    "jsonrpc": "2.0",
    "method": "WorkOrderSubmit",
    "id": 3886,
    "params": {
        "workOrderId": "3cfef868dbce7eef32e52a47af1b885b0b8d86a606b666ff80d72dd4f6bdd94b",
        "responseTimeoutMSecs": 6000,
        "payloadFormat": "JSON-RPC",
        "requesterNonce": "fa0a3d27fe449c0971710bf25b41877e",
        "workloadId": "68656172742d646973656173652d6576616c",
        "workerId": "0b03616a46ea9cf574f3f8eedc93a62c691a60dbd3783427c0243bacfe5bba94",
        "requesterId": "2cdf82c94ed63b31c0b6a6926d586f81fe481fce09ec928562c2ab53667c23af",
        "sessionKeyIv": "1803BEEE396C48EC21BD801C",
        "workerEncryptionKey": "2d2d2d2d2d424547494e205055424c4943204b45592d2d2d2d2d0a4d4949426f6a414e42676b71686b6947397730424151454641414f43415938414d49494269674b43415945417a52655a445a654d3933336b51483762786a59760a36555361613955363934424f783467794b462f4d726b592f69514b436243307a71315354543555634d36445055482b2f594c726d33454b44693367734f3238750a67576d573041435956363676675a5039414e2f424c597434777550416b6e51333172617935503378526d4b2b524c5332695258544c6679384a513072485a6d460a784f504f622f6641756551357333345532746a67494b53516f42454e4b35766f512b514336554f795a2b4e476c7743574574316134774d4f5644496941774b490a486c776738474e6478545a614f4e4f5a564748322f4d704c7074436b474b584330676948787036462b70574b714c495367685464754148517067416e32344d6c0a4d336357426b686a523461664236357050706f317a7571305268693636535669365958386666507955595941624d737a612f2b5653614357344154494162795a0a505235695445613259673263312f4f5871782b465573445a316d4a5839553679374330473952455a4d41553835494e46326c324569543766517a4a4236324f2f0a68497574666d452f572b673838516e34784a5168624d55546252696754684d42554147502f7449637456534557704568734d37377643686553774d65525770740a396c59334147316d72625a4b5742704b413777583466383477475254654a443766376634435043475137557841674d424141453d0a2d2d2d2d2d454e44205055424c4943204b45592d2d2d2d2d0a",
        "dataEncryptionAlgorithm": "AES-GCM-256",
        "encryptedSessionKey": "626E62FA8C7DAE8CFCC3A8859C2E1E481A5381154F15EF4F264330D6BFE03BB081D6C6F7F3AC83E05E0DE166F737C8A7302AE71045991D27986EE0EBB0DA35AC588EB3C25BB49B76D54065E9FF73F6D07D3907EC881445F249318F9187E1637B9DC902306A618311F120EB5EF74A74D26B0466291EF0068AB071FCF2CFFEA99874F9E8BAA261C3C417B1944A3E3EEC9E63037DD1F03FC861D0E54B24BE5ED83D34FEE0CD3780C8150CF4C76946111A5A7BA57E5125E226E6FBEC8DBA4552EBB50DB7803CD609BBE4C7F492FED14A5B3BCA6096A288C15123E7A4E1F28DC85C50ECA79E148B2DD60C7A989D72FBB75071CF28E8A55315ECA7D83C0C6B7B933F6622BB12E55DA04BE490F9781E5FC3F212E84131E114BC94D55036614ACCE3AA2D1F27EF64576F7BA5185449E7766A5D78807635803BA13CE0AD79A041345C8AEF5547B085A5E0BD1C09C00E38A39FB3425BDAC91E36002DA5E765D3B806AE8E5587B83FF11504D4A7A2D1601AE4E6321DBD722117595DA179838E99D017F76519",
        "encryptedRequestHash": "49805D709B4948AA2D64A42508E95AC418BFA9695DCA8F342B0890DD2D0A0B1EA686D0098A361CF7C341C1E5831725D2",
        "requesterSignature": "",
        "inData": [
            {
                "index": 0,
                "data": "B210cmyxydLYklQ6+fXNxSZc2UiEwfC63fSlDzluTGOCEb3MtU9yFds9jonmwN6awDYNKVurcLzps742"
            }
        ]
    }
}

2020-12-01 03:11:19,664 - INFO - Work order submit response : {
    "error": {
        "code": 5,
        "message": "Work order is computing. Please query for WorkOrderGetResult to view the result",
        "data": {
            "workOrderId": "3cfef868dbce7eef32e52a47af1b885b0b8d86a606b666ff80d72dd4f6bdd94b"
        }
    },
    "id": 3886,
    "jsonrpc": "2.0"
}

2020-12-01 03:11:27,756 - INFO - Work order get result {
    "result": {
        "workOrderId": "3cfef868dbce7eef32e52a47af1b885b0b8d86a606b666ff80d72dd4f6bdd94b",
        "workloadId": "68656172742d646973656173652d6576616c",
        "workerId": "0b03616a46ea9cf574f3f8eedc93a62c691a60dbd3783427c0243bacfe5bba94",
        "requesterId": "2cdf82c94ed63b31c0b6a6926d586f81fe481fce09ec928562c2ab53667c23af",
        "workerNonce": "dKzw7zxKOXBlmlc/fuTz/O4DwZOFGNSfPyFvNtYQPEQ=",
        "workerSignature": "MEQCIGNiKVk9Gg38ZnaFbigp0yn5yUa4gONHSDZsyyWQHk1cAiAs+Tjl6pFLyjSHrJYalzLHVgWRye/T5SJgt8iKqKTzVw==",
        "outData": [
            {
                "index": 0,
                "dataHash": "3EC9AFF5583A9AC72B9BCE888B38B740D6B7DBE154FC1C35651890EC202437CE",
                "data": "GmN1Mz7wjYLYwkQu//DbgG8eglrLluLnmKT3QiwqEDDWQO6YzHGJ7oTdqv1kUJgw86aWNg==",
                "encryptedDataEncryptionKey": "",
                "iv": ""
            }
        ]
    },
    "id": 1633,
    "jsonrpc": "2.0"
}
2020-12-01 03:11:27,765 - INFO - Signature verification Successful
Decryption result at client - b'You have a 47% risk of heart disease'
2020-12-01 03:11:27,766 - INFO - Decryption result at client - b'You have a 47% risk of heart disease'
2020-12-01 03:11:27,767 - INFO -
Decrypted response:
 [{'index': 0, 'dataHash': '3EC9AFF5583A9AC72B9BCE888B38B740D6B7DBE154FC1C35651890EC202437CE', 'data': b'You have a 47% risk of heart disease', 'encryptedDataEncryptionKey': '', 'iv': ''}]
```

# さいごに

今回はHyperledger Avalonの概要とサンプルの動かし方を紹介しました。
Hyperledger Avalonは現在も開発が進んでいますので、引き続きその動向や使い方などを紹介していきたいと思います。