openlawteam / tribute-contracts

A new modular DAO framework, inspired by the Moloch smart contracts
https://tributedao.com
MIT License
297 stars 110 forks source link

cost effective voting with merkle trees #2

Closed adridadou closed 4 years ago

adridadou commented 4 years ago

Why

Onchain governance is always expensive because it involves so many transactions. The goal of this document is to discuss an approach to bring most of the voting mechanisms off chain but still have the same level of verifiability with a few assumptions. The goal here is to describe those assumptions, see if they are reasonable or not and maybe get feedback on how to improve this approach even further.

The properties we are looking for are: near constant gas cost for a vote round reasonable cost to create a vote simple approach on chain verification / audit possible if something doesn’t seem right

Design

The goal here is to create two merkle tree: The vote definition merkle tree. It represents every voting rights The vote results merkle tree. It represents the result of the vote

The vote definition root is being submitted at the same time as we create the vote onchain. The vote results are being submitted once the voting has ended.

VoteRoundId

Each round needs to be uniquely identified. To do this, we use the function: hash(Moloch address, proposalId) which is always unique.

Voting

A Voter should be able to vote as well. To do this, the user needs to signs with his key the following data: for yes: hash(voteRoundId, 1) for No: hash(voteRoundId, -1) for abstain : hash(voteRoundId, 0)

The vote definition merkle tree

Its structure is as follows: leaf: voter address, voter weight. The hash representation of the leaf (used for parent nodes) is hash ( voter address, voter weight) node: standard merkle tree node, i.e. hash of its children

Each leaf is sorted by the address

The vote results merkle tree

Its structure is as follows:

leaf

it has the entries:

root

then the hash of the root is being published with the accumulation result. The accumulation result is the result of the voting

Happy path

If everyone is happy with the voting result (no fraud has been committed) then the DAO just take the result and acts accordingly.

Fraud

This is the most important part. We describe here the fraud / attack vector, and how this system can respond to them.

Wrong data

If someone tries to vote with the wrong data (not signed by the right key, not the right weight etc ...) anyone can publish the proof that the leaf was wrong by publishing the incriminating leaf with its path to root, the proof in the vote definition and show that the data doesn't match.

unknown address

if someone shouldn't be able to vote, anyone can publish a proof that the address doesn't exist in the vote definition tree. The way to prove that is as follows:

if. the address is smaller or higher than any other address, just prove that the smaller / highest address in the tree definition is not this address and is higher / smaller than the one that has voted

Failsafe

if anything goes wrong, we should make it possible to invalidate an offchain voting and switch back to onchain if a quorum of voters mark it as fraudulent. TBD: do we want to just cancel the vote or switch it to on chain ? maybe configurable ?

Staking

It seems to me that using some form of staking to reward the participants and also having a way to punish bad behaviour makes sense but the details of this part is still TBD

Assumptions

In order for this to work, we make a few assumptions:

Smart Contract design

TBD: Let's start with the high level design and then I can work on the smart contract itself

mcchan1 commented 4 years ago

I think for FAILSAFE situations - If there was enough incentive to commit a fraudulent vote (a certain gov proposal would unfairly benefit a certain member), and if a quorom of voters think something wrong happened, then we should move to on-chain. A FAILSAFE scenario means that the stakes were high enough to warrant on-chain voting.

adridadou commented 4 years ago

So for me the whole conflict resolution is still TBD My biggest fear here is:

mcchan1 commented 4 years ago

from our slack conversation.. If we are using Snapshot, how do we account for any rage quitting in between block times? .... If a member voted No then they can ragequit, otherwise if they voted YES, then they have to wait until the last proposal voted YES on is processed. From the moloch code a member-- "cannot ragequit until highest index proposal member voted YES on is processed"

mcchan1 commented 4 years ago

for reference https://github.com/MolochVentures/moloch/tree/master/v1_contracts#game-theory

adridadou commented 4 years ago

Modified idea to manage voting offchain

Snapshot: Ordered merkle tree with all the participants and their vote weight

Result: the merkle tree is built as follows: The tree itself is a standard merkle tree The leaves are built like this: they have the following properties:

address : the address of the person who votes weight: how much his vote weights vote: the signed version of the vote nbYes: accumulator, how many votes have been yes nbNo: accumulator, how many votes have been no previous vote address: address of the previous vote (0x0 if none). makes it easier to check sequential steps next vote address: address of the next vote (0x0 if none). makes it easier to check sequential steps and to see that one vote is the last one

each step should be order by address

Challenging a result:

prove that someone's vote is not correct (wrong weight, wrong signature or wrong type (yes instead of no for ex))

prove that a step is wrong

prove that the steps are out of order -give proofs of two adjacent steps

Accepting a vote:

If the quorum has been reached, no need to wait anymore and we close the voting. Censorship doesn't matter in this case because any additional vote wouldn't change the result. The only thing we need to make sure is that the result is correct. A grace period (configurable, by default 1 day) to wait for anyone to challenge the result

If the voting period is finished and an absolute majority has not been reached, then it is a bit trickier: A vote result can be published. Let's say the % of voters is n.

Then once the result has been published, a grace period starts (configurable, default 1 day) If someone that should be able to vote prove that his vote has not been taken into account, then the result is cancelled and a new result with at least n + voting weight of the person missing needs to be submitted.

If the new result is > 50 %, then apply the rule above, otherwise, go bac to the rule of grace period and possibility to say that you have not been taken into account.

Security:

Assumption:

staking / reward strategy This part is open for debate / discussion. I think we need a bit of both Anyone starting a vote or proposing a result should have tokens at stake If anyone proves that the result is bad, then the tokens at stake should come back to him if someone says he hasn't been taken into account in the vote and someone else proposes a result, the new person should get the reward from the tokens at stake

mcchan1 commented 4 years ago

from Slack... we're trying to solve 1) spam 2) getting sufficient participation, 3) and dealing with bad result. -- A possible solution is a Swiss style of voting, where a member has to collect a signature of another member(s) and pool together enough signatures to bring to call for a vote. This could solve 1 and 2, because if you have to collect signatures then the issue is relevant/material enough to vote on.