|
@@ -14,24 +14,31 @@
|
|
|
// You should have received a copy of the GNU General Public License
|
|
|
// along with Joystream node. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
-use hex_literal::{hex, hex_impl};
|
|
|
-use joystream_node_runtime::{
|
|
|
- forum::InputValidationLengthConstraint, AccountId, ActorsConfig, BalancesConfig,
|
|
|
- ConsensusConfig, CouncilConfig, CouncilElectionConfig, DataObjectStorageRegistryConfig,
|
|
|
- DataObjectTypeRegistryConfig, DownloadSessionsConfig, ForumConfig, GenesisConfig,
|
|
|
- GrandpaConfig, IndicesConfig, MembersConfig, Perbill, ProposalsConfig, SessionConfig,
|
|
|
- StakerStatus, StakingConfig, SudoConfig, TimestampConfig,
|
|
|
+use hex_literal::hex;
|
|
|
+use node_runtime::{
|
|
|
+ versioned_store::InputValidationLengthConstraint as VsInputValidation, AccountId, ActorsConfig,
|
|
|
+ AuthorityDiscoveryConfig, BabeConfig, Balance, BalancesConfig, ContentWorkingGroupConfig,
|
|
|
+ CouncilConfig, CouncilElectionConfig, DataObjectStorageRegistryConfig,
|
|
|
+ DataObjectTypeRegistryConfig, GenesisConfig, GrandpaConfig, ImOnlineConfig, IndicesConfig,
|
|
|
+ MembersConfig, Perbill, ProposalsConfig, SessionConfig, SessionKeys, Signature, StakerStatus,
|
|
|
+ StakingConfig, SudoConfig, SystemConfig, VersionedStoreConfig, DAYS, WASM_BINARY,
|
|
|
};
|
|
|
-use primitives::{crypto::UncheckedInto, ed25519, sr25519, Pair};
|
|
|
+use primitives::{crypto::UncheckedInto, sr25519, Pair, Public};
|
|
|
+use runtime_primitives::traits::{IdentifyAccount, Verify};
|
|
|
+
|
|
|
+use babe_primitives::AuthorityId as BabeId;
|
|
|
+use grandpa_primitives::AuthorityId as GrandpaId;
|
|
|
+use im_online::sr25519::AuthorityId as ImOnlineId;
|
|
|
+use serde_json as json;
|
|
|
use substrate_service;
|
|
|
use substrate_telemetry::TelemetryEndpoints;
|
|
|
|
|
|
-use ed25519::Public as AuthorityId;
|
|
|
+type AccountPublic = <Signature as Verify>::Signer;
|
|
|
|
|
|
// Note this is the URL for the telemetry server
|
|
|
const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";
|
|
|
|
|
|
-/// Specialised `ChainSpec`. This is a specialisation of the general Substrate ChainSpec type.
|
|
|
+/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.
|
|
|
pub type ChainSpec = substrate_service::ChainSpec<GenesisConfig>;
|
|
|
|
|
|
/// The chain specification option. This is expected to come in from the CLI and
|
|
@@ -49,16 +56,40 @@ pub enum Alternative {
|
|
|
LiveTestnet,
|
|
|
}
|
|
|
|
|
|
-fn authority_key(s: &str) -> AuthorityId {
|
|
|
- ed25519::Pair::from_string(&format!("//{}", s), None)
|
|
|
+/// Helper function to generate a crypto pair from seed
|
|
|
+pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
|
|
|
+ TPublic::Pair::from_string(&format!("//{}", seed), None)
|
|
|
.expect("static values are valid; qed")
|
|
|
.public()
|
|
|
}
|
|
|
|
|
|
-fn account_key(s: &str) -> AccountId {
|
|
|
- sr25519::Pair::from_string(&format!("//{}", s), None)
|
|
|
- .expect("static values are valid; qed")
|
|
|
- .public()
|
|
|
+/// Helper function to generate an account ID from seed
|
|
|
+pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId
|
|
|
+where
|
|
|
+ AccountPublic: From<<TPublic::Pair as Pair>::Public>,
|
|
|
+{
|
|
|
+ AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()
|
|
|
+}
|
|
|
+
|
|
|
+/// Helper function to generate stash, controller and session key from seed
|
|
|
+pub fn get_authority_keys_from_seed(
|
|
|
+ seed: &str,
|
|
|
+) -> (AccountId, AccountId, GrandpaId, BabeId, ImOnlineId) {
|
|
|
+ (
|
|
|
+ get_account_id_from_seed::<sr25519::Public>(&format!("{}//stash", seed)),
|
|
|
+ get_account_id_from_seed::<sr25519::Public>(seed),
|
|
|
+ get_from_seed::<GrandpaId>(seed),
|
|
|
+ get_from_seed::<BabeId>(seed),
|
|
|
+ get_from_seed::<ImOnlineId>(seed),
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+fn session_keys(grandpa: GrandpaId, babe: BabeId, im_online: ImOnlineId) -> SessionKeys {
|
|
|
+ SessionKeys {
|
|
|
+ grandpa,
|
|
|
+ babe,
|
|
|
+ im_online,
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
impl Alternative {
|
|
@@ -70,26 +101,20 @@ impl Alternative {
|
|
|
"dev",
|
|
|
|| {
|
|
|
testnet_genesis(
|
|
|
+ vec![get_authority_keys_from_seed("Alice")],
|
|
|
+ get_account_id_from_seed::<sr25519::Public>("Alice"),
|
|
|
vec![
|
|
|
- // stash, controller, authority
|
|
|
- (
|
|
|
- account_key("Alice//stash"),
|
|
|
- account_key("Alice"),
|
|
|
- authority_key("Alice"),
|
|
|
- ),
|
|
|
- ],
|
|
|
- vec![
|
|
|
- // endowed account
|
|
|
- account_key("Alice"),
|
|
|
+ get_account_id_from_seed::<sr25519::Public>("Alice"),
|
|
|
+ get_account_id_from_seed::<sr25519::Public>("Bob"),
|
|
|
+ get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
|
|
|
+ get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
|
|
|
],
|
|
|
- // sudo key
|
|
|
- account_key("Alice"),
|
|
|
)
|
|
|
},
|
|
|
vec![],
|
|
|
None,
|
|
|
None,
|
|
|
- None,
|
|
|
+ Some(chain_spec_properties()),
|
|
|
None,
|
|
|
),
|
|
|
Alternative::LocalTestnet => ChainSpec::from_genesis(
|
|
@@ -98,32 +123,30 @@ impl Alternative {
|
|
|
|| {
|
|
|
testnet_genesis(
|
|
|
vec![
|
|
|
- (
|
|
|
- account_key("Alice//stash"),
|
|
|
- account_key("Alice"),
|
|
|
- authority_key("Alice"),
|
|
|
- ),
|
|
|
- (
|
|
|
- account_key("Bob//stash"),
|
|
|
- account_key("Bob"),
|
|
|
- authority_key("Bob"),
|
|
|
- ),
|
|
|
+ get_authority_keys_from_seed("Alice"),
|
|
|
+ get_authority_keys_from_seed("Bob"),
|
|
|
],
|
|
|
+ get_account_id_from_seed::<sr25519::Public>("Alice"),
|
|
|
vec![
|
|
|
- account_key("Alice"),
|
|
|
- account_key("Bob"),
|
|
|
- account_key("Charlie"),
|
|
|
- account_key("Dave"),
|
|
|
- account_key("Eve"),
|
|
|
- account_key("Ferdie"),
|
|
|
+ get_account_id_from_seed::<sr25519::Public>("Alice"),
|
|
|
+ get_account_id_from_seed::<sr25519::Public>("Bob"),
|
|
|
+ get_account_id_from_seed::<sr25519::Public>("Charlie"),
|
|
|
+ get_account_id_from_seed::<sr25519::Public>("Dave"),
|
|
|
+ get_account_id_from_seed::<sr25519::Public>("Eve"),
|
|
|
+ get_account_id_from_seed::<sr25519::Public>("Ferdie"),
|
|
|
+ get_account_id_from_seed::<sr25519::Public>("Alice//stash"),
|
|
|
+ get_account_id_from_seed::<sr25519::Public>("Bob//stash"),
|
|
|
+ get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),
|
|
|
+ get_account_id_from_seed::<sr25519::Public>("Dave//stash"),
|
|
|
+ get_account_id_from_seed::<sr25519::Public>("Eve//stash"),
|
|
|
+ get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),
|
|
|
],
|
|
|
- account_key("Alice"),
|
|
|
)
|
|
|
},
|
|
|
vec![],
|
|
|
None,
|
|
|
None,
|
|
|
- None,
|
|
|
+ Some(chain_spec_properties()),
|
|
|
None,
|
|
|
),
|
|
|
Alternative::StagingTestnet => staging_testnet_config(),
|
|
@@ -136,285 +159,352 @@ impl Alternative {
|
|
|
"dev" => Some(Alternative::Development),
|
|
|
"local" => Some(Alternative::LocalTestnet),
|
|
|
"staging" => Some(Alternative::StagingTestnet),
|
|
|
- "" | "testnet" => Some(Alternative::LiveTestnet),
|
|
|
+ "rome-experimental" => Some(Alternative::LiveTestnet),
|
|
|
+ // "" | "tesnet" => Some(Alternative::LiveTestnet),
|
|
|
_ => None,
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-/// LiveTestnet generator
|
|
|
+fn new_vs_validation(min: u16, max_min_diff: u16) -> VsInputValidation {
|
|
|
+ return VsInputValidation { min, max_min_diff };
|
|
|
+}
|
|
|
+
|
|
|
+/// Joystream LiveTestnet generator
|
|
|
pub fn live_testnet_config() -> Result<ChainSpec, String> {
|
|
|
- ChainSpec::from_embedded(include_bytes!("../res/joy_testnet_2.json"))
|
|
|
+ ChainSpec::from_json_bytes(&include_bytes!("../res/rome-experimental.json")[..])
|
|
|
+}
|
|
|
+
|
|
|
+pub fn chain_spec_properties() -> json::map::Map<String, json::Value> {
|
|
|
+ let mut properties: json::map::Map<String, json::Value> = json::map::Map::new();
|
|
|
+ properties.insert(
|
|
|
+ String::from("tokenDecimals"),
|
|
|
+ json::Value::Number(json::Number::from(0)),
|
|
|
+ );
|
|
|
+ properties.insert(
|
|
|
+ String::from("tokenSymbol"),
|
|
|
+ json::Value::String(String::from("JOY")),
|
|
|
+ );
|
|
|
+ properties
|
|
|
}
|
|
|
|
|
|
/// Staging testnet config
|
|
|
pub fn staging_testnet_config() -> ChainSpec {
|
|
|
let boot_nodes = vec![
|
|
|
- String::from("/dns4/bootnode1.joystream.org/tcp/30333/p2p/QmeDa8jASqMRpTh4YCkeVEuHo6nbMcFDzD9pkUxTr3WxhM"),
|
|
|
- String::from("/dns4/bootnode2.joystream.org/tcp/30333/p2p/QmbjzmNMjzQUMHpzqcPHW5DnFeUjM3x4hbiDSMkYv1McD3"),
|
|
|
- ];
|
|
|
+ String::from("/dns4/rome-reckless.joystream.org/tcp/30333/p2p/QmaTTdEF6YVCtynSjsXmGPSGcEesAahoZ8pmcCmmBwSE7S")
|
|
|
+ ];
|
|
|
+
|
|
|
ChainSpec::from_genesis(
|
|
|
- "Joystream Staging Testnet",
|
|
|
- "joy_staging_5",
|
|
|
+ "Joystream Rome Reckless Testnet",
|
|
|
+ "joy_rome_reckless_N",
|
|
|
staging_testnet_config_genesis,
|
|
|
boot_nodes,
|
|
|
Some(TelemetryEndpoints::new(vec![(
|
|
|
STAGING_TELEMETRY_URL.to_string(),
|
|
|
0,
|
|
|
)])),
|
|
|
- None,
|
|
|
- None,
|
|
|
+ // protocol_id
|
|
|
+ Some(&*"/joy/rome/reckless/N"),
|
|
|
+ // Properties
|
|
|
+ Some(chain_spec_properties()),
|
|
|
+ // Extensions
|
|
|
None,
|
|
|
)
|
|
|
}
|
|
|
|
|
|
-fn new_validation(min: u16, max_min_diff: u16) -> InputValidationLengthConstraint {
|
|
|
- return InputValidationLengthConstraint { min, max_min_diff };
|
|
|
-}
|
|
|
-
|
|
|
fn staging_testnet_config_genesis() -> GenesisConfig {
|
|
|
- let initial_authorities: Vec<(AccountId, AccountId, AuthorityId)> = vec![(
|
|
|
- hex!["0610d1a2b1d704723e588c842a934737491688b18b052baae1286f12e96adb65"].unchecked_into(), // stash
|
|
|
- hex!["609cee3edd9900e69be44bcbf7a1892cad10408840a2d72d563811d72d9bb339"].unchecked_into(), // controller
|
|
|
- hex!["65179fd9c39ec301457d1ee47a13f3bb0fef65812a57b6c93212e609b10d35d2"].unchecked_into(), // session key
|
|
|
+ let initial_authorities: Vec<(AccountId, AccountId, GrandpaId, BabeId, ImOnlineId)> = vec![(
|
|
|
+ hex!["4430a31121fc174b1c361b365580c54ef393813171e59542f5d2ce3d8b171a2d"].into(), // stash
|
|
|
+ hex!["58a743f1bab2f472fb99af98b6591e23a56fd84bc9c2a62037ed8867caae7c21"].into(), // controller
|
|
|
+ hex!["af5286fb1e403afd44d92ae3fb0b371a0f4f8faf3e6b2ff50ea91fb426b0015f"].unchecked_into(), // session - grandpa
|
|
|
+ hex!["d69529ed1549644977cec8dc027e71e1e2ae7aab99833a7f7dc08677a8d36307"].unchecked_into(), // session - babe
|
|
|
+ hex!["56bfd27715ce6c76e4d884c31374b9928391e461727ffaf27b94b6ce48570d39"].unchecked_into(), // session - im-online
|
|
|
)];
|
|
|
- let endowed_accounts = vec![hex![
|
|
|
- "0ae55282e669fc55cb9529c0b12b989f2c5bf636d0de7630b5a4850055ed9c30"
|
|
|
- ]
|
|
|
- .unchecked_into()];
|
|
|
+ let endowed_accounts =
|
|
|
+ vec![hex!["00680fb81473784017291ef0afd968b986966daa7842d5b5063c8427c2b62577"].into()];
|
|
|
|
|
|
- const CENTS: u128 = 1;
|
|
|
- const DOLLARS: u128 = 100 * CENTS;
|
|
|
-
|
|
|
- const SECS_PER_BLOCK: u64 = 6;
|
|
|
- const MINUTES: u64 = 60 / SECS_PER_BLOCK;
|
|
|
- const HOURS: u64 = MINUTES * 60;
|
|
|
- const DAYS: u64 = HOURS * 24;
|
|
|
- const STASH: u128 = 50 * DOLLARS;
|
|
|
- const ENDOWMENT: u128 = 100_000_000 * DOLLARS;
|
|
|
+ const CENTS: Balance = 1;
|
|
|
+ const DOLLARS: Balance = 100 * CENTS;
|
|
|
+ const STASH: Balance = 20 * DOLLARS;
|
|
|
+ const ENDOWMENT: Balance = 100_000 * DOLLARS;
|
|
|
|
|
|
GenesisConfig {
|
|
|
- consensus: Some(ConsensusConfig {
|
|
|
- code: include_bytes!("../substrate-runtime-joystream/wasm/target/wasm32-unknown-unknown/release/joystream_node_runtime_wasm.compact.wasm").to_vec(),
|
|
|
- authorities: initial_authorities.iter().map(|x| x.2.clone()).collect(),
|
|
|
- }),
|
|
|
- system: None,
|
|
|
- timestamp: Some(TimestampConfig {
|
|
|
- minimum_period: SECS_PER_BLOCK / 2, // due to the nature of aura the slots are 2*period
|
|
|
- }),
|
|
|
- indices: Some(IndicesConfig {
|
|
|
- ids: vec![],
|
|
|
- }),
|
|
|
- balances: Some(BalancesConfig {
|
|
|
- balances: endowed_accounts.iter().cloned()
|
|
|
- .map(|k| (k, ENDOWMENT))
|
|
|
- .chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH)))
|
|
|
- .collect(),
|
|
|
- existential_deposit: 0,
|
|
|
- transfer_fee: 0,
|
|
|
- creation_fee: 0,
|
|
|
- vesting: vec![],
|
|
|
- transaction_base_fee: 1,
|
|
|
- transaction_byte_fee: 0,
|
|
|
- }),
|
|
|
- sudo: Some(SudoConfig {
|
|
|
- key: endowed_accounts[0].clone(),
|
|
|
- }),
|
|
|
- session: Some(SessionConfig {
|
|
|
- validators: initial_authorities.iter().map(|x| x.1.clone()).collect(),
|
|
|
- session_length: 10 * MINUTES,
|
|
|
- keys: initial_authorities.iter().map(|x| (x.1.clone(), x.2.clone())).collect::<Vec<_>>(),
|
|
|
- }),
|
|
|
- staking: Some(StakingConfig {
|
|
|
- current_era: 0,
|
|
|
- offline_slash: Perbill::from_millionths(10_000), // 1/ 100 => 1%
|
|
|
- session_reward: Perbill::from_millionths(1_000), // 1/1000 => 0.1% (min stake -> 1000 units for reward to be GT 0)
|
|
|
- current_session_reward: 0,
|
|
|
- validator_count: 20,
|
|
|
- sessions_per_era: 6,
|
|
|
- bonding_duration: 1, // Number of ERAs
|
|
|
- offline_slash_grace: 4,
|
|
|
- minimum_validator_count: 1,
|
|
|
- stakers: initial_authorities.iter().map(|x| (x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator)).collect(),
|
|
|
- invulnerables: initial_authorities.iter().map(|x| x.1.clone()).collect(),
|
|
|
- }),
|
|
|
- grandpa: Some(GrandpaConfig {
|
|
|
- authorities: initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect(),
|
|
|
- }),
|
|
|
- council: Some(CouncilConfig {
|
|
|
- active_council: vec![],
|
|
|
- term_ends_at: 1,
|
|
|
- }),
|
|
|
- election: Some(CouncilElectionConfig {
|
|
|
- auto_start: true,
|
|
|
- announcing_period: 3 * DAYS,
|
|
|
- voting_period: 1 * DAYS,
|
|
|
- revealing_period: 1 * DAYS,
|
|
|
- council_size: 12,
|
|
|
- candidacy_limit: 25,
|
|
|
- min_council_stake: 10 * DOLLARS,
|
|
|
- new_term_duration: 14 * DAYS,
|
|
|
- min_voting_stake: 1 * DOLLARS,
|
|
|
- }),
|
|
|
- proposals: Some(ProposalsConfig {
|
|
|
- approval_quorum: 66,
|
|
|
- min_stake: 2 * DOLLARS,
|
|
|
- cancellation_fee: 10 * CENTS,
|
|
|
- rejection_fee: 1 * DOLLARS,
|
|
|
- voting_period: 2 * DAYS,
|
|
|
- name_max_len: 512,
|
|
|
- description_max_len: 10_000,
|
|
|
- wasm_code_max_len: 2_000_000,
|
|
|
- }),
|
|
|
- members: Some(MembersConfig {
|
|
|
- default_paid_membership_fee: 100u128,
|
|
|
- first_member_id: 1,
|
|
|
- }),
|
|
|
- forum: Some(ForumConfig {
|
|
|
- category_by_id: vec![],
|
|
|
- thread_by_id: vec![],
|
|
|
- post_by_id: vec![],
|
|
|
- next_category_id: 1,
|
|
|
- next_thread_id: 1,
|
|
|
- next_post_id: 1,
|
|
|
- forum_sudo: endowed_accounts[0].clone(),
|
|
|
- category_title_constraint: new_validation(10, 90),
|
|
|
- category_description_constraint: new_validation(10, 490),
|
|
|
- thread_title_constraint: new_validation(10, 90),
|
|
|
- post_text_constraint: new_validation(10, 990),
|
|
|
- thread_moderation_rationale_constraint: new_validation(10, 290),
|
|
|
- post_moderation_rationale_constraint: new_validation(10, 290)
|
|
|
- }),
|
|
|
- data_object_type_registry: Some(DataObjectTypeRegistryConfig {
|
|
|
- first_data_object_type_id: 1,
|
|
|
- }),
|
|
|
- data_object_storage_registry: Some(DataObjectStorageRegistryConfig{
|
|
|
- first_relationship_id: 1,
|
|
|
- }),
|
|
|
- downloads: Some(DownloadSessionsConfig{
|
|
|
- first_download_session_id: 1,
|
|
|
- }),
|
|
|
- actors: Some(ActorsConfig{
|
|
|
- enable_storage_role: true,
|
|
|
- request_life_time: 300,
|
|
|
- _genesis_phantom_data: Default::default(),
|
|
|
- })
|
|
|
- }
|
|
|
+ system: Some(SystemConfig {
|
|
|
+ code: WASM_BINARY.to_vec(),
|
|
|
+ changes_trie_config: Default::default(),
|
|
|
+ }),
|
|
|
+ balances: Some(BalancesConfig {
|
|
|
+ balances: endowed_accounts
|
|
|
+ .iter()
|
|
|
+ .cloned()
|
|
|
+ .map(|k| (k, ENDOWMENT))
|
|
|
+ .chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH)))
|
|
|
+ .collect(),
|
|
|
+ vesting: vec![],
|
|
|
+ }),
|
|
|
+ indices: Some(IndicesConfig { ids: vec![] }),
|
|
|
+ session: Some(SessionConfig {
|
|
|
+ keys: initial_authorities
|
|
|
+ .iter()
|
|
|
+ .map(|x| {
|
|
|
+ (
|
|
|
+ x.0.clone(),
|
|
|
+ session_keys(x.2.clone(), x.3.clone(), x.4.clone()),
|
|
|
+ )
|
|
|
+ })
|
|
|
+ .collect::<Vec<_>>(),
|
|
|
+ }),
|
|
|
+ staking: Some(StakingConfig {
|
|
|
+ current_era: 0,
|
|
|
+ validator_count: 20,
|
|
|
+ minimum_validator_count: 1,
|
|
|
+ stakers: initial_authorities
|
|
|
+ .iter()
|
|
|
+ .map(|x| (x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator))
|
|
|
+ .collect(),
|
|
|
+ invulnerables: initial_authorities.iter().map(|x| x.0.clone()).collect(),
|
|
|
+ slash_reward_fraction: Perbill::from_percent(10),
|
|
|
+ ..Default::default()
|
|
|
+ }),
|
|
|
+ sudo: Some(SudoConfig {
|
|
|
+ key: endowed_accounts[0].clone(),
|
|
|
+ }),
|
|
|
+ babe: Some(BabeConfig {
|
|
|
+ authorities: vec![],
|
|
|
+ }),
|
|
|
+ im_online: Some(ImOnlineConfig { keys: vec![] }),
|
|
|
+ authority_discovery: Some(AuthorityDiscoveryConfig { keys: vec![] }),
|
|
|
+ grandpa: Some(GrandpaConfig {
|
|
|
+ authorities: vec![],
|
|
|
+ }),
|
|
|
+ council: Some(CouncilConfig {
|
|
|
+ active_council: vec![],
|
|
|
+ term_ends_at: 1,
|
|
|
+ }),
|
|
|
+ election: Some(CouncilElectionConfig {
|
|
|
+ auto_start: true,
|
|
|
+ announcing_period: 3 * DAYS,
|
|
|
+ voting_period: 1 * DAYS,
|
|
|
+ revealing_period: 1 * DAYS,
|
|
|
+ council_size: 12,
|
|
|
+ candidacy_limit: 25,
|
|
|
+ min_council_stake: 10 * DOLLARS,
|
|
|
+ new_term_duration: 14 * DAYS,
|
|
|
+ min_voting_stake: 1 * DOLLARS,
|
|
|
+ }),
|
|
|
+ proposals: Some(ProposalsConfig {
|
|
|
+ approval_quorum: 66,
|
|
|
+ min_stake: 2 * DOLLARS,
|
|
|
+ cancellation_fee: 10 * CENTS,
|
|
|
+ rejection_fee: 1 * DOLLARS,
|
|
|
+ voting_period: 2 * DAYS,
|
|
|
+ name_max_len: 512,
|
|
|
+ description_max_len: 10_000,
|
|
|
+ wasm_code_max_len: 2_000_000,
|
|
|
+ }),
|
|
|
+ members: Some(MembersConfig {
|
|
|
+ default_paid_membership_fee: 100u128,
|
|
|
+ members: crate::members_config::initial_members(),
|
|
|
+ }),
|
|
|
+ forum: Some(crate::forum_config::from_serialized::create(
|
|
|
+ endowed_accounts[0].clone(),
|
|
|
+ )),
|
|
|
+ data_object_type_registry: Some(DataObjectTypeRegistryConfig {
|
|
|
+ first_data_object_type_id: 1,
|
|
|
+ }),
|
|
|
+ data_object_storage_registry: Some(DataObjectStorageRegistryConfig {
|
|
|
+ first_relationship_id: 1,
|
|
|
+ }),
|
|
|
+ actors: Some(ActorsConfig {
|
|
|
+ enable_storage_role: true,
|
|
|
+ request_life_time: 300,
|
|
|
+ }),
|
|
|
+ versioned_store: Some(VersionedStoreConfig {
|
|
|
+ class_by_id: vec![],
|
|
|
+ entity_by_id: vec![],
|
|
|
+ next_class_id: 1,
|
|
|
+ next_entity_id: 1,
|
|
|
+ property_name_constraint: new_vs_validation(1, 99),
|
|
|
+ property_description_constraint: new_vs_validation(1, 999),
|
|
|
+ class_name_constraint: new_vs_validation(1, 99),
|
|
|
+ class_description_constraint: new_vs_validation(1, 999),
|
|
|
+ }),
|
|
|
+ content_wg: Some(ContentWorkingGroupConfig {
|
|
|
+ mint_capacity: 100000,
|
|
|
+ curator_opening_by_id: vec![],
|
|
|
+ next_curator_opening_id: 0,
|
|
|
+ curator_application_by_id: vec![],
|
|
|
+ next_curator_application_id: 0,
|
|
|
+ channel_by_id: vec![],
|
|
|
+ next_channel_id: 1,
|
|
|
+ channel_id_by_handle: vec![],
|
|
|
+ curator_by_id: vec![],
|
|
|
+ next_curator_id: 0,
|
|
|
+ principal_by_id: vec![],
|
|
|
+ next_principal_id: 0,
|
|
|
+ channel_creation_enabled: true, // there is no extrinsic to change it so enabling at genesis
|
|
|
+ unstaker_by_stake_id: vec![],
|
|
|
+ channel_handle_constraint: crate::forum_config::new_validation(5, 20),
|
|
|
+ channel_description_constraint: crate::forum_config::new_validation(1, 1024),
|
|
|
+ opening_human_readable_text: crate::forum_config::new_validation(1, 2048),
|
|
|
+ curator_application_human_readable_text: crate::forum_config::new_validation(1, 2048),
|
|
|
+ curator_exit_rationale_text: crate::forum_config::new_validation(1, 2048),
|
|
|
+ channel_avatar_constraint: crate::forum_config::new_validation(5, 1024),
|
|
|
+ channel_banner_constraint: crate::forum_config::new_validation(5, 1024),
|
|
|
+ channel_title_constraint: crate::forum_config::new_validation(5, 1024),
|
|
|
+ }),
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-fn testnet_genesis(
|
|
|
- initial_authorities: Vec<(AccountId, AccountId, AuthorityId)>,
|
|
|
- endowed_accounts: Vec<AccountId>,
|
|
|
+/// Helper function to create GenesisConfig for testing
|
|
|
+pub fn testnet_genesis(
|
|
|
+ initial_authorities: Vec<(AccountId, AccountId, GrandpaId, BabeId, ImOnlineId)>,
|
|
|
root_key: AccountId,
|
|
|
+ endowed_accounts: Vec<AccountId>,
|
|
|
) -> GenesisConfig {
|
|
|
- const STASH: u128 = 100;
|
|
|
- const ENDOWMENT: u128 = 100_000_000;
|
|
|
+ const STASH: Balance = 2000;
|
|
|
+ const ENDOWMENT: Balance = 10_000_000;
|
|
|
+
|
|
|
+ // Static members
|
|
|
+ let initial_members = crate::members_config::initial_members();
|
|
|
+
|
|
|
+ // let mut additional_members = vec![
|
|
|
+ // // Make Root a member
|
|
|
+ // (
|
|
|
+ // root_key.clone(),
|
|
|
+ // String::from("system"),
|
|
|
+ // String::from("http://joystream.org/avatar.png"),
|
|
|
+ // String::from("I am root!"),
|
|
|
+ // ),
|
|
|
+ // ];
|
|
|
+
|
|
|
+ // // Additional members
|
|
|
+ // initial_members.append(&mut additional_members);
|
|
|
|
|
|
GenesisConfig {
|
|
|
- consensus: Some(ConsensusConfig {
|
|
|
- code: include_bytes!("../substrate-runtime-joystream/wasm/target/wasm32-unknown-unknown/release/joystream_node_runtime_wasm.compact.wasm").to_vec(),
|
|
|
- authorities: initial_authorities.iter().map(|x| x.2.clone()).collect(),
|
|
|
- }),
|
|
|
- system: None,
|
|
|
- timestamp: Some(TimestampConfig {
|
|
|
- minimum_period: 3, // 3*2=6 second block time.
|
|
|
- }),
|
|
|
- indices: Some(IndicesConfig {
|
|
|
- ids: vec![]
|
|
|
- }),
|
|
|
- balances: Some(BalancesConfig {
|
|
|
- existential_deposit: 0,
|
|
|
- transfer_fee: 0,
|
|
|
- creation_fee: 0,
|
|
|
- balances: endowed_accounts.iter().cloned()
|
|
|
- .map(|k| (k, ENDOWMENT))
|
|
|
- .chain(initial_authorities.iter().map(|x| (x.0.clone(), STASH)))
|
|
|
- .collect(),
|
|
|
- vesting: vec![],
|
|
|
- transaction_base_fee: 1,
|
|
|
- transaction_byte_fee: 0,
|
|
|
- }),
|
|
|
- sudo: Some(SudoConfig {
|
|
|
- key: root_key.clone(),
|
|
|
- }),
|
|
|
- session: Some(SessionConfig {
|
|
|
- validators: initial_authorities.iter().map(|x| x.1.clone()).collect(),
|
|
|
- session_length: 10,
|
|
|
- keys: initial_authorities.iter().map(|x| (x.1.clone(), x.2.clone())).collect::<Vec<_>>(),
|
|
|
- }),
|
|
|
- staking: Some(StakingConfig {
|
|
|
- current_era: 0,
|
|
|
- minimum_validator_count: 1,
|
|
|
- validator_count: 2,
|
|
|
- sessions_per_era: 5,
|
|
|
- bonding_duration: 1, // Number of Eras
|
|
|
- offline_slash: Perbill::zero(),
|
|
|
- session_reward: Perbill::zero(),
|
|
|
- current_session_reward: 0,
|
|
|
- offline_slash_grace: 0,
|
|
|
- stakers: initial_authorities.iter().map(|x| (x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator)).collect(),
|
|
|
- invulnerables: initial_authorities.iter().map(|x| x.1.clone()).collect(),
|
|
|
- }),
|
|
|
- grandpa: Some(GrandpaConfig {
|
|
|
- authorities: initial_authorities.iter().map(|x| (x.2.clone(), 1)).collect(),
|
|
|
- }),
|
|
|
- council: Some(CouncilConfig {
|
|
|
- active_council: vec![],
|
|
|
- term_ends_at: 1,
|
|
|
- }),
|
|
|
- election: Some(CouncilElectionConfig {
|
|
|
- auto_start: true,
|
|
|
- announcing_period: 50,
|
|
|
- voting_period: 50,
|
|
|
- revealing_period: 50,
|
|
|
- council_size: 2,
|
|
|
- candidacy_limit: 25,
|
|
|
- min_council_stake: 100,
|
|
|
- new_term_duration: 1000,
|
|
|
- min_voting_stake: 10,
|
|
|
- }),
|
|
|
- proposals: Some(ProposalsConfig {
|
|
|
- approval_quorum: 66,
|
|
|
- min_stake: 100,
|
|
|
- cancellation_fee: 5,
|
|
|
- rejection_fee: 10,
|
|
|
- voting_period: 100,
|
|
|
- name_max_len: 100,
|
|
|
- description_max_len: 10_000,
|
|
|
- wasm_code_max_len: 2_000_000,
|
|
|
- }),
|
|
|
- members: Some(MembersConfig {
|
|
|
- default_paid_membership_fee: 100u128,
|
|
|
- first_member_id: 1,
|
|
|
- }),
|
|
|
- forum: Some(ForumConfig {
|
|
|
- category_by_id: vec![],
|
|
|
- thread_by_id: vec![],
|
|
|
- post_by_id: vec![],
|
|
|
- next_category_id: 1,
|
|
|
- next_thread_id: 1,
|
|
|
- next_post_id: 1,
|
|
|
- forum_sudo: root_key,
|
|
|
- category_title_constraint: new_validation(10, 90),
|
|
|
- category_description_constraint: new_validation(10, 490),
|
|
|
- thread_title_constraint: new_validation(10, 90),
|
|
|
- post_text_constraint: new_validation(10, 990),
|
|
|
- thread_moderation_rationale_constraint: new_validation(10, 290),
|
|
|
- post_moderation_rationale_constraint: new_validation(10, 290)
|
|
|
- }),
|
|
|
- data_object_type_registry: Some(DataObjectTypeRegistryConfig {
|
|
|
- first_data_object_type_id: 1,
|
|
|
- }),
|
|
|
- data_object_storage_registry: Some(DataObjectStorageRegistryConfig{
|
|
|
- first_relationship_id: 1,
|
|
|
- }),
|
|
|
- downloads: Some(DownloadSessionsConfig{
|
|
|
- first_download_session_id: 1,
|
|
|
- }),
|
|
|
- actors: Some(ActorsConfig{
|
|
|
- enable_storage_role: true,
|
|
|
- request_life_time: 300,
|
|
|
- _genesis_phantom_data: Default::default(),
|
|
|
- })
|
|
|
- }
|
|
|
+ //substrate modules
|
|
|
+ system: Some(SystemConfig {
|
|
|
+ code: WASM_BINARY.to_vec(),
|
|
|
+ changes_trie_config: Default::default(),
|
|
|
+ }),
|
|
|
+ balances: Some(BalancesConfig {
|
|
|
+ balances: endowed_accounts
|
|
|
+ .iter()
|
|
|
+ .map(|k| (k.clone(), ENDOWMENT))
|
|
|
+ .collect(),
|
|
|
+ vesting: vec![],
|
|
|
+ }),
|
|
|
+ indices: Some(IndicesConfig { ids: vec![] }),
|
|
|
+ staking: Some(StakingConfig {
|
|
|
+ current_era: 0,
|
|
|
+ minimum_validator_count: 1,
|
|
|
+ validator_count: 2,
|
|
|
+ stakers: initial_authorities
|
|
|
+ .iter()
|
|
|
+ .map(|x| (x.0.clone(), x.1.clone(), STASH, StakerStatus::Validator))
|
|
|
+ .collect(),
|
|
|
+ invulnerables: initial_authorities.iter().map(|x| x.0.clone()).collect(),
|
|
|
+ slash_reward_fraction: Perbill::from_percent(10),
|
|
|
+ ..Default::default()
|
|
|
+ }),
|
|
|
+ session: Some(SessionConfig {
|
|
|
+ keys: initial_authorities
|
|
|
+ .iter()
|
|
|
+ .map(|x| {
|
|
|
+ (
|
|
|
+ x.0.clone(),
|
|
|
+ session_keys(x.2.clone(), x.3.clone(), x.4.clone()),
|
|
|
+ )
|
|
|
+ })
|
|
|
+ .collect::<Vec<_>>(),
|
|
|
+ }),
|
|
|
+ sudo: Some(SudoConfig {
|
|
|
+ key: root_key.clone(),
|
|
|
+ }),
|
|
|
+ babe: Some(BabeConfig {
|
|
|
+ authorities: vec![],
|
|
|
+ }),
|
|
|
+ im_online: Some(ImOnlineConfig { keys: vec![] }),
|
|
|
+ authority_discovery: Some(AuthorityDiscoveryConfig { keys: vec![] }),
|
|
|
+ grandpa: Some(GrandpaConfig {
|
|
|
+ authorities: vec![],
|
|
|
+ }),
|
|
|
+ // joystream modules
|
|
|
+ council: Some(CouncilConfig {
|
|
|
+ active_council: vec![],
|
|
|
+ term_ends_at: 1,
|
|
|
+ }),
|
|
|
+ election: Some(CouncilElectionConfig {
|
|
|
+ auto_start: true,
|
|
|
+ announcing_period: 50,
|
|
|
+ voting_period: 50,
|
|
|
+ revealing_period: 50,
|
|
|
+ council_size: 2,
|
|
|
+ candidacy_limit: 25,
|
|
|
+ min_council_stake: 100,
|
|
|
+ new_term_duration: 1000,
|
|
|
+ min_voting_stake: 10,
|
|
|
+ }),
|
|
|
+ proposals: Some(ProposalsConfig {
|
|
|
+ approval_quorum: 66,
|
|
|
+ min_stake: 100,
|
|
|
+ cancellation_fee: 5,
|
|
|
+ rejection_fee: 10,
|
|
|
+ voting_period: 100,
|
|
|
+ name_max_len: 100,
|
|
|
+ description_max_len: 10_000,
|
|
|
+ wasm_code_max_len: 2_000_000,
|
|
|
+ }),
|
|
|
+ members: Some(MembersConfig {
|
|
|
+ default_paid_membership_fee: 100u128,
|
|
|
+ members: initial_members,
|
|
|
+ }),
|
|
|
+ forum: Some(crate::forum_config::from_serialized::create(
|
|
|
+ root_key.clone(),
|
|
|
+ )),
|
|
|
+ data_object_type_registry: Some(DataObjectTypeRegistryConfig {
|
|
|
+ first_data_object_type_id: 1,
|
|
|
+ }),
|
|
|
+ data_object_storage_registry: Some(DataObjectStorageRegistryConfig {
|
|
|
+ first_relationship_id: 1,
|
|
|
+ }),
|
|
|
+ actors: Some(ActorsConfig {
|
|
|
+ enable_storage_role: true,
|
|
|
+ request_life_time: 300,
|
|
|
+ }),
|
|
|
+ versioned_store: Some(VersionedStoreConfig {
|
|
|
+ class_by_id: vec![],
|
|
|
+ entity_by_id: vec![],
|
|
|
+ next_class_id: 1,
|
|
|
+ next_entity_id: 1,
|
|
|
+ property_name_constraint: new_vs_validation(1, 99),
|
|
|
+ property_description_constraint: new_vs_validation(1, 999),
|
|
|
+ class_name_constraint: new_vs_validation(1, 99),
|
|
|
+ class_description_constraint: new_vs_validation(1, 999),
|
|
|
+ }),
|
|
|
+ content_wg: Some(ContentWorkingGroupConfig {
|
|
|
+ mint_capacity: 100000,
|
|
|
+ curator_opening_by_id: vec![],
|
|
|
+ next_curator_opening_id: 0,
|
|
|
+ curator_application_by_id: vec![],
|
|
|
+ next_curator_application_id: 0,
|
|
|
+ channel_by_id: vec![],
|
|
|
+ next_channel_id: 1,
|
|
|
+ channel_id_by_handle: vec![],
|
|
|
+ curator_by_id: vec![],
|
|
|
+ next_curator_id: 0,
|
|
|
+ principal_by_id: vec![],
|
|
|
+ next_principal_id: 0,
|
|
|
+ channel_creation_enabled: true, // there is no extrinsic to change it so enabling at genesis
|
|
|
+ unstaker_by_stake_id: vec![],
|
|
|
+ channel_handle_constraint: crate::forum_config::new_validation(5, 20),
|
|
|
+ channel_description_constraint: crate::forum_config::new_validation(1, 1024),
|
|
|
+ opening_human_readable_text: crate::forum_config::new_validation(1, 2048),
|
|
|
+ curator_application_human_readable_text: crate::forum_config::new_validation(1, 2048),
|
|
|
+ curator_exit_rationale_text: crate::forum_config::new_validation(1, 2048),
|
|
|
+ channel_avatar_constraint: crate::forum_config::new_validation(5, 1024),
|
|
|
+ channel_banner_constraint: crate::forum_config::new_validation(5, 1024),
|
|
|
+ channel_title_constraint: crate::forum_config::new_validation(5, 1024),
|
|
|
+ }),
|
|
|
+ }
|
|
|
}
|