From 9e01a9a38025db646d8028d7cc599f1516277aed Mon Sep 17 00:00:00 2001 From: Ondra Chaloupka Date: Thu, 20 Oct 2022 11:11:47 +0200 Subject: [PATCH] Governance: MultiChoiceType as part of the type MultiChoice --- governance/program/src/state/proposal.rs | 88 ++++++++++++------- .../use_proposals_with_multiple_options.rs | 21 ++++- 2 files changed, 71 insertions(+), 38 deletions(-) diff --git a/governance/program/src/state/proposal.rs b/governance/program/src/state/proposal.rs index 27245cd45a9..056455dd1ed 100644 --- a/governance/program/src/state/proposal.rs +++ b/governance/program/src/state/proposal.rs @@ -88,6 +88,10 @@ pub enum VoteType { /// Ex. voters are given 5 options, can choose up to 3 (max_voter_options) /// and only 1 (max_winning_options) option can win and be executed MultiChoice { + /// Type of MultiChoice + #[allow(dead_code)] + choice_type: MultiChoiceType, + /// The max number of options a voter can choose /// By default it equals to the number of available options /// Note: In the current version the limit is not supported and not enforced yet @@ -101,18 +105,19 @@ pub enum VoteType { #[allow(dead_code)] max_winning_options: u8, }, +} + +/// Type of MultiChoice. +#[derive(Clone, Debug, PartialEq, Eq, BorshDeserialize, BorshSerialize, BorshSchema)] +pub enum MultiChoiceType { + /// Normal multi choice type that requires decision for only one option when voting. + Approval, /// The multi weighted choice behaves the same way as the MultiChoice /// while it considers the weight_percentage defined in the VoteChoice - MultiWeightedChoice { - /// The max number of options a voter can choose; see MultiChoice - #[allow(dead_code)] - max_voter_options: u8, - - /// The max number of wining options; see MultiChoice - #[allow(dead_code)] - max_winning_options: u8, - }, + Weighted, + // Quadartic multi choice, not available yet + // Quadratic, } /// Governance Proposal @@ -222,7 +227,7 @@ pub struct ProposalV2 { impl AccountMaxSize for ProposalV2 { fn get_max_size(&self) -> Option { let options_size: usize = self.options.iter().map(|o| o.label.len() + 19).sum(); - Some(self.name.len() + self.description_link.len() + options_size + 295) + Some(self.name.len() + self.description_link.len() + options_size + 296) } } @@ -391,7 +396,7 @@ impl ProposalV2 { // If none of the individual options succeeded then the proposal as a whole is defeated ProposalState::Defeated } else { - match self.vote_type { + match &self.vote_type { VoteType::SingleChoice => { let proposal_state = if best_succeeded_option_count > 1 { // If there is more than one winning option then the single choice proposal is considered as defeated @@ -413,10 +418,7 @@ impl ProposalV2 { proposal_state } VoteType::MultiChoice { - max_voter_options: _n, - max_winning_options: _m, - } - | VoteType::MultiWeightedChoice { + choice_type: _t, max_voter_options: _n, max_winning_options: _m, } => { @@ -783,7 +785,8 @@ impl ProposalV2 { return Err(GovernanceError::InvalidVote.into()); } - if let VoteType::MultiWeightedChoice { + if let VoteType::MultiChoice { + choice_type: MultiChoiceType::Weighted, max_voter_options: _m, max_winning_options: _n, } = self.vote_type @@ -807,6 +810,7 @@ impl ProposalV2 { } } VoteType::MultiChoice { + choice_type: MultiChoiceType::Approval, max_voter_options: _n, max_winning_options: _m, } => { @@ -814,7 +818,8 @@ impl ProposalV2 { return Err(GovernanceError::InvalidVote.into()); } } - VoteType::MultiWeightedChoice { + VoteType::MultiChoice { + choice_type: MultiChoiceType::Weighted, max_voter_options: _n, max_winning_options: _m, } => { @@ -1065,17 +1070,14 @@ pub fn assert_valid_proposal_options( } if let VoteType::MultiChoice { + choice_type: _choice_type, max_voter_options, max_winning_options, - } - | VoteType::MultiWeightedChoice { - max_voter_options, - max_winning_options, - } = *vote_type + } = vote_type { if options.len() == 1 - || max_voter_options as usize != options.len() - || max_winning_options as usize != options.len() + || *max_voter_options as usize != options.len() + || *max_winning_options as usize != options.len() { return Err(GovernanceError::InvalidProposalOptions.into()); } @@ -1227,6 +1229,7 @@ mod test { fn test_max_size() { let mut proposal = create_test_proposal(); proposal.vote_type = VoteType::MultiChoice { + choice_type: MultiChoiceType::Approval, max_voter_options: 1, max_winning_options: 1, }; @@ -1240,6 +1243,7 @@ mod test { fn test_multi_option_proposal_max_size() { let mut proposal = create_test_multi_option_proposal(); proposal.vote_type = VoteType::MultiChoice { + choice_type: MultiChoiceType::Approval, max_voter_options: 3, max_winning_options: 3, }; @@ -2398,6 +2402,7 @@ mod test { // Arrange let mut proposal = create_test_multi_option_proposal(); proposal.vote_type = VoteType::MultiChoice { + choice_type: MultiChoiceType::Approval, max_voter_options: 3, max_winning_options: 3, }; @@ -2434,6 +2439,7 @@ mod test { // Arrange let mut proposal = create_test_multi_option_proposal(); proposal.vote_type = VoteType::MultiChoice { + choice_type: MultiChoiceType::Approval, max_voter_options: 3, max_winning_options: 3, }; @@ -2470,6 +2476,7 @@ mod test { ) { // Arrange let vote_type = VoteType::MultiChoice { + choice_type: MultiChoiceType::Approval, max_voter_options: 3, max_winning_options: 3, }; @@ -2487,6 +2494,7 @@ mod test { pub fn test_assert_valid_proposal_options_with_no_options_for_multi_choice_vote_error() { // Arrange let vote_type = VoteType::MultiChoice { + choice_type: MultiChoiceType::Approval, max_voter_options: 3, max_winning_options: 3, }; @@ -2518,6 +2526,7 @@ mod test { pub fn test_assert_valid_proposal_options_for_multi_choice_vote() { // Arrange let vote_type = VoteType::MultiChoice { + choice_type: MultiChoiceType::Approval, max_voter_options: 3, max_winning_options: 3, }; @@ -2539,6 +2548,7 @@ mod test { pub fn test_assert_valid_proposal_options_for_multi_choice_vote_with_empty_option_error() { // Arrange let vote_type = VoteType::MultiChoice { + choice_type: MultiChoiceType::Approval, max_voter_options: 3, max_winning_options: 3, }; @@ -2561,7 +2571,8 @@ mod test { // Multi weighted choice may be weighted but sum of choices has to be 100% // Arrange let mut proposal = create_test_multi_option_proposal(); - proposal.vote_type = VoteType::MultiWeightedChoice { + proposal.vote_type = VoteType::MultiChoice { + choice_type: MultiChoiceType::Weighted, max_voter_options: 3, max_winning_options: 3, }; @@ -2597,7 +2608,8 @@ mod test { // Multi weighted choice may be weighted to 100% and 0% rest // Arrange let mut proposal = create_test_multi_option_proposal(); - proposal.vote_type = VoteType::MultiWeightedChoice { + proposal.vote_type = VoteType::MultiChoice { + choice_type: MultiChoiceType::Weighted, max_voter_options: 3, max_winning_options: 3, }; @@ -2632,7 +2644,8 @@ mod test { pub fn test_assert_valid_vote_with_no_choices_for_multi_weighted_choice_error() { // Arrange let mut proposal = create_test_multi_option_proposal(); - proposal.vote_type = VoteType::MultiWeightedChoice { + proposal.vote_type = VoteType::MultiChoice { + choice_type: MultiChoiceType::Weighted, max_voter_options: 2, max_winning_options: 2, }; @@ -2668,7 +2681,8 @@ mod test { // Multi weighted choice does not permit vote with sum weight over 100% // Arrange let mut proposal = create_test_multi_option_proposal(); - proposal.vote_type = VoteType::MultiWeightedChoice { + proposal.vote_type = VoteType::MultiChoice { + choice_type: MultiChoiceType::Weighted, max_voter_options: 3, max_winning_options: 3, }; @@ -2703,7 +2717,8 @@ mod test { pub fn test_assert_valid_proposal_options_with_invalid_choice_number_for_multi_weighted_choice_vote_error( ) { // Arrange - let vote_type = VoteType::MultiWeightedChoice { + let vote_type = VoteType::MultiChoice { + choice_type: MultiChoiceType::Weighted, max_voter_options: 3, max_winning_options: 3, }; @@ -2721,7 +2736,8 @@ mod test { pub fn test_assert_valid_proposal_options_with_no_options_for_multi_weighted_choice_vote_error() { // Arrange - let vote_type = VoteType::MultiWeightedChoice { + let vote_type = VoteType::MultiChoice { + choice_type: MultiChoiceType::Weighted, max_voter_options: 3, max_winning_options: 3, }; @@ -2738,7 +2754,8 @@ mod test { #[test] pub fn test_assert_valid_proposal_options_for_multi_weighted_choice_vote() { // Arrange - let vote_type = VoteType::MultiWeightedChoice { + let vote_type = VoteType::MultiChoice { + choice_type: MultiChoiceType::Weighted, max_voter_options: 3, max_winning_options: 3, }; @@ -2760,7 +2777,8 @@ mod test { pub fn test_assert_valid_proposal_options_for_multi_weighted_choice_vote_with_empty_option_error( ) { // Arrange - let vote_type = VoteType::MultiWeightedChoice { + let vote_type = VoteType::MultiChoice { + choice_type: MultiChoiceType::Weighted, max_voter_options: 3, max_winning_options: 3, }; @@ -2781,7 +2799,8 @@ mod test { #[test] pub fn test_assert_more_than_ten_proposal_options_for_multi_weighted_choice_error() { // Arrange - let vote_type = VoteType::MultiWeightedChoice { + let vote_type = VoteType::MultiChoice { + choice_type: MultiChoiceType::Weighted, max_voter_options: 3, max_winning_options: 3, }; @@ -2810,7 +2829,8 @@ mod test { #[test] pub fn test_assert_same_label_options_for_multi_weighted_choice_error() { // Arrange - let vote_type = VoteType::MultiWeightedChoice { + let vote_type = VoteType::MultiChoice { + choice_type: MultiChoiceType::Weighted, max_voter_options: 1, max_winning_options: 1, }; diff --git a/governance/program/tests/use_proposals_with_multiple_options.rs b/governance/program/tests/use_proposals_with_multiple_options.rs index 1b23df27ee2..94b217086c5 100644 --- a/governance/program/tests/use_proposals_with_multiple_options.rs +++ b/governance/program/tests/use_proposals_with_multiple_options.rs @@ -5,6 +5,7 @@ use solana_program_test::*; mod program_test; use program_test::*; +use spl_governance::state::proposal::MultiChoiceType; use spl_governance::{ error::GovernanceError, state::{ @@ -92,6 +93,7 @@ async fn test_create_proposal_with_multiple_choice_options_and_without_deny_opti options, false, VoteType::MultiChoice { + choice_type: MultiChoiceType::Approval, max_winning_options: 2, max_voter_options: 2, }, @@ -106,6 +108,7 @@ async fn test_create_proposal_with_multiple_choice_options_and_without_deny_opti assert_eq!( proposal_account.vote_type, VoteType::MultiChoice { + choice_type: MultiChoiceType::Approval, max_winning_options: 2, max_voter_options: 2, } @@ -360,6 +363,7 @@ async fn test_vote_on_none_executable_multi_choice_proposal_with_multiple_option ], false, VoteType::MultiChoice { + choice_type: MultiChoiceType::Approval, max_winning_options: 3, max_voter_options: 3, }, @@ -488,6 +492,7 @@ async fn test_vote_on_executable_proposal_with_multiple_options_and_partial_succ ], true, VoteType::MultiChoice { + choice_type: MultiChoiceType::Approval, max_winning_options: 3, max_voter_options: 3, }, @@ -649,6 +654,7 @@ async fn test_execute_proposal_with_multiple_options_and_partial_success() { ], true, VoteType::MultiChoice { + choice_type: MultiChoiceType::Approval, max_winning_options: 3, max_voter_options: 3, }, @@ -856,6 +862,7 @@ async fn test_try_execute_proposal_with_multiple_options_and_full_deny() { ], true, VoteType::MultiChoice { + choice_type: MultiChoiceType::Approval, max_winning_options: 3, max_voter_options: 3, }, @@ -1021,6 +1028,7 @@ async fn test_create_proposal_with_10_options_and_cast_vote() { options, false, VoteType::MultiChoice { + choice_type: MultiChoiceType::Approval, max_winning_options: options_len, max_voter_options: options_len, }, @@ -1071,6 +1079,7 @@ async fn test_create_proposal_with_10_options_and_cast_vote() { assert_eq!( proposal_account.vote_type, VoteType::MultiChoice { + choice_type: MultiChoiceType::Approval, max_winning_options: options_len, max_voter_options: options_len, } @@ -1117,7 +1126,8 @@ async fn test_vote_multi_weighted_choice_proposal_non_executable() { "option 4".to_string(), ], false, - VoteType::MultiWeightedChoice { + VoteType::MultiChoice { + choice_type: MultiChoiceType::Weighted, max_winning_options: 4, max_voter_options: 4, }, @@ -1260,7 +1270,8 @@ async fn test_vote_multi_weighted_choice_proposal_with_partial_success() { "option 4".to_string(), ], true, - VoteType::MultiWeightedChoice { + VoteType::MultiChoice { + choice_type: MultiChoiceType::Weighted, max_winning_options: 4, max_voter_options: 4, }, @@ -1482,7 +1493,8 @@ async fn test_vote_multi_weighted_choice_proposal_with_multi_success() { "option 3".to_string(), ], true, - VoteType::MultiWeightedChoice { + VoteType::MultiChoice { + choice_type: MultiChoiceType::Weighted, max_winning_options: 3, max_voter_options: 3, }, @@ -1662,7 +1674,8 @@ async fn test_vote_multi_weighted_choice_proposal_executable_with_full_deny() { &mut governance_cookie, vec!["option 1".to_string(), "option 2".to_string()], true, - VoteType::MultiWeightedChoice { + VoteType::MultiChoice { + choice_type: MultiChoiceType::Weighted, max_winning_options: 2, max_voter_options: 2, },