mod.rs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478
  1. // Copyright 2019 Joystream Contributors
  2. // This file is part of Joystream node.
  3. // Joystream node is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation, either version 3 of the License, or
  6. // (at your option) any later version.
  7. // Joystream node is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU General Public License for more details.
  11. // You should have received a copy of the GNU General Public License
  12. // along with Joystream node. If not, see <http://www.gnu.org/licenses/>.
  13. // Clippy linter warning.
  14. // Disable it because we use such syntax for a code readability.
  15. // Example: voting_period: 1 * DAY
  16. #![allow(clippy::identity_op)]
  17. use pallet_im_online::sr25519::AuthorityId as ImOnlineId;
  18. use serde_json as json;
  19. use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId;
  20. use sp_consensus_babe::AuthorityId as BabeId;
  21. use sp_core::{sr25519, Pair, Public};
  22. use sp_finality_grandpa::AuthorityId as GrandpaId;
  23. use sp_runtime::traits::{IdentifyAccount, Verify};
  24. use sp_runtime::Perbill;
  25. use node_runtime::{
  26. membership, AuthorityDiscoveryConfig, BabeConfig, Balance, BalancesConfig,
  27. ContentDirectoryConfig, ContentDirectoryWorkingGroupConfig, ContentWorkingGroupConfig,
  28. CouncilConfig, CouncilElectionConfig, DataDirectoryConfig, DataObjectStorageRegistryConfig,
  29. DataObjectTypeRegistryConfig, ElectionParameters, ForumConfig, GrandpaConfig, ImOnlineConfig,
  30. MembersConfig, Moment, ProposalsCodexConfig, SessionConfig, SessionKeys, Signature,
  31. StakerStatus, StakingConfig, StorageWorkingGroupConfig, SudoConfig, SystemConfig,
  32. VersionedStoreConfig, VersionedStorePermissionsConfig, DAYS, WASM_BINARY,
  33. };
  34. // Exported to be used by chain-spec-builder
  35. pub use node_runtime::{AccountId, GenesisConfig};
  36. pub mod content_config;
  37. pub mod forum_config;
  38. pub mod initial_balances;
  39. pub mod initial_members;
  40. pub mod proposals_config;
  41. type AccountPublic = <Signature as Verify>::Signer;
  42. /// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.
  43. pub type ChainSpec = sc_service::GenericChainSpec<GenesisConfig>;
  44. use sc_chain_spec::ChainType;
  45. /// The chain specification option. This is expected to come in from the CLI and
  46. /// is little more than one of a number of alternatives which can easily be converted
  47. /// from a string (`--chain=...`) into a `ChainSpec`.
  48. #[derive(Clone, Debug)]
  49. pub enum Alternative {
  50. /// Whatever the current runtime is, with just Alice as an auth.
  51. Development,
  52. /// Whatever the current runtime is, with simple Alice/Bob auths.
  53. LocalTestnet,
  54. }
  55. /// Helper function to generate a crypto pair from seed
  56. pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
  57. TPublic::Pair::from_string(&format!("//{}", seed), None)
  58. .expect("static values are valid; qed")
  59. .public()
  60. }
  61. /// Helper function to generate an account ID from seed
  62. pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId
  63. where
  64. AccountPublic: From<<TPublic::Pair as Pair>::Public>,
  65. {
  66. AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()
  67. }
  68. /// Helper function to generate stash, controller and session key from seed
  69. pub fn get_authority_keys_from_seed(
  70. seed: &str,
  71. ) -> (
  72. AccountId,
  73. AccountId,
  74. GrandpaId,
  75. BabeId,
  76. ImOnlineId,
  77. AuthorityDiscoveryId,
  78. ) {
  79. (
  80. get_account_id_from_seed::<sr25519::Public>(&format!("{}//stash", seed)),
  81. get_account_id_from_seed::<sr25519::Public>(seed),
  82. get_from_seed::<GrandpaId>(seed),
  83. get_from_seed::<BabeId>(seed),
  84. get_from_seed::<ImOnlineId>(seed),
  85. get_from_seed::<AuthorityDiscoveryId>(seed),
  86. )
  87. }
  88. fn session_keys(
  89. grandpa: GrandpaId,
  90. babe: BabeId,
  91. im_online: ImOnlineId,
  92. authority_discovery: AuthorityDiscoveryId,
  93. ) -> SessionKeys {
  94. SessionKeys {
  95. grandpa,
  96. babe,
  97. im_online,
  98. authority_discovery,
  99. }
  100. }
  101. impl Alternative {
  102. /// Get an actual chain config from one of the alternatives.
  103. pub(crate) fn load(self) -> Result<ChainSpec, String> {
  104. Ok(match self {
  105. Alternative::Development => ChainSpec::from_genesis(
  106. "Development",
  107. "dev",
  108. ChainType::Development,
  109. || {
  110. testnet_genesis(
  111. vec![get_authority_keys_from_seed("Alice")],
  112. get_account_id_from_seed::<sr25519::Public>("Alice"),
  113. vec![
  114. get_account_id_from_seed::<sr25519::Public>("Alice"),
  115. get_account_id_from_seed::<sr25519::Public>("Bob"),
  116. get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
  117. get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
  118. ],
  119. proposals_config::development(),
  120. initial_members::none(),
  121. forum_config::empty(get_account_id_from_seed::<sr25519::Public>("Alice")),
  122. content_config::empty_versioned_store_config(),
  123. content_config::empty_versioned_store_permissions_config(),
  124. content_config::empty_data_directory_config(),
  125. content_config::empty_content_working_group_config(),
  126. vec![],
  127. )
  128. },
  129. Vec::new(),
  130. None,
  131. None,
  132. Some(chain_spec_properties()),
  133. None,
  134. ),
  135. Alternative::LocalTestnet => ChainSpec::from_genesis(
  136. "Local Testnet",
  137. "local_testnet",
  138. ChainType::Local,
  139. || {
  140. testnet_genesis(
  141. vec![
  142. get_authority_keys_from_seed("Alice"),
  143. get_authority_keys_from_seed("Bob"),
  144. ],
  145. get_account_id_from_seed::<sr25519::Public>("Alice"),
  146. vec![
  147. get_account_id_from_seed::<sr25519::Public>("Alice"),
  148. get_account_id_from_seed::<sr25519::Public>("Bob"),
  149. get_account_id_from_seed::<sr25519::Public>("Charlie"),
  150. get_account_id_from_seed::<sr25519::Public>("Dave"),
  151. get_account_id_from_seed::<sr25519::Public>("Eve"),
  152. get_account_id_from_seed::<sr25519::Public>("Ferdie"),
  153. get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
  154. get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
  155. get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),
  156. get_account_id_from_seed::<sr25519::Public>("Dave//stash"),
  157. get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
  158. get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
  159. ],
  160. proposals_config::development(),
  161. initial_members::none(),
  162. forum_config::empty(get_account_id_from_seed::<sr25519::Public>("Alice")),
  163. content_config::empty_versioned_store_config(),
  164. content_config::empty_versioned_store_permissions_config(),
  165. content_config::empty_data_directory_config(),
  166. content_config::empty_content_working_group_config(),
  167. vec![],
  168. )
  169. },
  170. Vec::new(),
  171. None,
  172. None,
  173. Some(chain_spec_properties()),
  174. None,
  175. ),
  176. })
  177. }
  178. }
  179. pub fn chain_spec_properties() -> json::map::Map<String, json::Value> {
  180. let mut properties: json::map::Map<String, json::Value> = json::map::Map::new();
  181. properties.insert(
  182. String::from("tokenDecimals"),
  183. json::Value::Number(json::Number::from(0)),
  184. );
  185. properties.insert(
  186. String::from("tokenSymbol"),
  187. json::Value::String(String::from("JOY")),
  188. );
  189. properties
  190. }
  191. // This method should be refactored after Alexandria to reduce number of arguments
  192. // as more args will likely be needed
  193. #[allow(clippy::too_many_arguments)]
  194. pub fn testnet_genesis(
  195. initial_authorities: Vec<(
  196. AccountId,
  197. AccountId,
  198. GrandpaId,
  199. BabeId,
  200. ImOnlineId,
  201. AuthorityDiscoveryId,
  202. )>,
  203. root_key: AccountId,
  204. endowed_accounts: Vec<AccountId>,
  205. cpcp: node_runtime::ProposalsConfigParameters,
  206. members: Vec<membership::genesis::Member<u64, AccountId, Moment>>,
  207. forum_config: ForumConfig,
  208. versioned_store_config: VersionedStoreConfig,
  209. versioned_store_permissions_config: VersionedStorePermissionsConfig,
  210. data_directory_config: DataDirectoryConfig,
  211. content_working_group_config: ContentWorkingGroupConfig,
  212. initial_balances: Vec<(AccountId, Balance)>,
  213. ) -> GenesisConfig {
  214. const STASH: Balance = 5_000;
  215. const ENDOWMENT: Balance = 100_000_000;
  216. let default_text_constraint = node_runtime::working_group::default_text_constraint();
  217. GenesisConfig {
  218. system: Some(SystemConfig {
  219. code: WASM_BINARY.to_vec(),
  220. changes_trie_config: Default::default(),
  221. }),
  222. pallet_balances: Some(BalancesConfig {
  223. balances: endowed_accounts
  224. .iter()
  225. .cloned()
  226. .map(|k| (k, ENDOWMENT))
  227. .chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH)))
  228. .chain(
  229. initial_balances
  230. .iter()
  231. .map(|(account, balance)| (account.clone(), *balance)),
  232. )
  233. .collect(),
  234. }),
  235. pallet_staking: Some(StakingConfig {
  236. validator_count: 20,
  237. minimum_validator_count: initial_authorities.len() as u32,
  238. stakers: initial_authorities
  239. .iter()
  240. .map(|x| (x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator))
  241. .collect(),
  242. invulnerables: initial_authorities.iter().map(|x| x.0.clone()).collect(),
  243. slash_reward_fraction: Perbill::from_percent(10),
  244. history_depth: 336,
  245. ..Default::default()
  246. }),
  247. pallet_sudo: Some(SudoConfig { key: root_key }),
  248. pallet_babe: Some(BabeConfig {
  249. authorities: vec![],
  250. }),
  251. pallet_im_online: Some(ImOnlineConfig { keys: vec![] }),
  252. pallet_authority_discovery: Some(AuthorityDiscoveryConfig { keys: vec![] }),
  253. pallet_grandpa: Some(GrandpaConfig {
  254. authorities: vec![],
  255. }),
  256. pallet_session: Some(SessionConfig {
  257. keys: initial_authorities
  258. .iter()
  259. .map(|x| {
  260. (
  261. x.0.clone(),
  262. x.0.clone(),
  263. session_keys(x.2.clone(), x.3.clone(), x.4.clone(), x.5.clone()),
  264. )
  265. })
  266. .collect::<Vec<_>>(),
  267. }),
  268. council: Some(CouncilConfig {
  269. active_council: vec![],
  270. term_ends_at: 1,
  271. }),
  272. election: Some(CouncilElectionConfig {
  273. auto_start: true,
  274. election_parameters: ElectionParameters {
  275. announcing_period: 2 * DAYS,
  276. voting_period: 1 * DAYS,
  277. revealing_period: 1 * DAYS,
  278. council_size: 6,
  279. candidacy_limit: 25,
  280. min_council_stake: 1_000,
  281. new_term_duration: 10 * DAYS,
  282. min_voting_stake: 100,
  283. },
  284. }),
  285. membership: Some(MembersConfig {
  286. default_paid_membership_fee: 100u128,
  287. members,
  288. }),
  289. forum: Some(forum_config),
  290. data_directory: Some(data_directory_config),
  291. data_object_type_registry: Some(DataObjectTypeRegistryConfig {
  292. first_data_object_type_id: 1,
  293. }),
  294. data_object_storage_registry: Some(DataObjectStorageRegistryConfig {
  295. first_relationship_id: 1,
  296. }),
  297. working_group_Instance2: Some(StorageWorkingGroupConfig {
  298. phantom: Default::default(),
  299. storage_working_group_mint_capacity: 0,
  300. opening_human_readable_text_constraint: default_text_constraint,
  301. worker_application_human_readable_text_constraint: default_text_constraint,
  302. worker_exit_rationale_text_constraint: default_text_constraint,
  303. }),
  304. working_group_Instance3: Some(ContentDirectoryWorkingGroupConfig {
  305. phantom: Default::default(),
  306. storage_working_group_mint_capacity: 0,
  307. opening_human_readable_text_constraint: default_text_constraint,
  308. worker_application_human_readable_text_constraint: default_text_constraint,
  309. worker_exit_rationale_text_constraint: default_text_constraint,
  310. }),
  311. content_directory: Some({
  312. ContentDirectoryConfig {
  313. class_by_id: vec![],
  314. entity_by_id: vec![],
  315. curator_group_by_id: vec![],
  316. next_class_id: 1,
  317. next_entity_id: 1,
  318. next_curator_group_id: 1,
  319. }
  320. }),
  321. versioned_store: Some(versioned_store_config),
  322. versioned_store_permissions: Some(versioned_store_permissions_config),
  323. content_wg: Some(content_working_group_config),
  324. proposals_codex: Some(ProposalsCodexConfig {
  325. set_validator_count_proposal_voting_period: cpcp
  326. .set_validator_count_proposal_voting_period,
  327. set_validator_count_proposal_grace_period: cpcp
  328. .set_validator_count_proposal_grace_period,
  329. runtime_upgrade_proposal_voting_period: cpcp.runtime_upgrade_proposal_voting_period,
  330. runtime_upgrade_proposal_grace_period: cpcp.runtime_upgrade_proposal_grace_period,
  331. text_proposal_voting_period: cpcp.text_proposal_voting_period,
  332. text_proposal_grace_period: cpcp.text_proposal_grace_period,
  333. set_election_parameters_proposal_voting_period: cpcp
  334. .set_election_parameters_proposal_voting_period,
  335. set_election_parameters_proposal_grace_period: cpcp
  336. .set_election_parameters_proposal_grace_period,
  337. spending_proposal_voting_period: cpcp.spending_proposal_voting_period,
  338. spending_proposal_grace_period: cpcp.spending_proposal_grace_period,
  339. add_working_group_opening_proposal_voting_period: cpcp
  340. .add_working_group_opening_proposal_voting_period,
  341. add_working_group_opening_proposal_grace_period: cpcp
  342. .add_working_group_opening_proposal_grace_period,
  343. begin_review_working_group_leader_applications_proposal_voting_period: cpcp
  344. .begin_review_working_group_leader_applications_proposal_voting_period,
  345. begin_review_working_group_leader_applications_proposal_grace_period: cpcp
  346. .begin_review_working_group_leader_applications_proposal_grace_period,
  347. fill_working_group_leader_opening_proposal_voting_period: cpcp
  348. .fill_working_group_leader_opening_proposal_voting_period,
  349. fill_working_group_leader_opening_proposal_grace_period: cpcp
  350. .fill_working_group_leader_opening_proposal_grace_period,
  351. set_working_group_mint_capacity_proposal_voting_period: cpcp
  352. .set_working_group_mint_capacity_proposal_voting_period,
  353. set_working_group_mint_capacity_proposal_grace_period: cpcp
  354. .set_working_group_mint_capacity_proposal_grace_period,
  355. decrease_working_group_leader_stake_proposal_voting_period: cpcp
  356. .decrease_working_group_leader_stake_proposal_voting_period,
  357. decrease_working_group_leader_stake_proposal_grace_period: cpcp
  358. .decrease_working_group_leader_stake_proposal_grace_period,
  359. slash_working_group_leader_stake_proposal_voting_period: cpcp
  360. .slash_working_group_leader_stake_proposal_voting_period,
  361. slash_working_group_leader_stake_proposal_grace_period: cpcp
  362. .slash_working_group_leader_stake_proposal_grace_period,
  363. set_working_group_leader_reward_proposal_voting_period: cpcp
  364. .set_working_group_leader_reward_proposal_voting_period,
  365. set_working_group_leader_reward_proposal_grace_period: cpcp
  366. .set_working_group_leader_reward_proposal_grace_period,
  367. terminate_working_group_leader_role_proposal_voting_period: cpcp
  368. .terminate_working_group_leader_role_proposal_voting_period,
  369. terminate_working_group_leader_role_proposal_grace_period: cpcp
  370. .terminate_working_group_leader_role_proposal_grace_period,
  371. }),
  372. }
  373. }
  374. #[cfg(test)]
  375. pub(crate) mod tests {
  376. use super::*;
  377. use crate::service::{new_full, new_light};
  378. use sc_service_test;
  379. fn local_testnet_genesis_instant_single() -> GenesisConfig {
  380. testnet_genesis(
  381. vec![get_authority_keys_from_seed("Alice")],
  382. get_account_id_from_seed::<sr25519::Public>("Alice"),
  383. vec![get_authority_keys_from_seed("Alice").0],
  384. proposals_config::development(),
  385. initial_members::none(),
  386. forum_config::empty(get_account_id_from_seed::<sr25519::Public>("Alice")),
  387. content_config::empty_versioned_store_config(),
  388. content_config::empty_versioned_store_permissions_config(),
  389. content_config::empty_data_directory_config(),
  390. content_config::empty_content_working_group_config(),
  391. vec![],
  392. )
  393. }
  394. /// Local testnet config (single validator - Alice)
  395. pub fn integration_test_config_with_single_authority() -> ChainSpec {
  396. ChainSpec::from_genesis(
  397. "Integration Test",
  398. "test",
  399. ChainType::Development,
  400. local_testnet_genesis_instant_single,
  401. vec![],
  402. None,
  403. None,
  404. None,
  405. Default::default(),
  406. )
  407. }
  408. fn local_testnet_genesis() -> GenesisConfig {
  409. testnet_genesis(
  410. vec![
  411. get_authority_keys_from_seed("Alice"),
  412. get_authority_keys_from_seed("Bob"),
  413. ],
  414. get_account_id_from_seed::<sr25519::Public>("Alice"),
  415. vec![
  416. get_authority_keys_from_seed("Alice").0,
  417. get_authority_keys_from_seed("Bob").0,
  418. ],
  419. proposals_config::development(),
  420. initial_members::none(),
  421. forum_config::empty(get_account_id_from_seed::<sr25519::Public>("Alice")),
  422. content_config::empty_versioned_store_config(),
  423. content_config::empty_versioned_store_permissions_config(),
  424. content_config::empty_data_directory_config(),
  425. content_config::empty_content_working_group_config(),
  426. vec![],
  427. )
  428. }
  429. /// Local testnet config (multivalidator Alice + Bob)
  430. pub fn integration_test_config_with_two_authorities() -> ChainSpec {
  431. ChainSpec::from_genesis(
  432. "Integration Test",
  433. "test",
  434. ChainType::Development,
  435. local_testnet_genesis,
  436. vec![],
  437. None,
  438. None,
  439. None,
  440. Default::default(),
  441. )
  442. }
  443. #[test]
  444. #[ignore]
  445. fn test_connectivity() {
  446. sc_service_test::connectivity(
  447. integration_test_config_with_two_authorities(),
  448. |config| new_full(config),
  449. |config| new_light(config),
  450. );
  451. }
  452. }