ぼくのかんがえたさいきょうのSymbolブロックチェーンのアカウント管理方法

あらゆるハッキングから盗難リスクを下げることができると言われるマルチシグ。
最近ではヴァルキリー社とNEM/Symbolの匿名開発者であるコアデブとの間で800億円相当の資金管理の契約にも活用されました。

https://bittimes.net/news/120992.html

しかしながら、何重にもマルチシグをかければいいというものではありません。
鍵を分割することは紛失するリスクも高まります。
そこで、今回は僕の考えた2-of-4マルチシグによる最強のアカウント管理方法を紹介します。

:::note alert
自己責任でお願いします。
特に催眠術にかかりやすい人、寝言がひどいと言われる人はこの方法はお勧めできません。
:::

# ニーモニック作成

以下のスクリプトを実行してニーモニックを出力してください。
（NGLウォレットを使用してもニーモニックを生成することができます)

```js
sym = require("/node_modules/symbol-sdk");
hd = require("/node_modules/symbol-hd-wallets");

NODE = window.origin;
repo = new sym.RepositoryFactoryHttp(NODE);
generationHash = await repo.getGenerationHash().toPromise();
networkType = await repo.getNetworkType().toPromise();

mnemonic = hd.MnemonicPassPhrase.createRandom();
mnemonic.plain;

//>'naive share youth mesh gate rug circle slow gossip tenant point artwork coral march hazard tonight flee nation scout paddle link entry goat ****'
```

念のため、何回か出力して何度も同じニーモニックが出ないことを確認してください。
これを全力で1か月覚えます。話はそれからです。


# ニーモニックの覚え方

24個の単語です。気の遠くなる作業と思われるかもしれません。
4 x 6 = 24 で覚えましょう。1か月かけて一度覚えたらなかなか忘れないものです。
そして、これは一生の財産になります。
受験で中国の歴代王朝を暗記したことがある人ならわかると思います。まだ覚えてますよね。

まずはチャンクに分解します。

'naive share youth mesh gate rug circle slow gossip tenant point artwork coral march hazard tonight flee nation scout paddle link entry goat ****'

- naive share
- gate rug
- slow gossip
- march hazard
- link entry

こんな感じで、ニコイチでリズムをつけていきます。
次に24の数字を4進数ととらえて右手の小指から人差し指に向けて親指で弾きながら、
一巡したら、左手の親指から小指を折り曲げて単語を唱えます。


|   | (右手)子 | 薬 | 中 | 人 |
|:--:|:--:|:---:|:---:|:---:|:---:|
| 無       | naive | share | youth | mesh | 
| (左手)親 | gate | rug |circle |slow |
| 人       | gossip | tenant |point |artwork |
| 中       | coral | march |hazard |tonight |
| 薬       | flee | nation |scout |paddle |
| 子       | link | entry |goat |****|

これを、1000回唱えます。
それでは、1か月後にお会いしましょう


...


...




はい、覚えましたか？
完璧ですね。あなたの目はすでに、チャートの上げ下げには動じない澄んだ色をしています。
では次に進みましょう。

# メモしたニーモニックを燃やす

捨ててください。
大丈夫です。まだそのニーモニックで紐づけられるアカウントには1XYMたりとも入っていないはずです。
覚えているニーモニックが正しい(BIP39に準拠している)かどうかは以下で調べられます。

```js:alice
mnemonic = new hd.MnemonicPassPhrase(
  "ここにニーモニックを入力...naive share youth mesh gate rug circle slow gossip tenant point artwork coral march..."
);
mnemonic.isValid();
```

ニーモニックパスフレーズは好きな単語を並べることで生成できるようですが、BIP39が保証するランダム性（エントロピー）を得たい場合は先述の `hd.MnemonicPassPhrase.createRandom()` を使用するようにしてください。

# 召喚の儀

さぁ、何もないところから、あなたの頭の中にしか存在しない呪文で新たな命を吹き込みます。

```js:alice
mnemonic = new hd.MnemonicPassPhrase(
  "ここにニーモニックを入力...naive share youth mesh gate rug circle slow gossip tenant point artwork coral march..."
);

mnemonic.isValid();
seedHex = mnemonic.toSeed();
extendedKey = hd.ExtendedKey.createFromSeed(seedHex , hd.Network.SYMBOL);
aliceWallet = new hd.Wallet(extendedKey.derivePath("m/44'/4343'/0'/0'/0'"));
alice = nem.Account.createFromPrivateKey(aliceWallet.getAccountPrivateKey(), networkType);
```

無事、復元できまでしょうか？


# 1XYMを投入する

ウォレットを使って、alice.addressで出力されるアドレスに1XYM入金してみましょう。
テストネットで検証する場合はフォーセットをご利用ください。

# マルチシグ構成の検討

aliceをマルシグ化します。
bob,carol,dave,ellenアカウントを新規に作成し、2-of-4のマルチシグを構成します。

bob,carolはニーモニックからHDウォレットで芋づる式に作成します。
dave,ellenは新規にランダムな秘密鍵から作成します。


```js:bob
bobWallet = new hd.Wallet(extendedKey.derivePath("m/44'/4343'/1'/0'/0'"));
bob = sym.Account.createFromPrivateKey(bobWallet.getAccountPrivateKey(), networkType);
```

```js:carol
carolWallet = new hd.Wallet(extendedKey.derivePath("m/44'/4343'/2'/0'/0'"));
carol = sym.Account.createFromPrivateKey(carolWallet.getAccountPrivateKey(), networkType);
```

```js:dave
dave = sym.Account.generateNewAccount(networkType);
```

```js:ellen
ellen = sym.Account.generateNewAccount(networkType);
```

# マルチシグ化

Aliceアカウントを以下の図のようにマルチシグ化します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29187/c1a452d0-2cd3-9317-01e3-bf44165f3fc9.png)



```js
multisigTx = sym.MultisigAccountModificationTransaction.create(
  sym.Deadline.create(epochAdjustment), 2,2,
  [bob.address,carol.address,dave.address,ellen.address],
  [],networkType
);

aggregateTx = sym.AggregateTransaction.createComplete(
    sym.Deadline.create(epochAdjustment),
    [
        multisigTx.toAggregate(alice.publicAccount),
    ],
    networkType,
    [],
    sym.UInt64.fromUint(1000000)
);

signedTx =  alice.signTransactionWithCosignatories(
    aggregateTx,
    [bob,carol,dave,ellen],
    generationHash,
);

txRepo.announce(signedTx).subscribe(_ => console.log(_), err => console.error(err));

```

# 設定

bob, carolの秘密鍵を燃やします。
dave, ellenの秘密鍵を異なる端末のウォレット（ハードウェアウォレット）にインポートします。

これですべての準備が整いました。
資産を少しずつ移動させていきましょう。

# 使い方

##### 普段使い

普段はdaveとellenの鍵を使用してaliceの資産を動かします。
daveとellenは異なる端末に保管しているので、あらゆる送金を多要素認証で扱うことができます。

:::note alert
多要素認証とはいえ、ハーベスト設定時などに「心当たりのある」タイミングで署名を促してくるスキャムトランザクションにはご注意ください。
:::

##### 機種変するとき

daveとellenの鍵を保管していた機種を変更する場合は、それぞれのウォレットから秘密鍵をコピーしてそのまま移し替えてください。
破棄する端末からは秘密鍵を安全に消去しておいてください。

##### 鍵が漏洩した場合

dave,ellenの鍵情報を漏洩したかもしれない場合は、マルチシグ構成変更のトランザクションを発行します。
「マルチシグ変更の方法がよくわからない」という方はdave,ellenの署名でaliceから資産を移動させ、また一からやり直して下さい。

##### 紛失した場合

dave,ellenの鍵を紛失した場合はニーモニックから bobまたはcarolを復元し、マルチシグ構成変更のトランザクションを発行します。
「マルチシグ変更の方法がよくわからない」という方はbob,carolの署名でaliceから資産を移動させ、また一からやり直して下さい。

##### ニーモニックをど忘れした場合

ニーモニックが思い出せない場合はdave,carolの署名でaliceの資産を移動させまた1からやり直してください。

##### 注意点

ニーモニックを忘れたことに気付かず、秘密鍵を紛失した場合はアウトです。
ただ、1か月ニーモニックを必死に覚えた人はわかると思いますが、般若心経よりも心が落ち着くお経のように感じている人もいるのではないでしょうか？
1年のうちに数回、気が向いたら何度か唱えるだけで十分です。


# まとめ

ニーモニックのメモを控えずに頭の中にだけ存在させ、万が一忘れた場合のために普段使いの鍵を分散させておきます。
分散させた鍵に漏洩のリスクが高まった場合は、ニーモニックから緊急用の鍵を芋づる式に復元させて再構築することができます。
マルチシグの変更が難しいブロックチェーンの場合は、鍵の差し替えの度にニーモニックを覚えなおす必要があり、現実的ではありませんが、Symbolブロックチェーンの場合はマルチシグの変更が柔軟にできますのでこの構成がうまく機能します。
いきなりマルチシグアカウントに資産を突っ込むことなく、まずは空のニーモニックを完全に暗記することから始めることで、「いつでも後に戻れる」と確信を持ちながら作業を進めることができます。

自己責任にはなりますが、ぜひお試しください。