カタパルトで秒間4000内部トランザクションを目指してみる

# 秒間4000内部トランザクション

「カタパルトになると、秒間4000トランザクションになるんですか？」

「アグリゲートトランザクションなら可能かもしれません」が答えなのかもしれません。

アグリゲートトランザクションは、複数のトランザクションをまとめることが可能です。このまとめられたものを、内部トランザクションと呼びます。

内部トランザクションをカウント対象に含めてよいなら、秒間4000トランザクションいけるかもしれないということです。

そこで、せっかくオープンソースになっているので、自分で検証してみてるのも面白いなと思いました。

# イメージ

アグリゲートトランザクションひとつあたり、内部トランザクション数の最大数は、初期設定で1000です。

なので、秒間4000内部トランザクションは、秒間4トランザクション。

ちなみに、NEMは、秒間2トランザクションが最大です。

# 手順

それでは、秒間4000内部トランザクションの性能が出るかどうか、やってみます。

再現性を確保するために、できるだけありのままの設定でいきたいと思います。

マシンはAzure VMを使用し、サイズはF32s_v2を使用し、以下の環境で行います。

- ubuntu 18.04 LTS
- git 2.17.1
- docker 18.06.1
- docker-compose 1.22.0
- nodejs v10.11

また、VMでは、以下のポート開放を行っておきます。

- 22
- 3000
- 8000

# catapultを起動する

```bash
git clone https://github.com/tech-bureau/catapult-service-bootstrap
cd catapult-service-bootstrap
git checkout 77e6cf38a7845194aa2ce72f4ed4d87e5ab791e3
docker-compose -f docker-compose-with-explorer.yml up -d
```

※Alpacaバージョンでやります


## トランザクションをあらかじめ作成する

トランザクション作成のうち、署名する処理が重そうです。作成して送信を繰り返すと、間に合わない恐れがあるので、あらかじめ署名済みトランザクションを大量に作っておきます。

トランザクションタイプは、アグリゲートコンプリートとします。内部トランザクションの送信者はアグリゲートトランザクションの署名者と同一にし、受信者はランダムな秘密鍵から得られたアドレスとします。

```bash
git clone https://github.com/planethouki/yonsen.git
cd yonsen
npm install
```

残高のあるアカウントが必要なので、nemesisアドレスの秘密鍵を取得します。`addresses.yaml`を開いて、`nemesis_addresses:`以下の`private`の値をとってきて、`nemesiskeys.json`ファイルを作ります。

```
cat ../build/generated-addresses/addresses.yaml
vi nemesiskeys.json
```

```yaml:addresses.yaml
nemesis_addresses:
- private: 1947340C6102E18927B98D49FB4A7947AB0C5AFCDB31F34F7EA85209A2252CF2
  public: <something>
  address: <something>
- private: 1627E64F23841C748DB9B1650ADFEC8868003158D7803A0652FE76FBD2D617B0
 <and more>
```

↑のprivateのところを↓に列挙

```json:nemesiskeys.json
[
    "1947340C6102E18927B98D49FB4A7947AB0C5AFCDB31F34F7EA85209A2252CF2",
    "1627E64F23841C748DB9B1650ADFEC8868003158D7803A0652FE76FBD2D617B0",
    "2D280ADE3C870B2AD6B962DE191743C763823EC07E897846E5398546E9D69EC7",
    "354AF480EE43126FDC3DD11FD0F6537647F8413B7676536DFFFC671F850DF8A4",
    "<and more>"
]
```

それでは作成処理を走らせていきます。

**２時間くらいかかります。ゲームや読書をして時間をつぶしましょう。**

```bash
npm run createag
```

これにより、トランザクションが3000個入ったテキストファイルができます。

できあがったファイルは、ひたすらペイロードが並んでいます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/172833/79903fb7-cba0-47f0-a698-59eb75d8f104.png)


## 作成したトランザクションを送信する

まずはお試しで通常のトランザクションを送信します。

```bash
npm run send1
npm run send500
```

`send1`でトランザクションをひとつ投げます。`send500`で500個投げます。


そして、`sendag`で、先ほど作った3000個のトランザクションを投げます。

```
npm run sendag
```

15分くらいかかるでしょうか。終わるまで待ちます。

このとき、dockerのログと送信スクリプト、topコマンドを表示しておくとモニターしやすいと思います。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/172833/94ae6755-3162-a5ad-0f6b-6da3d006f2ae.png)


## トランザクション数の集計

ブロックチェーンエクスプローラーで見ると、このような感じになります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/172833/3ca1e97d-b5da-ed28-d610-d43aba0eaa21.png)

ブロックエクスプローラーの表示から集計してもいいですし、ブロックの情報を出力するスクリプトを使って集計してもよいです。

```bash
npm run view
```

<details><summary>Toggle</summary><div>


```
{"height":6,"timestamp":"2018-12-02T04:50:27.526Z","harvester":"SA4UGG-...","txes":0,"fees":0}
{"height":7,"timestamp":"2018-12-02T04:50:48.529Z","harvester":"SA4UGG-...","txes":0,"fees":0}
{"height":8,"timestamp":"2018-12-02T04:51:04.531Z","harvester":"SA4UGG-...","txes":46,"fees":0}
{"height":9,"timestamp":"2018-12-02T04:51:24.537Z","harvester":"SA4UGG-...","txes":83,"fees":0}
{"height":10,"timestamp":"2018-12-02T04:51:52.545Z","harvester":"SA4UGG-...","txes":116,"fees":0}
{"height":11,"timestamp":"2018-12-02T04:52:16.553Z","harvester":"SA4UGG-...","txes":100,"fees":0}
{"height":12,"timestamp":"2018-12-02T04:52:38.560Z","harvester":"SA4UGG-...","txes":92,"fees":0}
{"height":13,"timestamp":"2018-12-02T04:53:00.566Z","harvester":"SA4UGG-...","txes":92,"fees":0}
{"height":14,"timestamp":"2018-12-02T04:53:24.571Z","harvester":"SA4UGG-...","txes":98,"fees":0}
{"height":15,"timestamp":"2018-12-02T04:53:49.578Z","harvester":"SA4UGG-...","txes":104,"fees":0}
{"height":16,"timestamp":"2018-12-02T04:54:14.586Z","harvester":"SA4UGG-...","txes":104,"fees":0}
{"height":17,"timestamp":"2018-12-02T04:54:40.594Z","harvester":"SA4UGG-...","txes":108,"fees":0}
{"height":18,"timestamp":"2018-12-02T04:55:01.601Z","harvester":"SA4UGG-...","txes":87,"fees":0}
{"height":19,"timestamp":"2018-12-02T04:55:27.608Z","harvester":"SA4UGG-...","txes":106,"fees":0}
{"height":20,"timestamp":"2018-12-02T04:55:54.616Z","harvester":"SA4UGG-...","txes":112,"fees":0}
{"height":21,"timestamp":"2018-12-02T04:56:15.622Z","harvester":"SA4UGG-...","txes":87,"fees":0}
{"height":22,"timestamp":"2018-12-02T04:56:38.628Z","harvester":"SA4UGG-...","txes":93,"fees":0}
{"height":23,"timestamp":"2018-12-02T04:57:00.634Z","harvester":"SA4UGG-...","txes":92,"fees":0}
{"height":24,"timestamp":"2018-12-02T04:57:26.641Z","harvester":"SA4UGG-...","txes":108,"fees":0}
{"height":25,"timestamp":"2018-12-02T04:57:51.649Z","harvester":"SA4UGG-...","txes":104,"fees":0}
{"height":26,"timestamp":"2018-12-02T04:58:14.655Z","harvester":"SA4UGG-...","txes":96,"fees":0}
{"height":27,"timestamp":"2018-12-02T04:58:37.661Z","harvester":"SA4UGG-...","txes":95,"fees":0}
{"height":28,"timestamp":"2018-12-02T04:58:58.668Z","harvester":"SA4UGG-...","txes":88,"fees":0}
{"height":29,"timestamp":"2018-12-02T04:59:10.672Z","harvester":"SA4UGG-...","txes":48,"fees":0}
{"height":30,"timestamp":"2018-12-02T04:59:21.675Z","harvester":"SA4UGG-...","txes":45,"fees":0}
{"height":31,"timestamp":"2018-12-02T04:59:40.679Z","harvester":"SA4UGG-...","txes":80,"fees":0}
{"height":32,"timestamp":"2018-12-02T04:59:58.685Z","harvester":"SA4UGG-...","txes":74,"fees":0}
{"height":33,"timestamp":"2018-12-02T05:00:17.691Z","harvester":"SA4UGG-...","txes":80,"fees":0}
{"height":34,"timestamp":"2018-12-02T05:00:32.697Z","harvester":"SA4UGG-...","txes":62,"fees":0}
{"height":35,"timestamp":"2018-12-02T05:00:54.702Z","harvester":"SA4UGG-...","txes":92,"fees":0}
{"height":36,"timestamp":"2018-12-02T05:01:08.706Z","harvester":"SA4UGG-...","txes":58,"fees":0}
{"height":37,"timestamp":"2018-12-02T05:01:23.710Z","harvester":"SA4UGG-...","txes":62,"fees":0}
{"height":38,"timestamp":"2018-12-02T05:01:40.714Z","harvester":"SA4UGG-...","txes":71,"fees":0}
{"height":39,"timestamp":"2018-12-02T05:01:56.719Z","harvester":"SA4UGG-...","txes":67,"fees":0}
{"height":40,"timestamp":"2018-12-02T05:02:04.722Z","harvester":"SA4UGG-...","txes":33,"fees":0}
{"height":41,"timestamp":"2018-12-02T05:02:20.725Z","harvester":"SA4UGG-...","txes":67,"fees":0}
{"height":42,"timestamp":"2018-12-02T05:02:35.729Z","harvester":"SA4UGG-...","txes":62,"fees":0}
{"height":43,"timestamp":"2018-12-02T05:02:49.733Z","harvester":"SA4UGG-...","txes":58,"fees":0}
{"height":44,"timestamp":"2018-12-02T05:03:02.736Z","harvester":"SA4UGG-...","txes":20,"fees":0}
{"height":45,"timestamp":"2018-12-02T05:03:23.740Z","harvester":"SA4UGG-...","txes":0,"fees":0}
{"height":46,"timestamp":"2018-12-02T05:03:38.743Z","harvester":"SA4UGG-...","txes":0,"fees":0}
{"height":47,"timestamp":"2018-12-02T05:03:52.745Z","harvester":"SA4UGG-...","txes":0,"fees":0}
{"height":48,"timestamp":"2018-12-02T05:04:11.748Z","harvester":"SA4UGG-...","txes":0,"fees":0}
{"height":49,"timestamp":"2018-12-02T05:04:23.751Z","harvester":"SA4UGG-...","txes":0,"fees":0}
```

</div>


* TXs：ブロックに含まれるトランザクション数
* [sec]：ブロック生成にかかった時間
* [tx/sec]：秒間トランザクション

| Height | Timestamp | TXs | [sec] | [tx/sec] |
|:--:|:--:|:--:|:--:|:--:|
| 9 | 2018-12-02T04:51:24.537Z | 83 | 20 | 4.15 |
| 10 | 2018-12-02T04:51:52.545Z | 116 | 28 | 4.14 |
| 11 | 2018-12-02T04:52:16.553Z | 100 | 24 | 4.17 |
| 12 | 2018-12-02T04:52:38.560Z | 92 | 22 | 4.18 |
| 13 | 2018-12-02T04:53:00.566Z | 92 | 22 | 4.18 |
| 14 | 2018-12-02T04:53:24.571Z | 98 | 24 | 4.08 |
| 15 | 2018-12-02T04:53:49.578Z | 104 | 25 | 4.16 |
| 16 | 2018-12-02T04:54:14.586Z | 104 | 25 | 4.16 |
| 17 | 2018-12-02T04:54:40.594Z | 108 | 26 | 4.15 |
| 18 | 2018-12-02T04:55:01.601Z | 87 | 21 | 4.14 |
| 19 | 2018-12-02T04:55:27.608Z | 106 | 26 | 4.08 |
| 20 | 2018-12-02T04:55:54.616Z | 112 | 27 | 4.15 |
| 21 | 2018-12-02T04:56:15.622Z | 87 | 21 | 4.14 |
| 22 | 2018-12-02T04:56:38.628Z | 93 | 23 | 4.04 |
| 23 | 2018-12-02T04:57:00.634Z | 92 | 22 | 4.18 |
| 24 | 2018-12-02T04:57:26.641Z | 108 | 26 | 4.15 |
| 25 | 2018-12-02T04:57:51.649Z | 104 | 25 | 4.16 |
| 26 | 2018-12-02T04:58:14.655Z | 96 | 23 | 4.17 |
| 27 | 2018-12-02T04:58:37.661Z | 95 | 23 | 4.13 |
| 28 | 2018-12-02T04:58:58.668Z | 88 | 21 | 4.19 |
| 29 | 2018-12-02T04:59:10.672Z | 48 | 12 | 4.00 |
| 30 | 2018-12-02T04:59:21.675Z | 45 | 11 | 4.09 |
| 31 | 2018-12-02T04:59:40.679Z | 80 | 19 | 4.21 |
| 32 | 2018-12-02T04:59:58.685Z | 74 | 18 | 4.11 |
| 33 | 2018-12-02T05:00:17.691Z | 80 | 19 | 4.21 |
| 34 | 2018-12-02T05:00:32.697Z | 62 | 15 | 4.13 |
| 35 | 2018-12-02T05:00:54.702Z | 92 | 22 | 4.18 |
| 36 | 2018-12-02T05:01:08.706Z | 58 | 14 | 4.14 |
| 37 | 2018-12-02T05:01:23.710Z | 62 | 15 | 4.13 |
| 38 | 2018-12-02T05:01:40.714Z | 71 | 17 | 4.18 |
| 39 | 2018-12-02T05:01:56.719Z | 67 | 16 | 4.19 |
| 40 | 2018-12-02T05:02:04.722Z | 33 | 8 | 4.13 |
| 41 | 2018-12-02T05:02:20.725Z | 67 | 16 | 4.19 |
| 42 | 2018-12-02T05:02:35.729Z | 62 | 15 | 4.13 |
| 43 | 2018-12-02T05:02:49.733Z | 58 | 14 | 4.14 |


# 結果

平均して**秒間 4.14 トランザクション**

（９～４３ブロックを計算に使用）（705秒で2,924TX）

各トランザクションは、1000内部トランザクションです。

なので、秒間4000内部トランザクションを達成したと言えるでしょう。


## おねだん

それでは、そのマシンはおいくらなんでしょうか。

Azure VMの価格表です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/172833/8eff0e1a-a229-b106-da6c-b252b7209cca.png)

今回は、Azure VM F32s_v2を使いました。月間コストは、およそ17万円。

（コスト計算は詳しくないですが、これにデータ転送やディスク使用などのコストが載ってくると思います。）

この価格、安いでしょうか、高いでしょうか。

あなたはどう思いますか？

# まとめ

これで、「アグリゲートトランザクションなら可能かもしれません」が、より身近に感じられるようになりました。