SubstrateでDemocracy(民主主義)機能を試してみる

# はじめに

[Polkadot](https://polkadot.network/ja/)では[Democracy(民主主義)](https://wiki.polkadot.network/docs/maintain-guides-democracy)という機能がありますが、提案(あるアカウントに運営側から100トークン付与する、など)をして各アカウントがその提案に対して、賛成か反対かを投票することができ、可決されればその提案内容を実行する事ができたりします。

また[評議会](https://wiki.polkadot.network/docs/maintain-guides-how-to-join-council)というものがあり、評議会のメンバーになると提案を優先的に可決させたり、否決させたりする事ができます。

今回はこのDemocracy機能を[Substrate node template](https://github.com/substrate-developer-hub/substrate-node-template)に導入して動作確認をしてみたいと思います。

# 導入手順

## 記事のソース

https://github.com/shohu/substrate-democracy-template

## pallet-democracyの導入

[pallet-democracy](https://github.com/paritytech/substrate/tree/master/frame/democracy)を導入します。
こちらのpalletを導入することで、提案する事ができ、その提案に対する投票ができるようになります。

### Cargo.toml

こちらのpalletを導入するにあたり関連のpalletもCargo.tomlに導入する事になります。

実際に導入するpalletは[こちらを参照](https://github.com/shohu/substrate-democracy-template/commit/340f5f10746817672e6bb9f3f29fcbeffd935d24#diff-6431a3eec6e102bbcffb94387cda89efbe02002649745273fb575234c0018de4R57)してください。

### node/src/chain_spec.rs

pallet追加に伴う[chain_specのソース修正](https://github.com/shohu/substrate-democracy-template/commit/340f5f10746817672e6bb9f3f29fcbeffd935d24#diff-f2256017c4e606a30f53708578da46675512cc1300be6542ed5f77e58af0d6dc)を行います。

testnet の genesis config 設定で、democracy, council, technical_committee, treasury を追加します。

### runtime/src/constants.rs

[Substrateソースであるconstants.rs](https://github.com/paritytech/substrate/blob/8cbda809d3495f38ce04eec46e90330db213af8a/bin/node/runtime/src/constants.rs)をコピーして runtime/src/constants.rs とします。

### runtime/src/lib.rs

追加したpallet毎に、parameter_types、pallet_XXXXX::Config を設定します。
ちなみにこの時のConfig設定で投票期間などの時間系も設定できます。

[追加内容はこちら](https://github.com/shohu/substrate-democracy-template/commit/340f5f10746817672e6bb9f3f29fcbeffd935d24#diff-0ec06ea58bd455f09ce6b3bb4c2c1c0d37bda51c1e1be2151c560c9c973959ec)

試験用に投票期間などを短くした修正は[こちら](https://github.com/shohu/substrate-democracy-template/commit/7796a2d2c6bdbe23641508f87a29e5b36db21966)です。

```rs
	pub const LaunchPeriod: BlockNumber = 6 * MINUTES;  // 投票受付のサイクル
	pub const VotingPeriod: BlockNumber = 6 * MINUTES;  // 投票期間
	pub const FastTrackVotingPeriod: BlockNumber = 1 * MINUTES;
	pub const EnactmentPeriod: BlockNumber = 7 * MINUTES;  // 提案可決後に提案実行するまでの期間
	pub const CooloffPeriod: BlockNumber = 6 * MINUTES;  // 拒否された後に外部提案を再提出できない期間
```

## Council(評議会)対応

pallet-democracy関連のpalletを導入しただけですと(pallet-democracyを導入してcompileを通しただけ)、提案＆提案に対する投票はできますがCouncil(評議会)へのメンバー参加や、そのメンバーになれるかどうかの投票ができません。

このため[pallet-elections-phragmen](https://github.com/paritytech/substrate/tree/master/frame/elections-phragmen)を導入します。

[修正内容はこちらです](https://github.com/shohu/substrate-democracy-template/commit/303fef9298cf75ebd9cca06483e6198508f4404c)

# 確認手順

## 提案(プロポーザル)作成から提案実行まで

提案(プロポーザル)をするには[preimage hash]と呼ばれるものを送信する必要があります。
[preimage hash]は登録する提案のhashです。

大きな[preimage hash]を提出するための保管コストはかなり高くつく可能性があるため、提案を作成する行為と、提案の[preimage hash]を提出することと分けています。
[preimage hash]の送信を別のトランザクションとして許可するということは、資金がない場合に別のアカウントが[preimage hash]を送信できることを意味します。

では、この[preimage hash]を作成するために[Submit preimage]ボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38387/9ee0ee5a-9aa6-e284-9b22-5a83faa60939.png)

画面上で提案内容を入力して（下の画面は FERDIEの残高を設定するという提案）[preimage hash]を覚えておき、画面の指示にしたがいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38387/17850413-d6bf-b9e8-1c7b-2356d64153e1.png)

今度は[Submit proposal]ボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38387/910ab07a-6962-fac7-1dcf-f84e2500f5cd.png)

そして前回の画面でコピーしておいた[preimage hash]を入力して[Submit proposal]ボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38387/502bf09e-62e5-4bd9-a774-745b740b014d.png)

無事Submitするとproposalsセクションに提案内容が表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38387/d8d431fd-649e-6482-e7d2-cf344eafe36d.png)

[launch period]の期間が過ぎると（画面上は6分です)、以下のように proposals から referenda（国民投票） に移動し Vote(投票) できるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38387/a2130ee9-8e03-090b-f0b8-b7988ea7de93.png)

ALICEでこの提案に対してYES[Aye]でVoteしてみます。
この際以下画面の[vote value(投票に使うトークン量)]と[conviction(ロックする期間)]によって[vote power]が変わってきます。詳しくは[こちら](https://wiki.polkadot.network/docs/learn-governance#voting-on-a-referendum)を参照してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38387/41865406-cc7b-ff10-8834-a0ae0450f685.png)

すると以下のように緑チェックマークがついてAye(YES)にVoteした量が表示されています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38387/c0bda44c-7f40-3a0e-d11a-b544574ce154.png)

Bobで否定してみます。Aliceより少なくなるように[vote value][conviction]を入力して[Vote Nay]ボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38387/0a38c139-2c5d-7dd5-01de-e3978197e2d3.png)

Ayeの方が多いので、可決予定のままです。
ただ、この辺りの[vote power]については[こちら](https://wiki.polkadot.network/docs/learn-governance#voting-on-a-referendum)に詳しく記載があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38387/1d92f352-7840-2c47-137c-f15e46bdd72c.png)

そして[Launch period]の期間がすぎるとDispatchのqueueにたまります。
以下画面ですと enact, remaining が6分36秒後に実施する事になっています。
これは [EnactmentPeriod](#runtime/src/lib.rs)を7分として設定しているため24秒経過している状態です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38387/2d010094-5bfd-8234-62da-cf5d548a8a15.png)

7分経過後、以下のように提案が実行されて FERDIE を見ると 100 UNIT 振り込まれてる事が確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38387/3100a2f0-d575-69e6-b641-6d76e623f684.png)

## 評議会のメンバー追加

冒頭でも軽く紹介しましたが[評議会](https://wiki.polkadot.network/docs/maintain-guides-how-to-join-council)では、評議会のメンバーになると提案を優先的に可決させたり、否決させたりする事ができます。

こちらの評議会のメンバーになるには上記タブメニューから Governance - カウンシル を選択したあと[Submit candidacy]を押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38387/7fa67ba7-db97-cef7-e50e-a8199b6d7a59.png)

この後、評議会に推薦するアカウントを指名することになりますが、推薦するアカウントの残高をかなり多めに持たせておかないと、推薦できないので注意が必要です。
今回は 10000000000000000000 を付与しておきました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38387/cda18fde-12ca-ea31-5718-0cbbedb1681b.png)

[submit your council candidacy]画面で推薦するアカウントを選択後に[Submit]ボタンを押します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38387/3a09341c-0b91-91db-7ddc-de4a155b110b.png)

すると[candidates]セクションに、推薦したアカウントが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38387/ef40cc44-898a-e1ab-a578-c9989aecea38.png)

candidateしただけだと、メンバーになることはできず、このあとVoteする必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38387/deba27a5-ca57-a76d-6cc3-75f527eb1ad6.png)

Voteボタンを押して[Vote value]、投票するアカウントを決めてVoteします。これで[member]もしくは[runners up]のセクションに[term processes]の期間を過ぎると移動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38387/c5cd8661-af40-6b6c-996c-5eb29a5aa685.png)

今回、すでに評議会メンバーである Alice と Bob の backing が 1MUNIT(デフォルト)で、先ほどVoteしたvalueが足りないため[runners up]にまわされます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38387/b1f317d2-543d-24ad-7e39-3f30d862a5cc.png)

推薦したアカウントを評議会メンバーにしたいので[Vote]を改めて行い[vote power]を増やす事によって既存のメンバーと入れ替える事ができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38387/bdb27609-274e-138b-5bdf-602d898c70a1.png)

これで評議会メンバーに新たなアカウントを入れる事ができました。

# 終わりに

今回は Substrate の Democracy(民主主義)機能 について触れてみました。

運営側で強制的に何かしらの処理をSudo機能で実行もできますが、こういった全アカウント対象として投票制で処理を実行できるかどうかを決めれる機能が用意されてるブロックチェーンフレームワークもそうないのではないでしょうか（あったらすみません）。

Substrate ではこういった機能がpalletを追加する事によって動作させる事が可能で非常に使い勝手が良いと考えています。（palletによっては追加が多少面倒な時もありますが）
今後も他に気になる機能があったら記事として紹介していこうと思います！