lib.rs 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909
  1. //! The Joystream Substrate Node runtime.
  2. #![cfg_attr(not(feature = "std"), no_std)]
  3. // `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256.
  4. #![recursion_limit = "256"]
  5. // srml_staking_reward_curve::build! - substrate macro produces a warning.
  6. // TODO: remove after post-Rome substrate upgrade
  7. #![allow(array_into_iter)]
  8. // Runtime integration tests
  9. mod tests;
  10. // Make the WASM binary available.
  11. // This is required only by the node build.
  12. // A dummy wasm_binary.rs will be built for the IDE.
  13. #[cfg(feature = "std")]
  14. include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs"));
  15. mod integration;
  16. use authority_discovery_primitives::{
  17. AuthorityId as EncodedAuthorityId, Signature as EncodedSignature,
  18. };
  19. use babe_primitives::{AuthorityId as BabeId, AuthoritySignature as BabeSignature};
  20. use codec::{Decode, Encode};
  21. use grandpa::fg_primitives;
  22. use grandpa::{AuthorityId as GrandpaId, AuthorityWeight as GrandpaWeight};
  23. use im_online::sr25519::AuthorityId as ImOnlineId;
  24. use primitives::OpaqueMetadata;
  25. use rstd::prelude::*;
  26. use sr_primitives::curve::PiecewiseLinear;
  27. use sr_primitives::traits::{
  28. BlakeTwo256, Block as BlockT, IdentifyAccount, NumberFor, StaticLookup, Verify,
  29. };
  30. use sr_primitives::weights::Weight;
  31. use sr_primitives::{
  32. create_runtime_str, generic, impl_opaque_keys, transaction_validity::TransactionValidity,
  33. ApplyResult, MultiSignature,
  34. };
  35. use substrate_client::{
  36. block_builder::api::{self as block_builder_api, CheckInherentsResult, InherentData},
  37. impl_runtime_apis, runtime_api as client_api,
  38. };
  39. use system::offchain::TransactionSubmitter;
  40. #[cfg(feature = "std")]
  41. use version::NativeVersion;
  42. use version::RuntimeVersion;
  43. // A few exports that help ease life for downstream crates.
  44. pub use balances::Call as BalancesCall;
  45. #[cfg(any(feature = "std", test))]
  46. pub use sr_primitives::BuildStorage;
  47. pub use sr_primitives::{Perbill, Permill};
  48. pub use srml_support::{
  49. construct_runtime, parameter_types, traits::Currency, traits::Imbalance, traits::Randomness,
  50. StorageLinkedMap, StorageMap, StorageValue,
  51. };
  52. pub use staking::StakerStatus;
  53. pub use timestamp::Call as TimestampCall;
  54. use integration::proposals::{CouncilManager, ExtrinsicProposalEncoder, MembershipOriginValidator};
  55. pub use proposals_codex::ProposalsConfigParameters;
  56. pub use common;
  57. pub use forum;
  58. pub use working_group;
  59. pub use governance::election_params::ElectionParameters;
  60. use governance::{council, election};
  61. use membership::members;
  62. use storage::{data_directory, data_object_storage_registry, data_object_type_registry};
  63. pub use versioned_store;
  64. pub use content_working_group as content_wg;
  65. mod migration;
  66. /// Alias for ContentId, used in various places.
  67. pub type ContentId = primitives::H256;
  68. /// An index to a block.
  69. pub type BlockNumber = u32;
  70. /// Alias to 512-bit hash when used in the context of a transaction signature on the chain.
  71. pub type Signature = MultiSignature;
  72. /// Some way of identifying an account on the chain. We intentionally make it equivalent
  73. /// to the public key of our transaction signing scheme.
  74. pub type AccountId = <<Signature as Verify>::Signer as IdentifyAccount>::AccountId;
  75. /// The type for looking up accounts. We don't expect more than 4 billion of them, but you
  76. /// never know...
  77. pub type AccountIndex = u32;
  78. /// Balance of an account.
  79. pub type Balance = u128;
  80. /// Index of a transaction in the chain.
  81. pub type Index = u32;
  82. /// A hash of some data used by the chain.
  83. pub type Hash = primitives::H256;
  84. /// Digest item type.
  85. pub type DigestItem = generic::DigestItem<Hash>;
  86. /// Moment type
  87. pub type Moment = u64;
  88. /// Credential type
  89. pub type Credential = u64;
  90. /// Represents a thread identifier for both Forum and Proposals Discussion
  91. ///
  92. /// Note: Both modules expose type names ThreadId and PostId (which are defined on their Trait) and
  93. /// used in state storage and dispatchable method's argument types,
  94. /// and are therefore part of the public API/metadata of the runtime.
  95. /// In the currenlty version the polkadot-js/api that is used and is compatible with the runtime,
  96. /// the type registry has flat namespace and its not possible
  97. /// to register identically named types from different modules, separately. And so we MUST configure
  98. /// the underlying types to be identicaly to avoid issues with encoding/decoding these types on the client side.
  99. pub type ThreadId = u64;
  100. /// Represents a post identifier for both Forum and Proposals Discussion
  101. ///
  102. /// See the Note about ThreadId
  103. pub type PostId = u64;
  104. /// Represent an actor in membership group, which is the same in the working groups.
  105. pub type ActorId = u64;
  106. /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know
  107. /// the specifics of the runtime. They can then be made to be agnostic over specific formats
  108. /// of data like extrinsics, allowing for them to continue syncing the network through upgrades
  109. /// to even the core datastructures.
  110. pub mod opaque {
  111. use super::*;
  112. pub use sr_primitives::OpaqueExtrinsic as UncheckedExtrinsic;
  113. /// Opaque block header type.
  114. pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
  115. /// Opaque block type.
  116. pub type Block = generic::Block<Header, UncheckedExtrinsic>;
  117. /// Opaque block identifier type.
  118. pub type BlockId = generic::BlockId<Block>;
  119. pub type SessionHandlers = (Grandpa, Babe, ImOnline);
  120. impl_opaque_keys! {
  121. pub struct SessionKeys {
  122. pub grandpa: Grandpa,
  123. pub babe: Babe,
  124. pub im_online: ImOnline,
  125. }
  126. }
  127. }
  128. /// This runtime version.
  129. pub const VERSION: RuntimeVersion = RuntimeVersion {
  130. spec_name: create_runtime_str!("joystream-node"),
  131. impl_name: create_runtime_str!("joystream-node"),
  132. authoring_version: 6,
  133. spec_version: 20,
  134. impl_version: 0,
  135. apis: RUNTIME_API_VERSIONS,
  136. };
  137. /// Constants for Babe.
  138. /// Since BABE is probabilistic this is the average expected block time that
  139. /// we are targetting. Blocks will be produced at a minimum duration defined
  140. /// by `SLOT_DURATION`, but some slots will not be allocated to any
  141. /// authority and hence no block will be produced. We expect to have this
  142. /// block time on average following the defined slot duration and the value
  143. /// of `c` configured for BABE (where `1 - c` represents the probability of
  144. /// a slot being empty).
  145. /// This value is only used indirectly to define the unit constants below
  146. /// that are expressed in blocks. The rest of the code should use
  147. /// `SLOT_DURATION` instead (like the timestamp module for calculating the
  148. /// minimum period).
  149. /// <https://research.web3.foundation/en/latest/polkadot/BABE/Babe/#6-practical-results>
  150. pub const MILLISECS_PER_BLOCK: Moment = 6000;
  151. pub const SECS_PER_BLOCK: Moment = MILLISECS_PER_BLOCK / 1000;
  152. pub const SLOT_DURATION: Moment = 6000;
  153. pub const EPOCH_DURATION_IN_BLOCKS: BlockNumber = 10 * MINUTES;
  154. pub const EPOCH_DURATION_IN_SLOTS: u64 = {
  155. const SLOT_FILL_RATE: f64 = MILLISECS_PER_BLOCK as f64 / SLOT_DURATION as f64;
  156. (EPOCH_DURATION_IN_BLOCKS as f64 * SLOT_FILL_RATE) as u64
  157. };
  158. // These time units are defined in number of blocks.
  159. pub const MINUTES: BlockNumber = 60 / (SECS_PER_BLOCK as BlockNumber);
  160. pub const HOURS: BlockNumber = MINUTES * 60;
  161. pub const DAYS: BlockNumber = HOURS * 24;
  162. // 1 in 4 blocks (on average, not counting collisions) will be primary babe blocks.
  163. pub const PRIMARY_PROBABILITY: (u64, u64) = (1, 4);
  164. /// The version infromation used to identify this runtime when compiled natively.
  165. #[cfg(feature = "std")]
  166. pub fn native_version() -> NativeVersion {
  167. NativeVersion {
  168. runtime_version: VERSION,
  169. can_author_with: Default::default(),
  170. }
  171. }
  172. parameter_types! {
  173. pub const BlockHashCount: BlockNumber = 250;
  174. pub const MaximumBlockWeight: Weight = 1_000_000_000;
  175. pub const AvailableBlockRatio: Perbill = Perbill::from_percent(75);
  176. pub const MaximumBlockLength: u32 = 5 * 1024 * 1024;
  177. pub const Version: RuntimeVersion = VERSION;
  178. }
  179. impl system::Trait for Runtime {
  180. /// The identifier used to distinguish between accounts.
  181. type AccountId = AccountId;
  182. /// The aggregated dispatch type that is available for extrinsics.
  183. type Call = Call;
  184. /// The lookup mechanism to get account ID from whatever is passed in dispatchers.
  185. type Lookup = Indices;
  186. /// The index type for storing how many extrinsics an account has signed.
  187. type Index = Index;
  188. /// The index type for blocks.
  189. type BlockNumber = BlockNumber;
  190. /// The type for hashing blocks and tries.
  191. type Hash = Hash;
  192. /// The hashing algorithm used.
  193. type Hashing = BlakeTwo256;
  194. /// The header type.
  195. type Header = generic::Header<BlockNumber, BlakeTwo256>;
  196. /// The ubiquitous event type.
  197. type Event = Event;
  198. /// The ubiquitous origin type.
  199. type Origin = Origin;
  200. /// Maximum number of block number to block hash mappings to keep (oldest pruned first).
  201. type BlockHashCount = BlockHashCount;
  202. /// Maximum weight of each block. With a default weight system of 1byte == 1weight, 4mb is ok.
  203. type MaximumBlockWeight = MaximumBlockWeight;
  204. /// Maximum size of all encoded transactions (in bytes) that are allowed in one block.
  205. type MaximumBlockLength = MaximumBlockLength;
  206. /// Portion of the block weight that is available to all normal transactions.
  207. type AvailableBlockRatio = AvailableBlockRatio;
  208. type Version = Version;
  209. }
  210. parameter_types! {
  211. pub const EpochDuration: u64 = EPOCH_DURATION_IN_SLOTS as u64;
  212. pub const ExpectedBlockTime: Moment = MILLISECS_PER_BLOCK;
  213. }
  214. impl babe::Trait for Runtime {
  215. type EpochDuration = EpochDuration;
  216. type ExpectedBlockTime = ExpectedBlockTime;
  217. type EpochChangeTrigger = babe::ExternalTrigger;
  218. }
  219. impl grandpa::Trait for Runtime {
  220. type Event = Event;
  221. }
  222. impl indices::Trait for Runtime {
  223. /// The type for recording indexing into the account enumeration. If this ever overflows, there
  224. /// will be problems!
  225. type AccountIndex = u32;
  226. /// Use the standard means of resolving an index hint from an id.
  227. type ResolveHint = indices::SimpleResolveHint<Self::AccountId, Self::AccountIndex>;
  228. /// Determine whether an account is dead.
  229. type IsDeadAccount = Balances;
  230. /// The ubiquitous event type.
  231. type Event = Event;
  232. }
  233. parameter_types! {
  234. pub const MinimumPeriod: Moment = SLOT_DURATION / 2;
  235. }
  236. impl timestamp::Trait for Runtime {
  237. /// A timestamp: milliseconds since the unix epoch.
  238. type Moment = Moment;
  239. type OnTimestampSet = Babe;
  240. type MinimumPeriod = MinimumPeriod;
  241. }
  242. parameter_types! {
  243. pub const ExistentialDeposit: u128 = 0;
  244. pub const TransferFee: u128 = 0;
  245. pub const CreationFee: u128 = 0;
  246. pub const TransactionBaseFee: u128 = 1;
  247. pub const TransactionByteFee: u128 = 0;
  248. pub const InitialMembersBalance: u32 = 2000;
  249. }
  250. impl balances::Trait for Runtime {
  251. /// The type for recording an account's balance.
  252. type Balance = Balance;
  253. /// What to do if an account's free balance gets zeroed.
  254. type OnFreeBalanceZero = (Staking, Session);
  255. /// What to do if a new account is created.
  256. type OnNewAccount = (); // Indices; // disable use of Indices feature
  257. /// The ubiquitous event type.
  258. type Event = Event;
  259. type DustRemoval = ();
  260. type TransferPayment = ();
  261. type ExistentialDeposit = ExistentialDeposit;
  262. type TransferFee = TransferFee;
  263. type CreationFee = CreationFee;
  264. }
  265. impl transaction_payment::Trait for Runtime {
  266. type Currency = Balances;
  267. type OnTransactionPayment = ();
  268. type TransactionBaseFee = TransactionBaseFee;
  269. type TransactionByteFee = TransactionByteFee;
  270. type WeightToFee = ();
  271. type FeeMultiplierUpdate = ();
  272. }
  273. impl sudo::Trait for Runtime {
  274. type Event = Event;
  275. type Proposal = Call;
  276. }
  277. parameter_types! {
  278. pub const UncleGenerations: BlockNumber = 5;
  279. }
  280. impl authorship::Trait for Runtime {
  281. type FindAuthor = session::FindAccountFromAuthorIndex<Self, Babe>;
  282. type UncleGenerations = UncleGenerations;
  283. type FilterUncle = ();
  284. type EventHandler = Staking;
  285. }
  286. type SessionHandlers = (Grandpa, Babe, ImOnline);
  287. impl_opaque_keys! {
  288. pub struct SessionKeys {
  289. pub grandpa: Grandpa,
  290. pub babe: Babe,
  291. pub im_online: ImOnline,
  292. }
  293. }
  294. // NOTE: `SessionHandler` and `SessionKeys` are co-dependent: One key will be used for each handler.
  295. // The number and order of items in `SessionHandler` *MUST* be the same number and order of keys in
  296. // `SessionKeys`.
  297. // TODO: Introduce some structure to tie these together to make it a bit less of a footgun. This
  298. // should be easy, since OneSessionHandler trait provides the `Key` as an associated type. #2858
  299. parameter_types! {
  300. pub const DisabledValidatorsThreshold: Perbill = Perbill::from_percent(17);
  301. }
  302. impl session::Trait for Runtime {
  303. type OnSessionEnding = Staking;
  304. type SessionHandler = SessionHandlers;
  305. type ShouldEndSession = Babe;
  306. type Event = Event;
  307. type Keys = SessionKeys;
  308. type ValidatorId = AccountId;
  309. type ValidatorIdOf = staking::StashOf<Self>;
  310. type SelectInitialValidators = Staking;
  311. type DisabledValidatorsThreshold = DisabledValidatorsThreshold;
  312. }
  313. impl session::historical::Trait for Runtime {
  314. type FullIdentification = staking::Exposure<AccountId, Balance>;
  315. type FullIdentificationOf = staking::ExposureOf<Runtime>;
  316. }
  317. srml_staking_reward_curve::build! {
  318. const REWARD_CURVE: PiecewiseLinear<'static> = curve!(
  319. min_inflation: 0_025_000,
  320. max_inflation: 0_300_000,
  321. ideal_stake: 0_300_000,
  322. falloff: 0_050_000,
  323. max_piece_count: 100,
  324. test_precision: 0_005_000,
  325. );
  326. }
  327. parameter_types! {
  328. pub const SessionsPerEra: sr_staking_primitives::SessionIndex = 6;
  329. pub const BondingDuration: staking::EraIndex = 24;
  330. pub const RewardCurve: &'static PiecewiseLinear<'static> = &REWARD_CURVE;
  331. }
  332. impl staking::Trait for Runtime {
  333. type Currency = Balances;
  334. type Time = Timestamp;
  335. type CurrencyToVote = common::currency::CurrencyToVoteHandler;
  336. type RewardRemainder = ();
  337. type Event = Event;
  338. type Slash = (); // where to send the slashed funds.
  339. type Reward = (); // rewards are minted from the void
  340. type SessionsPerEra = SessionsPerEra;
  341. type BondingDuration = BondingDuration;
  342. type SessionInterface = Self;
  343. type RewardCurve = RewardCurve;
  344. }
  345. type SubmitTransaction = TransactionSubmitter<ImOnlineId, Runtime, UncheckedExtrinsic>;
  346. parameter_types! {
  347. pub const SessionDuration: BlockNumber = EPOCH_DURATION_IN_SLOTS as _;
  348. }
  349. impl im_online::Trait for Runtime {
  350. type AuthorityId = ImOnlineId;
  351. type Call = Call;
  352. type Event = Event;
  353. type SubmitTransaction = SubmitTransaction;
  354. type ReportUnresponsiveness = Offences;
  355. type SessionDuration = SessionDuration;
  356. }
  357. impl offences::Trait for Runtime {
  358. type Event = Event;
  359. type IdentificationTuple = session::historical::IdentificationTuple<Self>;
  360. type OnOffenceHandler = Staking;
  361. }
  362. impl authority_discovery::Trait for Runtime {
  363. type AuthorityId = BabeId;
  364. }
  365. parameter_types! {
  366. pub const WindowSize: BlockNumber = 101;
  367. pub const ReportLatency: BlockNumber = 1000;
  368. }
  369. impl finality_tracker::Trait for Runtime {
  370. type OnFinalizationStalled = Grandpa;
  371. type WindowSize = WindowSize;
  372. type ReportLatency = ReportLatency;
  373. }
  374. impl versioned_store::Trait for Runtime {
  375. type Event = Event;
  376. }
  377. impl versioned_store_permissions::Trait for Runtime {
  378. type Credential = Credential;
  379. type CredentialChecker = (
  380. integration::content_working_group::ContentWorkingGroupCredentials,
  381. SudoKeyHasAllCredentials,
  382. );
  383. type CreateClassPermissionsChecker = ContentLeadOrSudoKeyCanCreateClasses;
  384. }
  385. // Credential Checker that gives the sudo key holder all credentials
  386. pub struct SudoKeyHasAllCredentials {}
  387. impl versioned_store_permissions::CredentialChecker<Runtime> for SudoKeyHasAllCredentials {
  388. fn account_has_credential(
  389. account: &AccountId,
  390. _credential: <Runtime as versioned_store_permissions::Trait>::Credential,
  391. ) -> bool {
  392. <sudo::Module<Runtime>>::key() == *account
  393. }
  394. }
  395. // Allow sudo key holder permission to create classes
  396. pub struct SudoKeyCanCreateClasses {}
  397. impl versioned_store_permissions::CreateClassPermissionsChecker<Runtime>
  398. for SudoKeyCanCreateClasses
  399. {
  400. fn account_can_create_class_permissions(account: &AccountId) -> bool {
  401. <sudo::Module<Runtime>>::key() == *account
  402. }
  403. }
  404. pub struct ContentLeadOrSudoKeyCanCreateClasses {}
  405. impl versioned_store_permissions::CreateClassPermissionsChecker<Runtime>
  406. for ContentLeadOrSudoKeyCanCreateClasses
  407. {
  408. fn account_can_create_class_permissions(account: &AccountId) -> bool {
  409. ContentLeadCanCreateClasses::account_can_create_class_permissions(account)
  410. || SudoKeyCanCreateClasses::account_can_create_class_permissions(account)
  411. }
  412. }
  413. // Allow content working group lead to create classes in content directory
  414. pub struct ContentLeadCanCreateClasses {}
  415. impl versioned_store_permissions::CreateClassPermissionsChecker<Runtime>
  416. for ContentLeadCanCreateClasses
  417. {
  418. fn account_can_create_class_permissions(account: &AccountId) -> bool {
  419. // get current lead id
  420. let maybe_current_lead_id = content_wg::CurrentLeadId::<Runtime>::get();
  421. if let Some(lead_id) = maybe_current_lead_id {
  422. let lead = content_wg::LeadById::<Runtime>::get(lead_id);
  423. lead.role_account == *account
  424. } else {
  425. false
  426. }
  427. }
  428. }
  429. impl hiring::Trait for Runtime {
  430. type OpeningId = u64;
  431. type ApplicationId = u64;
  432. type ApplicationDeactivatedHandler = (); // TODO - what needs to happen?
  433. type StakeHandlerProvider = hiring::Module<Self>;
  434. }
  435. impl minting::Trait for Runtime {
  436. type Currency = <Self as common::currency::GovernanceCurrency>::Currency;
  437. type MintId = u64;
  438. }
  439. impl recurringrewards::Trait for Runtime {
  440. type PayoutStatusHandler = (); // TODO - deal with successful and failed payouts
  441. type RecipientId = u64;
  442. type RewardRelationshipId = u64;
  443. }
  444. parameter_types! {
  445. pub const StakePoolId: [u8; 8] = *b"joystake";
  446. }
  447. impl stake::Trait for Runtime {
  448. type Currency = <Self as common::currency::GovernanceCurrency>::Currency;
  449. type StakePoolId = StakePoolId;
  450. type StakingEventsHandler = (
  451. crate::integration::content_working_group::ContentWorkingGroupStakingEventHandler,
  452. (
  453. crate::integration::proposals::StakingEventsHandler<Self>,
  454. crate::integration::working_group::StakingEventsHandler<Self>,
  455. ),
  456. );
  457. type StakeId = u64;
  458. type SlashId = u64;
  459. }
  460. impl content_wg::Trait for Runtime {
  461. type Event = Event;
  462. }
  463. impl common::currency::GovernanceCurrency for Runtime {
  464. type Currency = balances::Module<Self>;
  465. }
  466. impl governance::election::Trait for Runtime {
  467. type Event = Event;
  468. type CouncilElected = (Council, integration::proposals::CouncilElectedHandler);
  469. }
  470. impl governance::council::Trait for Runtime {
  471. type Event = Event;
  472. type CouncilTermEnded = (CouncilElection,);
  473. }
  474. impl memo::Trait for Runtime {
  475. type Event = Event;
  476. }
  477. parameter_types! {
  478. pub const MaxObjectsPerInjection: u32 = 100;
  479. }
  480. impl storage::data_object_type_registry::Trait for Runtime {
  481. type Event = Event;
  482. type DataObjectTypeId = u64;
  483. }
  484. impl storage::data_directory::Trait for Runtime {
  485. type Event = Event;
  486. type ContentId = ContentId;
  487. type StorageProviderHelper = integration::storage::StorageProviderHelper;
  488. type IsActiveDataObjectType = DataObjectTypeRegistry;
  489. type MemberOriginValidator = MembershipOriginValidator<Self>;
  490. type MaxObjectsPerInjection = MaxObjectsPerInjection;
  491. }
  492. impl storage::data_object_storage_registry::Trait for Runtime {
  493. type Event = Event;
  494. type DataObjectStorageRelationshipId = u64;
  495. type ContentIdExists = DataDirectory;
  496. }
  497. impl members::Trait for Runtime {
  498. type Event = Event;
  499. type MemberId = u64;
  500. type PaidTermId = u64;
  501. type SubscriptionId = u64;
  502. type ActorId = ActorId;
  503. type InitialMembersBalance = InitialMembersBalance;
  504. }
  505. /*
  506. * Forum module integration
  507. *
  508. * ForumUserRegistry could have been implemented directly on
  509. * the membership module, and likewise ForumUser on Profile,
  510. * however this approach is more loosely coupled.
  511. *
  512. * Further exploration required to decide what the long
  513. * run convention should be.
  514. */
  515. /// Shim registry which will proxy ForumUserRegistry behaviour to the members module
  516. pub struct ShimMembershipRegistry {}
  517. impl forum::ForumUserRegistry<AccountId> for ShimMembershipRegistry {
  518. fn get_forum_user(id: &AccountId) -> Option<forum::ForumUser<AccountId>> {
  519. if members::Module::<Runtime>::is_member_account(id) {
  520. // For now we don't retreive the members profile since it is not used for anything,
  521. // but in the future we may need it to read out more
  522. // information possibly required to construct a
  523. // ForumUser.
  524. // Now convert member profile to a forum user
  525. Some(forum::ForumUser { id: id.clone() })
  526. } else {
  527. None
  528. }
  529. }
  530. }
  531. impl forum::Trait for Runtime {
  532. type Event = Event;
  533. type MembershipRegistry = ShimMembershipRegistry;
  534. type ThreadId = ThreadId;
  535. type PostId = PostId;
  536. }
  537. impl migration::Trait for Runtime {
  538. type Event = Event;
  539. }
  540. // The storage working group instance alias.
  541. pub type StorageWorkingGroupInstance = working_group::Instance2;
  542. parameter_types! {
  543. pub const MaxWorkerNumberLimit: u32 = 100;
  544. }
  545. impl working_group::Trait<StorageWorkingGroupInstance> for Runtime {
  546. type Event = Event;
  547. type MaxWorkerNumberLimit = MaxWorkerNumberLimit;
  548. }
  549. impl service_discovery::Trait for Runtime {
  550. type Event = Event;
  551. }
  552. parameter_types! {
  553. pub const ProposalCancellationFee: u64 = 10000;
  554. pub const ProposalRejectionFee: u64 = 5000;
  555. pub const ProposalTitleMaxLength: u32 = 40;
  556. pub const ProposalDescriptionMaxLength: u32 = 3000;
  557. pub const ProposalMaxActiveProposalLimit: u32 = 5;
  558. }
  559. impl proposals_engine::Trait for Runtime {
  560. type Event = Event;
  561. type ProposerOriginValidator = MembershipOriginValidator<Self>;
  562. type VoterOriginValidator = CouncilManager<Self>;
  563. type TotalVotersCounter = CouncilManager<Self>;
  564. type ProposalId = u32;
  565. type StakeHandlerProvider = proposals_engine::DefaultStakeHandlerProvider;
  566. type CancellationFee = ProposalCancellationFee;
  567. type RejectionFee = ProposalRejectionFee;
  568. type TitleMaxLength = ProposalTitleMaxLength;
  569. type DescriptionMaxLength = ProposalDescriptionMaxLength;
  570. type MaxActiveProposalLimit = ProposalMaxActiveProposalLimit;
  571. type DispatchableCallCode = Call;
  572. }
  573. impl Default for Call {
  574. fn default() -> Self {
  575. panic!("shouldn't call default for Call");
  576. }
  577. }
  578. parameter_types! {
  579. pub const ProposalMaxPostEditionNumber: u32 = 0; // post update is disabled
  580. pub const ProposalMaxThreadInARowNumber: u32 = 100_000; // will not be used
  581. pub const ProposalThreadTitleLengthLimit: u32 = 40;
  582. pub const ProposalPostLengthLimit: u32 = 1000;
  583. }
  584. impl proposals_discussion::Trait for Runtime {
  585. type Event = Event;
  586. type PostAuthorOriginValidator = MembershipOriginValidator<Self>;
  587. type ThreadId = ThreadId;
  588. type PostId = PostId;
  589. type MaxPostEditionNumber = ProposalMaxPostEditionNumber;
  590. type ThreadTitleLengthLimit = ProposalThreadTitleLengthLimit;
  591. type PostLengthLimit = ProposalPostLengthLimit;
  592. type MaxThreadInARowNumber = ProposalMaxThreadInARowNumber;
  593. }
  594. parameter_types! {
  595. pub const TextProposalMaxLength: u32 = 5_000;
  596. pub const RuntimeUpgradeWasmProposalMaxLength: u32 = 2_000_000;
  597. }
  598. impl proposals_codex::Trait for Runtime {
  599. type MembershipOriginValidator = MembershipOriginValidator<Self>;
  600. type TextProposalMaxLength = TextProposalMaxLength;
  601. type RuntimeUpgradeWasmProposalMaxLength = RuntimeUpgradeWasmProposalMaxLength;
  602. type ProposalEncoder = ExtrinsicProposalEncoder;
  603. }
  604. construct_runtime!(
  605. pub enum Runtime where
  606. Block = Block,
  607. NodeBlock = opaque::Block,
  608. UncheckedExtrinsic = UncheckedExtrinsic
  609. {
  610. // Substrate
  611. System: system::{Module, Call, Storage, Config, Event},
  612. Babe: babe::{Module, Call, Storage, Config, Inherent(Timestamp)},
  613. Timestamp: timestamp::{Module, Call, Storage, Inherent},
  614. Authorship: authorship::{Module, Call, Storage, Inherent},
  615. Indices: indices,
  616. Balances: balances,
  617. TransactionPayment: transaction_payment::{Module, Storage},
  618. Staking: staking::{default, OfflineWorker},
  619. Session: session::{Module, Call, Storage, Event, Config<T>},
  620. FinalityTracker: finality_tracker::{Module, Call, Inherent},
  621. Grandpa: grandpa::{Module, Call, Storage, Config, Event},
  622. ImOnline: im_online::{Module, Call, Storage, Event<T>, ValidateUnsigned, Config<T>},
  623. AuthorityDiscovery: authority_discovery::{Module, Call, Config<T>},
  624. Offences: offences::{Module, Call, Storage, Event},
  625. RandomnessCollectiveFlip: randomness_collective_flip::{Module, Call, Storage},
  626. Sudo: sudo,
  627. // Joystream
  628. Migration: migration::{Module, Call, Storage, Event<T>, Config},
  629. CouncilElection: election::{Module, Call, Storage, Event<T>, Config<T>},
  630. Council: council::{Module, Call, Storage, Event<T>, Config<T>},
  631. Memo: memo::{Module, Call, Storage, Event<T>},
  632. Members: members::{Module, Call, Storage, Event<T>, Config<T>},
  633. Forum: forum::{Module, Call, Storage, Event<T>, Config<T>},
  634. VersionedStore: versioned_store::{Module, Call, Storage, Event<T>, Config},
  635. VersionedStorePermissions: versioned_store_permissions::{Module, Call, Storage},
  636. Stake: stake::{Module, Call, Storage},
  637. Minting: minting::{Module, Call, Storage},
  638. RecurringRewards: recurringrewards::{Module, Call, Storage},
  639. Hiring: hiring::{Module, Call, Storage},
  640. ContentWorkingGroup: content_wg::{Module, Call, Storage, Event<T>, Config<T>},
  641. // --- Storage
  642. DataObjectTypeRegistry: data_object_type_registry::{Module, Call, Storage, Event<T>, Config<T>},
  643. DataDirectory: data_directory::{Module, Call, Storage, Event<T>},
  644. DataObjectStorageRegistry: data_object_storage_registry::{Module, Call, Storage, Event<T>, Config<T>},
  645. Discovery: service_discovery::{Module, Call, Storage, Event<T>},
  646. // --- Proposals
  647. ProposalsEngine: proposals_engine::{Module, Call, Storage, Event<T>},
  648. ProposalsDiscussion: proposals_discussion::{Module, Call, Storage, Event<T>},
  649. ProposalsCodex: proposals_codex::{Module, Call, Storage, Error, Config<T>},
  650. // --- Working groups
  651. // reserved for the future use: ForumWorkingGroup: working_group::<Instance1>::{Module, Call, Storage, Event<T>},
  652. StorageWorkingGroup: working_group::<Instance2>::{Module, Call, Storage, Config<T>, Error, Event<T>},
  653. }
  654. );
  655. /// The address format for describing accounts.
  656. pub type Address = <Indices as StaticLookup>::Source;
  657. /// Block header type as expected by this runtime.
  658. pub type Header = generic::Header<BlockNumber, BlakeTwo256>;
  659. /// Block type as expected by this runtime.
  660. pub type Block = generic::Block<Header, UncheckedExtrinsic>;
  661. /// A Block signed with a Justification
  662. pub type SignedBlock = generic::SignedBlock<Block>;
  663. /// BlockId type as expected by this runtime.
  664. pub type BlockId = generic::BlockId<Block>;
  665. /// The SignedExtension to the basic transaction logic.
  666. pub type SignedExtra = (
  667. system::CheckVersion<Runtime>,
  668. system::CheckGenesis<Runtime>,
  669. system::CheckEra<Runtime>,
  670. system::CheckNonce<Runtime>,
  671. system::CheckWeight<Runtime>,
  672. transaction_payment::ChargeTransactionPayment<Runtime>,
  673. );
  674. /// Unchecked extrinsic type as expected by this runtime.
  675. pub type UncheckedExtrinsic = generic::UncheckedExtrinsic<Address, Call, Signature, SignedExtra>;
  676. /// Extrinsic type that has already been checked.
  677. pub type CheckedExtrinsic = generic::CheckedExtrinsic<AccountId, Call, SignedExtra>;
  678. /// Executive: handles dispatch to the various modules.
  679. pub type Executive =
  680. executive::Executive<Runtime, Block, system::ChainContext<Runtime>, Runtime, AllModules>;
  681. impl_runtime_apis! {
  682. impl client_api::Core<Block> for Runtime {
  683. fn version() -> RuntimeVersion {
  684. VERSION
  685. }
  686. fn execute_block(block: Block) {
  687. Executive::execute_block(block)
  688. }
  689. fn initialize_block(header: &<Block as BlockT>::Header) {
  690. Executive::initialize_block(header)
  691. }
  692. }
  693. impl client_api::Metadata<Block> for Runtime {
  694. fn metadata() -> OpaqueMetadata {
  695. Runtime::metadata().into()
  696. }
  697. }
  698. impl block_builder_api::BlockBuilder<Block> for Runtime {
  699. fn apply_extrinsic(extrinsic: <Block as BlockT>::Extrinsic) -> ApplyResult {
  700. Executive::apply_extrinsic(extrinsic)
  701. }
  702. fn finalize_block() -> <Block as BlockT>::Header {
  703. Executive::finalize_block()
  704. }
  705. fn inherent_extrinsics(data: InherentData) -> Vec<<Block as BlockT>::Extrinsic> {
  706. data.create_extrinsics()
  707. }
  708. fn check_inherents(block: Block, data: InherentData) -> CheckInherentsResult {
  709. data.check_extrinsics(&block)
  710. }
  711. fn random_seed() -> <Block as BlockT>::Hash {
  712. RandomnessCollectiveFlip::random_seed()
  713. }
  714. }
  715. impl client_api::TaggedTransactionQueue<Block> for Runtime {
  716. fn validate_transaction(tx: <Block as BlockT>::Extrinsic) -> TransactionValidity {
  717. Executive::validate_transaction(tx)
  718. }
  719. }
  720. impl offchain_primitives::OffchainWorkerApi<Block> for Runtime {
  721. fn offchain_worker(number: NumberFor<Block>) {
  722. Executive::offchain_worker(number)
  723. }
  724. }
  725. impl fg_primitives::GrandpaApi<Block> for Runtime {
  726. fn grandpa_authorities() -> Vec<(GrandpaId, GrandpaWeight)> {
  727. Grandpa::grandpa_authorities()
  728. }
  729. }
  730. impl babe_primitives::BabeApi<Block> for Runtime {
  731. fn configuration() -> babe_primitives::BabeConfiguration {
  732. // The choice of `c` parameter (where `1 - c` represents the
  733. // probability of a slot being empty), is done in accordance to the
  734. // slot duration and expected target block time, for safely
  735. // resisting network delays of maximum two seconds.
  736. // <https://research.web3.foundation/en/latest/polkadot/BABE/Babe/#6-practical-results>
  737. babe_primitives::BabeConfiguration {
  738. slot_duration: Babe::slot_duration(),
  739. epoch_length: EpochDuration::get(),
  740. c: PRIMARY_PROBABILITY,
  741. genesis_authorities: Babe::authorities(),
  742. randomness: Babe::randomness(),
  743. secondary_slots: true,
  744. }
  745. }
  746. }
  747. impl authority_discovery_primitives::AuthorityDiscoveryApi<Block> for Runtime {
  748. fn authorities() -> Vec<EncodedAuthorityId> {
  749. AuthorityDiscovery::authorities().into_iter()
  750. .map(|id| id.encode())
  751. .map(EncodedAuthorityId)
  752. .collect()
  753. }
  754. fn sign(payload: &Vec<u8>) -> Option<(EncodedSignature, EncodedAuthorityId)> {
  755. AuthorityDiscovery::sign(payload).map(|(sig, id)| {
  756. (EncodedSignature(sig.encode()), EncodedAuthorityId(id.encode()))
  757. })
  758. }
  759. fn verify(payload: &Vec<u8>, signature: &EncodedSignature, authority_id: &EncodedAuthorityId) -> bool {
  760. let signature = match BabeSignature::decode(&mut &signature.0[..]) {
  761. Ok(s) => s,
  762. _ => return false,
  763. };
  764. let authority_id = match BabeId::decode(&mut &authority_id.0[..]) {
  765. Ok(id) => id,
  766. _ => return false,
  767. };
  768. AuthorityDiscovery::verify(payload, signature, authority_id)
  769. }
  770. }
  771. impl system_rpc_runtime_api::AccountNonceApi<Block, AccountId, Index> for Runtime {
  772. fn account_nonce(account: AccountId) -> Index {
  773. System::account_nonce(account)
  774. }
  775. }
  776. impl substrate_session::SessionKeys<Block> for Runtime {
  777. fn generate_session_keys(seed: Option<Vec<u8>>) -> Vec<u8> {
  778. let seed = seed.as_ref().map(|s| rstd::str::from_utf8(&s).expect("Seed is an utf8 string"));
  779. opaque::SessionKeys::generate(seed)
  780. }
  781. }
  782. }