Skip to content

Commit

Permalink
Governance: MultiChoiceType as part of the type MultiChoice
Browse files Browse the repository at this point in the history
  • Loading branch information
ochaloup committed Oct 26, 2022
1 parent add01bf commit 9e01a9a
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 38 deletions.
88 changes: 54 additions & 34 deletions governance/program/src/state/proposal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -222,7 +227,7 @@ pub struct ProposalV2 {
impl AccountMaxSize for ProposalV2 {
fn get_max_size(&self) -> Option<usize> {
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)
}
}

Expand Down Expand Up @@ -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
Expand All @@ -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,
} => {
Expand Down Expand Up @@ -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
Expand All @@ -807,14 +810,16 @@ impl ProposalV2 {
}
}
VoteType::MultiChoice {
choice_type: MultiChoiceType::Approval,
max_voter_options: _n,
max_winning_options: _m,
} => {
if choice_count == 0 {
return Err(GovernanceError::InvalidVote.into());
}
}
VoteType::MultiWeightedChoice {
VoteType::MultiChoice {
choice_type: MultiChoiceType::Weighted,
max_voter_options: _n,
max_winning_options: _m,
} => {
Expand Down Expand Up @@ -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());
}
Expand Down Expand Up @@ -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,
};
Expand All @@ -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,
};
Expand Down Expand Up @@ -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,
};
Expand Down Expand Up @@ -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,
};
Expand Down Expand Up @@ -2470,6 +2476,7 @@ mod test {
) {
// Arrange
let vote_type = VoteType::MultiChoice {
choice_type: MultiChoiceType::Approval,
max_voter_options: 3,
max_winning_options: 3,
};
Expand All @@ -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,
};
Expand Down Expand Up @@ -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,
};
Expand All @@ -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,
};
Expand All @@ -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,
};
Expand Down Expand Up @@ -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,
};
Expand Down Expand Up @@ -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,
};
Expand Down Expand Up @@ -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,
};
Expand Down Expand Up @@ -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,
};
Expand All @@ -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,
};
Expand All @@ -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,
};
Expand All @@ -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,
};
Expand All @@ -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,
};
Expand Down Expand Up @@ -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,
};
Expand Down
21 changes: 17 additions & 4 deletions governance/program/tests/use_proposals_with_multiple_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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,
},
Expand All @@ -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,
}
Expand Down Expand Up @@ -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,
},
Expand Down Expand Up @@ -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,
},
Expand Down Expand Up @@ -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,
},
Expand Down Expand Up @@ -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,
},
Expand Down Expand Up @@ -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,
},
Expand Down Expand Up @@ -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,
}
Expand Down Expand Up @@ -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,
},
Expand Down Expand Up @@ -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,
},
Expand Down Expand Up @@ -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,
},
Expand Down Expand Up @@ -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,
},
Expand Down

0 comments on commit 9e01a9a

Please sign in to comment.