//! The Joystream Substrate Node runtime. #![cfg_attr(not(feature = "std"), no_std)] // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. #![recursion_limit = "256"] //Substrate internal issues. #![allow(clippy::large_enum_variant)] #![allow(clippy::unnecessary_mut_passed)] // Make the WASM binary available. // This is required only by the node build. // A dummy wasm_binary.rs will be built for the IDE. #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); mod constants; mod integration; pub mod primitives; mod proposals_configuration; mod runtime_api; #[cfg(test)] mod tests; /// Weights for pallets used in the runtime. mod weights; // Runtime integration tests #[macro_use] extern crate lazy_static; // for proposals_configuration module use frame_support::traits::{KeyOwnerProofSystem, LockIdentifier}; use frame_support::weights::{ constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}, Weight, }; use frame_support::{construct_runtime, parameter_types}; use frame_system::EnsureRoot; 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; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_core::crypto::KeyTypeId; use sp_runtime::curve::PiecewiseLinear; use sp_runtime::traits::{BlakeTwo256, Block as BlockT, IdentityLookup, OpaqueKeys, Saturating}; use sp_runtime::{create_runtime_str, generic, impl_opaque_keys, Perbill}; use sp_std::boxed::Box; use sp_std::vec::Vec; #[cfg(feature = "std")] use sp_version::NativeVersion; use sp_version::RuntimeVersion; pub use constants::*; pub use primitives::*; pub use proposals_configuration::*; pub use runtime_api::*; use integration::proposals::{CouncilManager, ExtrinsicProposalEncoder, MembershipOriginValidator}; use governance::{council, election}; use storage::data_object_storage_registry; // Node dependencies pub use common; pub use content_directory; pub use content_directory::{ HashedTextMaxLength, InputValidationLengthConstraint, MaxNumber, TextMaxLength, VecMaxLength, }; pub use forum; pub use governance::election_params::ElectionParameters; pub use membership; #[cfg(any(feature = "std", test))] pub use pallet_balances::Call as BalancesCall; pub use pallet_staking::StakerStatus; pub use proposals_engine::ProposalParameters; pub use storage::{data_directory, data_object_type_registry}; pub use working_group; #[cfg(feature = "std")] /// Wasm binary unwrapped. If built with `BUILD_DUMMY_WASM_BINARY`, the function panics. pub fn wasm_binary_unwrap() -> &'static [u8] { WASM_BINARY.expect( "Development wasm binary is not available. This means the client is \ built with `BUILD_DUMMY_WASM_BINARY` flag and it is only usable for \ production chains. Please rebuild with the flag disabled.", ) } /// This runtime version. pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("joystream-node"), impl_name: create_runtime_str!("joystream-node"), authoring_version: 7, spec_version: 8, impl_version: 0, apis: crate::runtime_api::EXPORTED_RUNTIME_API_VERSIONS, transaction_version: 1, }; /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { NativeVersion { runtime_version: VERSION, can_author_with: Default::default(), } } parameter_types! { pub const BlockHashCount: BlockNumber = 250; /// We allow for 2 seconds of compute with a 6 second average block time. pub const MaximumBlockWeight: Weight = 2 * frame_support::weights::constants::WEIGHT_PER_SECOND; pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75); pub const MaximumBlockLength: u32 = 5 * 1024 * 1024; pub const Version: RuntimeVersion = VERSION; /// Assume 10% of weight for average on_initialize calls. pub MaximumExtrinsicWeight: Weight = AvailableBlockRatio::get().saturating_sub(AVERAGE_ON_INITIALIZE_WEIGHT) * MaximumBlockWeight::get(); } const AVERAGE_ON_INITIALIZE_WEIGHT: Perbill = Perbill::from_percent(10); // TODO: adjust weight impl frame_system::Trait for Runtime { type BaseCallFilter = (); type Origin = Origin; type Call = Call; type Index = Index; type BlockNumber = BlockNumber; type Hash = Hash; type Hashing = BlakeTwo256; type AccountId = AccountId; type Lookup = IdentityLookup; type Header = generic::Header; type Event = Event; type BlockHashCount = BlockHashCount; type MaximumBlockWeight = MaximumBlockWeight; type DbWeight = RocksDbWeight; type BlockExecutionWeight = BlockExecutionWeight; type ExtrinsicBaseWeight = ExtrinsicBaseWeight; type MaximumExtrinsicWeight = MaximumExtrinsicWeight; type MaximumBlockLength = MaximumBlockLength; type AvailableBlockRatio = AvailableBlockRatio; type Version = Version; type PalletInfo = PalletInfo; type AccountData = pallet_balances::AccountData; type OnNewAccount = (); type OnKilledAccount = (); type SystemWeightInfo = weights::frame_system::WeightInfo; } impl pallet_utility::Trait for Runtime { type Event = Event; type Call = Call; type WeightInfo = weights::pallet_utility::WeightInfo; } parameter_types! { pub const EpochDuration: u64 = EPOCH_DURATION_IN_SLOTS as u64; pub const ExpectedBlockTime: Moment = MILLISECS_PER_BLOCK; } impl pallet_babe::Trait for Runtime { type EpochDuration = EpochDuration; type ExpectedBlockTime = ExpectedBlockTime; type EpochChangeTrigger = pallet_babe::ExternalTrigger; type KeyOwnerProofSystem = Historical; type KeyOwnerProof = >::Proof; type KeyOwnerIdentification = >::IdentificationTuple; type HandleEquivocation = pallet_babe::EquivocationHandler; type WeightInfo = (); } impl pallet_grandpa::Trait for Runtime { type Event = Event; type Call = Call; type KeyOwnerProof = >::Proof; type KeyOwnerIdentification = >::IdentificationTuple; type KeyOwnerProofSystem = Historical; type HandleEquivocation = pallet_grandpa::EquivocationHandler; type WeightInfo = (); } impl frame_system::offchain::CreateSignedTransaction for Runtime where Call: From, { fn create_transaction>( call: Call, public: ::Signer, account: AccountId, nonce: Index, ) -> Option<( Call, ::SignaturePayload, )> { integration::transactions::create_transaction::(call, public, account, nonce) } } impl frame_system::offchain::SigningTypes for Runtime { type Public = ::Signer; type Signature = Signature; } impl frame_system::offchain::SendTransactionTypes for Runtime where Call: From, { type Extrinsic = UncheckedExtrinsic; type OverarchingCall = Call; } parameter_types! { pub const MinimumPeriod: Moment = SLOT_DURATION / 2; } impl pallet_timestamp::Trait for Runtime { type Moment = Moment; type OnTimestampSet = Babe; type MinimumPeriod = MinimumPeriod; type WeightInfo = weights::pallet_timestamp::WeightInfo; } parameter_types! { pub const ExistentialDeposit: u128 = 0; pub const TransferFee: u128 = 0; pub const CreationFee: u128 = 0; pub const InitialMembersBalance: u32 = 2000; pub const MaxLocks: u32 = 50; } impl pallet_balances::Trait for Runtime { type Balance = Balance; type DustRemoval = (); type Event = Event; type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; type WeightInfo = weights::pallet_balances::WeightInfo; type MaxLocks = MaxLocks; } parameter_types! { pub const TransactionByteFee: Balance = 0; // TODO: adjust fee } impl pallet_transaction_payment::Trait for Runtime { type Currency = Balances; type OnTransactionPayment = (); type TransactionByteFee = TransactionByteFee; type WeightToFee = integration::transactions::NoWeights; // TODO: adjust weight type FeeMultiplierUpdate = (); // TODO: adjust fee } impl pallet_sudo::Trait for Runtime { type Event = Event; type Call = Call; } parameter_types! { pub const UncleGenerations: BlockNumber = 0; } impl pallet_authorship::Trait for Runtime { type FindAuthor = pallet_session::FindAccountFromAuthorIndex; type UncleGenerations = UncleGenerations; type FilterUncle = (); type EventHandler = (Staking, ImOnline); } impl_opaque_keys! { pub struct SessionKeys { pub grandpa: Grandpa, pub babe: Babe, pub im_online: ImOnline, pub authority_discovery: AuthorityDiscovery, } } // NOTE: `SessionHandler` and `SessionKeys` are co-dependent: One key will be used for each handler. // The number and order of items in `SessionHandler` *MUST* be the same number and order of keys in // `SessionKeys`. // TODO: Introduce some structure to tie these together to make it a bit less of a footgun. This // should be easy, since OneSessionHandler trait provides the `Key` as an associated type. #2858 parameter_types! { pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(17); } impl pallet_session::Trait for Runtime { type Event = Event; type ValidatorId = AccountId; type ValidatorIdOf = pallet_staking::StashOf; type ShouldEndSession = Babe; type NextSessionRotation = Babe; type SessionManager = pallet_session::historical::NoteHistoricalRoot; type SessionHandler = ::KeyTypeIdProviders; type Keys = SessionKeys; type DisabledValidatorsThreshold = DisabledValidatorsThreshold; type WeightInfo = weights::pallet_session::WeightInfo; } impl pallet_session::historical::Trait for Runtime { type FullIdentification = pallet_staking::Exposure; type FullIdentificationOf = pallet_staking::ExposureOf; } pallet_staking_reward_curve::build! { const REWARD_CURVE: PiecewiseLinear<'static> = curve!( min_inflation: 0_050_000, max_inflation: 0_750_000, ideal_stake: 0_250_000, falloff: 0_050_000, max_piece_count: 100, test_precision: 0_005_000, ); } parameter_types! { pub const SessionDuration: BlockNumber = EPOCH_DURATION_IN_SLOTS as _; pub const ImOnlineUnsignedPriority: TransactionPriority = TransactionPriority::max_value(); /// We prioritize im-online heartbeats over election solution submission. pub const StakingUnsignedPriority: TransactionPriority = TransactionPriority::max_value() / 2; } parameter_types! { pub const SessionsPerEra: sp_staking::SessionIndex = 6; pub const BondingDuration: pallet_staking::EraIndex = BONDING_DURATION; pub const SlashDeferDuration: pallet_staking::EraIndex = BONDING_DURATION - 1; // 'slightly less' than the bonding duration. pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE; pub const MaxNominatorRewardedPerValidator: u32 = 64; pub const ElectionLookahead: BlockNumber = EPOCH_DURATION_IN_BLOCKS / 4; pub const MaxIterations: u32 = 10; // 0.05%. The higher the value, the more strict solution acceptance becomes. pub MinSolutionScoreBump: Perbill = Perbill::from_rational_approximation(5u32, 10_000); } impl pallet_staking::Trait for Runtime { type Currency = Balances; type UnixTime = Timestamp; type CurrencyToVote = common::currency::CurrencyToVoteHandler; type RewardRemainder = (); // Could be Treasury. type Event = Event; type Slash = (); // Where to send the slashed funds. Could be Treasury. type Reward = (); // Rewards are minted from the void. type SessionsPerEra = SessionsPerEra; type BondingDuration = BondingDuration; type SlashDeferDuration = SlashDeferDuration; type SlashCancelOrigin = EnsureRoot; // Requires sudo. Parity recommends: a super-majority of the council can cancel the slash. type SessionInterface = Self; type RewardCurve = RewardCurve; type NextNewSession = Session; type ElectionLookahead = ElectionLookahead; type Call = Call; type MaxIterations = MaxIterations; type MinSolutionScoreBump = MinSolutionScoreBump; type MaxNominatorRewardedPerValidator = MaxNominatorRewardedPerValidator; type UnsignedPriority = StakingUnsignedPriority; type WeightInfo = weights::pallet_staking::WeightInfo; } impl pallet_im_online::Trait for Runtime { type AuthorityId = ImOnlineId; type Event = Event; type SessionDuration = SessionDuration; type ReportUnresponsiveness = Offences; type UnsignedPriority = ImOnlineUnsignedPriority; type WeightInfo = weights::pallet_im_online::WeightInfo; } parameter_types! { pub OffencesWeightSoftLimit: Weight = Perbill::from_percent(60) * MaximumBlockWeight::get(); } impl pallet_offences::Trait for Runtime { type Event = Event; type IdentificationTuple = pallet_session::historical::IdentificationTuple; type OnOffenceHandler = Staking; type WeightSoftLimit = OffencesWeightSoftLimit; } impl pallet_authority_discovery::Trait for Runtime {} parameter_types! { pub const WindowSize: BlockNumber = 101; pub const ReportLatency: BlockNumber = 1000; } impl pallet_finality_tracker::Trait for Runtime { type OnFinalizationStalled = (); type WindowSize = WindowSize; type ReportLatency = ReportLatency; } type EntityId = ::EntityId; parameter_types! { pub const PropertyNameLengthConstraint: InputValidationLengthConstraint = InputValidationLengthConstraint::new(1, 49); pub const PropertyDescriptionLengthConstraint: InputValidationLengthConstraint = InputValidationLengthConstraint::new(1, 500); pub const ClassNameLengthConstraint: InputValidationLengthConstraint = InputValidationLengthConstraint::new(1, 49); pub const ClassDescriptionLengthConstraint: InputValidationLengthConstraint = InputValidationLengthConstraint::new(1, 500); pub const MaxNumberOfClasses: MaxNumber = 100; pub const MaxNumberOfMaintainersPerClass: MaxNumber = 10; pub const MaxNumberOfSchemasPerClass: MaxNumber = 20; pub const MaxNumberOfPropertiesPerSchema: MaxNumber = 40; pub const MaxNumberOfEntitiesPerClass: MaxNumber = 400; pub const MaxNumberOfCuratorsPerGroup: MaxNumber = 50; pub const MaxNumberOfOperationsDuringAtomicBatching: MaxNumber = 500; pub const VecMaxLengthConstraint: VecMaxLength = 200; pub const TextMaxLengthConstraint: TextMaxLength = 5000; pub const HashedTextMaxLengthConstraint: HashedTextMaxLength = Some(25000); pub const IndividualEntitiesCreationLimit: EntityId = 50; } impl content_directory::Trait for Runtime { type Event = Event; type Nonce = u64; type ClassId = u64; type EntityId = u64; type PropertyNameLengthConstraint = PropertyNameLengthConstraint; type PropertyDescriptionLengthConstraint = PropertyDescriptionLengthConstraint; type ClassNameLengthConstraint = ClassNameLengthConstraint; type ClassDescriptionLengthConstraint = ClassDescriptionLengthConstraint; type MaxNumberOfClasses = MaxNumberOfClasses; type MaxNumberOfMaintainersPerClass = MaxNumberOfMaintainersPerClass; type MaxNumberOfSchemasPerClass = MaxNumberOfSchemasPerClass; type MaxNumberOfPropertiesPerSchema = MaxNumberOfPropertiesPerSchema; type MaxNumberOfEntitiesPerClass = MaxNumberOfEntitiesPerClass; type MaxNumberOfCuratorsPerGroup = MaxNumberOfCuratorsPerGroup; type MaxNumberOfOperationsDuringAtomicBatching = MaxNumberOfOperationsDuringAtomicBatching; type VecMaxLengthConstraint = VecMaxLengthConstraint; type TextMaxLengthConstraint = TextMaxLengthConstraint; type HashedTextMaxLengthConstraint = HashedTextMaxLengthConstraint; type IndividualEntitiesCreationLimit = IndividualEntitiesCreationLimit; } impl minting::Trait for Runtime { type Currency = ::Currency; type MintId = u64; } impl recurring_rewards::Trait for Runtime { type PayoutStatusHandler = (); // TODO - deal with successful and failed payouts type RecipientId = u64; type RewardRelationshipId = u64; } parameter_types! { pub const StakePoolId: [u8; 8] = *b"joystake"; } impl stake::Trait for Runtime { type Currency = ::Currency; type StakePoolId = StakePoolId; type StakingEventsHandler = (); type StakeId = u64; type SlashId = u64; } impl common::currency::GovernanceCurrency for Runtime { type Currency = pallet_balances::Module; } impl governance::election::Trait for Runtime { type Event = Event; type CouncilElected = (Council, integration::proposals::CouncilElectedHandler); } impl governance::council::Trait for Runtime { type Event = Event; type CouncilTermEnded = (CouncilElection,); } impl memo::Trait for Runtime { type Event = Event; } parameter_types! { pub const MaxObjectsPerInjection: u32 = 100; } impl storage::data_object_type_registry::Trait for Runtime { type Event = Event; type DataObjectTypeId = u64; } impl storage::data_directory::Trait for Runtime { type Event = Event; type ContentId = ContentId; type StorageProviderHelper = integration::storage::StorageProviderHelper; type IsActiveDataObjectType = DataObjectTypeRegistry; type MemberOriginValidator = MembershipOriginValidator; type MaxObjectsPerInjection = MaxObjectsPerInjection; } impl storage::data_object_storage_registry::Trait for Runtime { type Event = Event; type DataObjectStorageRelationshipId = u64; type ContentIdExists = DataDirectory; } impl membership::Trait for Runtime { type Event = Event; type MemberId = MemberId; type PaidTermId = u64; type SubscriptionId = u64; type ActorId = ActorId; } parameter_types! { pub const MaxCategoryDepth: u64 = 5; pub const MaxSubcategories: u64 = 20; pub const MaxThreadsInCategory: u64 = 20; pub const MaxPostsInThread: u64 = 20; pub const MaxModeratorsForCategory: u64 = 20; pub const MaxCategories: u64 = 20; pub const MaxPollAlternativesNumber: u64 = 20; } pub struct MapLimits; impl forum::StorageLimits for MapLimits { type MaxSubcategories = MaxSubcategories; type MaxThreadsInCategory = MaxThreadsInCategory; type MaxPostsInThread = MaxPostsInThread; type MaxModeratorsForCategory = MaxModeratorsForCategory; type MaxCategories = MaxCategories; type MaxPollAlternativesNumber = MaxPollAlternativesNumber; } // Alias for forum working group type ForumGroup = working_group::Module; impl forum::Trait for Runtime { type Event = Event; //type MembershipRegistry = ShimMembershipRegistry; type ThreadId = ThreadId; type PostId = PostId; type ForumUserId = ForumUserId; type ModeratorId = ModeratorId; type CategoryId = u64; type PostReactionId = u64; type MaxCategoryDepth = MaxCategoryDepth; type MapLimits = MapLimits; fn is_lead(_account_id: &AccountId) -> bool { // get current lead id let maybe_current_lead_id = ForumGroup::::current_lead(); if let Some(ref current_lead_id) = maybe_current_lead_id { if let Ok(worker) = working_group::ensure_worker_exists::< Runtime, ForumWorkingGroupInstance, >(current_lead_id) { *_account_id == worker.role_account_id } else { false } } else { false } } fn is_forum_member(_account_id: &Self::AccountId, _forum_user_id: &Self::ForumUserId) -> bool { membership::Module::::ensure_is_controller_account_for_member( _forum_user_id, _account_id, ) .is_ok() } fn is_moderator(_account_id: &Self::AccountId, _moderator_id: &Self::ModeratorId) -> bool { if let Ok(worker) = working_group::ensure_worker_exists::(_moderator_id) { *_account_id == worker.role_account_id } else { false } } fn calculate_hash(text: &[u8]) -> Self::Hash { Self::Hash::from_slice(text) } } // The forum working group instance alias. pub type ForumWorkingGroupInstance = working_group::Instance1; // The storage working group instance alias. pub type StorageWorkingGroupInstance = working_group::Instance2; // The content directory working group instance alias. pub type ContentDirectoryWorkingGroupInstance = working_group::Instance3; parameter_types! { pub const MaxWorkerNumberLimit: u32 = 100; pub const MinUnstakingPeriodLimit: u32 = 43200; pub const ForumWorkingGroupRewardPeriod: u32 = 14400 + 10; pub const StorageWorkingGroupRewardPeriod: u32 = 14400 + 20; pub const ContentWorkingGroupRewardPeriod: u32 = 14400 + 30; pub const StorageWorkingGroupLockId: LockIdentifier = [6; 8]; pub const ContentWorkingGroupLockId: LockIdentifier = [7; 8]; pub const ForumGroupLockId: LockIdentifier = [8; 8]; } impl working_group::Trait for Runtime { type Event = Event; type MaxWorkerNumberLimit = MaxWorkerNumberLimit; type StakingHandler = staking_handler::StakingManager; type MemberOriginValidator = MembershipOriginValidator; type MinUnstakingPeriodLimit = MinUnstakingPeriodLimit; type RewardPeriod = ForumWorkingGroupRewardPeriod; } impl working_group::Trait for Runtime { type Event = Event; type MaxWorkerNumberLimit = MaxWorkerNumberLimit; type StakingHandler = staking_handler::StakingManager; type MemberOriginValidator = MembershipOriginValidator; type MinUnstakingPeriodLimit = MinUnstakingPeriodLimit; type RewardPeriod = StorageWorkingGroupRewardPeriod; } impl working_group::Trait for Runtime { type Event = Event; type MaxWorkerNumberLimit = MaxWorkerNumberLimit; type StakingHandler = staking_handler::StakingManager; type MemberOriginValidator = MembershipOriginValidator; type MinUnstakingPeriodLimit = MinUnstakingPeriodLimit; type RewardPeriod = ContentWorkingGroupRewardPeriod; } impl service_discovery::Trait for Runtime { type Event = Event; } parameter_types! { pub const ProposalCancellationFee: u64 = 10000; pub const ProposalRejectionFee: u64 = 5000; pub const ProposalTitleMaxLength: u32 = 40; pub const ProposalDescriptionMaxLength: u32 = 3000; pub const ProposalMaxActiveProposalLimit: u32 = 5; pub const ProposalsLockId: LockIdentifier = [5; 8]; } impl proposals_engine::Trait for Runtime { type Event = Event; type ProposerOriginValidator = MembershipOriginValidator; type VoterOriginValidator = CouncilManager; type TotalVotersCounter = CouncilManager; type ProposalId = u32; type StakingHandler = staking_handler::StakingManager; type CancellationFee = ProposalCancellationFee; type RejectionFee = ProposalRejectionFee; type TitleMaxLength = ProposalTitleMaxLength; type DescriptionMaxLength = ProposalDescriptionMaxLength; type MaxActiveProposalLimit = ProposalMaxActiveProposalLimit; type DispatchableCallCode = Call; type ProposalObserver = ProposalsCodex; type WeightInfo = weights::proposals_engine::WeightInfo; } impl Default for Call { fn default() -> Self { panic!("shouldn't call default for Call"); } } parameter_types! { pub const MaxWhiteListSize: u32 = 20; } impl proposals_discussion::Trait for Runtime { type Event = Event; type AuthorOriginValidator = MembershipOriginValidator; type CouncilOriginValidator = CouncilManager; type ThreadId = ThreadId; type PostId = PostId; type MaxWhiteListSize = MaxWhiteListSize; type WeightInfo = weights::proposals_discussion::WeightInfo; } parameter_types! { pub const TextProposalMaxLength: u32 = 5_000; pub const RuntimeUpgradeWasmProposalMaxLength: u32 = 3_000_000; } impl proposals_codex::Trait for Runtime { type TextProposalMaxLength = TextProposalMaxLength; type RuntimeUpgradeWasmProposalMaxLength = RuntimeUpgradeWasmProposalMaxLength; type MembershipOriginValidator = MembershipOriginValidator; type ProposalEncoder = ExtrinsicProposalEncoder; type SetValidatorCountProposalParameters = SetValidatorCountProposalParameters; type RuntimeUpgradeProposalParameters = RuntimeUpgradeProposalParameters; type TextProposalParameters = TextProposalParameters; type SpendingProposalParameters = SpendingProposalParameters; type AddWorkingGroupOpeningProposalParameters = AddWorkingGroupOpeningProposalParameters; type BeginReviewWorkingGroupApplicationsProposalParameters = BeginReviewWorkingGroupApplicationsProposalParameters; type FillWorkingGroupOpeningProposalParameters = FillWorkingGroupOpeningProposalParameters; type SetWorkingGroupBudgetCapacityProposalParameters = SetWorkingGroupBudgetCapacityProposalParameters; type DecreaseWorkingGroupLeaderStakeProposalParameters = DecreaseWorkingGroupLeaderStakeProposalParameters; type SlashWorkingGroupLeaderStakeProposalParameters = SlashWorkingGroupLeaderStakeProposalParameters; type SetWorkingGroupLeaderRewardProposalParameters = SetWorkingGroupLeaderRewardProposalParameters; type TerminateWorkingGroupLeaderRoleProposalParameters = TerminateWorkingGroupLeaderRoleProposalParameters; type AmendConstitutionProposalParameters = AmendConstitutionProposalParameters; } impl constitution::Trait for Runtime { type Event = Event; } parameter_types! { pub const TombstoneDeposit: Balance = 1; // TODO: adjust fee pub const RentByteFee: Balance = 1; // TODO: adjust fee pub const RentDepositOffset: Balance = 0; // no rent deposit pub const SurchargeReward: Balance = 0; // no reward } /// Forum identifiers for user, moderator and category pub type ForumUserId = u64; pub type ModeratorId = u64; pub type CategoryId = u64; /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know /// the specifics of the runtime. They can then be made to be agnostic over specific formats /// of data like extrinsics, allowing for them to continue syncing the network through upgrades /// to even the core datastructures. pub mod opaque { use super::*; pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; /// Opaque block header type. pub type Header = generic::Header; /// Opaque block type. pub type Block = generic::Block; /// Opaque block identifier type. pub type BlockId = generic::BlockId; } construct_runtime!( pub enum Runtime where Block = Block, NodeBlock = opaque::Block, UncheckedExtrinsic = UncheckedExtrinsic { // Substrate System: frame_system::{Module, Call, Storage, Config, Event}, Utility: pallet_utility::{Module, Call, Event}, Babe: pallet_babe::{Module, Call, Storage, Config, Inherent, ValidateUnsigned}, Timestamp: pallet_timestamp::{Module, Call, Storage, Inherent}, Authorship: pallet_authorship::{Module, Call, Storage, Inherent}, Balances: pallet_balances::{Module, Call, Storage, Config, Event}, TransactionPayment: pallet_transaction_payment::{Module, Storage}, Staking: pallet_staking::{Module, Call, Config, Storage, Event, ValidateUnsigned}, Session: pallet_session::{Module, Call, Storage, Event, Config}, Historical: pallet_session_historical::{Module}, FinalityTracker: pallet_finality_tracker::{Module, Call, Inherent}, Grandpa: pallet_grandpa::{Module, Call, Storage, Config, Event}, ImOnline: pallet_im_online::{Module, Call, Storage, Event, ValidateUnsigned, Config}, AuthorityDiscovery: pallet_authority_discovery::{Module, Call, Config}, Offences: pallet_offences::{Module, Call, Storage, Event}, RandomnessCollectiveFlip: pallet_randomness_collective_flip::{Module, Call, Storage}, Sudo: pallet_sudo::{Module, Call, Config, Storage, Event}, // Joystream CouncilElection: election::{Module, Call, Storage, Event, Config}, Council: council::{Module, Call, Storage, Event, Config}, Memo: memo::{Module, Call, Storage, Event}, Members: membership::{Module, Call, Storage, Event, Config}, Forum: forum::{Module, Call, Storage, Event, Config}, Stake: stake::{Module, Call, Storage}, Minting: minting::{Module, Call, Storage}, RecurringRewards: recurring_rewards::{Module, Call, Storage}, ContentDirectory: content_directory::{Module, Call, Storage, Event, Config}, Constitution: constitution::{Module, Call, Storage, Event}, // --- Storage DataObjectTypeRegistry: data_object_type_registry::{Module, Call, Storage, Event, Config}, DataDirectory: data_directory::{Module, Call, Storage, Event}, DataObjectStorageRegistry: data_object_storage_registry::{Module, Call, Storage, Event, Config}, Discovery: service_discovery::{Module, Call, Storage, Event}, // --- Proposals ProposalsEngine: proposals_engine::{Module, Call, Storage, Event}, ProposalsDiscussion: proposals_discussion::{Module, Call, Storage, Event}, ProposalsCodex: proposals_codex::{Module, Call, Storage}, // --- Working groups ForumWorkingGroup: working_group::::{Module, Call, Storage, Event}, StorageWorkingGroup: working_group::::{Module, Call, Storage, Event}, ContentDirectoryWorkingGroup: working_group::::{Module, Call, Storage, Event}, } );