暗号通貨カルダノのノードであるcardano-sl ver.1.2を一足先に触ってみました

# はじめに

暗号通貨の１つである[カルダノ](https://github.com/input-output-hk/cardano-sl)の次期アップデートがもうじきリリースされます。今回は開発ブランチを利用して一足先にどのような機能が実装されるのかを試してみようと思います。また今回はノードを安定して実行できるようにビルドしたものをdocker imageとしてビルドし、docker環境で実行します。

**追記**：ビルドしたイメージをdocker hubにて公開しました。
https://hub.docker.com/r/shioihi/cardano-container-mainnet/
以下のコマンドによってイメージをプルすることができます

```terminal
$ docker pull shioihi/cardano-container-mainnet
```

実行コマンドは公式のものとほぼ一緒です

```terminal
$ docker run --name cardano-mainnet-wallet --rm -it -p 127.0.0.1:8090:8090 -p 127.0.0.1:8000:8000 -v state-wallet-mainnet:/wallet shioihi/cardano-container-mainnet:latest
```

## 注意点

これは開発バージョンです。もし試される場合には**決して**実際のADA（カルダノネットワーク内で流通している暗号通貨)を使った操作は行わないでください。また正式にリリースされるものとは異なる場合もあります。

## 参考になったドキュメント

- https://github.com/input-output-hk/cardano-sl/blob/develop/docs/how-to/build-cardano-sl-and-daedalus-from-source-code.md
- https://github.com/input-output-hk/cardano-sl/blob/develop/docs/how-to/connect-to-cluster.md
- https://github.com/input-output-hk/cardano-sl/blob/develop/docs/exchange-onboarding.md

最後のドキュメントは取引所向けとはありますが、Dockerに関する詳細な説明があって非常に助かりました。

## 環境

- Ubuntu 16.04
- [Nix](https://nixos.org/nixos/manual/index.html#ch-installation), [stack](https://docs.haskellstack.org/en/stable/README/)インストール済み
[^1]

Nixのインストール方法に関しては以下のサイトが参考になりました。
https://nixos.org/nixos/manual/index.html#ch-installation


## セットアップ手順

以下の手順でノードのビルドを行います。

1. 公式リポジトリからクローン
2. ブランチを`develop`にする
3. Nixの設定
4. ビルド
5. docker imageのビルド

#### 公式レポジトリからクローン

まずはGithubからレポジトリをクローンします。

```terminal
$ git clone git@github.com:input-output-hk/cardano-sl.git
$ cd cardano-sl
```

#### ブランチを`develop`に切り替える

安定している開発バージョンは`develop`ブランチにあるので切り替えます。

```terminal
$ git branch develop
```

#### Nixの設定

ドキュメントによるとビルドする前に`nix.conf`ファイルを設定する必要があるらしいのでそれを行います。

```vim
$ sudo mkdir -p /etc/nix
$ sudo vi /etc/nix/nix.conf       # ..or any other editor, if you prefer
```

```/etc/nix/nix.conf                                                 
binary-caches            = https://cache.nixos.org https://hydra.iohk.io
binary-cache-public-keys = hydra.iohk.io:f/Ea+s+dFdN+3Y/G+FDgSq+a5NEWhJGzdjvKNGv0/EQ= cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=
```

#### ビルド

ビルドは２回に分けて行います。まずは１回めのビルドです。 [^2]

```terminal
$ nix-build -A cardano-sl-node-static --cores 0 --max-jobs 2 --no-build-output --out-link master
```

次にメインネットに接続するためのビルドです。

```terminal
$ nix-build -A connectScripts.mainnetWallet -o connect-to-mainnet
```

ここでワークディレクトリ内に`connect-to-mainnet`ファイルが生成されていればOKです。

### Docker imageをビルドする。

[このドキュメント](https://github.com/input-output-hk/cardano-sl/blob/develop/docs/exchange-onboarding.md#building-and-running)を参考にしてdocker imageをビルドします。

```terminal
$ docker load < $(nix-build --no-out-link -A dockerImages.mainnetWallet)
```

ここで`docker image ls`をして`cardano-container-mainnet:latest`があればOKです。

## 実行する

カルダノはブロックチェーンプロトコルなのでブロックのデータをどこかに保存しておく必要があります。なので実行時には`-v`コマンドで`docker volume`を指定しましょう。以下は公式ドキュメントにある実行コマンドです。

```terminal
$ docker run --name cardano-mainnet-wallet --rm -it -p 127.0.0.1:8090:8090 -p 127.0.0.1:8000:8000 -v state-wallet-mainnet:/wallet cardano-container-mainnet:latest
```

ログが大量に流れ始めたらブラウザを開いて次の`URL`にアクセスしてみましょう。

http://localhost:8000/

以下のようなウェブページが表示されればOKです。

<img src="https://qiita-image-store.s3.amazonaws.com/0/118558/34a67dba-f29a-2c46-2e63-da8d61af1e98.png" alt="drawing" style="width: 50px;"/>

## カルダノV1.2の変更点

### Cardano Wallet API V1
Cardano-sl ver1.2で注目すべきはウォレットAPI V1が利用可能になることです。
APIドキュメントに関してはノード実行時に以下のリンクにてアクセスできます。

https://127.0.0.1:8090/docs/v1/index/

初期アクセス時には以下のようなページが表示されます。
![dest.jpg](https://qiita-image-store.s3.amazonaws.com/0/118558/bbfc021c-7242-4692-90c3-1648eef2eaba.jpeg)

ここでは「Advanced」から「Proceed to localhost (unsafe)」を選択してください。

![Screenshot from 2018-05-23 16-06-57.png](https://qiita-image-store.s3.amazonaws.com/0/118558/6a8c7a2a-2d3b-64fa-1edd-c269c949b872.png)

#### 主要なコマンド一覧

|API   |Request |Description   |
|---|---|-----|
|/api/settings/sync/progress | GET  | ノードの同期状況を取得  |
|/api/v1/node-settings   |GET   |ノードの設定情報を取得する   |
|/api/v1/node-info   |GET   |ノード情報を取得する   |
|/api/v1/wallets   |GET   |ウォレット情報を取得する  |
|/api/v1/wallets |GET|利用可能なウォレットのリストを取得する |
|/api/v1/wallets/{walletId}/accounts |GET   |特定のウォレットのアカウント情報を取得する   |
|/api/v1/addresses   |GET   |ウォレットアドレスを取得する   |
|/api/v1/transactions?wallet_id={walletId}|GET   |トランザクション情報を取得する    |
|/api/v1/addresses   |POST   |ウォレットアドレスを生成する   |
|/api/v1/wallets/{walletId}/accounts |POST   |ウォレットアカウントの新規作成   |
|/api/v1/wallets   |POST   |ウォレットの新規作成及び復元   |
|/api/v1/wallets/{walletId}|DELETE   |ウォレットの削除   |

毎回`curl`で呼び出すのは面倒なので僕は[Postman](https://www.getpostman.com/)を利用しました。

#### ウォレットの生成

ウォレットがないとほとんどのコマンドが利用できません。生成には[bip39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki)に順守して生成された12個のフレーズが必要なのですが、どうやらウォレットAPIにはフレーズを生成する機能は提供されていないようです。よって以下のサイトからフレーズを生成しました。 [^3]

https://iancoleman.io/bip39/

フレーズを手に入れたら以下のリクエストを送信することでウォレットを新規作成できます。

```terminal
$ curl -X POST https://localhost:8090/api/v1/wallets \
  -H "Accept: application/json; charset=utf-8" \
  -H "Content-Type: application/json; charset=utf-8" \
  -d '{
  "operation": "create",
  "backupPhrase": ["ここに", "12個の", "フレーズを", "書き込んで", "ください",
    "foo", "bar", "baz", "foo", "bar", "baz", "foo"],
  "assuranceLevel": "normal",
  "name": "MyFirstWallet"
}'
```

### その他の変更点

その他に感じたのはブロック同期がものすごく早くなりました。以前は最初から同期となると何時間もかかったのに、v1.2では1分1%ペースで同期していました。ウォレットが遅くて使いづらいと感じた人には朗報でしょう。

またウォレット復元にも大幅な改善が見受けられました。新規ウォレットを削除して復元したところ、約6分で利用可能な状態になりました。また復元状況もAPIを通じて確認できるようになっています。

https://127.0.0.1:8090/api/v1/wallets

```json
{
    "data": [
        {
            "id": "Ae2tdPwUPEZ8wYRVqugbC4h4ucKv4GYF74S7U234n1EbZNRYR1TpNVSaoJB",
            "name": "MyFirstWallet",
            "balance": 0,
            "hasSpendingPassword": false,
            "spendingPasswordLastUpdate": "2018-05-23T22:53:31.41669",
            "createdAt": "2018-05-23T22:53:31.41669",
            "assuranceLevel": "normal",
            "syncState": {
                "tag": "restoring",
                "data": {
                    "throughput": {
                        "quantity": 0,
                        "unit": "blocksPerSecond"
                    },
                    "percentage": {
                        "quantity": 0,
                        "unit": "percent"
                    },
                    "estimatedCompletionTime": {
                        "quantity": 1045534000,
                        "unit": "milliseconds"
                    }
                }
            }
        }
    ],
    "status": "success",
    "meta": {
        "pagination": {
            "totalPages": 1,
            "page": 1,
            "perPage": 10,
            "totalEntries": 1
        }
    }
}
```

`syncState`が復元状況に関する情報です。これをフロントエンドが利用することでユーザーに復元進捗をいい感じに表示できそうです。

## ウォレットフロントエンドの変更点

カルダノではウォレットのフロントエンドとして[ダイダロス](https://daedaluswallet.io/)が採用されており、通常はカルダノのアップデートリリースとともにダイダロスもアップデートも行います。
ダイダロスの次期アップデート内容に関してはレポジトリにある[CHANGELOG](https://github.com/input-output-hk/daedalus/blob/develop/CHANGELOG.md)にて確認できます。
以下が主要なアップデートのようです。

#### ウォレットの非同期な復元

これはつまりウォレット復元中はプログレスバーが表示され、ユーザーはウォレットを復元中もウォレット操作が可能になることです。

#### ペーパーウォレット

ついにカルダノにもコールドストレージ（つまり送金ができないウォレット）が利用可能になります。もし長期に渡ってADAを保管するのであればペーパーウォレットを利用しましょう。

## 最後に

正直、公式ドキュメントは茨の道でした。ドキュメントにあるコマンドのいくつかはほとんど実行できず、`issue`や`PR`を見て回ってやっとビルドできたという感じです。また異なる環境で安定して実行できるのか不安だったのですが、dockerを利用できるときいてすごく安心しました。（しかもイメージの容量がめちゃくちゃ小さい）

フロントエンドに関してもなにかしたらレポート出来ればいいのですが、何分フロントエンド開発をしばらくしていないのでリリースまでにビルドできるかどうか微妙です。

[^1]: ビルド時にはNixは必須ですが、ドキュメントを読んだ感じではstackは必要ないかもしれません。
[^2]: Issueを読んだところ、このビルドをスキップしてもノードをビルドできたという話をききました。
[^3]: 今回は新しいAPIをテストするという目的なので適当なサイトからフレーズを生成してきましたが、実際に利用するウォレットを生成する際には信頼できるソースからフレーズを生成してください。