소스 검색

Create bureaucracy module mocks

Shamil Gadelshin 4 년 전
부모
커밋
72b0e997e8
5개의 변경된 파일334개의 추가작업 그리고 112개의 파일을 삭제
  1. 6 0
      Cargo.lock
  2. 58 9
      runtime-modules/bureaucracy/Cargo.toml
  3. 28 28
      runtime-modules/bureaucracy/src/constraints.rs
  4. 151 30
      runtime-modules/bureaucracy/src/lib.rs
  5. 91 45
      runtime-modules/bureaucracy/src/types.rs

+ 6 - 0
Cargo.lock

@@ -4470,11 +4470,17 @@ dependencies = [
  "sr-io",
  "sr-primitives",
  "sr-std",
+ "srml-balances",
  "srml-support",
  "srml-system",
+ "srml-timestamp",
+ "substrate-common-module",
  "substrate-hiring-module",
+ "substrate-membership-module",
  "substrate-primitives",
+ "substrate-recurring-reward-module",
  "substrate-stake-module",
+ "substrate-token-mint-module",
 ]
 
 [[package]]

+ 58 - 9
runtime-modules/bureaucracy/Cargo.toml

@@ -14,18 +14,29 @@ std = [
 	'rstd/std',
 	'serde',
     'hiring/std',
-    'stake/std'
+    'stake/std',
+    'membership/std',
+    'minting/std',
+    'recurringrewards/std',
 ]
 
+[dependencies.primitives]
+default_features = false
+git = 'https://github.com/paritytech/substrate.git'
+package = 'substrate-primitives'
+rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
 
-[dependencies]
-codec = { package = 'parity-scale-codec', version = '1.0.0', default-features = false, features = ['derive'] }
-primitives = { package = 'substrate-primitives', git = 'https://github.com/paritytech/substrate.git', rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'}
-rstd = { package = 'sr-std', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'}
-
+[dependencies.codec]
+default-features = false
+features = ['derive']
+package = 'parity-scale-codec'
+version = '1.0.0'
 
-[dev-dependencies]
-runtime-io = { package = 'sr-io', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'}
+[dependencies.rstd]
+default_features = false
+git = 'https://github.com/paritytech/substrate.git'
+package = 'sr-std'
+rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
 
 [dependencies.serde]
 features = ['derive']
@@ -58,4 +69,42 @@ path = '../hiring'
 [dependencies.stake]
 default_features = false
 package = 'substrate-stake-module'
-path = '../stake'
+path = '../stake'
+
+[dependencies.membership]
+default_features = false
+package = 'substrate-membership-module'
+path = '../membership'
+
+[dependencies.recurringrewards]
+default_features = false
+package = 'substrate-recurring-reward-module'
+path = '../recurring-reward'
+
+[dependencies.minting]
+default_features = false
+package = 'substrate-token-mint-module'
+path = '../token-minting'
+
+[dev-dependencies.runtime-io]
+default_features = false
+git = 'https://github.com/paritytech/substrate.git'
+package = 'sr-io'
+rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+
+[dev-dependencies.balances]
+default_features = false
+git = 'https://github.com/paritytech/substrate.git'
+package = 'srml-balances'
+rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'
+
+[dev-dependencies.common]
+default_features = false
+package = 'substrate-common-module'
+path = '../common'
+
+[dev-dependencies.timestamp]
+default_features = false
+git = 'https://github.com/paritytech/substrate.git'
+package = 'srml-timestamp'
+rev = 'c37bb08535c49a12320af7facfd555ce05cce2e8'

+ 28 - 28
runtime-modules/bureaucracy/src/constraints.rs

@@ -1,40 +1,40 @@
+use codec::{Decode, Encode};
 #[cfg(feature = "std")]
 use serde::{Deserialize, Serialize};
-use codec::{Encode, Decode};
 
 /// Length constraint for input validation
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize, Debug))]
 #[derive(Encode, Decode, Default, Clone, PartialEq, Eq)]
 pub struct InputValidationLengthConstraint {
-	/// Minimum length
-	pub min: u16,
+    /// Minimum length
+    pub min: u16,
 
-	/// Difference between minimum length and max length.
-	/// While having max would have been more direct, this
-	/// way makes max < min unrepresentable semantically,
-	/// which is safer.
-	pub max_min_diff: u16,
+    /// Difference between minimum length and max length.
+    /// While having max would have been more direct, this
+    /// way makes max < min unrepresentable semantically,
+    /// which is safer.
+    pub max_min_diff: u16,
 }
 
 impl InputValidationLengthConstraint {
-	/// Helper for computing max
-	pub fn max(&self) -> u16 {
-		self.min + self.max_min_diff
-	}
+    /// Helper for computing max
+    pub fn max(&self) -> u16 {
+        self.min + self.max_min_diff
+    }
 
-	pub fn ensure_valid(
-		&self,
-		len: usize,
-		too_short_msg: &'static str,
-		too_long_msg: &'static str,
-	) -> Result<(), &'static str> {
-		let length = len as u16;
-		if length < self.min {
-			Err(too_short_msg)
-		} else if length > self.max() {
-			Err(too_long_msg)
-		} else {
-			Ok(())
-		}
-	}
-}
+    pub fn ensure_valid(
+        &self,
+        len: usize,
+        too_short_msg: &'static str,
+        too_long_msg: &'static str,
+    ) -> Result<(), &'static str> {
+        let length = len as u16;
+        if length < self.min {
+            Err(too_short_msg)
+        } else if length > self.max() {
+            Err(too_long_msg)
+        } else {
+            Ok(())
+        }
+    }
+}

+ 151 - 30
runtime-modules/bureaucracy/src/lib.rs

@@ -1,21 +1,28 @@
 // Ensure we're `no_std` when compiling for Wasm.
 #![cfg_attr(not(feature = "std"), no_std)]
 
-mod types;
 mod constraints;
+mod types;
 
-use system;
-use srml_support::{decl_module, decl_storage, dispatch};
 use rstd::collections::btree_set::BTreeSet;
-use sr_primitives::traits::{One, }; // Member, SimpleArithmetic, MaybeSerialize, Zero
+use sr_primitives::traits::One; // Member, SimpleArithmetic, MaybeSerialize, Zero
 use srml_support::traits::Currency;
+use srml_support::{decl_module, decl_storage, dispatch, ensure};
+use system::{self, ensure_signed};
 
-use types::{OpeningPolicyCommitment, CuratorOpening};
 use constraints::InputValidationLengthConstraint;
-
+use types::{CuratorOpening, Lead, OpeningPolicyCommitment};
 
 pub static MSG_CHANNEL_DESCRIPTION_TOO_SHORT: &str = "Channel description too short";
 pub static MSG_CHANNEL_DESCRIPTION_TOO_LONG: &str = "Channel description too long";
+pub static MSG_ORIGIN_IS_NOT_LEAD: &str = "Origin is not lead";
+pub static MSG_CURRENT_LEAD_NOT_SET: &str = "Current lead is not set";
+
+/// Type constraint for identifer used for actors in members module in this runtime.
+pub type ActorIdInMembersModule<T> = <T as membership::members::Trait>::ActorId;
+
+/// Type identifier for lead role, which must be same as membership actor identifeir
+pub type LeadId<T> = ActorIdInMembersModule<T>;
 
 /// Type for the identifer for an opening for a curator.
 pub type CuratorOpeningId<T> = <T as hiring::Trait>::OpeningId;
@@ -23,23 +30,35 @@ pub type CuratorOpeningId<T> = <T as hiring::Trait>::OpeningId;
 /// Tyoe for the indentifier for an application as a curator.
 pub type CuratorApplicationId<T> = <T as hiring::Trait>::ApplicationId;
 
+/// Type of mintin reward relationship identifiers
+pub type RewardRelationshipId<T> = <T as recurringrewards::Trait>::RewardRelationshipId;
+
 /// Balance type of runtime
 pub type BalanceOf<T> =
-<<T as stake::Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::Balance;
+    <<T as stake::Trait>::Currency as Currency<<T as system::Trait>::AccountId>>::Balance;
 
-
-pub trait Trait<I: Instance>: system::Trait + hiring::Trait{}
+pub trait Trait<I: Instance>:
+    system::Trait + hiring::Trait + recurringrewards::Trait + membership::members::Trait
+{
+}
 
 decl_storage! {
     trait Store for Module<T: Trait<I>, I: Instance> as Bureaucracy {
         pub TestData get(test_data): u32;
 
-        /// Next identifier valuefor new curator opening.
+        /// Next identifier value for new curator opening.
         pub NextCuratorOpeningId get(next_curator_opening_id): CuratorOpeningId<T>;
 
-        /// Maps identifeir to curator opening.
+        /// Maps identifier to curator opening.
         pub CuratorOpeningById get(curator_opening_by_id): linked_map CuratorOpeningId<T> => CuratorOpening<T::OpeningId, T::BlockNumber, BalanceOf<T>, CuratorApplicationId<T>>;
 
+        /// The current lead.
+        pub CurrentLeadId get(current_lead_id) : Option<LeadId<T>>;
+
+        /// Maps identifier to corresponding lead.
+        pub LeadById get(lead_by_id): linked_map LeadId<T> => Lead<T::AccountId, T::RewardRelationshipId, T::BlockNumber>;
+
+
         pub OpeningHumanReadableText get(opening_human_readable_text): InputValidationLengthConstraint;
     }
 }
@@ -50,9 +69,8 @@ decl_module! {
         pub fn add_curator_opening(origin, activate_at: hiring::ActivateOpeningAt<T::BlockNumber>, commitment: OpeningPolicyCommitment<T::BlockNumber, BalanceOf<T>>, human_readable_text: Vec<u8>)  {
 
             // Ensure lead is set and is origin signer
- //           Self::ensure_origin_is_set_lead(origin)?;
+            Self::ensure_origin_is_set_lead(origin)?;
 
-            // Ensure human radable text is valid
             Self::ensure_opening_human_readable_text_is_valid(&human_readable_text)?;
 
             // Add opening
@@ -104,9 +122,8 @@ decl_module! {
     }
 }
 
-
 impl<T: Trait<I>, I: Instance> Module<T, I> {
-    pub fn set_test_data(data : u32) {
+    pub fn set_test_data(data: u32) {
         <TestData<I>>::put(data);
     }
 
@@ -117,9 +134,55 @@ impl<T: Trait<I>, I: Instance> Module<T, I> {
             MSG_CHANNEL_DESCRIPTION_TOO_LONG,
         )
     }
-}
 
+    pub fn ensure_lead_is_set() -> Result<
+        (
+            LeadId<T>,
+            Lead<T::AccountId, T::RewardRelationshipId, T::BlockNumber>,
+        ),
+        &'static str,
+    > {
+        // Ensure lead id is set
+        let lead_id = Self::ensure_lead_id_set()?;
+
+        // If so, grab actual lead
+        let lead = <LeadById<T,I>>::get(lead_id);
+
+        // and return both
+        Ok((lead_id, lead))
+    }
+
+    fn ensure_lead_id_set() -> Result<LeadId<T>, &'static str> {
+        let opt_current_lead_id = <CurrentLeadId<T, I>>::get();
 
+        if let Some(lead_id) = opt_current_lead_id {
+            Ok(lead_id)
+        } else {
+            Err(MSG_CURRENT_LEAD_NOT_SET)
+        }
+    }
+
+    fn ensure_origin_is_set_lead(
+        origin: T::Origin,
+    ) -> Result<
+        (
+            LeadId<T>,
+            Lead<T::AccountId, T::RewardRelationshipId, T::BlockNumber>,
+        ),
+        &'static str,
+    > {
+        // Ensure lead is actually set
+        let (lead_id, lead) = Self::ensure_lead_is_set()?;
+
+        // Ensure is signed
+        let signer = ensure_signed(origin)?;
+
+        // Ensure signer is lead
+        ensure!(signer == lead.role_account, MSG_ORIGIN_IS_NOT_LEAD);
+
+        Ok((lead_id, lead))
+    }
+}
 
 #[cfg(test)]
 mod test {
@@ -144,6 +207,11 @@ mod test {
         pub const MaximumBlockLength: u32 = 2 * 1024;
         pub const AvailableBlockRatio: Perbill = Perbill::one();
         pub const MinimumPeriod: u64 = 5;
+        pub const InitialMembersBalance: u64 = 2000;
+        pub const StakePoolId: [u8; 8] = *b"joystake";
+        pub const ExistentialDeposit: u32 = 0;
+        pub const TransferFee: u32 = 0;
+        pub const CreationFee: u32 = 0;
     }
 
     // Workaround for https://github.com/rust-lang/rust/issues/26925 . Remove when sorted.
@@ -168,6 +236,65 @@ mod test {
         type Version = ();
     }
 
+    impl recurringrewards::Trait for Test {
+        type PayoutStatusHandler = ();
+        type RecipientId = u64;
+        type RewardRelationshipId = u64;
+    }
+
+    impl hiring::Trait for Test {
+        type OpeningId = u64;
+        type ApplicationId = u64;
+        type ApplicationDeactivatedHandler = ();
+        type StakeHandlerProvider = hiring::Module<Self>;
+    }
+
+    impl minting::Trait for Test {
+        type Currency = Balances;
+        type MintId = u64;
+    }
+
+    impl stake::Trait for Test {
+        type Currency = Balances;
+        type StakePoolId = StakePoolId;
+        type StakingEventsHandler = ();
+        type StakeId = u64;
+        type SlashId = u64;
+    }
+
+    impl membership::members::Trait for Test {
+        type Event = ();
+        type MemberId = u64;
+        type PaidTermId = u64;
+        type SubscriptionId = u64;
+        type ActorId = u64;
+        type InitialMembersBalance = InitialMembersBalance;
+    }
+
+    impl common::currency::GovernanceCurrency for Test {
+        type Currency = Balances;
+    }
+
+    impl timestamp::Trait for Test {
+        type Moment = u64;
+        type OnTimestampSet = ();
+        type MinimumPeriod = MinimumPeriod;
+    }
+
+    impl balances::Trait for Test {
+        type Balance = u64;
+        type OnFreeBalanceZero = ();
+        type OnNewAccount = ();
+        type Event = ();
+        type DustRemoval = ();
+        type TransferPayment = ();
+        type ExistentialDeposit = ExistentialDeposit;
+        type TransferFee = TransferFee;
+        type CreationFee = CreationFee;
+    }
+
+    pub type Balances = balances::Module<Test>;
+
     impl Trait<Instance1> for Test {}
     impl Trait<Instance2> for Test {}
 
@@ -177,21 +304,15 @@ mod test {
     type Bureaucracy1 = Module<Test, Instance1>;
     type Bureaucracy2 = Module<Test, Instance2>;
 
-    impl Trait<Instance15> for Test {}
-    use crate::Instance15;
-    type Bureaucracy16 = Module<Test, Instance15>;
-
-	pub fn build_test_externalities() -> runtime_io::TestExternalities {
-		let t = system::GenesisConfig::default()
-			.build_storage::<Test>()
-			.unwrap();
-
-		t.into()
-	}
-
+    pub fn build_test_externalities() -> runtime_io::TestExternalities {
+        let t = system::GenesisConfig::default()
+            .build_storage::<Test>()
+            .unwrap();
 
+        t.into()
+    }
 
-	#[test]
+    #[test]
     fn test_instances_storage_separation() {
         build_test_externalities().execute_with(|| {
             Bureaucracy1::set_test_data(10);
@@ -199,5 +320,5 @@ mod test {
             assert_eq!(Bureaucracy1::test_data(), 10);
             assert_eq!(Bureaucracy2::test_data(), 10);
         });
-	}
+    }
 }

+ 91 - 45
runtime-modules/bureaucracy/src/types.rs

@@ -1,33 +1,33 @@
+use codec::{Decode, Encode};
+use rstd::collections::btree_set::BTreeSet;
 #[cfg(feature = "std")]
 use serde::{Deserialize, Serialize};
-use codec::{Encode, Decode};
-use rstd::collections::btree_set::BTreeSet;
 
 /// Terms for slashings applied to a given role
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, Debug, Clone, PartialEq, Eq)]
 pub struct SlashableTerms {
-	/// Maximum number of slashes.
-	pub max_count: u16,
+    /// Maximum number of slashes.
+    pub max_count: u16,
 
-	/// Maximum percentage points of remaining stake which may be slashed in a single slash.
-	pub max_percent_pts_per_time: u16,
+    /// Maximum percentage points of remaining stake which may be slashed in a single slash.
+    pub max_percent_pts_per_time: u16,
 }
 
 /// Terms for what slashing can be applied in some context
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, Debug, Clone, PartialEq, Eq)]
 pub enum SlashingTerms {
-	Unslashable,
-	Slashable(SlashableTerms),
+    Unslashable,
+    Slashable(SlashableTerms),
 }
 
 /// Must be default constructible because it indirectly is a value in a storage map.
 /// ***SHOULD NEVER ACTUALLY GET CALLED, IS REQUIRED TO DUE BAD STORAGE MODEL IN SUBSTRATE***
 impl Default for SlashingTerms {
-	fn default() -> Self {
-		Self::Unslashable
-	}
+    fn default() -> Self {
+        Self::Unslashable
+    }
 }
 
 /// A commitment to the set of policy variables relevant to an opening.
@@ -36,57 +36,103 @@ impl Default for SlashingTerms {
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, Debug, Clone, Default, PartialEq, Eq)]
 pub struct OpeningPolicyCommitment<BlockNumber, Balance> {
-	/// Rationing to be used
-	pub application_rationing_policy: Option<hiring::ApplicationRationingPolicy>,
+    /// Rationing to be used
+    pub application_rationing_policy: Option<hiring::ApplicationRationingPolicy>,
 
-	/// Maximum length of review period of applications
-	pub max_review_period_length: BlockNumber,
+    /// Maximum length of review period of applications
+    pub max_review_period_length: BlockNumber,
 
-	/// Staking policy for application
-	pub application_staking_policy: Option<hiring::StakingPolicy<Balance, BlockNumber>>,
+    /// Staking policy for application
+    pub application_staking_policy: Option<hiring::StakingPolicy<Balance, BlockNumber>>,
 
-	/// Staking policy for role itself
-	pub role_staking_policy: Option<hiring::StakingPolicy<Balance, BlockNumber>>,
+    /// Staking policy for role itself
+    pub role_staking_policy: Option<hiring::StakingPolicy<Balance, BlockNumber>>,
 
-	// Slashing terms during application
-	// pub application_slashing_terms: SlashingTerms,
+    // Slashing terms during application
+    // pub application_slashing_terms: SlashingTerms,
 
-	// Slashing terms during role, NOT application itself!
-	pub role_slashing_terms: SlashingTerms,
+    // Slashing terms during role, NOT application itself!
+    pub role_slashing_terms: SlashingTerms,
 
-	/// When filling an opening: Unstaking period for application stake of successful applicants
-	pub fill_opening_successful_applicant_application_stake_unstaking_period: Option<BlockNumber>,
+    /// When filling an opening: Unstaking period for application stake of successful applicants
+    pub fill_opening_successful_applicant_application_stake_unstaking_period: Option<BlockNumber>,
 
-	/// When filling an opening:
-	pub fill_opening_failed_applicant_application_stake_unstaking_period: Option<BlockNumber>,
+    /// When filling an opening:
+    pub fill_opening_failed_applicant_application_stake_unstaking_period: Option<BlockNumber>,
 
-	/// When filling an opening:
-	pub fill_opening_failed_applicant_role_stake_unstaking_period: Option<BlockNumber>,
+    /// When filling an opening:
+    pub fill_opening_failed_applicant_role_stake_unstaking_period: Option<BlockNumber>,
 
-	/// When terminating a curator:
-	pub terminate_curator_application_stake_unstaking_period: Option<BlockNumber>,
+    /// When terminating a curator:
+    pub terminate_curator_application_stake_unstaking_period: Option<BlockNumber>,
 
-	/// When terminating a curator:
-	pub terminate_curator_role_stake_unstaking_period: Option<BlockNumber>,
+    /// When terminating a curator:
+    pub terminate_curator_role_stake_unstaking_period: Option<BlockNumber>,
 
-	/// When a curator exists: ..
-	pub exit_curator_role_application_stake_unstaking_period: Option<BlockNumber>,
+    /// When a curator exists: ..
+    pub exit_curator_role_application_stake_unstaking_period: Option<BlockNumber>,
 
-	/// When a curator exists: ..
-	pub exit_curator_role_stake_unstaking_period: Option<BlockNumber>,
+    /// When a curator exists: ..
+    pub exit_curator_role_stake_unstaking_period: Option<BlockNumber>,
 }
 
-
 /// An opening for a curator role.
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
 pub struct CuratorOpening<OpeningId, BlockNumber, Balance, CuratorApplicationId: core::cmp::Ord> {
-	/// Identifer for underlying opening in the hiring module.
-	pub opening_id: OpeningId,
+    /// Identifer for underlying opening in the hiring module.
+    pub opening_id: OpeningId,
+
+    /// Set of identifiers for all curator applications ever added
+    pub curator_applications: BTreeSet<CuratorApplicationId>,
+
+    /// Commitment to policies in opening.
+    pub policy_commitment: OpeningPolicyCommitment<BlockNumber, Balance>,
+}
+
+/// The exit stage of a lead involvement in the working group.
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[derive(Encode, Decode, Debug, Clone, PartialEq)]
+pub struct ExitedLeadRole<BlockNumber> {
+    /// When exit was initiated.
+    pub initiated_at_block_number: BlockNumber,
+}
+
+/// The stage of the involvement of a lead in the working group.
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[derive(Encode, Decode, Debug, Clone, PartialEq)]
+pub enum LeadRoleState<BlockNumber> {
+    /// Currently active.
+    Active,
 
-	/// Set of identifiers for all curator applications ever added
-	pub curator_applications: BTreeSet<CuratorApplicationId>,
+    /// No longer active, for some reason
+    Exited(ExitedLeadRole<BlockNumber>),
+}
+
+/// Must be default constructible because it indirectly is a value in a storage map.
+/// ***SHOULD NEVER ACTUALLY GET CALLED, IS REQUIRED TO DUE BAD STORAGE MODEL IN SUBSTRATE***
+impl<BlockNumber> Default for LeadRoleState<BlockNumber> {
+    fn default() -> Self {
+        LeadRoleState::Active
+    }
+}
 
-	/// Commitment to policies in opening.
-	pub policy_commitment: OpeningPolicyCommitment<BlockNumber, Balance>,
-}
+/// Working group lead: curator lead
+/// For now this role is not staked or inducted through an structured process, like the hiring module,
+/// hence information about this is missing. Recurring rewards is included, somewhat arbitrarily!
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+#[derive(Encode, Decode, Default, Debug, Clone, PartialEq)]
+pub struct Lead<AccountId, RewardRelationshipId, BlockNumber> {
+    /// Account used to authenticate in this role,
+    pub role_account: AccountId,
+
+    /// Whether the role has recurring reward, and if so an identifier for this.
+    pub reward_relationship: Option<RewardRelationshipId>,
+
+    /// When was inducted
+    /// TODO: Add richer information about circumstances of induction, like referencing a council proposal?
+    pub inducted: BlockNumber,
+
+    /// The stage of the involvement of this lead in the working group.
+    pub stage: LeadRoleState<BlockNumber>,
+}