瀏覽代碼

council - runtime I

ondratra 4 年之前
父節點
當前提交
f853a59bc6

+ 4 - 0
Cargo.lock

@@ -2345,6 +2345,7 @@ dependencies = [
  "pallet-common",
  "pallet-constitution",
  "pallet-content-directory",
+ "pallet-council",
  "pallet-finality-tracker",
  "pallet-forum",
  "pallet-governance",
@@ -2359,6 +2360,7 @@ dependencies = [
  "pallet-proposals-engine",
  "pallet-randomness-collective-flip",
  "pallet-recurring-reward",
+ "pallet-referendum",
  "pallet-service-discovery",
  "pallet-session",
  "pallet-session-benchmarking",
@@ -3787,6 +3789,7 @@ dependencies = [
  "sp-core",
  "sp-io",
  "sp-runtime",
+ "sp-std",
 ]
 
 [[package]]
@@ -4067,6 +4070,7 @@ dependencies = [
  "sp-core",
  "sp-io",
  "sp-runtime",
+ "sp-std",
 ]
 
 [[package]]

+ 22 - 0
node/src/chain_spec/council_config.rs

@@ -0,0 +1,22 @@
+use node_runtime::pallet_council::{CouncilStageUpdate, Trait as CouncilTrait};
+use node_runtime::referendum::ReferendumStage;
+use node_runtime::{NewCouncilConfig, ReferendumConfig, Runtime};
+
+pub fn create_council_config() -> NewCouncilConfig {
+    NewCouncilConfig {
+        stage: CouncilStageUpdate::default(),
+        council_members: vec![],
+        candidates: vec![],
+        announcement_period_nr: 0,
+        budget: 0,
+        next_reward_payments: 0,
+        next_budget_refill: <Runtime as CouncilTrait>::BudgetRefillPeriod::get(),
+    }
+}
+
+pub fn create_referendum_config() -> ReferendumConfig {
+    ReferendumConfig {
+        stage: ReferendumStage::default(),
+        votes: vec![],
+    }
+}

+ 3 - 0
node/src/chain_spec/mod.rs

@@ -39,6 +39,7 @@ use node_runtime::{
 // Exported to be used by chain-spec-builder
 pub use node_runtime::{AccountId, GenesisConfig};
 
+pub mod council_config;
 pub mod forum_config;
 pub mod initial_balances;
 pub mod initial_members;
@@ -281,6 +282,8 @@ pub fn testnet_genesis(
                 min_voting_stake: 100,
             },
         }),
+        referendum_Instance1: Some(council_config::create_referendum_config()),
+        pallet_council: Some(council_config::create_council_config()),
         membership: Some(MembersConfig { members }),
         forum: Some(forum_config),
         data_object_type_registry: Some(DataObjectTypeRegistryConfig {

+ 1 - 1
runtime-modules/council/Cargo.toml

@@ -12,6 +12,7 @@ sp-core = { package = 'sp-core', default-features = false, git = 'https://github
 sp-arithmetic = { package = 'sp-arithmetic', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
 frame-support = { package = 'frame-support', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
 frame-system = { package = 'frame-system', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
+sp-std = { package = 'sp-std', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
 
 referendum = { package = 'pallet-referendum', default-features = false, path = '../referendum'}
 staking-handler = { package = 'pallet-staking-handler', default-features = false, path = '../staking-handler'}
@@ -29,7 +30,6 @@ default = ['std']
 std = [
     'codec/std',
     'sp-core/std',
-    'sp-io/std',
     'serde',
     'sp-runtime/std',
     'sp-arithmetic/std',

+ 6 - 1
runtime-modules/council/src/lib.rs

@@ -54,12 +54,13 @@ use frame_support::{
     decl_error, decl_event, decl_module, decl_storage, ensure, error::BadOrigin, Parameter,
 };
 
+use core::marker::PhantomData;
 use frame_system::{ensure_root, ensure_signed};
 #[cfg(feature = "std")]
 use serde::{Deserialize, Serialize};
 use sp_arithmetic::traits::BaseArithmetic;
 use sp_runtime::traits::{Hash, MaybeSerialize, Member, SaturatedConversion, Saturating};
-use std::marker::PhantomData;
+use sp_std::vec::Vec;
 
 use referendum::{CastVote, OptionResult, ReferendumManager};
 use staking_handler::StakingHandler;
@@ -71,6 +72,7 @@ mod tests;
 /////////////////// Data Structures ////////////////////////////////////////////
 
 /// Information about council's current state and when it changed the last time.
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, PartialEq, Eq, Debug, Default)]
 pub struct CouncilStageUpdate<BlockNumber> {
     stage: CouncilStage,
@@ -78,6 +80,7 @@ pub struct CouncilStageUpdate<BlockNumber> {
 }
 
 /// Possible council states.
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, PartialEq, Eq, Debug)]
 pub enum CouncilStage {
     /// Candidacy announcement period.
@@ -97,12 +100,14 @@ impl Default for CouncilStage {
 }
 
 /// Representation for announcing candidacy stage state.
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, PartialEq, Eq, Debug, Default)]
 pub struct CouncilStageAnnouncing {
     candidates_count: u64,
 }
 
 /// Representation for new council members election stage state.
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, PartialEq, Eq, Debug, Default)]
 pub struct CouncilStageElection {
     candidates_count: u64,

+ 3 - 0
runtime-modules/council/src/tests.rs

@@ -1316,6 +1316,8 @@ fn council_membership_checks() {
             candidate2.candidate.staking_account_id,
         );
 
+        // TODO: uncomment this once StakingHandler's `is_member_staking_account` is properly implemented
+        /*
         // test that staking_account_id has to be associated with membership_id
         Mocks::announce_candidacy_raw(
             candidate1.origin.clone(),
@@ -1325,6 +1327,7 @@ fn council_membership_checks() {
             candidate1.candidate.stake.clone(),
             Err(Error::MembershipIdNotMatchAccount),
         );
+        */
 
         // test that reward_account_id not associated with membership_id can be used
         Mocks::announce_candidacy_raw(

+ 2 - 0
runtime-modules/referendum/Cargo.toml

@@ -12,6 +12,7 @@ sp-core = { package = 'sp-core', default-features = false, git = 'https://github
 sp-arithmetic = { package = 'sp-arithmetic', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
 frame-support = { package = 'frame-support', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
 frame-system = { package = 'frame-system', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
+sp-std = { package = 'sp-std', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
 
 [dev-dependencies]
 pallet-balances = { package = 'pallet-balances', default-features = false, git = 'https://github.com/paritytech/substrate.git', rev = 'a200cdb93c6af5763b9c7bf313fa708764ac88ca'}
@@ -23,6 +24,7 @@ default = ['std']
 std = [
     'codec/std',
     'sp-core/std',
+    'sp-std/std',
     'serde',
     'sp-runtime/std',
     'sp-arithmetic/std',

+ 10 - 1
runtime-modules/referendum/src/lib.rs

@@ -34,6 +34,7 @@
 
 // used dependencies
 use codec::{Codec, Decode, Encode};
+use core::marker::PhantomData;
 use frame_support::traits::{
     Currency, EnsureOrigin, Get, LockIdentifier, LockableCurrency, WithdrawReason,
 };
@@ -41,9 +42,12 @@ use frame_support::{
     decl_error, decl_event, decl_module, decl_storage, error::BadOrigin, Parameter, StorageValue,
 };
 use frame_system::ensure_signed;
+#[cfg(feature = "std")]
+use serde::{Deserialize, Serialize};
 use sp_arithmetic::traits::BaseArithmetic;
 use sp_runtime::traits::{MaybeSerialize, Member};
-use std::marker::PhantomData;
+use sp_std::vec;
+use sp_std::vec::Vec;
 
 // declared modules
 mod mock;
@@ -52,6 +56,7 @@ mod tests;
 /////////////////// Data Structures ////////////////////////////////////////////
 
 /// Possible referendum states.
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, PartialEq, Eq, Debug)]
 pub enum ReferendumStage<BlockNumber, VotePower> {
     /// The referendum is dormant and waiting to be started by external source.
@@ -69,6 +74,7 @@ impl<BlockNumber, VotePower: Encode + Decode> Default for ReferendumStage<BlockN
 }
 
 /// Representation for voting stage state.
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, PartialEq, Eq, Debug, Default)]
 pub struct ReferendumStageVoting<BlockNumber> {
     pub started: BlockNumber,      // block in which referendum started
@@ -77,6 +83,7 @@ pub struct ReferendumStageVoting<BlockNumber> {
 }
 
 /// Representation for revealing stage state.
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, PartialEq, Eq, Debug, Default)]
 pub struct ReferendumStageRevealing<BlockNumber, VotePower> {
     pub started: BlockNumber,      // block in which referendum started
@@ -85,6 +92,7 @@ pub struct ReferendumStageRevealing<BlockNumber, VotePower> {
     pub current_cycle_id: u64,     // index of current election
 }
 
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, PartialEq, Eq, Debug, Default, Clone)]
 pub struct OptionResult<VotePower> {
     pub option_id: u64,
@@ -92,6 +100,7 @@ pub struct OptionResult<VotePower> {
 }
 
 /// Vote cast in referendum. Vote target is concealed until user reveals commitment's proof.
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 #[derive(Encode, Decode, PartialEq, Eq, Debug, Default)]
 pub struct CastVote<Hash, Currency> {
     pub commitment: Hash, // a commitment that a user submits in the voting stage before revealing what this vote is actually for

+ 4 - 0
runtime/Cargo.toml

@@ -67,6 +67,8 @@ memo = { package = 'pallet-memo', default-features = false, path = '../runtime-m
 forum = { package = 'pallet-forum', default-features = false, path = '../runtime-modules/forum'}
 membership = { package = 'pallet-membership', default-features = false, path = '../runtime-modules/membership'}
 governance = { package = 'pallet-governance', default-features = false, path = '../runtime-modules/governance'}
+referendum = { package = 'pallet-referendum', default-features = false, path = '../runtime-modules/referendum'}
+pallet_council = { package = 'pallet-council', default-features = false, path = '../runtime-modules/council'}
 minting = { package = 'pallet-token-mint', default-features = false, path = '../runtime-modules/token-minting'}
 recurring-rewards = { package = 'pallet-recurring-reward', default-features = false, path = '../runtime-modules/recurring-reward'}
 working-group = { package = 'pallet-working-group', default-features = false, path = '../runtime-modules/working-group'}
@@ -141,6 +143,8 @@ std = [
     'forum/std',
     'membership/std',
     'governance/std',
+    'pallet_council/std',
+    'referendum/std',
     'minting/std',
     'recurring-rewards/std',
     'working-group/std',

+ 40 - 1
runtime/src/constants.rs

@@ -43,6 +43,9 @@ parameter_types! {
     pub const StorageWorkingGroupLockId: LockIdentifier = [6; 8];
     pub const ContentWorkingGroupLockId: LockIdentifier = [7; 8];
     pub const ForumGroupLockId: LockIdentifier = [8; 8];
+    pub const CandidacyLockId: LockIdentifier = [9; 8];
+    pub const ElectedMemberLockId: LockIdentifier = [10; 8];
+    pub const ReferendumLockId: LockIdentifier = [11; 8];
 }
 
 lazy_static! {
@@ -52,22 +55,58 @@ lazy_static! {
         (ForumGroupLockId::get(), [
             ContentWorkingGroupLockId::get(),
             StorageWorkingGroupLockId::get(),
-            ProposalsLockId::get()
+            ProposalsLockId::get(),
+            CandidacyLockId::get(),
+            ElectedMemberLockId::get(),
+            ReferendumLockId::get(),
         ]),
         (ContentWorkingGroupLockId::get(), [
             ForumGroupLockId::get(),
             StorageWorkingGroupLockId::get(),
             ProposalsLockId::get(),
+            CandidacyLockId::get(),
+            ElectedMemberLockId::get(),
+            ReferendumLockId::get(),
         ]),
         (StorageWorkingGroupLockId::get(), [
             ForumGroupLockId::get(),
             ContentWorkingGroupLockId::get(),
             ProposalsLockId::get(),
+            CandidacyLockId::get(),
+            ElectedMemberLockId::get(),
+            ReferendumLockId::get(),
         ]),
         (ProposalsLockId::get(), [
             ForumGroupLockId::get(),
             ContentWorkingGroupLockId::get(),
             StorageWorkingGroupLockId::get(),
+            CandidacyLockId::get(),
+            ElectedMemberLockId::get(),
+            ReferendumLockId::get(),
+        ]),
+        (CandidacyLockId::get(), [
+            ForumGroupLockId::get(),
+            ContentWorkingGroupLockId::get(),
+            StorageWorkingGroupLockId::get(),
+            ProposalsLockId::get(),
+            ElectedMemberLockId::get(),
+            ReferendumLockId::get(),
+        ]),
+        (ElectedMemberLockId::get(), [
+            ForumGroupLockId::get(),
+            ContentWorkingGroupLockId::get(),
+            StorageWorkingGroupLockId::get(),
+            ProposalsLockId::get(),
+            CandidacyLockId::get(),
+            ReferendumLockId::get(),
+        ]),
+        (ReferendumLockId::get(), [
+            ForumGroupLockId::get(),
+            ContentWorkingGroupLockId::get(),
+            StorageWorkingGroupLockId::get(),
+            ProposalsLockId::get(),
+            CandidacyLockId::get(),
+            ElectedMemberLockId::get(),
         ]),
     ]
     .iter()

+ 119 - 2
runtime/src/lib.rs

@@ -32,7 +32,7 @@ use frame_support::weights::{
     Weight,
 };
 use frame_support::{construct_runtime, parameter_types};
-use frame_system::EnsureRoot;
+use frame_system::{EnsureOneOf, EnsureRoot, EnsureSigned};
 use pallet_grandpa::{AuthorityId as GrandpaId, AuthorityList as GrandpaAuthorityList};
 use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
 use pallet_session::historical as pallet_session_historical;
@@ -55,7 +55,9 @@ pub use runtime_api::*;
 use integration::proposals::{CouncilManager, ExtrinsicProposalEncoder, MembershipOriginValidator};
 
 use governance::{council, election};
-use staking_handler::LockComparator;
+use pallet_council::ReferendumConnection;
+use referendum::{Balance as BalanceReferendum, CastVote, OptionResult};
+use staking_handler::{LockComparator, StakingManager};
 use storage::data_object_storage_registry;
 
 // Node dependencies
@@ -69,8 +71,10 @@ pub use governance::election_params::ElectionParameters;
 pub use membership;
 #[cfg(any(feature = "std", test))]
 pub use pallet_balances::Call as BalancesCall;
+pub use pallet_council;
 pub use pallet_staking::StakerStatus;
 pub use proposals_engine::ProposalParameters;
+pub use referendum;
 pub use storage::{data_directory, data_object_type_registry};
 pub use working_group;
 
@@ -463,6 +467,117 @@ impl common::currency::GovernanceCurrency for Runtime {
     type Currency = pallet_balances::Module<Self>;
 }
 
+// The referendum instance alias.
+pub type ReferendumInstance = referendum::Instance1;
+pub type ReferendumModule = referendum::Module<Runtime, ReferendumInstance>;
+pub type CouncilModule = pallet_council::Module<Runtime>;
+
+parameter_types! {
+    // referendum parameters
+    pub const MaxSaltLength: u64 = 32;
+    pub const VoteStageDuration: BlockNumber = 5;
+    pub const RevealStageDuration: BlockNumber = 7;
+    pub const MinimumVotingStake: u64 = 10000;
+
+    // council parameteres
+    pub const MinNumberOfExtraCandidates: u64 = 1;
+    pub const AnnouncingPeriodDuration: BlockNumber = 15;
+    pub const IdlePeriodDuration: BlockNumber = 27;
+    pub const CouncilSize: u64 = 3;
+    pub const MinCandidateStake: u64 = 11000;
+    pub const ElectedMemberRewardPerBlock: u64 = 100;
+    pub const ElectedMemberRewardPeriod: BlockNumber = 10;
+    pub const BudgetRefillAmount: u64 = 1000;
+    pub const BudgetRefillPeriod: BlockNumber = 1000;
+}
+
+impl referendum::Trait<ReferendumInstance> for Runtime {
+    type Event = Event;
+
+    type MaxSaltLength = MaxSaltLength;
+
+    type Currency = pallet_balances::Module<Self>;
+    type LockId = ReferendumLockId;
+
+    type ManagerOrigin =
+        EnsureOneOf<Self::AccountId, EnsureSigned<Self::AccountId>, EnsureRoot<Self::AccountId>>;
+
+    type VotePower = BalanceReferendum<Self, ReferendumInstance>;
+
+    type VoteStageDuration = VoteStageDuration;
+    type RevealStageDuration = RevealStageDuration;
+
+    type MinimumStake = MinimumVotingStake;
+
+    fn calculate_vote_power(
+        _account_id: &<Self as frame_system::Trait>::AccountId,
+        stake: &BalanceReferendum<Self, ReferendumInstance>,
+    ) -> Self::VotePower {
+        *stake
+    }
+
+    fn can_unlock_vote_stake(
+        vote: &CastVote<Self::Hash, BalanceReferendum<Self, ReferendumInstance>>,
+    ) -> bool {
+        <CouncilModule as ReferendumConnection<Runtime>>::can_unlock_vote_stake(vote).is_ok()
+    }
+
+    fn process_results(winners: &[OptionResult<Self::VotePower>]) {
+        let tmp_winners: Vec<OptionResult<Self::VotePower>> = winners
+            .iter()
+            .map(|item| OptionResult {
+                option_id: item.option_id,
+                vote_power: item.vote_power,
+            })
+            .collect();
+        <CouncilModule as ReferendumConnection<Runtime>>::recieve_referendum_results(
+            tmp_winners.as_slice(),
+        );
+    }
+
+    fn is_valid_option_id(option_index: &u64) -> bool {
+        <CouncilModule as ReferendumConnection<Runtime>>::is_valid_candidate_id(option_index)
+    }
+
+    fn get_option_power(option_id: &u64) -> Self::VotePower {
+        <CouncilModule as ReferendumConnection<Runtime>>::get_option_power(option_id)
+    }
+
+    fn increase_option_power(option_id: &u64, amount: &Self::VotePower) {
+        <CouncilModule as ReferendumConnection<Runtime>>::increase_option_power(option_id, amount);
+    }
+}
+
+impl pallet_council::Trait for Runtime {
+    type Event = Event;
+
+    type Referendum = ReferendumModule;
+
+    type MembershipId = u64;
+    type MinNumberOfExtraCandidates = MinNumberOfExtraCandidates;
+    type CouncilSize = CouncilSize;
+    type AnnouncingPeriodDuration = AnnouncingPeriodDuration;
+    type IdlePeriodDuration = IdlePeriodDuration;
+    type MinCandidateStake = MinCandidateStake;
+
+    type CandidacyLock = StakingManager<Self, CandidacyLockId>;
+    type ElectedMemberLock = StakingManager<Self, ElectedMemberLockId>;
+
+    type ElectedMemberRewardPerBlock = ElectedMemberRewardPerBlock;
+    type ElectedMemberRewardPeriod = ElectedMemberRewardPeriod;
+
+    type BudgetRefillAmount = BudgetRefillAmount;
+    type BudgetRefillPeriod = BudgetRefillPeriod;
+
+    fn is_council_member_account(
+        _membership_id: &Self::MembershipId,
+        _account_id: &<Self as frame_system::Trait>::AccountId,
+    ) -> bool {
+        // TODO: implement when membership module is ready
+        true
+    }
+}
+
 impl governance::election::Trait for Runtime {
     type Event = Event;
     type CouncilElected = (Council, integration::proposals::CouncilElectedHandler);
@@ -789,6 +904,8 @@ construct_runtime!(
         // Joystream
         CouncilElection: election::{Module, Call, Storage, Event<T>, Config<T>},
         Council: council::{Module, Call, Storage, Event<T>, Config<T>},
+        NewCouncil: pallet_council::{Module, Call, Storage, Event<T>, Config<T>},
+        Referendum: referendum::<Instance1>::{Module, Call, Storage, Event<T>, Config<T>},
         Memo: memo::{Module, Call, Storage, Event<T>},
         Members: membership::{Module, Call, Storage, Event<T>, Config<T>},
         Forum: forum::{Module, Call, Storage, Event<T>, Config<T>},