Browse Source

Merge branch 'development' into wg-fix-mint-config

Mokhtar Naamani 5 years ago
parent
commit
c9585689ff
8 changed files with 204 additions and 96 deletions
  1. 3 3
      Cargo.lock
  2. 1 1
      Cargo.toml
  3. 1 1
      README.md
  4. 72 0
      banner_new.svg
  5. 71 60
      src/content_working_group/lib.rs
  6. 10 28
      src/content_working_group/tests.rs
  7. 41 0
      src/membership/members.rs
  8. 5 3
      src/memo.rs

+ 3 - 3
Cargo.lock

@@ -1002,7 +1002,7 @@ dependencies = [
  "substrate-client 2.0.0 (git+https://github.com/paritytech/substrate.git?rev=0e3001a1ad6fa3d1ba7da7342a8d0d3b3facb2f3)",
  "substrate-consensus-babe-primitives 2.0.0 (git+https://github.com/paritytech/substrate.git?rev=0e3001a1ad6fa3d1ba7da7342a8d0d3b3facb2f3)",
  "substrate-forum-module 1.1.0 (git+https://github.com/Joystream/substrate-forum-module?rev=4bdeadaadfcca1fd6e822c520f429d4beacc4c8a)",
- "substrate-hiring-module 1.0.0 (git+https://github.com/Joystream/substrate-hiring-module?rev=30ac830aecb2e61fb943a8c4327bcf52c289e383)",
+ "substrate-hiring-module 1.0.0 (git+https://github.com/Joystream/substrate-hiring-module?rev=b400e3008c98989da7b310c71b7d6d4e4dca34e4)",
  "substrate-offchain-primitives 2.0.0 (git+https://github.com/paritytech/substrate.git?rev=0e3001a1ad6fa3d1ba7da7342a8d0d3b3facb2f3)",
  "substrate-primitives 2.0.0 (git+https://github.com/paritytech/substrate.git?rev=0e3001a1ad6fa3d1ba7da7342a8d0d3b3facb2f3)",
  "substrate-recurring-reward-module 1.0.0 (git+https://github.com/Joystream/substrate-recurring-reward-module?rev=417f7bb5b82ae50f02716ac4eefa2fc7952e0f61)",
@@ -3208,7 +3208,7 @@ dependencies = [
 [[package]]
 name = "substrate-hiring-module"
 version = "1.0.0"
-source = "git+https://github.com/Joystream/substrate-hiring-module?rev=30ac830aecb2e61fb943a8c4327bcf52c289e383#30ac830aecb2e61fb943a8c4327bcf52c289e383"
+source = "git+https://github.com/Joystream/substrate-hiring-module?rev=b400e3008c98989da7b310c71b7d6d4e4dca34e4#b400e3008c98989da7b310c71b7d6d4e4dca34e4"
 dependencies = [
  "hex-literal 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  "parity-scale-codec 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -4491,7 +4491,7 @@ dependencies = [
 "checksum substrate-finality-grandpa-primitives 2.0.0 (git+https://github.com/paritytech/substrate.git?rev=0e3001a1ad6fa3d1ba7da7342a8d0d3b3facb2f3)" = "<none>"
 "checksum substrate-forum-module 1.1.0 (git+https://github.com/Joystream/substrate-forum-module?rev=4bdeadaadfcca1fd6e822c520f429d4beacc4c8a)" = "<none>"
 "checksum substrate-header-metadata 2.0.0 (git+https://github.com/paritytech/substrate.git?rev=0e3001a1ad6fa3d1ba7da7342a8d0d3b3facb2f3)" = "<none>"
-"checksum substrate-hiring-module 1.0.0 (git+https://github.com/Joystream/substrate-hiring-module?rev=30ac830aecb2e61fb943a8c4327bcf52c289e383)" = "<none>"
+"checksum substrate-hiring-module 1.0.0 (git+https://github.com/Joystream/substrate-hiring-module?rev=b400e3008c98989da7b310c71b7d6d4e4dca34e4)" = "<none>"
 "checksum substrate-inherents 2.0.0 (git+https://github.com/paritytech/substrate.git?rev=0e3001a1ad6fa3d1ba7da7342a8d0d3b3facb2f3)" = "<none>"
 "checksum substrate-keyring 2.0.0 (git+https://github.com/paritytech/substrate.git?rev=0e3001a1ad6fa3d1ba7da7342a8d0d3b3facb2f3)" = "<none>"
 "checksum substrate-offchain-primitives 2.0.0 (git+https://github.com/paritytech/substrate.git?rev=0e3001a1ad6fa3d1ba7da7342a8d0d3b3facb2f3)" = "<none>"

+ 1 - 1
Cargo.toml

@@ -284,7 +284,7 @@ rev = '0516efe9230da112bc095e28f34a3715c2e03ca8'
 default_features = false
 git = 'https://github.com/Joystream/substrate-hiring-module'
 package = 'substrate-hiring-module'
-rev = '30ac830aecb2e61fb943a8c4327bcf52c289e383'
+rev = 'b400e3008c98989da7b310c71b7d6d4e4dca34e4'
 
 [dependencies.versioned_store]
 default_features = false

+ 1 - 1
README.md

@@ -1,4 +1,4 @@
-![Joystream Runtime](./banner.svg)
+![Joystream Runtime](./banner_new.svg)
 
 # Joystream Runtime
 

File diff suppressed because it is too large
+ 72 - 0
banner_new.svg


+ 71 - 60
src/content_working_group/lib.rs

@@ -86,6 +86,9 @@ pub type StakeId<T> = <T as stake::Trait>::StakeId;
 /// Type of permissions module prinicipal identifiers
 pub type PrincipalId<T> = <T as versioned_store_permissions::Trait>::PrincipalId;
 
+// Workaround for BTreeSet type
+pub type CuratorApplicationIdSet<T> = BTreeSet<CuratorApplicationId<T>>;
+
 /*
  * MOVE ALL OF THESE OUT TO COMMON LATER
  */
@@ -216,6 +219,8 @@ pub static MSG_APPLY_ON_CURATOR_OPENING_UNSIGNED_ORIGIN: &str = "Unsigned origin
 pub static MSG_APPLY_ON_CURATOR_OPENING_MEMBER_ID_INVALID: &str = "Member id is invalid";
 pub static MSG_APPLY_ON_CURATOR_OPENING_SIGNER_NOT_CONTROLLER_ACCOUNT: &str =
     "Signer does not match controller account";
+static MSG_ORIGIN_IS_NIETHER_MEMBER_CONTROLLER_OR_ROOT: &str =
+    "Origin must be controller or root account of member";
 
 /// The exit stage of a lead involvement in the working group.
 #[derive(Encode, Decode, Debug, Clone, PartialEq)]
@@ -1435,7 +1440,7 @@ decl_module! {
         pub fn fill_curator_opening(
             origin,
             curator_opening_id: CuratorOpeningId<T>,
-            successful_curator_application_ids: BTreeSet<CuratorApplicationId<T>>
+            successful_curator_application_ids: CuratorApplicationIdSet<T>,
         ) {
             // Ensure lead is set and is origin signer
             let (lead_id, _lead) = Self::ensure_origin_is_set_lead(origin)?;
@@ -1655,15 +1660,22 @@ decl_module! {
             member_id: T::MemberId,
             curator_opening_id: CuratorOpeningId<T>,
             role_account: T::AccountId,
-            source_account: T::AccountId,
             opt_role_stake_balance: Option<BalanceOf<T>>,
             opt_application_stake_balance: Option<BalanceOf<T>>,
             human_readable_text: Vec<u8>
         ) {
-            // Ensure that origin is signed by member with given id.
-            ensure_on_wrapped_error!(
-                members::Module::<T>::ensure_member_controller_account_signed(origin, &member_id)
-            )?;
+            // Ensure origin which will server as the source account for staked funds is signed
+            let source_account = ensure_signed(origin)?;
+
+            // In absense of a more general key delegation system which allows an account with some funds to
+            // grant another account permission to stake from its funds, the origin of this call must have the funds
+            // and cannot specify another arbitrary account as the source account.
+            // Ensure the source_account is either the controller or root account of member with given id
+            ensure!(
+                members::Module::<T>::ensure_member_controller_account(&source_account, &member_id).is_ok() ||
+                members::Module::<T>::ensure_member_root_account(&source_account, &member_id).is_ok(),
+                MSG_ORIGIN_IS_NIETHER_MEMBER_CONTROLLER_OR_ROOT
+            );
 
             // Ensure curator opening exists
             let (curator_opening, _opening) = Self::ensure_curator_opening_exists(&curator_opening_id)?;
@@ -1895,60 +1907,6 @@ decl_module! {
             Self::deposit_event(RawEvent::LeadUnset(lead_id));
         }
 
-        /// The stake, with the given id, was unstaked.
-        pub fn unstaked(
-            origin,
-            stake_id: StakeId<T>
-        ) {
-            // Ensure its a runtime root origin
-            ensure_root(origin)?;
-
-            // Ensure its an unstaker in this group
-            let unstaker = Self::ensure_unstaker_exists(&stake_id)?;
-
-            // Get curator doing the unstaking,
-            // urrently the only possible unstaker in this module.
-            let curator_id =
-                if let WorkingGroupUnstaker::Curator(curator_id) = unstaker {
-                    curator_id
-                } else {
-                    panic!("Should not be possible, only curators unstake in this module currently");
-                };
-
-            // Grab curator from id, unwrap, because this curator _must_ exist.
-            let unstaking_curator = Self::ensure_curator_exists(&curator_id).unwrap();
-
-            //
-            // == MUTATION SAFE ==
-            //
-
-            // Update stage of curator
-            let curator_exit_summary =
-                if let CuratorRoleStage::Unstaking(summary) = unstaking_curator.stage {
-                    summary
-                } else {
-                    panic!("Curator must be in unstaking stage");
-                };
-
-            let new_curator = Curator{
-                stage: CuratorRoleStage::Exited(curator_exit_summary.clone()),
-                ..unstaking_curator
-            };
-
-            CuratorById::<T>::insert(curator_id, new_curator);
-
-            // Remove from unstaker
-            UnstakerByStakeId::<T>::remove(stake_id);
-
-            // Trigger event
-            let event = match curator_exit_summary.origin {
-                CuratorExitInitiationOrigin::Lead => RawEvent::TerminatedCurator(curator_id),
-                CuratorExitInitiationOrigin::Curator => RawEvent::CuratorExited(curator_id),
-            };
-
-            Self::deposit_event(event);
-        }
-
         /// Add an opening for a curator role.
         pub fn set_channel_creation_enabled(origin, enabled: bool)  {
 
@@ -2690,4 +2648,57 @@ impl<T: Trait> Module<T> {
 
         Ok(())
     }
+
+    /// The stake, with the given id, was unstaked. Infalliable. Has no side effects if stake_id is not relevant
+    /// to this module.
+    pub fn unstaked(stake_id: StakeId<T>) {
+        // Ignore if unstaked doesn't exist
+        if !<UnstakerByStakeId<T>>::exists(stake_id) {
+            return;
+        }
+
+        // Unstaker must be in this group
+        let unstaker = Self::ensure_unstaker_exists(&stake_id).unwrap();
+
+        // Get curator doing the unstaking,
+        // urrently the only possible unstaker in this module.
+        let curator_id = if let WorkingGroupUnstaker::Curator(curator_id) = unstaker {
+            curator_id
+        } else {
+            panic!("Should not be possible, only curators unstake in this module currently.");
+        };
+
+        // Grab curator from id, unwrap, because this curator _must_ exist.
+        let unstaking_curator = Self::ensure_curator_exists(&curator_id).unwrap();
+
+        //
+        // == MUTATION SAFE ==
+        //
+
+        // Update stage of curator
+        let curator_exit_summary =
+            if let CuratorRoleStage::Unstaking(summary) = unstaking_curator.stage {
+                summary
+            } else {
+                panic!("Curator must be in unstaking stage.");
+            };
+
+        let new_curator = Curator {
+            stage: CuratorRoleStage::Exited(curator_exit_summary.clone()),
+            ..unstaking_curator
+        };
+
+        CuratorById::<T>::insert(curator_id, new_curator);
+
+        // Remove from unstaker
+        UnstakerByStakeId::<T>::remove(stake_id);
+
+        // Trigger event
+        let event = match curator_exit_summary.origin {
+            CuratorExitInitiationOrigin::Lead => RawEvent::TerminatedCurator(curator_id),
+            CuratorExitInitiationOrigin::Curator => RawEvent::CuratorExited(curator_id),
+        };
+
+        Self::deposit_event(event);
+    }
 }

+ 10 - 28
src/content_working_group/tests.rs

@@ -261,7 +261,6 @@ fn update_channel_as_curation_actor_success() {
                 2222,
                 to_vec("yoyoyo0"), // generate_valid_length_buffer(&ChannelHandleConstraint::get()),
                 2222 * 2,
-                2222 * 3,
                 generate_valid_length_buffer(&CuratorApplicationHumanReadableText::get()),
             );
 
@@ -424,7 +423,6 @@ fn begin_curator_applicant_review_success() {
                 333,
                 to_vec("CuratorWannabe"),
                 11111,
-                91000,
                 generate_valid_length_buffer(&CuratorApplicationHumanReadableText::get()),
             );
 
@@ -470,7 +468,6 @@ fn fill_curator_opening_success() {
                         2222,
                         to_vec("yoyoyo0"), // generate_valid_length_buffer(&ChannelHandleConstraint::get()),
                         2222 * 2,
-                        2222 * 3,
                         generate_valid_length_buffer(&CuratorApplicationHumanReadableText::get()),
                     ),
                     true,
@@ -480,7 +477,6 @@ fn fill_curator_opening_success() {
                         3333,
                         to_vec("yoyoyo1"), // generate_valid_length_buffer(&ChannelHandleConstraint::get()),
                         3333 * 2,
-                        3333 * 3,
                         generate_valid_length_buffer(&CuratorApplicationHumanReadableText::get()),
                     ),
                     true,
@@ -490,7 +486,6 @@ fn fill_curator_opening_success() {
                         5555,
                         to_vec("yoyoyo2"), // generate_valid_length_buffer(&ChannelHandleConstraint::get()),
                         5555 * 2,
-                        5555 * 3,
                         generate_valid_length_buffer(&CuratorApplicationHumanReadableText::get()),
                     ),
                     false,
@@ -500,7 +495,6 @@ fn fill_curator_opening_success() {
                         6666,
                         to_vec("yoyoyo3"), // generate_valid_length_buffer(&ChannelHandleConstraint::get()),
                         6666 * 2,
-                        6666 * 3,
                         generate_valid_length_buffer(&CuratorApplicationHumanReadableText::get()),
                     ),
                     true,
@@ -536,7 +530,6 @@ fn withdraw_curator_application_success() {
                 curator_applicant_root_and_controller_account,
                 to_vec("CuratorWannabe"),
                 curator_applicant_role_account,
-                91000,
                 human_readable_text,
             );
 
@@ -582,7 +575,6 @@ fn terminate_curator_application_success() {
                 333,
                 to_vec("CuratorWannabe"),
                 11111,
-                91000,
                 generate_valid_length_buffer(&CuratorApplicationHumanReadableText::get()),
             );
 
@@ -643,7 +635,7 @@ fn apply_on_curator_opening_success() {
                 .amount;
             let total_balance = role_stake_balance + application_stake_balance;
 
-            let source_account = 918111;
+            let source_account = curator_applicant_root_and_controller_account;
 
             // Credit staking source account
             let _ = balances::Module::<Test>::deposit_creating(&source_account, total_balance);
@@ -667,7 +659,6 @@ fn apply_on_curator_opening_success() {
                     curator_applicant_member_id,
                     normal_opening_constructed.curator_opening_id,
                     curator_applicant_role_account,
-                    source_account,
                     Some(role_stake_balance),
                     Some(application_stake_balance),
                     human_readable_text
@@ -1168,13 +1159,12 @@ fn unset_lead_success() {
 }
 
 struct UnstakedFixture {
-    pub origin: Origin,
     pub stake_id: StakeId<Test>,
 }
 
 impl UnstakedFixture {
-    fn call(&self) -> Result<(), &'static str> {
-        ContentWorkingGroup::unstaked(self.origin.clone(), self.stake_id)
+    fn call(&self) {
+        ContentWorkingGroup::unstaked(self.stake_id);
     }
 
     pub fn call_and_assert_success(&self) {
@@ -1195,9 +1185,7 @@ impl UnstakedFixture {
                 panic!("Curator not unstaking")
             };
 
-        let call_result = self.call();
-
-        assert_eq!(call_result, Ok(()));
+        self.call();
 
         let expected_curator = Curator {
             stage: CuratorRoleStage::Exited(original_exit_summary),
@@ -1217,11 +1205,11 @@ impl UnstakedFixture {
         assert!(!UnstakerByStakeId::<Test>::exists(self.stake_id));
     }
 
-    pub fn call_and_assert_failed_result(&self, error_message: &'static str) {
-        let call_result = self.call();
+    // pub fn call_and_assert_failed_result(&self, error_message: &'static str) {
+    //     let call_result = self.call();
 
-        assert_eq!(call_result, Err(error_message));
-    }
+    //     assert_eq!(call_result, Err(error_message));
+    // }
 }
 
 #[test]
@@ -1244,7 +1232,6 @@ fn unstaked_curator_success() {
                 .stake_id;
 
             UnstakedFixture {
-                origin: Origin::system(system::RawOrigin::Root),
                 stake_id: curator_role_stake_id,
             }
             .call_and_assert_success();
@@ -1269,7 +1256,6 @@ fn make_generic_add_member_params() -> AddMemberAndApplyOnOpeningParams {
         2222,
         to_vec("yoyoyo0"), // generate_valid_length_buffer(&ChannelHandleConstraint::get()),
         2222 * 2,
-        2222 * 3,
         generate_valid_length_buffer(&CuratorApplicationHumanReadableText::get()),
     )
 }
@@ -1364,7 +1350,6 @@ pub struct AddMemberAndApplyOnOpeningParams {
     pub curator_applicant_root_and_controller_account: <Test as system::Trait>::AccountId,
     pub handle: Vec<u8>,
     pub curator_applicant_role_account: <Test as system::Trait>::AccountId,
-    pub source_account: <Test as system::Trait>::AccountId,
     pub human_readable_text: Vec<u8>,
 }
 
@@ -1373,14 +1358,12 @@ impl AddMemberAndApplyOnOpeningParams {
         curator_applicant_root_and_controller_account: <Test as system::Trait>::AccountId,
         handle: Vec<u8>,
         curator_applicant_role_account: <Test as system::Trait>::AccountId,
-        source_account: <Test as system::Trait>::AccountId,
         human_readable_text: Vec<u8>,
     ) -> Self {
         Self {
             curator_applicant_root_and_controller_account,
             handle,
             curator_applicant_role_account,
-            source_account,
             human_readable_text,
         }
     }
@@ -1399,7 +1382,6 @@ fn add_members_and_apply_on_opening(
                 params.curator_applicant_root_and_controller_account,
                 params.handle,
                 params.curator_applicant_role_account,
-                params.source_account,
                 params.human_readable_text,
             )
         })
@@ -1417,7 +1399,6 @@ fn add_member_and_apply_on_opening(
     curator_applicant_root_and_controller_account: <Test as system::Trait>::AccountId,
     handle: Vec<u8>,
     curator_applicant_role_account: <Test as system::Trait>::AccountId,
-    source_account: <Test as system::Trait>::AccountId,
     human_readable_text: Vec<u8>,
 ) -> NewMemberAppliedResult {
     // Make membership
@@ -1441,6 +1422,8 @@ fn add_member_and_apply_on_opening(
 
     let total_balance = role_stake_balance + application_stake_balance;
 
+    let source_account = curator_applicant_root_and_controller_account;
+
     // Credit staking source account if required
     if total_balance > 0 {
         let _ = balances::Module::<Test>::deposit_creating(&source_account, total_balance);
@@ -1462,7 +1445,6 @@ fn add_member_and_apply_on_opening(
             curator_applicant_member_id,
             curator_opening_id,
             curator_applicant_role_account,
-            source_account,
             Some(role_stake_balance),
             Some(application_stake_balance),
             human_readable_text

+ 41 - 0
src/membership/members.rs

@@ -395,6 +395,15 @@ pub enum MemberControllerAccountDidNotSign {
     SignerControllerAccountMismatch,
 }
 
+pub enum MemberControllerAccountMismatch {
+    MemberIdInvalid,
+    SignerControllerAccountMismatch,
+}
+pub enum MemberRootAccountMismatch {
+    MemberIdInvalid,
+    SignerRootAccountMismatch,
+}
+
 impl<T: Trait> Module<T> {
     /// Provided that the memberid exists return its profile. Returns error otherwise.
     pub fn ensure_profile(id: T::MemberId) -> Result<Profile<T>, &'static str> {
@@ -594,6 +603,38 @@ impl<T: Trait> Module<T> {
         Ok(signer_account)
     }
 
+    pub fn ensure_member_controller_account(
+        signer_account: &T::AccountId,
+        member_id: &T::MemberId,
+    ) -> Result<(), MemberControllerAccountMismatch> {
+        // Ensure member exists
+        let profile = Self::ensure_profile(member_id.clone())
+            .map_err(|_| MemberControllerAccountMismatch::MemberIdInvalid)?;
+
+        ensure!(
+            profile.controller_account == *signer_account,
+            MemberControllerAccountMismatch::SignerControllerAccountMismatch
+        );
+
+        Ok(())
+    }
+
+    pub fn ensure_member_root_account(
+        signer_account: &T::AccountId,
+        member_id: &T::MemberId,
+    ) -> Result<(), MemberRootAccountMismatch> {
+        // Ensure member exists
+        let profile = Self::ensure_profile(member_id.clone())
+            .map_err(|_| MemberRootAccountMismatch::MemberIdInvalid)?;
+
+        ensure!(
+            profile.root_account == *signer_account,
+            MemberRootAccountMismatch::SignerRootAccountMismatch
+        );
+
+        Ok(())
+    }
+
     // policy across all roles is:
     // members can only occupy a role at most once at a time
     // members can enter any role

+ 5 - 3
src/memo.rs

@@ -9,9 +9,11 @@ pub trait Trait: system::Trait + GovernanceCurrency {
     type Event: From<Event<Self>> + Into<<Self as system::Trait>::Event>;
 }
 
+pub type MemoText = Vec<u8>;
+
 decl_storage! {
     trait Store for Module<T: Trait> as Memo {
-        Memo get(memo) : map T::AccountId => Vec<u8>;
+        Memo get(memo) : map T::AccountId => MemoText;
         MaxMemoLength get(max_memo_length) : u32 = 4096;
     }
 }
@@ -26,13 +28,13 @@ decl_module! {
     pub struct Module<T: Trait> for enum Call where origin: T::Origin {
         fn deposit_event() = default;
 
-        fn update_memo(origin, memo: Vec<u8>) {
+        fn update_memo(origin, memo: MemoText) {
             let sender = ensure_signed(origin)?;
 
             ensure!(!T::Currency::total_balance(&sender).is_zero(), "account must have a balance");
             ensure!(memo.len() as u32 <= Self::max_memo_length(), "memo too long");
 
-            <Memo<T>>::insert(sender.clone(), memo);
+            <Memo<T>>::insert(&sender, memo);
             Self::deposit_event(RawEvent::MemoUpdated(sender));
         }
     }

Some files were not shown because too many files changed in this diff