Symbolのデリゲーテッドハーベスティングのトランザクションレベルでのやり取りなどをざっくり説明してみる

#はじめに
大した内容ではありませんが知らない人向けに

ハーベスティングに関しての細かいことは『[Symbolドキュメンテーション](https://docs.symbolplatform.com/ja/)』を読んでください。仕組みを完全に理解したいガチ勢の方は[ホワイトペーパー](https://docs.symbolplatform.com/catapult-whitepaper/main.pdf)をどうぞ


本記事は[nem Advent Calendar 2020](https://qiita.com/advent-calendar/2020/nem)の記事になります。
[nem #2 Advent Calendar 2020はこちら](https://qiita.com/advent-calendar/2020/nem-2)

過去のアドカレはこちら
[nem Advent Calendar 2019](https://qiita.com/advent-calendar/2019/nem)
[nem #2 Advent Calendar 2019](https://qiita.com/advent-calendar/2019/nem-2)
[nem Advent Calendar 2018](https://qiita.com/advent-calendar/2018/nem)
[nem #2 Advent Calendar 2018](https://qiita.com/advent-calendar/2018/nem-2)
[nem Advent Calendar 2017](https://qiita.com/advent-calendar/2017/nem)

注意：
本記事は2020年末時点のテストネット時の記事になります。
最新の情報は公式情報を参照してください。
また、関連記事として 以下記事もあわせて参照してください。
　【[Symbolのハーベスティング周りの情報を整理する](https://qiita.com/GodTanu2/items/2426b748bcf1ec13443e)】


#Symbolのハーベスティング
ご存じの通りSymbolのブロック生成は**NEMと同じように**ハーベスティングで行われています。

**NEMと同じように**大まかに2種類の方法があります。

    1. ローカルハーベスティング(自前ノードでハーベスティング)
    2. デリゲーテッドハーベスティング(委譲/委任ハーベスティング)
**つまり、大体NEMと同じ**です。

1.は「ローカルハーベスティング」とか「自前ハーベスティング」とか表現する人が多いです。
2.は「委任ハーベスティング」とか「委託/委譲」とか表現する人が多いです。もしくは「デリゲード」とか「デリゲーテッド」とか。

一部界隈では1のローカル相当のハーベスティングを行うような人々を「バリデーター」と呼び、2を実施している人々を「デリゲーター」などと呼んでいるようです。この呼び方が近年のトレンドです。

Symbolの公式ドキュメントやホワイトペーパーなどでは
**『delegated harvesting』**
と表現されていますが、いかんせん長いです。日本人特有の言葉を省略する文化に沿って、本文章では~~長くて面倒なので~~以降~~デリ毛~~ ***デリゲ***と表現させて頂きます。

#ローカルハーベスティング
本記事ではデリゲをメインに説明するのでローカルについての説明は省略します。

[nemlog](https://nemlog.nem.social/)に書かれている[こちらの記事](https://nemlog.nem.social/blog/50604)を参照してください
[Symbolテストネットノードでローカルハーベスティングせよ (v0.10.x Hippo)](https://nemlog.nem.social/blog/50604)

他にも以下の記事が参考になるかと思います。
[NEM Symbol テストノード構築で GoTo 大家](https://qiita.com/curupo/items/30569a4ddc9255f65331)
[AnsibleでSymbol テストノードを量産できる体制を作る(https化もできるよ)](https://qiita.com/keisukefunatsu/items/846d51113949772025d4)

#デリゲハーベスティング
ここから本題です。
まず、ローカルハーベスティングに比べて以下のメリットがあります。

    1. 自らノードを用意しなくて良い == 維持管理しなくていいので凄くラク
    2. 残高0のアドレス(リモートアカウント)でハーベスティングを行うためセキュリティ的に安心

##SymbolのデリゲはNEMと比較してどうなっているのか？
デリゲハーベスティングは重要度スコアを所有しているアドレスの**重要度だけ**を残高0の他のアドレス(リモートアカウント)に渡します。そのアドレスを使ってごにょごにょしてハーベスティングします。
**要するに、大体NEMと同じ**です。


デスクトップウォレットから実行する場合、Txをまとめて発行するアグリゲートコンプリートトランザクションを使って簡単に有効にしていますが、1個ずつのトランザクションレベルでは実際にどうなっているのか、少し中身を覗いてみます。


##デリゲ実現のために必要なトランザクションとアカウント達
結構多いです。4個ぐらい投げます。登場人物やTxの種類、必要なデータなどが予想以上に多いです。
最新の公式ドキュメントはこちらです。
[デリゲートハーベスティングの有効化](https://docs.symbolplatform.com/ja/guides/accountlink/activating-delegated-harvesting.html)

※なお、ローンチ前なので内容が変わる可能性がありますが本記事では執筆時点の内容で説明していきます。ご容赦ください。

**関連トランザクション(カタカナ読みは適当)**
1. accountkeylink Transaction (アカウント キーリンク)
2. vrfkeylink Transaction (VRF キーリンク)
3. nodekeylink Transaction (ノード キーリンク)
4. persistentharvestdelegation Transaction (パーシステント ハーベスト デリゲーション)※読めない

**登場人物たち**
1. メインアカウント
2. リモートアカウント
3. VRFアカウント
4. アナウンスアカウント(面倒ならメインアカウントで代用可)
5. ハーベスティングを依頼するノード


**必要なデータ達**
1. リモートアカウントのパブリックキー(公開鍵)
2. リモートアカウントのプライベートキー(秘密鍵)
3. VRFアカウントのパブリックキー(公開鍵)
4. VRFアカウントのプライベートキー(秘密鍵)
5. 依頼するノードの専用公開鍵(そのうちnode/infoで取得できる予定)

もう、この時点で色々わかりにくいです。以下の図がサイトにありました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/856241/4fb0a392-9ba3-9685-8854-8b9f110f8c6a.png)


これでも分かりにくいので登場人物を雑に図にしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/856241/1210ed2f-800d-bf15-4beb-6d814c18a4f2.png)

まだ全然わかりにくいですね。
もう、かなり**やる気が削がれて**いきます。


署名者がやることを添えるとこうなります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/856241/f58706c2-87e8-df7e-3a3b-5d1337a2e9d1.png)

**我ながらイマイチわかりません。**
それぞれ噛み砕いて説明していきます。

まず登場人物達の説明が必要になりそうですのでそこから攻めていきましょう。

##登場人物紹介
###1人目：メインアカウント
その名の通りハーベスティングのメインになるアカウントです。主役です。Buy&HODLするアカウントです。インポータンスを持っているアドレス、と解釈しましょう。このアドレスには最低でも1万XYMを格納していなければなりません。そうしないとインポータンスを得ることができません。

※余談ですがNEMの場合はXEMをアドレスに寝かせることで「既得バランス」という値を得ることができました。この既得バランスは保管している期間で徐々に上がっていくのでハーベスティングをしたくてもすぐにはできない仕組みでした。Symbolでは**既得バランスは廃止**されています。180ブロックぐらい待てばアドレスのインポータンスが再計算される仕組みですのでとても早く反映されてとても嬉しいです。


###2人目：リモートアカウント
リモートアカウントです。このアカウントはアドレスが生成されてから一度も送金したりしてはいけない新品未開封のヴァージンなアドレスである必要があります。もちろん残高は0にしましょう。このアドレスにインポータンスを関連付けてハーベスティングが行われていきます。
なお、本アドレスの秘密鍵は（完全に暗号化された状態で、ですが）ネットワークに流す必要があります。怖いです。ですが、もし仮にこのアカウントが不正アクセスされてしまっても資産には影響がありません。残高0なので。
※このアカウントはTxを発行することはありません。

###3人目：VRFアカウント
VRF とは Verifiable Random Functionの略です。検証可能なランダム関数。秘密鍵の所有者のみがハッシュを算出できるが、公開鍵を持つ人であれば誰でもハッシュの正当性を検証できる仕組みです。
なるほど完全に理解しました。ググったりすると色々難解なサイトにHITしますので詳しく知りたい人は調べてみましょう。私は完全に理解しているので説明は**あえて**省きます。

目指せ北海道さんがnemlogに投稿されたホワイトペーパー和訳記事がとても参考になります。
[3.3 検証可能な乱数化関数（Verifiable Random Function, VRF）](https://nemlog.nem.social/blog/46373)


とにかく必要になりますので、このアドレスも生まれたてホヤホヤで残高0にしておきましょう。
※このアカウントはTxを発行することはありません。

###4人目：アナウンスアカウント
後述する手順で必要なアカウントです。無くてもいいですが、あると「より良いだろう」という説明があります。面倒ならメインアカウントで代用可です。
デリゲでは最後の手順として
「このアドレスがこのノードでハーベスティングしたいってよ！」
と**叫ぶ工程**があります。その時の叫ぶ人です。メインアカウントで叫んでも問題ありませんが、恥ずかしがり屋の人はこのアカウントに代わりに叫んでもらう事ができます。

このアカウントは叫ぶ際にTx手数料分のXYMが少しだけ必要になります。


###5人目：ハーベスティングを依頼するノード
その名の通り、ノードです。
ノードはデリゲで使用する専用のパブリックキーを公開している必要があります。
2020/11/30現在、ノード管理者しかこのパブリックキーは分からなくなっています。
`node.key.pem`というファイルからopensslで鍵を生成する必要があります。
近いうちにAPIでキーを取得できるようになるようですが執筆現在は未実装です。
未ローンチ現在、テストネットではNGL(NEM GROUP Limited)が運営しているノードのパブリックキーが公開されていますので当面はそちらを使う感じです。
もしノード管理者の人で自分の鍵を知りたい人は`node.key.pem`があるDIRで

```
$ openssl pkey -inform PEM -text -noout -in node.key.pem
```

と打ち込むと鍵が生成されますので是非試してみて下さい。


なお、@planethouki さんが気合いで鍵を取りに行く記事を書いてくださっています。
[Symbol-Testnet@0.10.0.3でnode.key.pemの公開鍵を取得する](https://qiita.com/planethouki/items/91acf9eeba4a9abe2df4)




##デリゲ手順
ここからは実際にデリゲを実現するための手順を説明していきます。

### Step.1 accountkeylinkを投げる
accountkeylinkはメインアカウントのimportanceをリモートアカウントに覚えさせる儀式です。
事前に空のアカウントを作成し、そのアドレスをリモートアカウントとして確保しておきます。

<dl>
  <dt>accountkeylink Tx発行者</dt>
  <dd>メインアカウント</dd>
  <dt>必要情報</dt>
  <dd>リモートアカウントの公開鍵</dd>
</dl>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/856241/2dd7f26d-db4b-2c8b-6953-5eb76ba6e68b.png)

```
CLIでの実施例：※メインアカウントにて実施
$ symbol-cli transaction accountkeylink

 Enter your wallet password: … **********
 Enter the public key of the remote account:  … リモートアカウントの公開鍵
 Select an action: ? Link
 Enter the maximum fee (absolute amount): … 1000000　※1XYM手数料載せてる(爆速になるはず)
 Select the transaction announce mode: ? normal
```
---


### Step.2 vrfkeylink を投げる
vrfkeylinkはメインアカウントとVRFアカウントを関連付ける処理です。
こちらも事前に空のアカウントを作成し、そのアドレスをVRFアカウントとして確保しておきます。

<dl>
  <dt>vrfkeylink Tx発行者</dt>
  <dd>メインアカウント</dd>
  <dt>必要情報</dt>
  <dd>VRFアカウントの公開鍵</dd>
</dl>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/856241/dc24d28b-22ca-a0b0-9026-cd70ddcea56d.png)

```
CLIでの実施例：※メインアカウントにて実施
$ symbol-cli  transaction vrfkeylink

 Enter your wallet password: … **********
 Enter the public key to link:  … VRFアカウントの公開鍵
 Select an action: ? Link
 Enter the maximum fee (absolute amount): … 1000000
 Select the transaction announce mode: ? normal
```
---

### Step.3 nodekeylink を投げる
nodekeylink はメインアカウントと委任をお願いするノードを関連付ける処理になります。
ノード側は`node.key.pem`というファイルから生成された公開鍵をデリゲーターの皆さんに公開しなければなりません。2020/11/30現在まだBootstrapやAPIも変更している最中ですのでそのうち取得できるようになるでしょう。


<dl>
  <dt>nodekeylink Tx発行者</dt>
  <dd>メインアカウント</dd>
  <dt>必要情報</dt>
  <dd>ノードの委任用公開鍵</dd>
</dl>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/856241/f768df1f-31cb-3501-cf49-d68b72f2be01.png)


```
CLIでの実施例：※メインアカウントにて実施
$ symbol-cli transaction nodekeylink

 Enter your wallet password: … **********
 Enter the public key to link:  …ノードの公開鍵
 Select an action: ? Link
 Enter the maximum fee (absolute amount): … 1000000
 Select the transaction announce mode: ? normal
```
---

### Step.4 persistentharvestdelegation を投げる
さぁ最後のステップです。名前が読みにくいです。永続的なデリゲの依頼、とでも呼ぶのでしょうか？

このトランザクションはネットワークに対して指定ノードでのデリゲ開始を通知するものになります。入力情報としてリモートアカウントの秘密鍵、VRFアカウントの秘密鍵、ノードの公開鍵が必要になります。この時点でStep3までの処理を行っているため、ここではメインアカウントが登場しなくても良いです。プライバシーが気になる方はこのTxを第三の捨て垢で行っても良い事になっていますので気になる人はそちらで、面倒な方はメインアカウントで投げましょう。
**「このアドレスがこのノードでハーベスティングしたいってよ！」**
って叫ぶだけですので。
なお、このTxは名前がついていますが実際はただのトランスファートランザクションでメッセージにINPUT情報を暗号化して送信しているとか。仕組みを知りたい人は詳しく調べてみると面白いかもしれません。そして仮にこのTxの暗号が解読されてもメインアカウントの秘密鍵ではないので資産は安全になっています。とても安心ですね。


<dl>
  <dt>persistentharvestdelegation Tx発行者</dt>
  <dd>アナウンス or メインアカウント(お好み)</dd>
  <dt>必要情報</dt>
  <dd>リモートアカウントの秘密鍵(公開鍵じゃない点に注意)</dd>
  <dd>VRFアカウントの秘密鍵(公開鍵じゃない点に注意)</dd>
  <dd>ノードの委任用公開鍵</dd>
</dl>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/856241/9596edd6-478b-d2e7-7dc7-9ba6532db9b0.png)


```
CLIでの実施例：※メインorアナウンスアカウントにて実施
$ symbol-cli symbol-cli transaction persistentharvestdelegation --profile アナウンスアカウント指定

※もしメインアカウントでやる場合は
symbol-cli symbol-cli transaction persistentharvestdelegation
だけで良いです

? Enter your wallet password: … **********
? Enter the remote account private key: …リモートアカウントの秘密鍵
? Enter the public key of the node: …ノードの公開鍵
? Enter the VRF private key linked to the main account: …VRFアカウントの秘密鍵
? Enter the maximum fee (absolute amount): … 1000000
? Select the transaction announce mode: ? normal
```


以上がデリゲーター側のデリゲの手順になります。結構面倒ですね。


### 備考：ノード側にharvesters.datが生成される
デリゲーターではなくノード側のお話になるのですが、これらの一連の手順を行った後、ハーベスティングを依頼されたノード側には
`symbol-bootstrap/target/nodes/api-node/data`の直下に`harvesters.dat`というファイルが生成されます。
このファイルに暗号化された色々な情報が詰まっているらしいです。
このデータさえ残っていればノードが何かの要因でDownしてしまった場合、例えばアップデートに伴い停止させた場合などのケースが想定されますが、そういうケースは復活したノードがこのファイルからハーベスティング依頼情報を再度GETして自動復帰する仕組みになります。
NEMの場合はノードの都合でハーベスティングが止まってしまったりしていましたが、そういう悩みからオサラバできます！これは便利！デリゲーターは半永久的に依頼したことになりますね。

せっかくなのでこのファイルの中身も覗いてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/856241/18603643-c761-f9f8-1e6b-51f67455ff90.png)

はい。私には何もわかりませんでした！
仮にこれを解読できたとしても残高0のVRFやリモートの秘密鍵が判るだけなので解析する価値すら感じませんでした！これならハーベスティングを依頼する人も安心ですね。

こちらも目指せ北海道さんが和訳したホワイトペーパーの記事を一読しておくと理解しやすいと思いますので、この機会に是非読んでおきましょう。
[【NEM技術勉強会】8.6 委任ハーベスターの自動検出【Symbol白書】](https://nemlog.nem.social/blog/40504)


#まとめ

デスクトップウォレットでは結構簡単にできるデリゲのハーベスティングですが結構複雑な動作になっています。こういう動きを大体理解しているとトラブルの際に何が怪しいのか目星を付けやすいので私のような一般ユーザーでも知っておいて損はないのではないでしょうか？

それでは皆様よきSymbolライフを
無事ローンチされることを祈って