From e161f16e4374c4b6998183f578025af0cb9b7ee4 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Tue, 27 Oct 2020 19:18:57 +1000 Subject: [PATCH 1/9] modify gov split proto modification --- proto/cosmos/gov/v1beta1/gov.proto | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proto/cosmos/gov/v1beta1/gov.proto b/proto/cosmos/gov/v1beta1/gov.proto index 1d72e64321..3c00d4b2b2 100644 --- a/proto/cosmos/gov/v1beta1/gov.proto +++ b/proto/cosmos/gov/v1beta1/gov.proto @@ -119,9 +119,9 @@ message Vote { option (gogoproto.goproto_stringer) = false; option (gogoproto.equal) = false; - uint64 proposal_id = 1 [(gogoproto.moretags) = "yaml:\"proposal_id\""]; - string voter = 2; - VoteOption option = 3; + uint64 proposal_id = 1 [(gogoproto.moretags) = "yaml:\"proposal_id\""]; + string voter = 2; + repeated VoteOption options = 3; } // DepositParams defines the params for deposits on governance proposals. From 5061b8fe19086e07f8f610babb2395b5b07113d1 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Wed, 28 Oct 2020 23:24:55 +1000 Subject: [PATCH 2/9] basic ADR for gov split vote --- docs/architecture/adr-033-gov-split-vote.md | 65 +++++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 docs/architecture/adr-033-gov-split-vote.md diff --git a/docs/architecture/adr-033-gov-split-vote.md b/docs/architecture/adr-033-gov-split-vote.md new file mode 100644 index 0000000000..f8e914b4a0 --- /dev/null +++ b/docs/architecture/adr-033-gov-split-vote.md @@ -0,0 +1,65 @@ +# ADR 028: Public Key Addresses + +## Changelog + +- 2020/10/28: Intial draft + +## Status + +Proposed + +## Abstract + +This ADR defines a validator to split votes into several pieces. Assuming a group with multisig address vote on a proposal, the members could have different opinion. In this case spliting voting power into pieces could be useful. + +## Context + +Currently, an address can cast vote with only one of vote options(yes/no/abstrain/no_with_veto) and full votingPower of that address goes to one vote option. + +To be more accurate in voting process, allowing the split of voting power could be very helpful. + +Assume that there are 100 members associated to a single validator address and they participate in voting process via that address. + +60 members cast yes vote, 30 members cast no vote, 5 members abstrain, 5 members no_with_veto. +If they just cast yes vote for 100% of voting power, it won't be fair enough for 40 members especially when that validator's voting power is quite high. + +If total voting power is 10000, and on above case we split voting power into 6000, 3000, 500, 500 pieces. + +## Decision + +We will modify cli command from +```sh +simd tx gov vote 1 yes --from mykey +``` +to +```sh +simd tx gov vote 1 "yes=60,no=30,abstain=5,no_with_veto=5" --from mykey +``` + +``` +simd tx gov vote 1 yes --from mykey +``` +Old command still works and it's automatically converted to like below +``` +simd tx gov vote 1 "yes=1" --from mykey +``` + +If you want to set VoteOption=1, you can omit `=1`. +``` +simd tx gov vote 1 "yes,no" --from mykey +``` +is same as +``` +simd tx gov vote 1 "yes=1,no=1" --from mykey +``` + +## Consequences + +### Positive +- It can make more accurate voting process especially for big validators. + +### Negative + +### Neutral + +## References From e91be95d30998d98c0fd9e879b4e4a75763e7031 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Wed, 28 Oct 2020 23:27:39 +1000 Subject: [PATCH 3/9] revert proto change --- proto/cosmos/gov/v1beta1/gov.proto | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/proto/cosmos/gov/v1beta1/gov.proto b/proto/cosmos/gov/v1beta1/gov.proto index 3c00d4b2b2..1d72e64321 100644 --- a/proto/cosmos/gov/v1beta1/gov.proto +++ b/proto/cosmos/gov/v1beta1/gov.proto @@ -119,9 +119,9 @@ message Vote { option (gogoproto.goproto_stringer) = false; option (gogoproto.equal) = false; - uint64 proposal_id = 1 [(gogoproto.moretags) = "yaml:\"proposal_id\""]; - string voter = 2; - repeated VoteOption options = 3; + uint64 proposal_id = 1 [(gogoproto.moretags) = "yaml:\"proposal_id\""]; + string voter = 2; + VoteOption option = 3; } // DepositParams defines the params for deposits on governance proposals. From ffced9ebefa1b92f0187636514c6f02a21571ee9 Mon Sep 17 00:00:00 2001 From: antstalepresh Date: Wed, 28 Oct 2020 23:31:45 +1000 Subject: [PATCH 4/9] modify title --- docs/architecture/adr-033-gov-split-vote.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/architecture/adr-033-gov-split-vote.md b/docs/architecture/adr-033-gov-split-vote.md index f8e914b4a0..d88ff773a8 100644 --- a/docs/architecture/adr-033-gov-split-vote.md +++ b/docs/architecture/adr-033-gov-split-vote.md @@ -1,4 +1,4 @@ -# ADR 028: Public Key Addresses +# ADR 033: Governance split votes ## Changelog From 3a871b86cef8c56baa6ed5bb6f1f1556dd60fab1 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Thu, 29 Oct 2020 14:09:05 -0400 Subject: [PATCH 5/9] sunny updates --- docs/architecture/adr-033-gov-split-vote.md | 74 +++++++++++++-------- 1 file changed, 45 insertions(+), 29 deletions(-) diff --git a/docs/architecture/adr-033-gov-split-vote.md b/docs/architecture/adr-033-gov-split-vote.md index d88ff773a8..5ef1cf5c9e 100644 --- a/docs/architecture/adr-033-gov-split-vote.md +++ b/docs/architecture/adr-033-gov-split-vote.md @@ -10,56 +10,72 @@ Proposed ## Abstract -This ADR defines a validator to split votes into several pieces. Assuming a group with multisig address vote on a proposal, the members could have different opinion. In this case spliting voting power into pieces could be useful. +This ADR defines a modification to the the governance module that would allow a staker to split their votes into several voting options. For example, it could use 70% of its voting power to vote Yes and 30% of its voting power to vote No. ## Context -Currently, an address can cast vote with only one of vote options(yes/no/abstrain/no_with_veto) and full votingPower of that address goes to one vote option. +Currently, an address can cast a vote with only one options (Yes/No/Abstain/NoWithVeto) and use their full voting power behind that choice. -To be more accurate in voting process, allowing the split of voting power could be very helpful. - -Assume that there are 100 members associated to a single validator address and they participate in voting process via that address. - -60 members cast yes vote, 30 members cast no vote, 5 members abstrain, 5 members no_with_veto. -If they just cast yes vote for 100% of voting power, it won't be fair enough for 40 members especially when that validator's voting power is quite high. - -If total voting power is 10000, and on above case we split voting power into 6000, 3000, 500, 500 pieces. +However, often times the entity owning that address might not be a single individual. For example, a company might have different stakeholders who want to vote differently, and so it makes sense to allow them to split their voting power. Another example use case is exchanges. Many centralized exchanges often stake a portion of their users' tokens in their custody. Currently, it is not possible for them to do "passthrough voting" and giving their users voting rights over their tokens. However, with this system, exchanges can poll their users for voting preferences, and then vote on-chain proportionally to the results of the poll. ## Decision -We will modify cli command from -```sh -simd tx gov vote 1 yes --from mykey -``` -to -```sh -simd tx gov vote 1 "yes=60,no=30,abstain=5,no_with_veto=5" --from mykey -``` +We modify the vote structs to be ``` -simd tx gov vote 1 yes --from mykey +Vote { + ProposalId int64 + Voter sdk.Address + Options []Option + Rates []sdk.Dec +} ``` -Old command still works and it's automatically converted to like below + +The `ValidateBasic` of a MsgVote struct would require that +1. The length of the Options slice is equal to the length of Rates slice +2. The sum of all the Rates is equal to 1.0 +3. No Option is repeated + +The governance tally function will iterate over all the options in a vote and add to the tally the result of the voter's voting power * the rate for that option. + +``` +tally() { + map tally + + for (_, vote) in votes { + for (i, options) in vote{ + tally.option += getVotingPower(vote.voter) * vote.rate[i] + } + } +} +``` + +The CLI command for creating a multi-option vote would be as such: +```sh +simd tx gov vote 1 "yes=0.6,no=0.3,abstain=0.05,no_with_veto=0.05" --from mykey +``` + +To create a single-option vote a user can do either ``` simd tx gov vote 1 "yes=1" --from mykey ``` -If you want to set VoteOption=1, you can omit `=1`. -``` -simd tx gov vote 1 "yes,no" --from mykey -``` -is same as -``` -simd tx gov vote 1 "yes=1,no=1" --from mykey +or + +```sh +simd tx gov vote 1 yes --from mykey ``` +to maintain backwards compatibility. + + ## Consequences ### Positive - It can make more accurate voting process especially for big validators. ### Negative +- ### Neutral - -## References +- Relatively minor change to governance tally function. From 71e551bbae237bf570779d451d2c4e21e9744548 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Thu, 29 Oct 2020 16:35:50 -0400 Subject: [PATCH 6/9] address @alexanderbez review --- docs/architecture/adr-033-gov-split-vote.md | 29 ++++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/docs/architecture/adr-033-gov-split-vote.md b/docs/architecture/adr-033-gov-split-vote.md index 5ef1cf5c9e..a567dd692d 100644 --- a/docs/architecture/adr-033-gov-split-vote.md +++ b/docs/architecture/adr-033-gov-split-vote.md @@ -23,28 +23,31 @@ However, often times the entity owning that address might not be a single indivi We modify the vote structs to be ``` -Vote { - ProposalId int64 - Voter sdk.Address - Options []Option - Rates []sdk.Dec +type WeightedVoteOption struct { + Option string + Weight sdk.Dec +} + +type Vote struct { + ProposalID int64 + Voter sdk.Address + Options []WeightedVoteOption } ``` The `ValidateBasic` of a MsgVote struct would require that -1. The length of the Options slice is equal to the length of Rates slice -2. The sum of all the Rates is equal to 1.0 -3. No Option is repeated +1. The sum of all the Rates is equal to 1.0 +2. No Option is repeated The governance tally function will iterate over all the options in a vote and add to the tally the result of the voter's voting power * the rate for that option. ``` tally() { - map tally + results := map[types.VoteOption]sdk.Dec - for (_, vote) in votes { - for (i, options) in vote{ - tally.option += getVotingPower(vote.voter) * vote.rate[i] + for _, vote := range votes { + for i, weightedOption := range vote.Options { + results[weightedOption.Option] += getVotingPower(vote.voter) * weightedOption.Weight } } } @@ -72,7 +75,7 @@ to maintain backwards compatibility. ## Consequences ### Positive -- It can make more accurate voting process especially for big validators. +- Can make the voting process more accurate for addresses representing multiple stakeholders, often some of the largest addresses. ### Negative - From ebe73fa28b5c1f320bb0a8a63f5c8228cb64ef72 Mon Sep 17 00:00:00 2001 From: antstalepresh <36045227+antstalepresh@users.noreply.github.com> Date: Mon, 2 Nov 2020 23:10:39 +1000 Subject: [PATCH 7/9] modify ADR for MsgVote backwards compatibility --- docs/architecture/adr-033-gov-split-vote.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/docs/architecture/adr-033-gov-split-vote.md b/docs/architecture/adr-033-gov-split-vote.md index a567dd692d..b473bfc3b2 100644 --- a/docs/architecture/adr-033-gov-split-vote.md +++ b/docs/architecture/adr-033-gov-split-vote.md @@ -35,7 +35,22 @@ type Vote struct { } ``` -The `ValidateBasic` of a MsgVote struct would require that +And for backwards compatibility, we introduce `MsgWeightedVote` while keeping `MsgVote`. +``` +type MsgVote struct { + ProposalID int64 + Voter sdk.Address + Option Option +} + +type MsgWeightedVote struct { + ProposalID int64 + Voter sdk.Address + Options []WeightedVoteOption +} +``` + +The `ValidateBasic` of a `MsgWeightedVote` struct would require that 1. The sum of all the Rates is equal to 1.0 2. No Option is repeated From e9d6a8a48dd1ccbc271521738246f27162e44421 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Mon, 2 Nov 2020 12:56:45 -0400 Subject: [PATCH 8/9] add backwards compatibility section --- docs/architecture/adr-033-gov-split-vote.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/architecture/adr-033-gov-split-vote.md b/docs/architecture/adr-033-gov-split-vote.md index b473bfc3b2..759778c0c4 100644 --- a/docs/architecture/adr-033-gov-split-vote.md +++ b/docs/architecture/adr-033-gov-split-vote.md @@ -89,11 +89,16 @@ to maintain backwards compatibility. ## Consequences +### Backwards Compatibility +- Previous VoteMsg types will remain the same and so clients will not have to update their procedure unless they want to support the WeightedVoteMsg feature. +- When querying a Vote struct from state, its structure will be different, and so clients wanting to display all voters and their respective votes will have to handle the new format and the fact that a single voter can have split votes. +- The result of querying the tally function should have the same API for clients. + ### Positive - Can make the voting process more accurate for addresses representing multiple stakeholders, often some of the largest addresses. ### Negative -- +- Is more complex than simple voting, and so may be harder to explain to users. However, this is mostly mitigated because the feature is opt-in. ### Neutral - Relatively minor change to governance tally function. From a0c1deb2e2c5eb65842d705ebb6612ce9399af69 Mon Sep 17 00:00:00 2001 From: Sunny Aggarwal Date: Wed, 11 Nov 2020 13:35:07 -0400 Subject: [PATCH 9/9] reassign to adr 037 --- docs/architecture/README.md | 1 + .../{adr-033-gov-split-vote.md => adr-037-gov-split-vote.md} | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) rename docs/architecture/{adr-033-gov-split-vote.md => adr-037-gov-split-vote.md} (99%) diff --git a/docs/architecture/README.md b/docs/architecture/README.md index d9a52d3898..d3ff033688 100644 --- a/docs/architecture/README.md +++ b/docs/architecture/README.md @@ -72,3 +72,4 @@ Read about the [PROCESS](./PROCESS.md). - [ADR 031: Protobuf Msg Services](./adr-031-msg-service.md) - [ADR 032: Typed Events](./adr-032-typed-events.md) - [ADR 035: Rosetta API Support](./adr-035-rosetta-api-support.md) +- [ADR 037: Governance Split Votes](./adr-037-gov-split-vote.md) \ No newline at end of file diff --git a/docs/architecture/adr-033-gov-split-vote.md b/docs/architecture/adr-037-gov-split-vote.md similarity index 99% rename from docs/architecture/adr-033-gov-split-vote.md rename to docs/architecture/adr-037-gov-split-vote.md index 759778c0c4..af9cd8d6f6 100644 --- a/docs/architecture/adr-033-gov-split-vote.md +++ b/docs/architecture/adr-037-gov-split-vote.md @@ -1,4 +1,4 @@ -# ADR 033: Governance split votes +# ADR 037: Governance split votes ## Changelog