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

Add threshold to cw3 flex #180

Merged
merged 28 commits into from
Dec 16, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e4ff708
Integrate Threshold into msg/state
ethanfrey Dec 14, 2020
185b6ab
cw3-flex compiles with threshold
ethanfrey Dec 14, 2020
09aff63
Existing tests updated and pass
ethanfrey Dec 14, 2020
b1e05c1
Test cases on message validation
ethanfrey Dec 14, 2020
4e1ec11
All message logic tested
ethanfrey Dec 14, 2020
a41b125
Properly calculate passing for Quorum - different if voting open/closed
ethanfrey Dec 14, 2020
011f27f
Test vote/tally logic, fix rounding issue
ethanfrey Dec 14, 2020
f798ddc
Extensive tests and fixes on threshold quorum
ethanfrey Dec 14, 2020
7dc1c75
Add test coverage to list/reverse proposals
ethanfrey Dec 15, 2020
31607dc
Test threshold, vote detail queries
ethanfrey Dec 15, 2020
65a7ee8
Scenario test with absolute percentage and dynamic group
ethanfrey Dec 15, 2020
01a77e7
Add scenario tests for percentage and quorum threshold variants
ethanfrey Dec 15, 2020
478fc3c
Update typos, rename some fields
ethanfrey Dec 15, 2020
3f3b379
Properly handle missing quorum and hitting threshold edge case
ethanfrey Dec 15, 2020
94af010
Extensive rustdoc on ThresholdResponse in cw3 spec
ethanfrey Dec 15, 2020
df6c9d3
cw3: Update query data types and more rustdoc
ethanfrey Dec 15, 2020
23de1be
Update cw3-fixed to match updated cw3 spec
ethanfrey Dec 15, 2020
09e9163
Update cw3-flex to new cw3 spec
ethanfrey Dec 15, 2020
0719092
Merge pull request #188 from CosmWasm/update-cw3-spec
maurolacy Dec 16, 2020
382cbf1
Format / fix cw3 spec details
maurolacy Dec 16, 2020
8a190f1
Update schemas
maurolacy Dec 16, 2020
8290c57
Update contracts/cw3-flex-multisig/src/state.rs
ethanfrey Dec 16, 2020
0fd5a88
Consider abstained votes when computing AbsoluteThreshold passing weight
maurolacy Dec 16, 2020
5ae15c6
Simplify branches in ThresholdQuora is_passed
ethanfrey Dec 16, 2020
526b0ff
Rename ThresholdQuora to ThresholdQuorum
ethanfrey Dec 16, 2020
e574ff7
Pull out PRECISION_FACTOR as mod level const
ethanfrey Dec 16, 2020
d87e498
Add one test for AbsolutePercentage and abstain, cargo schema
ethanfrey Dec 16, 2020
f33e3aa
Remove duplicate descriptions
maurolacy Dec 16, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions contracts/cw3-flex-multisig/schema/init_msg.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,10 @@
"type": "string"
},
"Threshold": {
"description": "This defines the different ways tallies can happen.\n\nThe total_weight used for calculating success as well as the weights of each individual voter used in tallying should be snapshotted at the beginning of the block at which the proposal starts (this is likely the responsibility of a correct cw4 implementation).",
"description": "This defines the different ways tallies can happen.\n\nThe total_weight used for calculating success as well as the weights of each individual voter used in tallying should be snapshotted at the beginning of the block at which the proposal starts (this is likely the responsibility of a correct cw4 implementation). See also `ThresholdResponse` in the cw3 spec.",
"anyOf": [
{
"description": "Declares that a fixed weight of yes votes is needed to pass. It does not matter how many no votes are cast, or how many do not vote, as long as `weight` yes votes are cast.\n\nThis is the simplest format and usually suitable for small multisigs of trusted parties, like 3 of 5. (weight: 3, total_weight: 5)\n\nA proposal of this type can pass early as soon as the needed weight of yes votes has been cast.",
"description": "Declares that a fixed weight of Yes votes is needed to pass. See `ThresholdResponse.AbsoluteCount` in the cw3 spec for details.",
"type": "object",
"required": [
"absolute_count"
Expand All @@ -83,7 +83,7 @@
}
},
{
"description": "Declares a percentage of the total weight that must cast yes votes in order for a proposal to pass. The percentage is computed over the total weight minus the weight of the abstained votes.\n\nThis is useful for similar circumstances as `AbsoluteCount`, where we have a relatively small set of voters and participation is required. The advantage here is that if the voting set (group) changes between proposals, the number of votes needed is adjusted accordingly.\n\nExample: we set `percentage` to 51%. Proposal 1 starts when there is a `total_weight` of 5. This will require 3 weight of yes votes in order to pass. Later, the Proposal 2 starts but the `total_weight` of the group has increased to 9. That proposal will then automatically require 5 yes of 9 to pass, rather than 3 yes of 9 as would be the case with `AbsoluteCount`.\n\nA proposal of this type can pass early as soon as the needed weight of yes votes has been cast.",
"description": "Declares a percentage of the total weight that must cast Yes votes in order for a proposal to pass. See `ThresholdResponse.AbsolutePercentage` in the cw3 spec for details.",
"type": "object",
"required": [
"absolute_percentage"
Expand All @@ -103,7 +103,7 @@
}
},
{
"description": "Declares a `quorum` of the total votes that must participate in the election in order for the vote to be considered at all. Within the votes that were cast, it requires `threshold` in favor. That is calculated by ignoring the abstain votes (they count towards `quorum` but do not influence `threshold`). That is, we calculate `yes / (yes + no + veto)` and compare that with `threshold` to consider if the proposal was passed.\n\nIt is rather difficult for a proposal of this type to pass early. That can only happen if the required quorum has been already met, and in the case if all remaining voters were to vote no, the threshold would still be met.\n\n30% yes votes, 10% no votes, and 20% abstain would pass early if quorum <= 60% (who has cast votes) and if the threshold is <= 37.5% (the remaining 40% voting no => 30% yes + 50% no). Once the voting period has passed with no additional votes, that same proposal would be considered successful if quorum <= 60% and threshold <= 75% (percent in favor if we ignore abstain votes).\n\nThis type is more common in general elections where participation is expected to often be low, and `AbsolutePercentage` would either be too restrictive to pass anything, or allow low percentages to pass if there was high participation in one election.",
"description": "Declares a `quorum` of the total votes that must participate in the election in order for the vote to be considered at all. See `ThresholdResponse.ThresholdQuorum` in the cw3 spec for details.",
"type": "object",
"required": [
"threshold_quorum"
Expand Down
49 changes: 8 additions & 41 deletions contracts/cw3-flex-multisig/src/msg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,55 +21,22 @@ pub struct InitMsg {
/// individual voter used in tallying should be snapshotted at the beginning of
/// the block at which the proposal starts (this is likely the responsibility of a
/// correct cw4 implementation).
/// See also `ThresholdResponse` in the cw3 spec.
#[derive(Serialize, Deserialize, Clone, PartialEq, JsonSchema, Debug)]
#[serde(rename_all = "snake_case")]
pub enum Threshold {
/// Declares that a fixed weight of yes votes is needed to pass.
/// It does not matter how many no votes are cast, or how many do not vote,
/// as long as `weight` yes votes are cast.
///
/// This is the simplest format and usually suitable for small multisigs of trusted parties,
/// like 3 of 5. (weight: 3, total_weight: 5)
///
/// A proposal of this type can pass early as soon as the needed weight of yes votes has been cast.
/// Declares that a fixed weight of Yes votes is needed to pass.
/// See `ThresholdResponse.AbsoluteCount` in the cw3 spec for details.
AbsoluteCount { weight: u64 },

/// Declares a percentage of the total weight that must cast yes votes in order for
/// a proposal to pass. The percentage is computed over the total weight minus the weight of the
/// abstained votes.
///
/// This is useful for similar circumstances as `AbsoluteCount`, where we have a relatively
/// small set of voters and participation is required. The advantage here is that if the
/// voting set (group) changes between proposals, the number of votes needed is adjusted
/// accordingly.
///
/// Example: we set `percentage` to 51%. Proposal 1 starts when there is a `total_weight` of 5.
/// This will require 3 weight of yes votes in order to pass. Later, the Proposal 2 starts but the
/// `total_weight` of the group has increased to 9. That proposal will then automatically
/// require 5 yes of 9 to pass, rather than 3 yes of 9 as would be the case with `AbsoluteCount`.
///
/// A proposal of this type can pass early as soon as the needed weight of yes votes has been cast.
/// Declares a percentage of the total weight that must cast Yes votes in order for
/// a proposal to pass.
/// See `ThresholdResponse.AbsolutePercentage` in the cw3 spec for details.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be cool to see these as hyperlinks.

These seem to be possible in RustDoc, and even better supported since 1.48
Also see the RFC for more details

(Side-note, we really need to review the RustDoc output once we push 0.4.0)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, they are possible, and are used extensively in the crates documentation. Here in particular, I first added and afterwards then removed the hyperlink formatting, because these comments go to the json files.

We definitely should start using these links, and confirm that they are working correctly in the crates docs.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Side-note, we really need to review the RustDoc output once we push 0.4.0)

I propose we create an issue in cosmwasm for that, and consider / mention all the projects.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, there are issues... for quite some time:

CosmWasm/cosmwasm#436

CosmWasm/cosmwasm#196

Just seems that all of us prefer to code than tidy up RustDoc

AbsolutePercentage { percentage: Decimal },

/// Declares a `quorum` of the total votes that must participate in the election in order
/// for the vote to be considered at all. Within the votes that were cast, it requires `threshold`
/// in favor. That is calculated by ignoring the abstain votes (they count towards `quorum`
/// but do not influence `threshold`). That is, we calculate `yes / (yes + no + veto)`
/// and compare that with `threshold` to consider if the proposal was passed.
///
/// It is rather difficult for a proposal of this type to pass early. That can only happen if
/// the required quorum has been already met, and in the case if all remaining voters were
/// to vote no, the threshold would still be met.
///
/// 30% yes votes, 10% no votes, and 20% abstain would pass early if quorum <= 60%
/// (who has cast votes) and if the threshold is <= 37.5% (the remaining 40% voting
/// no => 30% yes + 50% no). Once the voting period has passed with no additional votes,
/// that same proposal would be considered successful if quorum <= 60% and threshold <= 75%
/// (percent in favor if we ignore abstain votes).
///
/// This type is more common in general elections where participation is expected to often
/// be low, and `AbsolutePercentage` would either be too restrictive to pass anything,
/// or allow low percentages to pass if there was high participation in one election.
/// for the vote to be considered at all.
/// See `ThresholdResponse.ThresholdQuorum` in the cw3 spec for details.
ThresholdQuorum { threshold: Decimal, quorum: Decimal },
}

Expand Down