-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
85 additions
and
119 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,159 +1,124 @@ | ||
### Democracy Tutorial | ||
# Democracy Tutorial | ||
|
||
In this tutorial, we show a basic flow for two proposals in the democracy module using the CLI. On proposal will be approved and the other one will be rejected. | ||
Encointer is about distribution of power - both economically and in terms of governance. Therefore, communities can govern their own protocol parameters with an approximation of universal suffrance. This tutorial takes you through the process of proposing a change and voting on proposals. | ||
|
||
Go to the encointer-node repo and open 2 terminals: | ||
We assume you already have | ||
* [set up the CLI client](./tutorials-cli.md) | ||
* [registered a community](./tutorials-register-community.md) | ||
* [performed a virtual cycle gathering](./tutorials-perform-cycle.md) | ||
|
||
Terminal 1: | ||
## What can you vote on? | ||
|
||
``` | ||
git clone https://github.com/encointer/encointer-node.git | ||
cd encointer-node && git fetch && git checkout origin/personhood-democracy-1-delivery | ||
cd .. | ||
git clone https://github.com/encointer/pallets.git | ||
mv pallets/ encointer-pallets | ||
cd encointer-pallets && git fetch && git checkout origin/polkadot-v1.0.0-pallets-v1.3.0-democracy | ||
cd ../encointer-node | ||
cargo build --release | ||
./target/release/encointer-node-notee --dev --enable-offchain-indexing true -lencointer=debug,parity_ws=warn | ||
``` | ||
Please read our [democracy documentation](./protocol-democracy.md) to learn the details. In this tutorial, we will focus on [local community governance](./protocol-democracy.md#community-actions), like changinging the community income amount issued per cycle. | ||
|
||
Terminal 2: | ||
## Who can vote | ||
|
||
``` | ||
cd client | ||
python -m venv env | ||
source env/bin.activate | ||
pip install requirements.txt | ||
python bootstrap_demo_community.py | ||
``` | ||
Every reputable can vote on matters in the community where they have repuation. The current implementation grants reputables one vote per cycle attendance. This is a sybil-resilient approximation of universal suffrance and it gives those more voting power who engage more in cycles. | ||
|
||
Continuing in Terminal 2, we first move to the start of the next cycle, in order for the reputations of the last cycle to become eligible for voting: | ||
In the following, we will assume that one person only maintains one account. The protocol is sybil-resilient even if that's not the case, but the tutorial will be easier to follow with this assumption. | ||
|
||
``` | ||
../target/release/encointer-client-notee next-phase | ||
../target/release/encointer-client-notee next-phase | ||
../target/release/encointer-client-notee next-phase | ||
../target/release/encointer-client-notee listen -b 1 | ||
``` | ||
### Quorum | ||
|
||
After that, we submit two porposals for voting: | ||
Let's find out how many votes can maximally be cast for our community | ||
|
||
``` | ||
# Submitting proposal id 1, SetInactivityTimeout(8) | ||
../target/release/encointer-client-notee submit-set-inactivity-timeout-proposal //Alice 8 | ||
../target/release/encointer-client-notee listen -b 1 | ||
# Submitting proposal id 2, UpdateNominalIncome(cid, 44) | ||
../target/release/encointer-client-notee --cid sqm1v79dF6b submit-update-nominal-income-proposal //Alice 44 | ||
``` | ||
First, how many different accounts have reputation? | ||
|
||
We wait for the extrinsics to be in a block and list the proposals: | ||
```bash | ||
nctr-gsl list-reputables | ||
|
||
Listing the number of attested attendees for each community and ceremony for cycles [4607:4943] | ||
... | ||
Community ID: srcq45PYNyD | ||
... | ||
Cycle ID 4942: Total attested attendees: 3 (noshows: 0) | ||
Cycle ID 4943: Total attested attendees: 3 (noshows: 1) | ||
Reputables in srcq45PYNyD (unique accounts with at least one attendance) 4 | ||
``` | ||
../target/release/encointer-client-notee listen -b 1 | ||
../target/release/encointer-client-notee list-proposals | ||
``` | ||
Our test community has 4 reputable members who are eligible to vote. The quorum of votes will be the sum of attested attendances, in this case 6. Two accounts will have a voting power of 2, because they attended both cycles 4942 and 4943. Another two accounts have a voting power of 1 | ||
|
||
We expect to see the following output: | ||
Reputation becomes eligible for voting with 1 cycle delay. If you came here straight after the previous tutorial, you may need to wait for one cycle (30min on Gesell) for your fresh reputation to become eligible. | ||
|
||
``` | ||
id: 1 | ||
state: ProposalState::Ongoing | ||
action: ProposalAction::SetInactivityTimeout(8) | ||
start time: 1704685908002 | ||
start cindex: 3 | ||
electorate size: 3 | ||
turnout: 0 | ||
ayes: 0 | ||
id: 2 | ||
state: ProposalState::Ongoing | ||
action: ProposalAction::UpdateNominalIncome(sqm1v79dF6b, 44) | ||
start time: 1704685920000 | ||
start cindex: 3 | ||
electorate size: 3 | ||
turnout: 0 | ||
ayes: 0 | ||
``` | ||
Reputation loses its voting power after [ReputationLifetime](./protocol-reputation.md#reputation-lifetime) | ||
|
||
As an exmaple we show that Alice has 1 reputation and therefore a voting power of 1: | ||
``` | ||
../target/release/encointer-client-notee reputation //Alice | ||
``` | ||
which will yield: | ||
``` | ||
1, sqm1v79dF6b, Reputation::VerifiedUnlinked | ||
``` | ||
The same will hold for Bob and Charlie. | ||
For later reference, we list the 4 reputables here with their eligible votes: | ||
* `5F77sGnUhpjdFnzruhurGZgqPFtvdECXTGgX4Bgy2zGavbEw` (bootstrapper with 1 vote) | ||
* `5FyWbcwN1TGPdyzRzoEeem3MUcc7jXRs7ZoftZkAQLV47nS7` (bootstrapper with 2 votes) | ||
* `5CMVLJCC4Jn7QmLsFRkLWkm2w4LJswpZo1V2nd1tp64iVnCR` (bootstrapper with 2 votes) | ||
* `5FH44YdjmxbXJCAn9DuwpXuz5h2S8zLn752Vn5CyDa3quwEs` (reputable with 1 vote) | ||
|
||
|
||
Then, we let the users vote for the porposals: | ||
## Submit Proposals | ||
|
||
Anyone can submit a proposal anytime. See the [docs](./protocol-democracy.md#proposals) to learn about conflict resolution among proposals. | ||
|
||
```bash | ||
nctr-gsl submit-update-nominal-income-proposal 5FH44YdjmxbXJCAn9DuwpXuz5h2S8zLn752Vn5CyDa3quwEs 3.14 --cid srcq45PYNyD | ||
nctr-gsl list-proposals | ||
``` | ||
Let's inspect the details of our proposal | ||
``` | ||
# Alice votes aye for proposal 1 | ||
../target/release/encointer-client-notee vote //Alice 1 aye sqm1v79dF6b_1 | ||
# Alice votes again aye for proposal 1, this vote will not count as she has already voted | ||
../target/release/encointer-client-notee vote //Alice 1 aye sqm1v79dF6b_1 | ||
# Bob votes aye for proposal 1 | ||
../target/release/encointer-client-notee vote //Bob 1 aye sqm1v79dF6b_1 | ||
# Charlie votes aye for proposal 1 | ||
../target/release/encointer-client-notee vote //Charlie 1 aye sqm1v79dF6b_1 | ||
# Alice votes nay for proposal 2 | ||
../target/release/encointer-client-notee vote //Alice 2 nay sqm1v79dF6b_1 | ||
# Bob votes nay for proposal 2 | ||
../target/release/encointer-client-notee vote //Bob 2 nay sqm1v79dF6b_1 | ||
# Charlie votes aye for proposal 2 | ||
../target/release/encointer-client-notee vote //Charlie 2 aye sqm1v79dF6b_1 | ||
id: 3 | ||
action: ProposalAction::UpdateNominalIncome(srcq45PYNyD, 3.14000000000000012434) | ||
started at: 2024-03-24 15:58:48 UTC | ||
ends after: 2024-03-24 16:18:48 UTC | ||
start cindex: 4954 | ||
state: ProposalState::Ongoing | ||
``` | ||
So now we have at most 30min time to vote. | ||
|
||
Now, we wait for 5 blocks, as out confirmation period is 10 blocks and we already waited 6 blocks during voting: | ||
## Vote | ||
|
||
Let's check our voting power: | ||
```bash | ||
nctr-gsl reputation 5FH44YdjmxbXJCAn9DuwpXuz5h2S8zLn752Vn5CyDa3quwEs | ||
4943, srcq45PYNyD, Reputation::VerifiedUnlinked | ||
``` | ||
../target/release/encointer-client-notee listen -b 5 | ||
We have one vote in community srcq45PYNyD with our reputation from cindex 4943. We need this information to cast our vote: | ||
|
||
```bash | ||
nctr-gsl vote 5FH44YdjmxbXJCAn9DuwpXuz5h2S8zLn752Vn5CyDa3quwEs 3 aye srcq45PYNyD_4943 | ||
nctr-gsl list-proposals | ||
``` | ||
|
||
Now, we need to update the proposal state and check again the proposals and the enactment queue: | ||
The proposal will immediately enter the confirming phase which lasts 5min | ||
|
||
``` | ||
# Alice updates proposal state of proposal 1 | ||
../target/release/encointer-client-notee update-proposal-state //Alice 1 | ||
../target/release/encointer-client-notee list-proposals | ||
../target/release/encointer-client-notee list-enactment-queue | ||
id: 3 | ||
action: ProposalAction::UpdateNominalIncome(srcq45PYNyD, 3.14000000000000012434) | ||
started at: 2024-03-24 15:58:48 UTC | ||
ends after: 2024-03-24 16:18:48 UTC | ||
start cindex: 4954 | ||
state: ProposalState::Confirming { since: 1711296000000 } | ||
confirming since: 2024-03-24 16:00:00 UTC until 2024-03-24 16:00:00 UTC | ||
``` | ||
If no one else votes, it will be approved because in this case our vote is already more than 5% of the electorate. Please check [our docs on adaptive quorum biasing](./protocol-democracy.md#adaptive-quorum-biasing-aqb-and-minimum-approval) | ||
|
||
Proposals are lazily evaluated. after the end of the confirming phase you can call | ||
|
||
For the proposals, we expect proposal 1 to be Approved: | ||
```bash | ||
nctr-gsl update-proposal-state 5FH44YdjmxbXJCAn9DuwpXuz5h2S8zLn752Vn5CyDa3quwEs 3 | ||
nctr-gsl list-proposals | ||
``` | ||
|
||
``` | ||
id: 1 | ||
id: 3 | ||
action: ProposalAction::UpdateNominalIncome(srcq45PYNyD, 3.14000000000000012434) | ||
started at: 2024-03-24 15:58:48 UTC | ||
ends after: 2024-03-24 16:18:48 UTC | ||
start cindex: 4954 | ||
state: ProposalState::Approved | ||
action: ProposalAction::SetInactivityTimeout(8) | ||
start time: 1704685908002 | ||
start cindex: 3 | ||
electorate size: 3 | ||
turnout: 3 | ||
ayes: 3 | ||
id: 2 | ||
state: ProposalState::Ongoing | ||
action: ProposalAction::UpdateNominalIncome(sqm1v79dF6b, 44) | ||
start time: 1704685920000 | ||
start cindex: 3 | ||
electorate size: 3 | ||
turnout: 3 | ||
ayes: 1 | ||
``` | ||
|
||
And proposal 1 should be in the enactment queue, which means that it is scheduled for enactment at the start of the next cycle: | ||
All approved proposals will be enacted automatically at the start of the next *Registering* phase. Let's check the enactment queue: | ||
|
||
```bash | ||
nctr-gsl list-enactment-queue | ||
3 | ||
``` | ||
1 | ||
``` | ||
|
||
We wait for another 10 blocks, such that the proposal lifetime of 20 blocks for proposal 2 elapses and we expect proposal 2 to be cancelled: | ||
This returns all proposal id's which will be enacted. Please be aware that even approved proposals can be cancelled before enactment if another proposal for the same action passes before enactment. | ||
|
||
After the start of the next *Registering* phase, let's verify the enactment: | ||
```bash | ||
|
||
``` | ||
# Waiting 10 blocks... | ||
../target/release/encointer-client-notee listen -b 10 | ||
# Alice updates proposal state of proposal 2 | ||
../target/release/encointer-client-notee update-proposal-state //Alice 2 | ||
../target/release/encointer-client-notee list-proposals | ||
``` |