SymbolのNetworkTypeの意味 なぜMAINNETが104でTESTNETが152なのか

Symbolでアプリを作ったり一歩踏み込んだノード運営しているとよく目につくNetworkTypeという設定値

役割としてはとても単純で、メインネットなのかテストネットなのかを区別するもの
・・・なのですが、気になるのがその中身。

- MAINNET:104
- TESTNET:152

うん、わからん。
何だこの数字？

ちょっと気になるので調べてみよう

## 今わかってること

- MAINNET:メインネットとして認識される。Nから始まるアドレスが生成される。
- TESTNET:テストネットとして認識される。Tから始まるアドレスが生成される。


### もしかして：文字コード説

アドレスの先頭文字を文字コードで表してる説
JavaScriptで検証してみる

```js
// MainNet 
String.fromCharCode(104)
// 結果：h

// TestNet
String.fromCharCode(152)
// 結果: \x14(文字化け)
```

・・・ちがうな

16進数なのかな？
```js
String.fromCharCode(parseInt("0x104",16))
// 'Ą'
String.fromCharCode(parseInt("0x152",16))
// 'Œ'
```

あー、8進数？
```js
String.fromCharCode(parseInt("0104",8))
// 'D'

String.fromCharCode(parseInt("0152",8))
// 'j'
```

惜しい気がする。。。

### SDKを使って生成してみる
調べるよりもやってみるほうが早いと判断

symbol-sdkを使ってNetworkTypeを0から順に設定してアドレスを生成してみます。

```js
import { Account } from "symbol-sdk";
(() => {
    // NetworkType0～256まで生成
    for (let i = 0; i < 256; i++) {
        const account = Account.generateNewAccount(i);
        console.log(`NetworkType: ${i} Address: ${account.address.pretty()}`);
    }
})();
```

#### 結果
```
NetworkType: 0 Address: AAB3DW-2XZLTF-WYSRZ5-56TLZF-GOZGRX-OAEQGL-PQI
(省略)
NetworkType: 7 Address: A7CCR3-DTLAWV-MOQBKU-XMRTHB-LQF2RO-XYOGRW-5UI
NetworkType: 8 Address: BCKHNV-4EQVHT-2SANTH-S37CXP-RVB5AY-VSTNHM-GXY
(省略)
NetworkType: 15 Address: B4ZMDO-34CH4J-N5XCBY-M35F3E-W5POLV-4SBJZT-KTA
NetworkType: 16 Address: CD7KPJ-OM57H2-ISXZTQ-DDDM4G-ZN6DHD-OD7TK2-IFQ
(省略)
NetworkType: 23 Address: C4ZPGS-PQC3YM-TT63MT-BOSQJA-QTJH4M-ILU3AJ-OZY
NetworkType: 24 Address: DAJH4T-QCK4HJ-VY7EAC-NIOH5V-HK5UBJ-XSZTWN-TTA
(省略)
NetworkType: 31 Address: D4BLKL-TN6S2S-2PKOBV-KQ2MIL-3BRI4C-5T2SWO-BKA
NetworkType: 32 Address: EBQUYU-X33SIH-XO2T6G-UYT6OL-SISBJU-IYIZFS-5JA
(省略)
NetworkType: 103 Address: M6774I-NOGZPY-2UBWHW-D4BSCW-MFV5L5-2MMP2V-F3A
NetworkType: 104 Address: NCLCSU-6LAK4D-KCHN3S-T5KT33-3N5IIY-E2J65I-WEQ // メインネット
NetworkType: 152 Address: TAHOSO-LVGZVD-GAN2NU-UCXEUK-QOLZI4-IA6OJF-PTA // テストネット
(省略)
NetworkType: 207 Address: Z55XIL-LVPYRU-ICGQXG-AEU7ZY-O2NMAX-AMJLBB-J5Q
(省略)
NetworkType: 208 Address: 2C3XJL-G6LHMC-NZVGGM-Q26UHX-WAYONO-O27D55-O2Y
```

104,152以外でも一応はアドレスが生成できることが判明。
Aから始まって8個同じアドレスで生成したら次はB・・・のように進んでいき、
208以降は数値になることが判明。

メインネットはNで生成されるアドレスの1番目、テストネットはTで生成されるアドレスの1番目に生成されるアドレスの番号であることもわかりました。

### SDKの処理を追う
次に、アドレスを生成するロジックを追ってみます。

結論から言うと、[addressToString](https://github.com/symbol/symbol-sdk-typescript-javascript/blob/f094ab4be762986c593b0dbb1cb9cd4791977a33/src/core/format/RawAddress.ts#L72)メソッドの最後のほうでBase32に変換した際にアドレスの最初の文字が確定します。

```ts
    // 引数decodedにはランダムに生成された公開鍵の値が入っている
    // decoded[0]にNetworkTypeで指定した値が入ってる
    public static addressToString = (decoded: Uint8Array): string => {
        if (RawAddress.constants.sizes.addressDecoded !== decoded.length) {
            throw Error(`${Convert.uint8ToHex(decoded)} does not represent a valid decoded address`);
        }
        const padded = new Uint8Array(RawAddress.constants.sizes.addressDecoded + 1);
        padded.set(decoded);
        // 下記でUTF32の文字列に変換している
        return Base32.Base32Encode(padded).slice(0, -1);
    };

```

Wikipediaによると、以下のように説明されています。

>Base32 は 40 ビットを 8 文字に変換するエンコード方式である[1]。Base64 と異なり、大文字、小文字の違いが無視される環境においても正しく処理できる。以下に Base32 で用いる文字を示す。O, I と紛らわしい 0, 1 はない。 -- 引用元：[Wikipedia](https://ja.m.wikipedia.org/wiki/%E4%B8%89%E5%8D%81%E4%BA%8C%E9%80%B2%E6%B3%95#Base32)

0～7をBase32形式で表すとAとなるので、NetworkTypeに0を指定するとAから始まるアドレスとなるわけですね。
また、Base32には0,1が存在しないので、207で"Z"を生成した次の208は"2"から始まるアドレスになるわけです。

以下のサイトで数値→Base32への変換ができますので、こちらでも気軽に試せますね。
※試す際はInput typeを"HEX"に設定し、16進数で入力して下さい。
[Base32 Encode Online](https://emn178.github.io/online-tools/base32_encode.html)


## 結論

- NetworkTypeによってアドレスの最初の文字が変わる
- 最初の文字はNetworkTypeに指定した数値をBase32で表したもの
- プライベートチェーンを実装する際は好きな値が設定できる？
- ただし、104,152以外はSDK内で不正なアドレスと判断されエラーとなる可能性もある。


他にもなにか意味があるのかもしれませんが、普段React使ってJSONに色つけてる私ではここまでが限界でしたｗ
ちょっと疑問に思うことでも追っていくとなかなか面白いですね。