lib.rs 35 KB

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