council_origin_validator.rs 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. #![warn(missing_docs)]
  2. use sp_std::marker::PhantomData;
  3. use common::origin::ActorOriginValidator;
  4. use proposals_engine::VotersParameters;
  5. use super::{MemberId, MembershipOriginValidator};
  6. /// Handles work with the council.
  7. /// Provides implementations for ActorOriginValidator and VotersParameters.
  8. pub struct CouncilManager<T> {
  9. marker: PhantomData<T>,
  10. }
  11. impl<T: governance::council::Trait + membership::Trait>
  12. ActorOriginValidator<<T as system::Trait>::Origin, MemberId<T>, <T as system::Trait>::AccountId>
  13. for CouncilManager<T>
  14. {
  15. /// Check for valid combination of origin and actor_id. Actor_id should be valid member_id of
  16. /// the membership module
  17. fn ensure_actor_origin(
  18. origin: <T as system::Trait>::Origin,
  19. actor_id: MemberId<T>,
  20. ) -> Result<<T as system::Trait>::AccountId, &'static str> {
  21. let account_id = <MembershipOriginValidator<T>>::ensure_actor_origin(origin, actor_id)?;
  22. if <governance::council::Module<T>>::is_councilor(&account_id) {
  23. return Ok(account_id);
  24. }
  25. Err("Council validation failed: account id doesn't belong to a council member")
  26. }
  27. }
  28. impl<T: governance::council::Trait> VotersParameters for CouncilManager<T> {
  29. /// Implement total_voters_count() as council size
  30. fn total_voters_count() -> u32 {
  31. <governance::council::Module<T>>::active_council().len() as u32
  32. }
  33. }
  34. #[cfg(test)]
  35. mod tests {
  36. use super::CouncilManager;
  37. use crate::Runtime;
  38. use common::origin::ActorOriginValidator;
  39. use proposals_engine::VotersParameters;
  40. use sp_runtime::AccountId32;
  41. use system::RawOrigin;
  42. type Council = governance::council::Module<Runtime>;
  43. fn initial_test_ext() -> sp_io::TestExternalities {
  44. let t = system::GenesisConfig::default()
  45. .build_storage::<Runtime>()
  46. .unwrap();
  47. t.into()
  48. }
  49. type Membership = membership::Module<Runtime>;
  50. #[test]
  51. fn council_origin_validator_fails_with_unregistered_member() {
  52. initial_test_ext().execute_with(|| {
  53. let origin = RawOrigin::Signed(AccountId32::default());
  54. let member_id = 1;
  55. let error = "Membership validation failed: cannot find a profile for a member";
  56. let validation_result =
  57. CouncilManager::<Runtime>::ensure_actor_origin(origin.into(), member_id);
  58. assert_eq!(validation_result, Err(error));
  59. });
  60. }
  61. #[test]
  62. fn council_origin_validator_succeeds() {
  63. initial_test_ext().execute_with(|| {
  64. let councilor1 = AccountId32::default();
  65. let councilor2: [u8; 32] = [2; 32];
  66. let councilor3: [u8; 32] = [3; 32];
  67. assert!(Council::set_council(
  68. system::RawOrigin::Root.into(),
  69. vec![councilor1, councilor2.into(), councilor3.into()]
  70. )
  71. .is_ok());
  72. let account_id = AccountId32::default();
  73. let origin = RawOrigin::Signed(account_id.clone());
  74. let authority_account_id = AccountId32::default();
  75. Membership::set_screening_authority(
  76. RawOrigin::Root.into(),
  77. authority_account_id.clone(),
  78. )
  79. .unwrap();
  80. Membership::add_screened_member(
  81. RawOrigin::Signed(authority_account_id).into(),
  82. account_id.clone(),
  83. Some(b"handle".to_vec()),
  84. None,
  85. None,
  86. )
  87. .unwrap();
  88. let member_id = 0; // newly created member_id
  89. let validation_result =
  90. CouncilManager::<Runtime>::ensure_actor_origin(origin.into(), member_id);
  91. assert_eq!(validation_result, Ok(account_id));
  92. });
  93. }
  94. #[test]
  95. fn council_origin_validator_fails_with_incompatible_account_id_and_member_id() {
  96. initial_test_ext().execute_with(|| {
  97. let account_id = AccountId32::default();
  98. let error =
  99. "Membership validation failed: given account doesn't match with profile accounts";
  100. let authority_account_id = AccountId32::default();
  101. Membership::set_screening_authority(
  102. RawOrigin::Root.into(),
  103. authority_account_id.clone(),
  104. )
  105. .unwrap();
  106. Membership::add_screened_member(
  107. RawOrigin::Signed(authority_account_id).into(),
  108. account_id.clone(),
  109. Some(b"handle".to_vec()),
  110. None,
  111. None,
  112. )
  113. .unwrap();
  114. let member_id = 0; // newly created member_id
  115. let invalid_account_id: [u8; 32] = [2; 32];
  116. let validation_result = CouncilManager::<Runtime>::ensure_actor_origin(
  117. RawOrigin::Signed(invalid_account_id.into()).into(),
  118. member_id,
  119. );
  120. assert_eq!(validation_result, Err(error));
  121. });
  122. }
  123. #[test]
  124. fn council_origin_validator_fails_with_not_council_account_id() {
  125. initial_test_ext().execute_with(|| {
  126. let account_id = AccountId32::default();
  127. let origin = RawOrigin::Signed(account_id.clone());
  128. let error = "Council validation failed: account id doesn't belong to a council member";
  129. let authority_account_id = AccountId32::default();
  130. Membership::set_screening_authority(
  131. RawOrigin::Root.into(),
  132. authority_account_id.clone(),
  133. )
  134. .unwrap();
  135. Membership::add_screened_member(
  136. RawOrigin::Signed(authority_account_id).into(),
  137. account_id,
  138. Some(b"handle".to_vec()),
  139. None,
  140. None,
  141. )
  142. .unwrap();
  143. let member_id = 0; // newly created member_id
  144. let validation_result =
  145. CouncilManager::<Runtime>::ensure_actor_origin(origin.into(), member_id);
  146. assert_eq!(validation_result, Err(error));
  147. });
  148. }
  149. #[test]
  150. fn council_size_calculation_aka_total_voters_count_succeeds() {
  151. initial_test_ext().execute_with(|| {
  152. let councilor1 = AccountId32::default();
  153. let councilor2: [u8; 32] = [2; 32];
  154. let councilor3: [u8; 32] = [3; 32];
  155. let councilor4: [u8; 32] = [4; 32];
  156. assert!(Council::set_council(
  157. system::RawOrigin::Root.into(),
  158. vec![
  159. councilor1,
  160. councilor2.into(),
  161. councilor3.into(),
  162. councilor4.into()
  163. ]
  164. )
  165. .is_ok());
  166. assert_eq!(CouncilManager::<Runtime>::total_voters_count(), 4)
  167. });
  168. }
  169. }