Symbol Peer を起動する(MainNet)


## 各種ファイルを置くディレクトリの作成

`/opt`に`symbol-node`ディレクトリを作成し、この中で作業します。

```bash
sudo mkdir -p /opt/symbol-node
sudo chown harvestasya: /opt/symbol-node
cd /opt/symbol-node
```

## 証明書の作成

CA 証明書と Node 証明書が必要です。さらに X.509 v1 フォーマットでないといけません。公式の証明書作成ツールが古い SDK を使用していて動かすのが少し面倒なので、私が公式ツールをコピー作成した simple-symbol-node-cert-cli を使用します。

### Volta で Node.js をインストール

Node.js をインストールします。apt だと結構古いバージョンがインストールされるので、Node.js のバージョン管理ができる Volta 経由でインストールします。

```bash
sudo curl https://get.volta.sh | bash
exec $SHELL -l
volta install node@20
```

### OpenSSL をインストール

OpenSSL が必要なのでインストールします。X.509 v1 の生成がらみで OpenSSL のバージョンに縛りがありますが、2024 年 11 月現在の Ubuntu 24 では、その縛りに引っかからないので、apt でインストールします。

```bash
sudo apt update
sudo apt install -y openssl
```

### simple-symbol-node-cert-cli をインストール

simple-symbol-node-cert-cli をインストールします。

```bash
npm install -g simple-symbol-node-cert-cli
```

### 新規に証明書を作成

新規に証明書を作成する場合は、このまま以下のコマンドを実行します。

```bash
simple-symbol-node-cert-cli generate --certdir certificates
```

実行すると秘密鍵等を保存する際の暗号化に使うパスワードを聞かれるので、入力します。これで証明書が certificates ディレクトリに作成されます。

### 既存ノードから証明書を引き継ぐ場合

他のノードから引き継ぐ場合は、`privatekeys.yaml`を作成し main または transport の秘密鍵を入力して、上記コマンドを実行します。

冗長化のために引き継ぐ場合は、`transport`のみ引き継ぎます。

```privatekeys.yaml
transport:
  privateKey: BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB...
```

:::note alert
Symbol ネットワーク上に異なる IP/Host で同じ main アカウントを載せてはいけません。
自己攻撃してる状態になります。
違う場所から同じ証明書が出てきたら怪しいでしょう？逆もまた同じです。
:::

### 公開鍵とアドレスの確認

公開鍵とアドレスは、以下コマンドで確認できます。

```bash
simple-symbol-node-cert-cli info -n mainnet --certdir certificates
```

## ネメシス(ジェネシス)ブロックとコンフィグファイルの配置

ダウンロードして zip を展開します。

```bash
curl -OL https://github.com/symbol/symbol/releases/download/client%2Fcatapult%2Fv1.0.3.7/configuration-mainnet.zip
unzip configuration-mainnet.zip
rm configuration-mainnet.zip shoestring.ini README.md
```

## コンフィグファイルの変更

### ノード情報の設定

ノード情報を設定するために`resources/config-node.properties`を編集します。

- `host`: 自 IP やドメインを設定
- `friendlyName`: ノードの名前(なんでもいいです)※日本語不可
- `version`: 未設定
- `roles`: Peer

```resources/config-node.properties
...
[localnode]

host = <YOUR_NODE_IP>
friendlyName = <YOUR_FRIENDLY_NAME>
version =
roles = Peer
...
```

同時にこの辺りも変更しておくと、最初の同期が安定すると思います。

```resources/config-node.properties
...
maxChainBytesPerSyncAttempt = 10MB
...
blockDisruptorMaxMemorySize = 1000MB
...
```

### ハーベストの設定

ハーベスティングエクステンションが有効になっているか、`resources/config-extensions-server.properties`を開いて確認します。

```resources/config-extensions-server.properties
# p2p extensions
...
extension.harvesting = true
...
```

ハーベストの設定を`resources/config-harvesting.properties`に設定します。

- `harvesterSigningPrivateKey`: bootstrap では remote と呼ばれるアカウントの秘密鍵を設定します
- `harvesterVrfPrivateKey`: VRF アカウントの秘密鍵
- `enableAutoHarvesting`: true
- `maxUnlockedAccounts`: 委任を受け入れる最大値
- `delegatePrioritizationPolicy`: 委任者の最大を超えたときの追い出し挙動(Importance または Age)
- `beneficiaryAddress`: ハーベスト報酬の受け取りアドレス

```resources/config-harvesting.properties
[harvesting]

harvesterSigningPrivateKey = <HARVESTER_SIGNING_PRIVATE_KEY>
harvesterVrfPrivateKey = <HARVESTER_VRF_PRIVATE_KEY>

enableAutoHarvesting = true
maxUnlockedAccounts = 100
delegatePrioritizationPolicy = Importance
beneficiaryAddress = <BENEFICIARY_ADDRESS>
```

新規にノードを立てる場合、`harvesterSigningPrivateKey`と`harvesterVrfPrivateKey`は、何もしていない新しいアカウントを設定します。  
以下のコマンドで、メインネット用のアカウント 2 つが作成出来ます。

```bash
catapult.tools.addressgen -n mainnet -c 2
```

ノードのメインアカウントでハーベストする場合はノード立ち上げ後、AccountKeyLink と VRFKeyLink トランザクションを発行する必要があります。

### 各ディレクトリの場所を設定

各ディレクトリの場所が`resources/config-user.properties`に設定されています。基点は`catapult.server`を起動した時の作業ディレクトリです。

```resources/config-user.properties
[account]

enableDelegatedHarvestersAutoDetection = true

[storage]

seedDirectory = /opt/symbol-node/seed
certificateDirectory = /opt/symbol-node/certificates
dataDirectory = /opt/symbol-node/data
pluginsDirectory = /usr/local/catapult/lib
votingKeysDirectory = /opt/symbol-node/votingkeys
```

### 接続ピアリストの作成

起動時に接続する他のノード一覧`resources/peers-p2p.json`を作成します。
statistics-service(<https://symbol.services/nodes?filter=suggested&limit=10>) を使って作成すると良いでしょう。
面倒な人のためにランダム作成したリストを置いておきます。

```resources/peers-p2p.json
{
  "_info": "this file contains a list of peers",
  "knownPeers": [
    {
      "publicKey": "9FF3ED0814113E038810A1D4AD6128BB67143FDA103D8DB48A3EB7DF833889AA",
      "endpoint": {
        "host": "94.176.239.16",
        "port": 7900
      },
      "metadata": {
        "name": "9FF3ED0",
        "roles": "Peer, Api"
      }
    },
    {
      "publicKey": "C221C5E700DF2AB50909B31D171DDAA87DC99EE6FBF5A8CE56D60ACCCBCF853E",
      "endpoint": {
        "host": "03.symbol-jp.net",
        "port": 7933
      },
      "metadata": {
        "name": "symbol-jp.net(03)",
        "roles": "Peer, Api"
      }
    },
    {
      "publicKey": "B0C333CE072CE0B20CF03D305B8F913BDB64430EF217E36123D03A32F4A39017",
      "endpoint": {
        "host": "xym862.allnodes.me",
        "port": 7900
      },
      "metadata": {
        "name": "Allnodes862",
        "roles": "Peer, Api"
      }
    },
    {
      "publicKey": "6F0D20768154F8AEEF1F667401FFEAA6F8D9F84ACE040AB61022E5A481738AB9",
      "endpoint": {
        "host": "xym707.allnodes.me",
        "port": 7900
      },
      "metadata": {
        "name": "Allnodes707",
        "roles": "Peer, Api"
      }
    },
    {
      "publicKey": "79837F0B59BC67F95F5D8430781231519500F695BB5A8F070610D86B4776D364",
      "endpoint": {
        "host": "xym542.allnodes.me",
        "port": 7900
      },
      "metadata": {
        "name": "Allnodes542",
        "roles": "Peer, Api"
      }
    },
    {
      "publicKey": "B2D8B8EED9D17462B36B992ED0C4522289DAF3F996C0C6CDCC7D12B0811A953B",
      "endpoint": {
        "host": "89.47.164.194",
        "port": 7900
      },
      "metadata": {
        "name": "B2D8B8E",
        "roles": "Peer, Api"
      }
    },
    {
      "publicKey": "DD1CB539ED4DBE955EDAB87E3EAB98ACE3961BFF8FD09F8267D2BC1395CE421F",
      "endpoint": {
        "host": "0-0-0-0-0-0-2.harvesting.fan",
        "port": 7900
      },
      "metadata": {
        "name": "0-0-0-0-0-0-2.Harvesting.Fan",
        "roles": "Peer, Api"
      }
    },
    {
      "publicKey": "80A905CC70A5C620000DD5BA74EA6AF1480DAF753D4639D20E39FA7796A85287",
      "endpoint": {
        "host": "xym590.allnodes.me",
        "port": 7900
      },
      "metadata": {
        "name": "Allnodes590",
        "roles": "Peer, Api"
      }
    },
    {
      "publicKey": "D7733D31B701D478CF1F22B25DAA249BCDAB3FEFF1E374D813435078D78AD085",
      "endpoint": {
        "host": "0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-6.tokyo-node.jp",
        "port": 7900
      },
      "metadata": {
        "name": "Tokyo-Node.JP",
        "roles": "Peer, Api"
      }
    },
    {
      "publicKey": "62D3DB69489C3F93A974500A005079C67324E57D01F9E71538DD7C8B8FC6C904",
      "endpoint": {
        "host": "xym321.allnodes.me",
        "port": 7900
      },
      "metadata": {
        "name": "Allnodes321",
        "roles": "Peer, Api"
      }
    }
  ]
}
```

## ブロックデータを格納するディレクトリの作成

```bash
mkdir /opt/symbol-node/data
```

## ポートの開放

できれば 7900 ポートを開放しておいて下さい。

:::note warn
開放しなくても動作はしますが、同期遅れ等が発生するかもしれません。
:::

```bash
sudo ufw allow 7900
```

## ノードの起動

ノードを実行します。引数は`resources`ディレクトリのある場所です。デフォルトは`..`。

```bash
catapult.server .
```

終了は、`Ctrl + C`です。終了するまで時間がかかる場合がありますが、プロンプトが返ってくるまで待ってください。終了処理中にもう一度`Ctrl + C`すると即終了しますが、データが破損する可能性があります。

以下の様なログが出力されれば、同期しています。

```plaintext
<info> (disruptor::ConsumerDispatcher.cpp@44) completing processing of element 1 (360 blocks (heights 2 - 361) [7B055CD0] from Remote_Pull with size 143KB 472B), last consumer is 0 elements behind
```

## 次回

https://qiita.com/ccHarvestasya/items/f4039145780aaf1fda8a