Azure Blockchain Serviceを試してみる5（プライバシー機能編）

# はじめに
[前回の記事](https://qiita.com/hayago/items/c1785a785d891f56f192)では、Azure Blockchain Serviceのコンソーシアム管理機能を試しました。今回の記事では、コンソーシアムのメンバ間におけるプライバシーを実現する、プライベートなコントラクトおよびトランザクションについて実際に試してみます。

# プライベートコントラクト

プライベートコントラクトは特定のメンバのみがアクセス可能なコントラクトです。

### コントラクトのデプロイ
Truffleを利用してプライベートコントラクトをデプロイする場合は、デプロイスクリプト内のdeployメソッド呼出しのパラメータに`privateFor`要素を追加します。要素の値には公開先のトランザクションノードの公開鍵を配列で指定します。

トランザクションノードの公開鍵はポータル上で確認が可能です。
<img width="600" alt="スクリーンショット 2019-09-06 16.22.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16354/5763bfc6-0dc9-d6b3-c9fa-b4b326af7e9f.png">

デプロイスクリプトを編集します。

```javascript:2_deploy_contracts.js
const AlisToken = artifacts.require('AlisToken.sol');

module.exports = function deployContracts(deployer) {
  deployer.deploy(AlisToken, {
    privateFor: ["FZfPQmH3rEwPrrn/qXS6O4riab2uwlFHs5ls862djno=", "8PaJA+G+77dKlbJisrt2Lm9skU3yTuVrbkw9bMzyVSY="]
  });
};
```

デプロイします。

```
$ truffle deploy
```

### コントラクトにアクセス
[以前の記事の手順](https://qiita.com/hayago/items/ba4ca93bcd5d99735b9e#%E3%82%B3%E3%83%B3%E3%83%88%E3%83%A9%E3%82%AF%E3%83%88%E3%81%AE%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89%E5%91%BC%E5%87%BA%E3%81%97)でコントラクトのメソッドを呼出します。`privateFor`で指定したトランザクションノードのエンドポイント経由でメソッドを呼出すと通常通り結果が返ってきますが、それ以外のトランザクションノード経由でメソッドを呼び出すとエラーになります。

`privateFor`で指定していないトランザクションノードからメソッドを呼出した場合

```
$ node get_symbol.js
(node:10543) UnhandledPromiseRejectionWarning: Error: Returned values aren't valid, did it run Out of Gas?
    at ABICoder.decodeParameters (/Users/g-hayakawa/workspace/azure-deploy-contract-example/node_modules/web3-eth-abi/src/index.js:226:15)
    at Contract._decodeMethodReturn (/Users/g-hayakawa/workspace/azure-deploy-contract-example/node_modules/web3-eth-contract/src/index.js:465:22)
    at Method.outputFormatter (/Users/g-hayakawa/workspace/azure-deploy-contract-example/node_modules/web3-eth-contract/src/index.js:818:46)
    at Method.formatOutput (/Users/g-hayakawa/workspace/azure-deploy-contract-example/node_modules/web3-core-method/src/index.js:163:54)
    at sendTxCallback (/Users/g-hayakawa/workspace/azure-deploy-contract-example/node_modules/web3-core-method/src/index.js:473:33)
    at /Users/g-hayakawa/workspace/azure-deploy-contract-example/node_modules/web3-core-requestmanager/src/index.js:147:9
    at XMLHttpRequest.request.onreadystatechange (/Users/g-hayakawa/workspace/azure-deploy-contract-example/node_modules/web3-providers-http/src/index.js:96:13)
    at XMLHttpRequestEventTarget.dispatchEvent (/Users/g-hayakawa/workspace/azure-deploy-contract-example/node_modules/xhr2-cookies/dist/xml-http-request-event-target.js:34:22)
    at XMLHttpRequest._setReadyState (/Users/g-hayakawa/workspace/azure-deploy-contract-example/node_modules/xhr2-cookies/dist/xml-http-request.js:208:14)
    at XMLHttpRequest._onHttpResponseEnd (/Users/g-hayakawa/workspace/azure-deploy-contract-example/node_modules/xhr2-cookies/dist/xml-http-request.js:318:14)
    at IncomingMessage.<anonymous> (/Users/g-hayakawa/workspace/azure-deploy-contract-example/node_modules/xhr2-cookies/dist/xml-http-request.js:289:61)
    at IncomingMessage.emit (events.js:205:15)
    at endReadableNT (_stream_readable.js:1154:12)
    at processTicksAndRejections (internal/process/task_queues.js:84:9)
(node:10543) 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:10543) [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.
```

# プライベートトランザクション
プライベートコントラクトに対してトランザクションを送信する場合は、プライベートトランザクションとして送信します。
プライベートトランザクションの送信は、コントラクトデプロイ時と同様にトランザクションのパラメータに`privateFor`要素を追加します。

```javascript
AlisToken.transfer.sendTransaction(
  to, amount, {
    from: "0x1c3051cd7c8c4203e75d06d9ebdea63d67dc7a96",
    privateFor: ["FZfPQmH3rEwPrrn/qXS6O4riab2uwlFHs5ls862djno="]
  });
```

ここでは、コントラクトデプロイ時に`privateFor`で指定した２つのトランザクションノードのうち、一方のみを`privateFor`に指定しています。この場合、トランザクションの実行は`privateFor`で指定したトランザクションノードのみで実行されます。そのため、2つのトランザクションノード間でコントラクトの状態（残高）が異なるという結果になります。

なお、プライベートではないコントラクトに対してプライベートトランザクションは利用できません。同様にプライベートコントラクトに対して、プライベートではないトランザクションを送信することは出来ません。