Browse Source

Modifey working group module to support leader operations.

Changes:
- modify recurring rewards module - make fields public to support testing
- add RequireSignedOrigin to the working group module errors
- change update_reward_amount authorization
- change decrease_stake authorization
- add tests
Shamil Gadelshin 4 years ago
parent
commit
11e92d7894

+ 3 - 3
runtime-modules/recurring-reward/src/lib.rs

@@ -94,10 +94,10 @@ pub struct RewardRelationship<AccountId, Balance, BlockNumber, MintId, Recipient
     mint_id: MintId,
 
     /// Destination account for reward
-    account: AccountId,
+    pub account: AccountId,
 
     /// The payout amount at the next payout
-    amount_per_payout: Balance,
+    pub amount_per_payout: Balance,
 
     /// When set, identifies block when next payout should be processed,
     /// otherwise there is no pending payout
@@ -146,7 +146,7 @@ decl_storage! {
 
         RecipientsCreated get(recipients_created): T::RecipientId;
 
-        RewardRelationships get(reward_relationships): linked_map T::RewardRelationshipId => RewardRelationship<T::AccountId, BalanceOf<T>, T::BlockNumber, T::MintId, T::RecipientId>;
+        pub RewardRelationships get(reward_relationships): linked_map T::RewardRelationshipId => RewardRelationship<T::AccountId, BalanceOf<T>, T::BlockNumber, T::MintId, T::RecipientId>;
 
         RewardRelationshipsCreated get(reward_relationships_created): T::RewardRelationshipId;
     }

+ 4 - 0
runtime-modules/working-group/src/errors.rs

@@ -241,6 +241,9 @@ decl_error! {
 
         /// Require root origin in extrinsics.
         RequireRootOrigin,
+
+        /// Require signed origin in extrinsics.
+        RequireSignedOrigin,
     }
 }
 
@@ -249,6 +252,7 @@ impl From<system::Error> for Error {
         match error {
             system::Error::Other(msg) => Error::Other(msg),
             system::Error::RequireRootOrigin => Error::RequireRootOrigin,
+            system::Error::RequireSignedOrigin => Error::RequireSignedOrigin,
             _ => Error::Other(error.into()),
         }
     }

+ 4 - 6
runtime-modules/working-group/src/lib.rs

@@ -41,9 +41,6 @@
 // Do not delete! Cannot be uncommented by default, because of Parity decl_module! issue.
 //#![warn(missing_docs)]
 
-// TODO: slash_stake for a leader
-// TODO: decrease_stake for a leader
-// TODO: increase_stake for a leader
 // TODO: comments
 
 #[cfg(test)]
@@ -423,8 +420,8 @@ decl_module! {
             worker_id: WorkerId<T>,
             new_amount: BalanceOfMint<T>
         ) {
-            // Ensure lead is set and is origin signer
-            Self::ensure_origin_is_active_leader(origin)?;
+            // Ensure lead is set and is origin signer or it is the council.
+            Self::ensure_origin_for_leader(origin, worker_id)?;
 
             // Ensuring worker actually exists
             let worker = Self::ensure_worker_exists(&worker_id)?;
@@ -959,7 +956,8 @@ decl_module! {
         /// Decreases the worker/lead stake and returns the remainder to the worker role_account,
         /// demands a leader origin. Can be decreased to zero, no actions on zero stake.
         pub fn decrease_stake(origin, worker_id: WorkerId<T>, balance: BalanceOf<T>) {
-            Self::ensure_origin_is_active_leader(origin)?;
+            // Ensure lead is set or it is the council terminating the leader.
+            Self::ensure_origin_for_leader(origin, worker_id)?;
 
             let worker = Self::ensure_worker_exists(&worker_id)?;
 

+ 50 - 17
runtime-modules/working-group/src/tests/fixtures.rs

@@ -165,7 +165,7 @@ impl UpdateWorkerRewardAmountFixture {
     pub fn default_for_worker_id(worker_id: u64) -> Self {
         Self {
             worker_id,
-            amount: 100,
+            amount: 120,
             origin: RawOrigin::Signed(1),
         }
     }
@@ -174,14 +174,22 @@ impl UpdateWorkerRewardAmountFixture {
     }
 
     pub fn call_and_assert(&self, expected_result: Result<(), Error>) {
-        assert_eq!(
-            TestWorkingGroup::update_reward_amount(
-                self.origin.clone().into(),
-                self.worker_id,
-                self.amount
-            ),
-            expected_result
+        let actual_result = TestWorkingGroup::update_reward_amount(
+            self.origin.clone().into(),
+            self.worker_id,
+            self.amount,
         );
+
+        assert_eq!(actual_result.clone(), expected_result);
+
+        if actual_result.is_ok() {
+            let worker = TestWorkingGroup::worker_by_id(self.worker_id);
+            let relationship_id = worker.reward_relationship.unwrap();
+
+            let relationship = recurringrewards::RewardRelationships::<Test>::get(relationship_id);
+
+            assert_eq!(relationship.amount_per_payout, self.amount);
+        }
     }
 }
 pub struct UpdateWorkerRewardAccountFixture {
@@ -203,14 +211,22 @@ impl UpdateWorkerRewardAccountFixture {
     }
 
     pub fn call_and_assert(&self, expected_result: Result<(), Error>) {
-        assert_eq!(
-            TestWorkingGroup::update_reward_account(
-                self.origin.clone().into(),
-                self.worker_id,
-                self.new_reward_account_id
-            ),
-            expected_result
+        let actual_result = TestWorkingGroup::update_reward_account(
+            self.origin.clone().into(),
+            self.worker_id,
+            self.new_reward_account_id,
         );
+
+        assert_eq!(actual_result.clone(), expected_result);
+
+        if actual_result.is_ok() {
+            let worker = TestWorkingGroup::worker_by_id(self.worker_id);
+            let relationship_id = worker.reward_relationship.unwrap();
+
+            let relationship = recurringrewards::RewardRelationships::<Test>::get(relationship_id);
+
+            assert_eq!(relationship.account, self.new_reward_account_id);
+        }
     }
 }
 
@@ -611,20 +627,37 @@ impl SetLeadFixture {
 
 pub struct HireLeadFixture {
     setup_environment: bool,
+    stake: Option<u64>,
+    reward_policy: Option<RewardPolicy<u64, u64>>,
 }
 
 impl Default for HireLeadFixture {
     fn default() -> Self {
         Self {
             setup_environment: true,
+            stake: None,
+            reward_policy: None,
         }
     }
 }
 impl HireLeadFixture {
+    pub fn with_stake(self, stake: u64) -> Self {
+        Self {
+            stake: Some(stake),
+            ..self
+        }
+    }
+    pub fn with_reward_policy(self, reward_policy: RewardPolicy<u64, u64>) -> Self {
+        Self {
+            reward_policy: Some(reward_policy),
+            ..self
+        }
+    }
+
     pub fn hire_lead(self) -> u64 {
         fill_worker_position(
-            None,
-            None,
+            self.reward_policy,
+            self.stake,
             self.setup_environment,
             OpeningType::Leader,
             Some(b"leader".to_vec()),

+ 107 - 16
runtime-modules/working-group/src/tests/mod.rs

@@ -411,7 +411,7 @@ fn withdraw_worker_application_fails_invalid_origin() {
         let withdraw_application_fixture =
             WithdrawApplicationFixture::default_for_application_id(application_id)
                 .with_origin(RawOrigin::None);
-        withdraw_application_fixture.call_and_assert(Err(Error::Other("RequireSignedOrigin")));
+        withdraw_application_fixture.call_and_assert(Err(Error::RequireSignedOrigin));
     });
 }
 
@@ -515,7 +515,7 @@ fn terminate_worker_application_fails_invalid_origin() {
         let terminate_application_fixture =
             TerminateApplicationFixture::default_for_application_id(application_id)
                 .with_origin(RawOrigin::None);
-        terminate_application_fixture.call_and_assert(Err(Error::Other("RequireSignedOrigin")));
+        terminate_application_fixture.call_and_assert(Err(Error::RequireSignedOrigin));
     });
 }
 
@@ -642,8 +642,7 @@ fn begin_review_worker_applications_fails_with_invalid_origin() {
         let begin_review_worker_applications_fixture =
             BeginReviewWorkerApplicationsFixture::default_for_opening_id(opening_id)
                 .with_origin(RawOrigin::None);
-        begin_review_worker_applications_fixture
-            .call_and_assert(Err(Error::Other("RequireSignedOrigin")));
+        begin_review_worker_applications_fixture.call_and_assert(Err(Error::RequireSignedOrigin));
     });
 }
 
@@ -752,7 +751,7 @@ fn fill_worker_opening_fails_with_invalid_origin() {
         let fill_worker_opening_fixture =
             FillWorkerOpeningFixture::default_for_ids(opening_id, Vec::new())
                 .with_origin(RawOrigin::None);
-        fill_worker_opening_fixture.call_and_assert(Err(Error::Other("RequireSignedOrigin")));
+        fill_worker_opening_fixture.call_and_assert(Err(Error::RequireSignedOrigin));
     });
 }
 
@@ -920,7 +919,7 @@ fn update_worker_reward_account_succeeds() {
     build_test_externalities().execute_with(|| {
         let worker_id = fill_default_worker_position();
 
-        let new_role_account = 2;
+        let new_role_account = 22;
         let update_worker_account_fixture =
             UpdateWorkerRewardAccountFixture::default_with_ids(worker_id, new_role_account);
 
@@ -933,13 +932,32 @@ fn update_worker_reward_account_succeeds() {
     });
 }
 
+#[test]
+fn update_worker_reward_account_succeeds_for_leader() {
+    build_test_externalities().execute_with(|| {
+        let worker_id = HireLeadFixture::default()
+            .with_reward_policy(RewardPolicy {
+                amount_per_payout: 1000,
+                next_payment_at_block: 20,
+                payout_interval: None,
+            })
+            .hire_lead();
+
+        let new_reward_account = 22;
+        let update_worker_account_fixture =
+            UpdateWorkerRewardAccountFixture::default_with_ids(worker_id, new_reward_account);
+
+        update_worker_account_fixture.call_and_assert(Ok(()));
+    });
+}
+
 #[test]
 fn update_worker_reward_account_fails_with_invalid_origin() {
     build_test_externalities().execute_with(|| {
         let update_worker_account_fixture =
             UpdateWorkerRewardAccountFixture::default_with_ids(1, 1).with_origin(RawOrigin::None);
 
-        update_worker_account_fixture.call_and_assert(Err(Error::Other("RequireSignedOrigin")));
+        update_worker_account_fixture.call_and_assert(Err(Error::RequireSignedOrigin));
     });
 }
 
@@ -1002,13 +1020,50 @@ fn update_worker_reward_amount_succeeds() {
     });
 }
 
+#[test]
+fn update_worker_reward_amount_succeeds_for_leader() {
+    build_test_externalities().execute_with(|| {
+        let worker_id = HireLeadFixture::default()
+            .with_reward_policy(RewardPolicy {
+                amount_per_payout: 1000,
+                next_payment_at_block: 20,
+                payout_interval: None,
+            })
+            .hire_lead();
+
+        let update_worker_amount_fixture =
+            UpdateWorkerRewardAmountFixture::default_for_worker_id(worker_id)
+                .with_origin(RawOrigin::Root);
+
+        update_worker_amount_fixture.call_and_assert(Ok(()));
+    });
+}
+
 #[test]
 fn update_worker_reward_amount_fails_with_invalid_origin() {
     build_test_externalities().execute_with(|| {
+        HireLeadFixture::default().hire_lead();
+
+        let worker_id = 22; // random worker id
+
         let update_worker_amount_fixture =
-            UpdateWorkerRewardAmountFixture::default_for_worker_id(1).with_origin(RawOrigin::None);
+            UpdateWorkerRewardAmountFixture::default_for_worker_id(worker_id)
+                .with_origin(RawOrigin::None);
 
-        update_worker_amount_fixture.call_and_assert(Err(Error::Other("RequireSignedOrigin")));
+        update_worker_amount_fixture.call_and_assert(Err(Error::RequireSignedOrigin));
+    });
+}
+
+#[test]
+fn update_worker_reward_amount_fails_with_invalid_origin_for_leader() {
+    build_test_externalities().execute_with(|| {
+        let worker_id = HireLeadFixture::default().hire_lead();
+
+        let update_worker_amount_fixture =
+            UpdateWorkerRewardAmountFixture::default_for_worker_id(worker_id)
+                .with_origin(RawOrigin::None);
+
+        update_worker_amount_fixture.call_and_assert(Err(Error::RequireRootOrigin));
     });
 }
 
@@ -1028,7 +1083,7 @@ fn update_worker_reward_amount_fails_with_invalid_origin_signed_account() {
 #[test]
 fn update_worker_reward_amount_fails_with_invalid_worker_id() {
     build_test_externalities().execute_with(|| {
-        let invalid_worker_id = 1;
+        let invalid_worker_id = 12;
         fill_default_worker_position();
 
         let update_worker_amount_fixture =
@@ -1143,7 +1198,7 @@ fn leave_worker_role_fails_with_invalid_origin() {
         let leave_worker_role_fixture =
             LeaveWorkerRoleFixture::default_for_worker_id(1).with_origin(RawOrigin::None);
 
-        leave_worker_role_fixture.call_and_assert(Err(Error::Other("RequireSignedOrigin")));
+        leave_worker_role_fixture.call_and_assert(Err(Error::RequireSignedOrigin));
     });
 }
 
@@ -1415,7 +1470,7 @@ fn terminate_worker_role_fails_with_invalid_origin() {
             TerminateWorkerRoleFixture::default_for_worker_id(worker_id)
                 .with_origin(RawOrigin::None);
 
-        terminate_worker_role_fixture.call_and_assert(Err(Error::Other("RequireSignedOrigin")));
+        terminate_worker_role_fixture.call_and_assert(Err(Error::RequireSignedOrigin));
     });
 }
 
@@ -1445,6 +1500,17 @@ fn increase_worker_stake_succeeds() {
     });
 }
 
+#[test]
+fn increase_worker_stake_succeeds_for_leader() {
+    build_test_externalities().execute_with(|| {
+        let worker_id = HireLeadFixture::default().with_stake(100).hire_lead();
+
+        let increase_stake_fixture = IncreaseWorkerStakeFixture::default_for_worker_id(worker_id);
+
+        increase_stake_fixture.call_and_assert(Ok(()));
+    });
+}
+
 #[test]
 fn increase_worker_stake_fails_with_invalid_origin() {
     build_test_externalities().execute_with(|| {
@@ -1452,7 +1518,7 @@ fn increase_worker_stake_fails_with_invalid_origin() {
         let increase_stake_fixture = IncreaseWorkerStakeFixture::default_for_worker_id(worker_id)
             .with_origin(RawOrigin::None);
 
-        increase_stake_fixture.call_and_assert(Err(Error::Other("RequireSignedOrigin")));
+        increase_stake_fixture.call_and_assert(Err(Error::RequireSignedOrigin));
     });
 }
 
@@ -1517,14 +1583,39 @@ fn decrease_worker_stake_succeeds() {
     });
 }
 
+#[test]
+fn decrease_worker_stake_succeeds_for_leader() {
+    build_test_externalities().execute_with(|| {
+        let worker_id = HireLeadFixture::default().with_stake(100).hire_lead();
+
+        let decrease_stake_fixture = DecreaseWorkerStakeFixture::default_for_worker_id(worker_id)
+            .with_origin(RawOrigin::Root);
+
+        decrease_stake_fixture.call_and_assert(Ok(()));
+    });
+}
+
 #[test]
 fn decrease_worker_stake_fails_with_invalid_origin() {
     build_test_externalities().execute_with(|| {
-        let worker_id = 0;
+        HireLeadFixture::default().hire_lead();
+
+        let worker_id = 22; // random worker id
+        let decrease_stake_fixture = DecreaseWorkerStakeFixture::default_for_worker_id(worker_id)
+            .with_origin(RawOrigin::None);
+
+        decrease_stake_fixture.call_and_assert(Err(Error::RequireSignedOrigin));
+    });
+}
+
+#[test]
+fn decrease_worker_stake_fails_with_invalid_origin_for_leader() {
+    build_test_externalities().execute_with(|| {
+        let worker_id = HireLeadFixture::default().hire_lead();
         let decrease_stake_fixture = DecreaseWorkerStakeFixture::default_for_worker_id(worker_id)
             .with_origin(RawOrigin::None);
 
-        decrease_stake_fixture.call_and_assert(Err(Error::Other("RequireSignedOrigin")));
+        decrease_stake_fixture.call_and_assert(Err(Error::RequireRootOrigin));
     });
 }
 
@@ -1629,7 +1720,7 @@ fn slash_worker_stake_fails_with_invalid_origin() {
         let slash_stake_fixture = SlashWorkerStakeFixture::default_for_worker_id(invalid_worker_id)
             .with_origin(RawOrigin::None);
 
-        slash_stake_fixture.call_and_assert(Err(Error::Other("RequireSignedOrigin")));
+        slash_stake_fixture.call_and_assert(Err(Error::RequireSignedOrigin));
     });
 }