NEOブロックチェーンを利用した証明書プラットホームneo-vitaeで遊ぼう

# はじめに
NEO-Pythonを使ったDApps 「[Neo-vitae](https://github.com/blocksmithtech/neo-vitae)」で遊ぶ手順を説明していきます。
Neo-vitaeはNEOブロックチェーンとスマートコントラクトを使用する証明書のプラットフォームです。
証明書をIPFS(P2P技術を用いた分散ファイルシステム)に登録したハッシュ値を、NEOブロックチェーンで記録/検索します。

IPFSについての説明は割愛しています。
こちら [IPFS入門](https://ipfs-book.decentralized-web.jp/) を参照してください。

# 前提
[neo-pythonの環境構築 (Docker使用)](https://qiita.com/azusa-tarola/items/df6c22a57e34de545def)ができている状態

# 概要

下記の手順でNeo-vitaeを動かしてみます。

1. 環境を整える
1. neo-vitae.pyをビルドしてスマートコントラクトをデプロイ
2. 証明書の情報をブロックチェーンに登録
3. 登録内容を検索して、ちゃんと登録されたことを確認します


# 手順

## 環境を整える

開発環境コンテナ内でソースをDLします

```
root@neo-python:/neo-python# git clone https://github.com/blocksmithtech/neo-vitae.git
```

スマートコントラクトのデプロイにはガスが必要なため、ウォレットをダウンロードします

```
# cd neo-vitae
# wget https://s3.amazonaws.com/neo-experiments/neo-privnet.wallet
```

np-promptを起動してウォレットを開きます

```
# np-prompt -p -v
neo> wallet open neo-privnet.wallet
```

## neo-vitae.pyをビルドしてスマートコントラクトをデプロイ

下記コマンドでneo-vitae.pyをビルドします。
ビルドされると、中間ファイルであるneo-vitae.avmが作成されます。

```
neo> sc build contracts/neo-vitae.py
Saved output to contracts/neo-vitae.avm
```

neo-vitae.avmを使用して、スマートコントラクトをプライベートネットワークにデプロイしましょう。
デプロイする際に情報を入力する必要がありますが、Contract NameをTestVitaeにします。（その他は空欄でOKです）

```
neo> sc deploy contracts/neo-vitae.avm True False True 0710 07
Please fill out the following contract details:
[Contract Name] > TestVitae
[Contract Version] >
[Contract Author] >
[Contract Email] >
[Contract Description] >
```

ちなみに、sc deployコマンドの仕様は下記の通りです。


> Usage: sc deploy {path} {storage} {dynamic_invoke} {payable} {params} (returntype)

> path            - デプロイを行う (.avm) ファイルへのパス
storage         - コントラクトがストレージを必要とするか
dynamic_invoke  - 他のコントラクトを参照しているか
payable         - コントラクトが通貨の送金を扱うか
params          - コントラクトのインプットパラメーター
returntype      - (Optional) コントラクトの戻り値

デプロイが完了したらコントラクトを検索してみましょう。
下記のように表示されていればOKです。

```
neo> search contract TestVitae
Found 1 results for TestVitae
{
    "version": 0,
    "hash": "0xda1a218963ac77eb3cf6608ddef2a0bd8cb0a679",
    "script": "<省略>",
    "parameters": [
        "String",
        "Array"
    ],
    "returntype": "String",
    "name": "TestVitae",
    "code_version": "",
    "author": "",
    "email": "",
    "description": "",
    "properties": {
        "storage": true,
        "dynamic_invoke": false,
        "payable": true
    }
}
```

## 証明書の情報をブロックチェーンに登録

いよいよ証明書をブロックチェーンに登録します。
まずウォレットを作成して、証明書を登録される人のアドレスを作成します。

```
neo> wallet create vitae
Wallet {
    "path": "vitae",
    "addresses": [
        {
            "address": "AFq5gChGxEDtrM3orj9isFbSaSSqTNbMcL",
            "script_hash": "009b4a1d24e34054c261ed610d8334950795e830",
            "tokens": null
        }
    ],
    "height": 0,
    "percent_synced": 0,
    "synced_balances": [],
    "public_keys": [
        {
            "Address": "AFq5gChGxEDtrM3orj9isFbSaSSqTNbMcL",
            "Public Key": "039179e36ebeb879fcae95963023a66e614b96e8eb37992047acffeabd26e49f09"
        }
    ],
    "tokens": [],
    "claims": {
        "available": "0.0",
        "unavailable": "0.0"
    }
}
```

上記のウォレットは空なので、元のガスが入っているウォレットに開き直しておきます。

```
neo> wallet open neo-privnet.wallet
```

証明書をブロックチェーンに登録しましょう。
コマンドの仕様は下記のようになっており、contract_hash_hereにはTestVitaeのコントラクトハッシュを入力してください。

wallet_to_certifyは、上記で作成した証明書を登録される人(vitaeのウォレット)のアドレス、own_wallet_addressは実行者のアドレス(neo-privnet.walletのアドレス)を入力します。

本来であれば{hash_that_of_the_contents}には、IPFSのハッシュ値が入りますが、ここでは簡易的にHelloをいれて実行します。

> neo> sc invoke {contract_hash_here} certify ["{wallet_to_certify}","{own_wallet_address}","{hash_that_of_the_contents}"]

```
neo> sc invoke 0xda1a218963ac77eb3cf6608ddef2a0bd8cb0a679 certify ["AFq5gChGxEDtrM3orj9isFbSaSSqTNbMcL", "AK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y", "Hello"]
```

実行結果例です。Success: New certification addedが表示されていれば無事に証明書が追加できています。

```
neo> sc invoke 0xda1a218963ac77eb3cf6608ddef2a0bd8cb0a679 certify ["Ac7JxdyHkEo6RMikMAnb4eWUuPvwNGvPG3", "AK2nJJpJr6o664CWJKi1QRXjqeic2zRp8y", "Hello"]
[I 190303 13:16:38 EventHub:58] [test_mode][SmartContract.Storage.Get] [da1a218963ac77eb3cf6608ddef2a0bd8cb0a679] {'type': 'String', 'value': 'Ac7JxdyHkEo6RMikMAnb4eWUuPvwNGvPG3 -> 0'}
[I 190303 13:16:38 EventHub:58] [test_mode][SmartContract.Storage.Put] [da1a218963ac77eb3cf6608ddef2a0bd8cb0a679] {'type': 'String', 'value': 'Ac7JxdyHkEo6RMikMAnb4eWUuPvwNGvPG3 -> 3003972398935402681424980714991268993417086199862262488862900680196353'}
[I 190303 13:16:38 EventHub:58] [test_mode][SmartContract.Runtime.Log] [da1a218963ac77eb3cf6608ddef2a0bd8cb0a679] {'type': 'String', 'value': 'New certification added.'}
[I 190303 13:16:38 EventHub:58] [test_mode][SmartContract.Execution.Success] [da1a218963ac77eb3cf6608ddef2a0bd8cb0a679] {'type': 'Array', 'value': [{'type': 'ByteArray', 'value': b'Success: New certification added'}]}
Used 1.783 Gas

-------------------------------------------------------------------------------------------------------------------------------------
Test invoke successful
Total operations: 440
Results [{'type': 'ByteArray', 'value': '537563636573733a204e65772063657274696669636174696f6e206164646564'}]
Invoke TX GAS cost: 0.0
Invoke TX fee: 0.0001
-------------------------------------------------------------------------------------------------------------------------------------
```

## 登録内容を検索して、登録されたことを確認

先ほど登録した証明書を検索してみましょう。
コマンドの仕様は下記のようになっており、contract_hash_hereにはTestVitaeのコントラクトハッシュを入力してください。

about_walletには検索を行いたい人のアドレス(vitaeのウォレット)を入力します。

> neo> sc invoke {contract_hash_here} get ["{about_wallet}"]

```
neo> sc invoke 0xda1a218963ac77eb3cf6608ddef2a0bd8cb0a679 get ["AFq5gChGxEDtrM3orj9isFbSaSSqTNbMcL"]
```

実行結果です。Helloの文字列を取得することができました！

```
neo> [I 190303 13:17:30 EventHub:62] [SmartContract.Storage.Get][2522] [da1a218963ac77eb3cf6608ddef2a0bd8cb0a679] [tx 920f3cbb97628f918a95e0eb611cb353ccc531760b1a10b3251561bd63d82233] {'type': 'String', 'value': 'Ac7JxdyHkEo6RMikMAnb4eWUuPvwNGvPG3 -> 3003972398935402681424980714991268993417086199862262488862900680196353'}
[I 190303 13:17:30 EventHub:62] [SmartContract.Runtime.Notify][2522] [da1a218963ac77eb3cf6608ddef2a0bd8cb0a679] [tx 920f3cbb97628f918a95e0eb611cb353ccc531760b1a10b3251561bd63d82233] {'type': 'ByteArray', 'value': b'Found items, returning them'}
[I 190303 13:17:30 EventHub:62] [SmartContract.Execution.Success][2522] [da1a218963ac77eb3cf6608ddef2a0bd8cb0a679] [tx 920f3cbb97628f918a95e0eb611cb353ccc531760b1a10b3251561bd63d82233] {'type': 'Array', 'value': [{'type': 'ByteArray', 'value': bytearray(b'#\xba\'\x03\xc52c\xe8\xd6\xe5"\xdc2 39\xdc\xd8\xee\xe9Hello***')}]}
```


# 参考

[neo-vitae](https://github.com/blocksmithtech/neo-vitae)
[neo-python - Python Node and SDK for the NEO blockchain](https://neo-python.readthedocs.io/en/latest/neo/SmartContract/smartcontracts.html)