Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MvP Elections extension #439

Closed
ethanfrey opened this issue Mar 25, 2019 · 7 comments · Fixed by #523
Closed

MvP Elections extension #439

ethanfrey opened this issue Mar 25, 2019 · 7 comments · Fixed by #523
Assignees

Comments

@ethanfrey
Copy link
Contributor

ethanfrey commented Mar 25, 2019

Is your feature request related to a problem? Please describe.
In #419 we define an elections extension we need for on-chain governance, given hacking this off chain using multi-sig is not viable.

Describe the solution you'd like

We define a super minimal elections process with only "text proposals", which provide proof of agreement, but don't trigger any on-chain action. For this, I see three basic components, which we can extend later for more functionality: Electorate, Election Rules, and Proposal.

Electorate defines who may vote in an election. This same group will be used in many elections and we should store it for re-use. It can be of the form of []multisig.Participant or similar data, containing addresses and weights for each participant.

Election Rules defines how an election is run. A proposal must be voted upon via a pre-defined ruleset (majority of the senate, 60% of all residents of foo city, etc.). This also includes election length. Here are the basic fields to start with now.

  • Title
  • Electorate (reference via id)
  • Election length (timestamp, eg. 2 days, 1 week, ...)
  • Required Vote (integer in steps of 0.01%, so 10000 is 100%. should disallow anything below 5001) - note for now, this is percentage of all eligible voters, not the ones who voted. Discuss quorum later

Proposal can currently be created by anyone and triggers an election (we will have to refine this quite a bit later). eg. we will need a type field, and text is only present for text proposals. Control who can create a proposal, and which election rules can be used.

  • Title
  • Text (text string of what is being voted on)
  • Election Rules (reference via id)
  • Starts at (this must be > block timestamp when tx is included)

Initialization

For this first round, electorate and election rules are set in the genesis file with Initializers. We do not yet support creating them with Transactions.

Transactions

CreateProposal will create a new proposal, must have validate reference to election rules

Vote(proposal_id, decision) will vote yes/no/abstain for a given proposal. It will first check:

  • headerTime > proposal.starts_at
  • headerTime < proposal.starts_at + proposal.rules.length
  • voter has not voted on this proposal
  • voter is included in proposal.rule.electorate
  • Note: clarify who is voting, not just MainSigner.. voter should be in the tx

Tally(proposal_id) can only be executed after the election period is over and will update the proposal in the store with:

  • total votes yes (sum of weights of all the voters)
  • total votes no
  • total votes abstain
  • total weight of electorate
  • passed (boolean)

We assume the election rules and electorate are fixed and cannot change during the course of a running election.

Tally stores information on chain for reference (what was the vote), as well as a passed boolean that is based on the threshold from the rules, so we can filter for passed proposals. In a future iteration, this "passed" flag may trigger an automatic action.

Also, we may consider automatic vote tallying at the end of the period, but that is a different story, let's get the basic pieces together here.

Note: there is request for Acceptance Tests on this. Please add to bcpd application then (not bnsd) as this is quite experimental and internal format may/will change without warning. (TODO: future issue)

@alpe alpe self-assigned this Mar 28, 2019
@alpe
Copy link
Contributor

alpe commented Mar 28, 2019

Steps:

  • Define initial protobuf model with refernces
    • Electorate
    • Election Rules
    • Proposal
  • Initializer
    • Electorate
    • Election Rules
  • Messages + Handler
    • CreateProposal
    • Vote
    • Tally
  • Test corner cased for Electorate + ElectionRule validation
  • Optimization: rework voter archive into own voter bucket
  • Scenario tests BCPD

@alpe
Copy link
Contributor

alpe commented Mar 28, 2019

@ethanfrey Some questions came up during design phase:

  • Do we want a title for electorate?

  • The election length not fully clear. Should it always be a duration? days/ week is a duration but a timestamp is a fix date (timestamp, eg. 2 days, 1 week, ...) I have started with period in hours, WDYT? https://github.com/iov-one/weave/pull/450/files#diff-ac7a84d658879fb883e8697ad86373daR30

  • What is the max power value for an electorate participant?

  • Do we want to store with the proposal when it was submitted or the author?

  • What queries do we want to support beside by id (with an Index) ?

  • Any preferences on the genesis format? I would propose a single governance root element for a readable structure and a single initialization handler impl.

{
"governance":{
  "electorate": [],
  "rules":[]
  }
}

WDYT?

@ethanfrey
Copy link
Contributor Author

@alpe Good questions. Many of these will be refined over various issues, but let's get a good start.

Do we want a title for electorate?

Great idea.

The election length not fully clear. Should it always be a duration? days/ week is a duration but a timestamp is a fix date (timestamp, eg. 2 days, 1 week, ...) I have started with period in hours, WDYT?

Yes, it should be a duration. Resolution in hours is good.

What is the max power value for an electorate participant?

No opinion here. 255 is okay. so is 2^16-1. If you have no strong opinion, let's do 65535

Do we want to store with the proposal when it was submitted or the author?

Both are available in the transaction, but yeah, they will likely be needed often by the client. Sure, add the author (Address) and created_at (from the block_header)

What queries do we want to support beside by id (with an Index) ?

List non-expired proposals... open to yet-to-be-started.
I guess a secondary index on start_time would work for this, once we allow range queries (#413)

Any preferences on the genesis format?

Proposed format seems fine to group all the different elements.

@ethanfrey
Copy link
Contributor Author

ethanfrey commented Mar 28, 2019

@alpe I thought a bit more on testing, and I think we will make quite a few breaking API changes in the next few weeks. Until we have a clear final design, let's just stick with module level tests, and not integrate it with bnsd or bcpd. That means no scenario/unit tests.

We add them once we know what the final design is, so as not to waste time testing apis that will change 3 times in 3 weeks.

Let's just stick with happy path and major error cases (cannot vote before start, cannot vote after end, cannot tally before end, cannot vote twice, etc..) don't spend time covering everything or validation logic yet.

@alpe
Copy link
Contributor

alpe commented Apr 3, 2019

For the model validation I would need some concrete rules. This includes the following:

  • Electorate
    • title length/ regexp
    • max number participants
    • min weight
  • Election rules
  • min voting period hours
  • max voting period hours
  • min/max Fraction (??)

I have added some to https://github.com/iov-one/weave/pull/462/files#diff-564f72cccc6d5b2346f4b14a8cf2793c as a proposal

@ethanfrey
Copy link
Contributor Author

I added feedback on the above as PR comments.
Max number of participants was not addressed, but let's keep it quite large... say 2000 for now.
We should optimize this such that tally doesn't take O(N) time, but we keep a running count updated with each vote (to avoid a big delay at the final block)

@alpe alpe mentioned this issue Apr 4, 2019
@alpe
Copy link
Contributor

alpe commented Apr 4, 2019

I implement the votes as the first message to address the count updates. Simplest solution that comes into my mind to move the passed flag to the proposal type, so that we can collect vote counts in the result model instead. This would make it an intermediate result until the voting period has ended.
See new proposal

This was referenced Apr 5, 2019
@alpe alpe added this to the v0.15 milestone Apr 10, 2019
@alpe alpe closed this as completed in #523 Apr 12, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants