Azure Blockchain Service のチュートリアルをやってみた

# はじめに

本記事は「くふうカンパニー Advent Calendar 2019」の 9 日目です。

今回は、趣味で少し触っているブロックチェーンのクラウドサービスに関する記事を書きたいと思います。
各クラウドサービスではマネージドなブロックチェーンを構築するサービスがあります。

- [ブロックチェーン | AWS](https://aws.amazon.com/jp/blockchain/)
- [Blockchain - Google Cloud](https://cloud.google.com/customers/blockchain/?hl=ja)

今回はその中でも [Microsoft Azure のブロックチェーンサービス](https://azure.microsoft.com/ja-jp/solutions/blockchain/) を使いたいと思います。
Microsoft Azure を選択した理由は、単純に Azure を触ったことがなかったためです。
逆にその点が、今回の記事の大きなモチベーションになりました。

Azure にはチュートリアルが用意されているので、本記事ではこちらに沿って実施しました。
[クイック スタート:Azure portal を使用して Azure Blockchain Service ブロックチェーン メンバーを作成する](https://docs.microsoft.com/ja-jp/azure/blockchain/service/create-member)
基本的にはチュートリアルが丁寧なので、わざわざ記事を書くまでもないと思いましたが、私が調べた内容も補足として記載させていただきました。

Azure のアカウントは作成済みとします。
今回の内容は、無料サブスクリプションの範囲内のようです。

# リソースグループの作成

リソースの作成 > 「Azure Blockchain Service （プレビュー） を選択する

新規作成画面になりますので、このように入力します。
既存のパラメータは使用しないので、全て新規の値になります。

<img width="689" alt="スクリーンショット 2019-12-07 17.51.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118817/3c92b6ca-b247-9654-0c4e-fe02cd15e80f.png">

> プレビュー版の Azure Blockchain Service は現在、Quorum プロトコルをサポートしています。

とのことなので、 Protocol は Quorum で良さそうです。
[許可型ブロックチェーンQuorumとは？](https://baasinfo.net/?p=2143)

Consortium（コンソーシアム）は、今回作成するブロックチェーンネットワークの名前です。
テストなので適当な名前にします。
Member も同じです。
今回作成するネットワークに参加しているユーザーです。
特に今回のチュートリアルの中では使用しないので適当に名前とパスワードを設定します。

このあと AWS のようにタグもつけることができるのですが、そちらはお好みで良さそうです。
validation が完了すれば作成します。

通知にこのような表示が出ていれば大丈夫そうです。
約 10 分かかります。

<img width="506" alt="スクリーンショット 2019-12-07 19.21.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118817/03a6e619-cafb-65d6-11c3-764fdaa7c334.png">

リソースに移動すると、このような画面になりました。

<img width="822" alt="スクリーンショット 2019-12-07 19.09.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118817/14d2240b-1836-bc67-4cbc-9617fe9ecc32.png">

# ローカル環境構築

トランザクションのノードに接続する方法は、チュートリアル中にいくつかありますが、今回は VS Code で Azure Blockchain Development Kit for Ethereum 方法を使用します。
https://docs.microsoft.com/ja-jp/azure/blockchain/service/connect-vscode

開発マシンは Mac を使用しました。
以下が必要になります。（括弧内は今回使用したバージョン）

- VS Code（1.40.2）
- Node.js 10.15 以降（13.1.0）
- Git 2.10 以降（2.21.0）
- Python 2.7.15 以降（2.7.16）
- Truffle 5.0.0（5.1.3）
- Ganache CLI 6.0.0（6.7.0）
- Azure Blockchain Development Kit for Ethereum（0.1.12）

[Truffle](https://www.trufflesuite.com/) はスマートコントラクトの開発、ビルド、デプロイなどのためのフレームワークです。
[Truffle で始める Ethereum 入門 - ERC20 トークンを作ってみよう](https://qiita.com/amachino/items/8cf609f6345959ffc450)

[Ganache CLI](https://github.com/trufflesuite/ganache-cli) はローカル環境でブロックチェーンを構築するツールです。
[Ganache CLI + web3.jsでEthereum簡易投票アプリを構築](https://qiita.com/hitochan777/items/947a40181d8747f135f7)

このあたりを後日やってみようと思います。
[Ethereumのフレームワーク「Truffle」とローカル開発環境「Ganache」入門ログ](https://qiita.com/mejileben/items/ed840c606403b1776fb9)

[Azure Blockchain Development Kit for Ethereum](https://marketplace.visualstudio.com/items?itemName=AzBlockchain.azure-blockchain) は、必要なツールがちゃんとインストールされているか確認してくれるので、最後にインストールすると良さそうです。
インストールが完了すると、 VS Code のサイドメニューに以下のような表示がでます。

<img width="213" alt="スクリーンショット 2019-12-07 18.05.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118817/37365c84-8f82-249c-6771-be9d9ccae7f7.png">

Connect to network から、リソース、コンソーシアムを選択します。
途中、ログインしていないと Microsoft アカウントにログインするよう促されます。
接続がうまくいくと、サイドメニューにコンソーシアムが表示されます。

<img width="258" alt="スクリーンショット 2019-12-07 19.10.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118817/508b70fc-b6f2-42a3-1bd8-4f3fa3d23730.png">

# スマートコントラクトを実際に作成してみる

[チュートリアル:スマート コントラクトの作成、ビルド、Azure Blockchain Service へのデプロイ](https://docs.microsoft.com/ja-jp/azure/blockchain/service/send-transaction)

## プロジェクトの初期化

VS Code のコマンドパレットから、Azure Blockchain > New Solidity Project > Create basic project を選択します。

<img width="475" alt="スクリーンショット 2019-12-08 3.37.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118817/8de6cfc1-cdea-2d1b-2dff-6315f4c17eb5.png">

プロジェクトにファイルが作成されます。

<img width="256" alt="スクリーンショット 2019-12-08 3.40.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118817/e9e28a5b-b26b-4051-0f9b-f2a71ec11186.png">

## ビルドする

コンソーシアムにデプロイする前に、ビルドする必要があります。
スマートコントラクトは contracts ディレクトリに配置されています。

生成された contracts/HelloBlockchain.sol を右クリックし、 Build Contracts を選択します。
ビルドが完了すると、 build ディレクトリが生成され、結果が格納されます。

## デプロイする

> Truffle では、移行スクリプトを使用して、コントラクトが Ethereum ネットワークにデプロイされます。 
> 移行は、プロジェクトの migrations ディレクトリに配置されている JavaScript ファイルです。

contracts/HelloBlockchain.sol を右クリックし、 Deploy Contracts を選択します。
デプロイ対象のコンソーシアムを選択します。
Generate mnemonic を選択し、メンバーの秘密鍵を作成し、プロジェクトルートに保存します。

このとき、コンソールで Azure Blockchain を選択するとデプロイ時の出力が確認できます。
これはビルド時も同様です。

<img width="959" alt="スクリーンショット 2019-12-08 3.46.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118817/75dfe6c9-b662-b635-72ea-f64eab0a8d28.png">

## コントラクト関数を呼び出す

コントラクトにメッセージを送るスクリプトを作成します。
[web3.js](https://github.com/ethereum/web3.js/) の API を使用するので、少し普通の JavaScript とは書き方が異なります。
[Ethereum Javascript APIであるweb3.jsとは](https://blockmania.jp/%E6%9C%AA%E5%88%86%E9%A1%9E/411/)

sendrequest.js をプロジェクトルートに配置します。
今回のコードは RequestMessage 状態変数を変更するものです。

```js
var HelloBlockchain = artifacts.require("HelloBlockchain");

module.exports = function(done) {
  console.log("Getting the deployed version of the HelloBlockchain smart contract")
  HelloBlockchain.deployed().then(function(instance) {
    console.log("Calling SendRequest function for contract ", instance.address);
    return instance.SendRequest("Hello, blockchain!");
  }).then(function(result) {
    console.log("Transaction hash: ", result.tx);
    console.log("Request complete");
    done();
  }).catch(function(e) {
    console.log(e);
    done();
  });
};
```

これを実行してみます。
こちらのコマンドで実行できます。

```
$ truffle exec sendrequest.js --network <blockchain network>
```

このとき、blockchain network は自分の作成したものを使用するのですが、 `truffle-config.json` の値を使用します。
これはファイル生成時に作成されています。
私の場合はこちらでした。
今回の場合は開発環境ではなく、本番環境なので、 `abs_testblockchain_testblockchain_testblockchain` になるようです。

```js
  networks: {
    development: {
      host: "127.0.0.1",
      port: 8545,
      network_id: "*"
    },
    abs_testblockchain_testblockchain_testblockchain: {
      network_id: "*",
      gas: 0,<img width="745" alt="スクリーンショット 2019-12-08 3.53.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118817/c347e3b3-3ea2-fdd0-b0ca-7144c71a71f7.png">

      gasPrice: 0,
      provider: new HDWalletProvider(fs.readFileSync('/path/myblockchainmember.env', 'utf-8'), "https://testblockchain.blockchain.azure.com:3200/xxxx")
    }
  },
```

```
$ truffle exec sendrequest.js --network abs_testblockchain_testblockchain_testblockchain
Using network 'abs_testblockchain_testblockchain_testblockchain'.

Getting the deployed version of the HelloBlockchain smart contract
Calling SendRequest function for contract  0x5C3cdA6D8793Aa58CFa73455539BfB5A5F1F95ef
Transaction hash:  0x056ce1e8ecebd1abaa5b3ec0039660ef7cd7d460f2bc2c65657b10d9dfca9612
Request complete
```

実行するとこのように出力されます。
返り値はトランザクションの ID のようです。

## コントラクトの状態を照会する

状態変数の状態を確認する関数を作成します。
HelloBlockchain.sol に、 getMessage 関数を追加します。

```js
function getMessage() public view returns (string memory)
{
    if (State == StateType.Request)
        return RequestMessage;
    else
        return ResponseMessage;
}
```
保存したら、 Build Contrasts 、 Deploy Contracts でネットワークにデプロイします。

そして getMessage 関数を呼び出すスクリプト `getmessage.js` をプロジェクトルートに作成します。

```js
var HelloBlockchain = artifacts.require("HelloBlockchain");

module.exports = function(done) {
  console.log("Getting the deployed version of the HelloBlockchain smart contract")
  HelloBlockchain.deployed().then(function(instance) {
    console.log("Calling getMessage function for contract ", instance.address);
    return instance.getMessage();
  }).then(function(result) {
    console.log("Request message value: ", result);
    console.log("Request complete");
    done();
  }).catch(function(e) {
    console.log(e);
    done();
  });
};
```
このスクリプトを再度実行します。

```
$ truffle exec getmessage.js --network abs_testblockchain_testblockchain_testblockchain
Using network 'abs_testblockchain_testblockchain_testblockchain'.

Getting the deployed version of the HelloBlockchain smart contract
Calling getMessage function for contract  0x5C3cdA6D8793Aa58CFa73455539BfB5A5F1F95ef
Request message value:  Hello world
Request complete
```

`Request message value:  Hello world` なので、 sender で送信した値が取得されました。
sendrequest.js の値を変えて再度状態を変えて、 getmessage.js を実行すると、変更された値が取得されます。

# さいごに

ポータルの方でもグラフで確認できるようですね。

<img width="1067" alt="スクリーンショット 2019-12-08 4.07.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118817/c9b24e12-29e4-5e45-63df-647e9a3df255.png">


この後、 [Azure Blockchain Service での開発](https://docs.microsoft.com/ja-jp/azure/blockchain/service/develop) に進んでいきます。
ほとんど VS Code 上の作業で終わることが快適です。

ただ、やはりまだまだ知識が足りないことが実感できました。
また、 Azure の Active Directory はまだ慣れないですね。

今回は簡単ですが、これで終わります。
明日は ryoster さんの記事になります！