Browse Source

Add ‘create_set_validator_count_proposal’ extrinsic

- add ‘create_set_validator_count_proposal’ extrinsic to the codex module
- add tests
Shamil Gadelshin 5 years ago
parent
commit
b994ee7016

+ 3 - 0
Cargo.lock

@@ -5108,8 +5108,11 @@ dependencies = [
  "serde",
  "sr-io",
  "sr-primitives",
+ "sr-staking-primitives",
  "sr-std",
  "srml-balances",
+ "srml-staking",
+ "srml-staking-reward-curve",
  "srml-support",
  "srml-system",
  "srml-timestamp",

+ 21 - 0
runtime-modules/proposals/codex/Cargo.toml

@@ -15,6 +15,7 @@ std = [
     'sr-primitives/std',
     'system/std',
     'timestamp/std',
+    'staking/std',
     'serde',
     'proposal_engine/std',
     'proposal_discussion/std',
@@ -84,6 +85,12 @@ default-features = false
 git = 'https://github.com/paritytech/substrate.git'
 rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
 
+[dependencies.staking]
+default_features = false
+git = 'https://github.com/paritytech/substrate.git'
+package = 'srml-staking'
+rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+
 [dependencies.runtime-io]
 default_features = false
 git = 'https://github.com/paritytech/substrate.git'
@@ -159,3 +166,17 @@ path = '../../versioned-store-permissions'
 default_features = false
 package = 'substrate-recurring-reward-module'
 path = '../../recurring-reward'
+
+[dev-dependencies.sr-staking-primitives]
+default_features = false
+git = 'https://github.com/paritytech/substrate.git'
+package = 'sr-staking-primitives'
+rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+
+# don't rename the dependency it is causing some strange compiler error:
+# https://github.com/rust-lang/rust/issues/64450
+[dev-dependencies.srml-staking-reward-curve]
+package = 'srml-staking-reward-curve'
+git = 'https://github.com/paritytech/substrate.git'
+default_features = false
+rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'

+ 30 - 0
runtime-modules/proposals/codex/src/lib.rs

@@ -21,6 +21,7 @@
 //! - [create_spending_proposal](./struct.Module.html#method.create_spending_proposal)
 //! - [create_set_lead_proposal](./struct.Module.html#method.create_set_lead_proposal)
 //! - [create_evict_storage_provider_proposal](./struct.Module.html#method.create_evict_storage_provider_proposal)
+//! - [create_set_validator_count_proposal](./struct.Module.html#method.create_set_validator_count_proposal)
 //!
 //! ### Proposal implementations of this module
 //! - execute_text_proposal - prints the proposal to the log
@@ -70,6 +71,7 @@ pub trait Trait:
     + governance::election::Trait
     + content_working_group::Trait
     + roles::actors::Trait
+    + staking::Trait
 {
     /// Defines max allowed text proposal length.
     type TextProposalMaxLength: Get<u32>;
@@ -421,6 +423,34 @@ decl_module! {
             )?;
         }
 
+        /// Create 'Evict storage provider' proposal type.
+        /// This proposal uses `set_validator_count()` extrinsic from the Substrate `staking`  module.
+        pub fn create_set_validator_count_proposal(
+            origin,
+            member_id: MemberId<T>,
+            title: Vec<u8>,
+            description: Vec<u8>,
+            stake_balance: Option<BalanceOf<T>>,
+            new_validator_count: u32,
+        ) {
+            let proposal_code =
+                <staking::Call<T>>::set_validator_count(new_validator_count);
+
+            let proposal_parameters =
+                proposal_types::parameters::set_validator_count_proposal::<T>();
+
+            Self::create_proposal(
+                origin,
+                member_id,
+                title,
+                description,
+                stake_balance,
+                proposal_code.encode(),
+                proposal_parameters,
+                ProposalDetails::SetValidatorCount(new_validator_count),
+            )?;
+        }
+
 // *************** Extrinsic to execute
 
         /// Text proposal extrinsic. Should be used as callable object to pass to the `engine` module.

+ 3 - 0
runtime-modules/proposals/codex/src/proposal_types/mod.rs

@@ -34,6 +34,9 @@ pub enum ProposalDetails<MintedBalance, CurrencyBalance, BlockNumber, AccountId,
 
     /// AccountId for the `evict storage provider proposal`
     EvictStorageProvider(AccountId),
+
+    /// Validator count for the `set validator count proposal`
+    SetValidatorCount(u32),
 }
 
 impl<MintedBalance, CurrencyBalance, BlockNumber, AccountId, MemberId> Default

+ 14 - 0
runtime-modules/proposals/codex/src/proposal_types/parameters.rs

@@ -110,3 +110,17 @@ pub(crate) fn evict_storage_provider_proposal<T: crate::Trait>(
         required_stake: Some(<BalanceOf<T>>::from(500u32)),
     }
 }
+
+// Proposal parameters for the 'Set validator count' proposal
+pub(crate) fn set_validator_count_proposal<T: crate::Trait>(
+) -> ProposalParameters<T::BlockNumber, BalanceOf<T>> {
+    ProposalParameters {
+        voting_period: T::BlockNumber::from(50000u32),
+        grace_period: T::BlockNumber::from(10000u32),
+        approval_quorum_percentage: 40,
+        approval_threshold_percentage: 51,
+        slashing_quorum_percentage: 82,
+        slashing_threshold_percentage: 87,
+        required_stake: Some(<BalanceOf<T>>::from(500u32)),
+    }
+}

+ 51 - 4
runtime-modules/proposals/codex/src/tests/mock.rs

@@ -1,17 +1,20 @@
 #![cfg(test)]
-
-pub use system;
+// srml_staking_reward_curve::build! - substrate macro produces a warning.
+// TODO: remove after post-Rome substrate upgrade
+#![allow(array_into_iter)]
 
 pub use primitives::{Blake2Hasher, H256};
+use proposal_engine::VotersParameters;
+use sr_primitives::curve::PiecewiseLinear;
 pub use sr_primitives::{
     testing::{Digest, DigestItem, Header, UintAuthorityId},
     traits::{BlakeTwo256, Convert, IdentityLookup, OnFinalize},
     weights::Weight,
     BuildStorage, DispatchError, Perbill,
 };
-
-use proposal_engine::VotersParameters;
+use sr_staking_primitives::SessionIndex;
 use srml_support::{impl_outer_dispatch, impl_outer_origin, parameter_types};
+pub use system;
 
 impl_outer_origin! {
     pub enum Origin for Test {}
@@ -196,6 +199,50 @@ impl roles::actors::ActorRemoved<Test> for () {
     fn actor_removed(_: &u64) {}
 }
 
+srml_staking_reward_curve::build! {
+    const I_NPOS: PiecewiseLinear<'static> = curve!(
+        min_inflation: 0_025_000,
+        max_inflation: 0_100_000,
+        ideal_stake: 0_500_000,
+        falloff: 0_050_000,
+        max_piece_count: 40,
+        test_precision: 0_005_000,
+    );
+}
+
+parameter_types! {
+    pub const SessionsPerEra: SessionIndex = 3;
+    pub const BondingDuration: staking::EraIndex = 3;
+    pub const RewardCurve: &'static PiecewiseLinear<'static> = &I_NPOS;
+}
+impl staking::Trait for Test {
+    type Currency = balances::Module<Self>;
+    type Time = timestamp::Module<Self>;
+    type CurrencyToVote = ();
+    type RewardRemainder = ();
+    type Event = ();
+    type Slash = ();
+    type Reward = ();
+    type SessionsPerEra = SessionsPerEra;
+    type BondingDuration = BondingDuration;
+    type SessionInterface = Self;
+    type RewardCurve = RewardCurve;
+}
+
+impl staking::SessionInterface<u64> for Test {
+    fn disable_validator(_: &u64) -> Result<bool, ()> {
+        unimplemented!()
+    }
+
+    fn validators() -> Vec<u64> {
+        unimplemented!()
+    }
+
+    fn prune_historical_up_to(_: u32) {
+        unimplemented!()
+    }
+}
+
 impl crate::Trait for Test {
     type TextProposalMaxLength = TextProposalMaxLength;
     type RuntimeUpgradeWasmProposalMaxLength = RuntimeUpgradeWasmProposalMaxLength;

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

@@ -551,7 +551,7 @@ fn create_set_lead_proposal_common_checks_succeed() {
 }
 
 #[test]
-fn create_evict_storage_provider_common_checks_succeed() {
+fn create_evict_storage_provider_proposal_common_checks_succeed() {
     initial_test_ext().execute_with(|| {
         let proposal_fixture = ProposalTestFixture {
             insufficient_rights_call: || {
@@ -600,3 +600,56 @@ fn create_evict_storage_provider_common_checks_succeed() {
         proposal_fixture.check_all();
     });
 }
+
+#[test]
+fn create_set_validator_count_proposal_common_checks_succeed() {
+    initial_test_ext().execute_with(|| {
+        let proposal_fixture = ProposalTestFixture {
+            insufficient_rights_call: || {
+                ProposalCodex::create_set_validator_count_proposal(
+                    RawOrigin::None.into(),
+                    1,
+                    b"title".to_vec(),
+                    b"body".to_vec(),
+                    None,
+                    1,
+                )
+            },
+            empty_stake_call: || {
+                ProposalCodex::create_set_validator_count_proposal(
+                    RawOrigin::Signed(1).into(),
+                    1,
+                    b"title".to_vec(),
+                    b"body".to_vec(),
+                    None,
+                    1,
+                )
+            },
+            invalid_stake_call: || {
+                ProposalCodex::create_set_validator_count_proposal(
+                    RawOrigin::Signed(1).into(),
+                    1,
+                    b"title".to_vec(),
+                    b"body".to_vec(),
+                    Some(<BalanceOf<Test>>::from(5000u32)),
+                    1,
+                )
+            },
+            successful_call: || {
+                ProposalCodex::create_set_validator_count_proposal(
+                    RawOrigin::Signed(1).into(),
+                    1,
+                    b"title".to_vec(),
+                    b"body".to_vec(),
+                    Some(<BalanceOf<Test>>::from(500u32)),
+                    1,
+                )
+            },
+            proposal_parameters: crate::proposal_types::parameters::set_validator_count_proposal::<
+                Test,
+            >(),
+            proposal_details: ProposalDetails::SetValidatorCount(1),
+        };
+        proposal_fixture.check_all();
+    });
+}