Browse Source

Integrate engine module with council

- add governance dependency
- implement ActorOriginValidator for council voting (CouncilOriginValidator)
- change mocks
- add tests
Shamil Gadelshin 5 years ago
parent
commit
db0f440d77

+ 6 - 1
runtime-modules/proposals/codex/Cargo.toml

@@ -109,4 +109,9 @@ rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
 [dev-dependencies.common]
 default_features = false
 package = 'substrate-common-module'
-path = '../../common'
+path = '../../common'
+
+[dev-dependencies.governance]
+default_features = false
+package = 'substrate-governance-module'
+path = '../../governance'

+ 6 - 1
runtime-modules/proposals/codex/src/tests/mock.rs

@@ -103,7 +103,12 @@ impl proposal_engine::Trait for Test {
     type MaxActiveProposalLimit = MaxActiveProposalLimit;
 }
 
-impl membership::origin_validator::ActorOriginValidator<Origin, u64, u64> for () {
+impl governance::council::Trait for Test {
+    type Event = ();
+    type CouncilTermEnded = ();
+}
+
+impl common::origin_validator::ActorOriginValidator<Origin, u64, u64> for () {
     fn ensure_actor_origin(_: Origin, _: u64, _: &'static str) -> Result<u64, &'static str> {
         Ok(1)
     }

+ 5 - 5
runtime-modules/proposals/discussion/Cargo.toml

@@ -75,17 +75,17 @@ default_features = false
 package = 'substrate-membership-module'
 path = '../../membership'
 
+[dependencies.common]
+default_features = false
+package = 'substrate-common-module'
+path = '../../common'
+
 [dev-dependencies.runtime-io]
 default_features = false
 git = 'https://github.com/paritytech/substrate.git'
 package = 'sr-io'
 rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
 
-[dev-dependencies.common]
-default_features = false
-package = 'substrate-common-module'
-path = '../../common'
-
 [dev-dependencies.balances]
 package = 'srml-balances'
 default-features = false

+ 2 - 1
runtime-modules/proposals/discussion/src/lib.rs

@@ -28,7 +28,8 @@ use srml_support::{decl_event, decl_module, decl_storage, ensure, Parameter};
 use srml_support::traits::Get;
 use types::{Post, Thread, ThreadCounter};
 
-use membership::origin_validator::{ActorOriginValidator, MemberId};
+use common::origin_validator::ActorOriginValidator;
+use membership::origin_validator::MemberId;
 
 // TODO: move errors to decl_error macro (after substrate version upgrade)
 

+ 10 - 5
runtime-modules/proposals/engine/Cargo.toml

@@ -88,6 +88,16 @@ default_features = false
 package = 'substrate-membership-module'
 path = '../../membership'
 
+[dependencies.common]
+default_features = false
+package = 'substrate-common-module'
+path = '../../common'
+
+[dependencies.governance]
+default_features = false
+package = 'substrate-governance-module'
+path = '../../governance'
+
 [dev-dependencies]
 mockall = "0.6.0"
 
@@ -96,8 +106,3 @@ default_features = false
 git = 'https://github.com/paritytech/substrate.git'
 package = 'sr-io'
 rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
-
-[dev-dependencies.common]
-default_features = false
-package = 'substrate-common-module'
-path = '../../common'

+ 8 - 2
runtime-modules/proposals/engine/src/lib.rs

@@ -32,6 +32,7 @@ pub use types::{
 pub use types::{DefaultStakeHandlerProvider, StakeHandler, StakeHandlerProvider};
 pub use types::{ProposalCodeDecoder, ProposalExecutable};
 pub use types::{VoteKind, VotersParameters};
+pub use types::CouncilOriginValidator;
 
 mod errors;
 pub(crate) mod types;
@@ -48,11 +49,16 @@ use srml_support::{
 };
 use system::ensure_root;
 
-use membership::origin_validator::{ActorOriginValidator, MemberId};
+use common::origin_validator::ActorOriginValidator;
+use membership::origin_validator::MemberId;
 
 /// Proposals engine trait.
 pub trait Trait:
-    system::Trait + timestamp::Trait + stake::Trait + membership::members::Trait
+    system::Trait
+    + timestamp::Trait
+    + stake::Trait
+    + membership::members::Trait
+    + governance::council::Trait
 {
     /// Engine event type.
     type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;

+ 12 - 2
runtime-modules/proposals/engine/src/tests/mock/mod.rs

@@ -47,11 +47,16 @@ mod membership_mod {
     pub use membership::members::Event;
 }
 
+mod council_mod {
+    pub use governance::council::Event;
+}
+
 impl_outer_event! {
     pub enum TestEvent for Test {
         balances<T>,
         engine<T>,
-         membership_mod<T>,
+        membership_mod<T>,
+        council_mod<T>,
     }
 }
 
@@ -82,6 +87,11 @@ impl common::currency::GovernanceCurrency for Test {
     type Currency = balances::Module<Self>;
 }
 
+impl governance::council::Trait for Test {
+    type Event = TestEvent;
+    type CouncilTermEnded = ();
+}
+
 impl stake::Trait for Test {
     type Currency = Balances;
     type StakePoolId = StakePoolId;
@@ -122,7 +132,7 @@ impl crate::Trait for Test {
     type MaxActiveProposalLimit = MaxActiveProposalLimit;
 }
 
-impl membership::origin_validator::ActorOriginValidator<Origin, u64, u64> for () {
+impl common::origin_validator::ActorOriginValidator<Origin, u64, u64> for () {
     fn ensure_actor_origin(
         origin: Origin,
         _account_id: u64,

+ 1 - 1
runtime-modules/proposals/engine/src/tests/mod.rs

@@ -1,4 +1,4 @@
-mod mock;
+pub(crate) mod mock;
 
 use crate::*;
 use mock::*;

+ 161 - 0
runtime-modules/proposals/engine/src/types/council_origin_validator.rs

@@ -0,0 +1,161 @@
+use rstd::marker::PhantomData;
+
+use common::origin_validator::ActorOriginValidator;
+use membership::origin_validator::{MemberId, MembershipOriginValidator};
+
+/// Default discussion system actor origin validator. Valid for both thread and post authors.
+pub struct CouncilOriginValidator<T> {
+    marker: PhantomData<T>,
+}
+
+impl<T: crate::Trait>
+    ActorOriginValidator<<T as system::Trait>::Origin, MemberId<T>, <T as system::Trait>::AccountId>
+    for CouncilOriginValidator<T>
+{
+    /// Check for valid combination of origin and actor_id. Actor_id should be valid member_id of
+    /// the membership module
+    fn ensure_actor_origin(
+        origin: <T as system::Trait>::Origin,
+        actor_id: MemberId<T>,
+        error: &'static str,
+    ) -> Result<<T as system::Trait>::AccountId, &'static str> {
+        let account_id =
+            <MembershipOriginValidator<T>>::ensure_actor_origin(origin, actor_id, error)?;
+
+        if <governance::council::Module<T>>::is_councilor(&account_id) {
+            return Ok(account_id);
+        }
+
+        Err(error)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::tests::mock::{Test, initial_test_ext};
+    use common::origin_validator::ActorOriginValidator;
+    use membership::members::UserInfo;
+    use crate::CouncilOriginValidator;
+    use system::RawOrigin;
+
+    type Membership = membership::members::Module<Test>;
+    type Council = governance::council::Module<Test>;
+
+    #[test]
+    fn council_origin_validator_fails_with_unregistered_member() {
+        initial_test_ext().execute_with(|| {
+            let origin = RawOrigin::Signed(1);
+            let member_id = 1;
+            let error = "Error";
+
+            let validation_result = CouncilOriginValidator::<Test>::ensure_actor_origin(
+                origin.into(),
+                member_id,
+                error,
+            );
+
+            assert_eq!(validation_result, Err(error));
+        });
+    }
+
+    #[test]
+    fn council_origin_validator_succeeds() {
+        initial_test_ext().execute_with(|| {
+            assert!(Council::set_council(
+                system::RawOrigin::Root.into(),
+                vec![1, 2, 3]
+            ).is_ok());
+
+            let account_id = 1;
+            let origin = RawOrigin::Signed(account_id);
+            let error = "Error";
+            let authority_account_id = 10;
+            Membership::set_screening_authority(RawOrigin::Root.into(), authority_account_id)
+                .unwrap();
+
+            Membership::add_screened_member(
+                RawOrigin::Signed(authority_account_id).into(),
+                account_id,
+                UserInfo {
+                    handle: Some(b"handle".to_vec()),
+                    avatar_uri: None,
+                    about: None,
+                },
+            )
+            .unwrap();
+            let member_id = 0; // newly created member_id
+
+            let validation_result = CouncilOriginValidator::<Test>::ensure_actor_origin(
+                origin.into(),
+                member_id,
+                error,
+            );
+
+            assert_eq!(validation_result, Ok(account_id));
+        });
+    }
+
+    #[test]
+    fn council_origin_validator_fails_with_incompatible_account_id_and_member_id() {
+        initial_test_ext().execute_with(|| {
+            let account_id = 1;
+            let error = "Errorss";
+            let authority_account_id = 10;
+            Membership::set_screening_authority(RawOrigin::Root.into(), authority_account_id)
+                .unwrap();
+
+            Membership::add_screened_member(
+                RawOrigin::Signed(authority_account_id).into(),
+                account_id,
+                UserInfo {
+                    handle: Some(b"handle".to_vec()),
+                    avatar_uri: None,
+                    about: None,
+                },
+            )
+            .unwrap();
+            let member_id = 0; // newly created member_id
+
+            let invalid_account_id = 2;
+            let validation_result = CouncilOriginValidator::<Test>::ensure_actor_origin(
+                RawOrigin::Signed(invalid_account_id).into(),
+                member_id,
+                error,
+            );
+
+            assert_eq!(validation_result, Err(error));
+        });
+    }
+
+    #[test]
+    fn council_origin_validator_fails_with_not_council_account_id() {
+        initial_test_ext().execute_with(|| {
+            let account_id = 1;
+            let origin = RawOrigin::Signed(account_id);
+            let error = "Error";
+            let authority_account_id = 10;
+            Membership::set_screening_authority(RawOrigin::Root.into(), authority_account_id)
+                .unwrap();
+
+            Membership::add_screened_member(
+                RawOrigin::Signed(authority_account_id).into(),
+                account_id,
+                UserInfo {
+                    handle: Some(b"handle".to_vec()),
+                    avatar_uri: None,
+                    about: None,
+                },
+            )
+                .unwrap();
+            let member_id = 0; // newly created member_id
+
+            let validation_result = CouncilOriginValidator::<Test>::ensure_actor_origin(
+                origin.into(),
+                member_id,
+                error,
+            );
+
+            assert_eq!(validation_result, Err(error));
+        });
+    }
+}

+ 3 - 0
runtime-modules/proposals/engine/src/types/mod.rs

@@ -11,9 +11,12 @@ use serde::{Deserialize, Serialize};
 use srml_support::dispatch;
 use srml_support::traits::Currency;
 
+mod council_origin_validator;
 mod proposal_statuses;
 mod stakes;
 
+pub use council_origin_validator::CouncilOriginValidator;
+
 pub use proposal_statuses::{
     ApprovedProposalStatus, FinalizationData, ProposalDecisionStatus, ProposalStatus,
 };