From 9e96c40f23b4f002434d64bdf2e19c74de5618e0 Mon Sep 17 00:00:00 2001 From: vasylenko-yevhen Date: Fri, 18 Nov 2022 15:05:57 +0200 Subject: [PATCH 1/2] Update subzero runtime to be used for kusama. Remove GameDAO pallets. --- bin/subzero/node/Cargo.toml | 3 - bin/subzero/node/src/chain_spec.rs | 357 +------------------------- bin/subzero/node/src/command.rs | 2 - bin/subzero/runtime/Cargo.toml | 43 +--- bin/subzero/runtime/src/lib.rs | 197 ++++---------- bin/subzero/runtime/src/xcm_config.rs | 21 +- 6 files changed, 78 insertions(+), 545 deletions(-) diff --git a/bin/subzero/node/Cargo.toml b/bin/subzero/node/Cargo.toml index bb58b038ea..ba8c8f5f52 100644 --- a/bin/subzero/node/Cargo.toml +++ b/bin/subzero/node/Cargo.toml @@ -59,7 +59,6 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkad sp-session = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } try-runtime-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } @@ -90,8 +89,6 @@ cumulus-relay-chain-interface = { git = "https://github.com/paritytech/cumulus", cumulus-relay-chain-rpc-interface = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } primitives = { version = "2.0.0", package = "zero-primitives", default-features = false, path = "../../../modules/primitives" } -gamedao-control = { path = "../../../modules/gamedao-protocol/control", default-features = false } -orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch= "polkadot-v0.9.28", default-features = false } [build-dependencies] substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } diff --git a/bin/subzero/node/src/chain_spec.rs b/bin/subzero/node/src/chain_spec.rs index 7603bb7398..c904950025 100644 --- a/bin/subzero/node/src/chain_spec.rs +++ b/bin/subzero/node/src/chain_spec.rs @@ -3,17 +3,12 @@ use subzero_runtime::{AccountId, AuraId, SS58Prefix, Signature, SudoConfig}; use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup, Properties}; use sc_service::ChainType; use serde::{Deserialize, Serialize}; -use sp_core::{sr25519, Pair, Public, crypto::UncheckedInto}; -use sp_runtime::{BoundedVec, traits::{IdentifyAccount, Verify, Zero}}; -use sp_std::collections::btree_map::BTreeMap; -use hex_literal::hex; - -use gamedao_control::types::{OrgType, AccessModel, FeeModel}; -use orml_tokens; +use sp_core::{sr25519, Pair, Public}; +use sp_runtime::traits::{IdentifyAccount, Verify}; use primitives::{ - currency::{ZERO, PLAY, GAME, DOT, TokenInfo, CurrencyId}, - cent, dollar, Balance + currency::{ZERO, PLAY, GAME, DOT, TokenInfo}, + cent }; /// Specialized `ChainSpec` for the normal parachain runtime. @@ -246,350 +241,6 @@ fn testnet_genesis( technical_committee: Default::default(), elections: Default::default(), technical_membership: Default::default(), - control: Default::default(), - asset_registry: Default::default(), - } -} - -pub fn development_subzero_config() -> ChainSpec { - let properties = get_properties(); - - ChainSpec::from_genesis( - // Name - "Subzero Development", - // ID - "subzero-dev", - ChainType::Local, - // SECRET="..." - // docker run --rm parity/subkey inspect "$SECRET//subzero//root" - // docker run --rm parity/subkey inspect "$SECRET//subzero//1//collator" - // docker run --rm parity/subkey inspect "$SECRET//subzero//1//aura" - // docker run --rm parity/subkey inspect "$SECRET//subzero//2//collator" - // docker run --rm parity/subkey inspect "$SECRET//subzero//2//aura" - // docker run --rm parity/subkey inspect "$SECRET//subzero//zero-treasury" - // docker run --rm parity/subkey inspect "$SECRET//subzero//gamedao-treasury" - // docker run --rm parity/subkey inspect "$SECRET//subzero//game3-treasury" - // docker run --rm parity/subkey inspect "$SECRET//subzero//prime" - move || { - subzero_genesis( - // Initial collators - vec![ - ( - // 5FyCQF345qawarNwSoUgg5ankQt1g4J4wHwryMsEiUHi592W - hex!["acbd8ce2c37263c4964f4babcc6eaedd5276006c448e046290d366318c3b0016"].into(), - hex!["d081d0b6ee6fe89fca7ed9ee7a927da7462389798a2ed1a62caa456de487f574"].unchecked_into(), - ), - ( - // 5FP7zjy4uZ46uGSTrXBhkk6L7RkKtS8emD9BLAFAXBDS5nD2 - hex!["92c0609c5bc85053246436c99e5474163e2f73f59adef926bc0897502eca1945"].into(), - hex!["d008cd73618b8bce15531f693516635800ec1ee69f19e43f25f32129c5d5fd39"].unchecked_into(), - ), - ], - vec![ - // Faucet Bot - // 5Ef24TjfGNPnxrALTsPN3wJ9XoTTY4coMvryNed4MkZmqKaL - hex!["72a416a9270487e9fa301883780fe22edfac394bcf018b5da4444dff38937574"].into(), - // Org Prime - // 5GWchgf4qbaJZTBbmKTGWDCVPJt1XPLQfxaKsDe3Y3LqyHbT - hex!["c4b3f61d4f896a660d35bdf6a78c54cf2aa2af48ba0945f568dc67674247e136"].into(), - // Root - // 5CwWu8QwK8hdHcC5JHWWVSbxAFcLD4eUPsWY1BEy48LxjjMf - hex!["26c0a10c263cf2583936ff9714a645de855e39090765a0a23fe8a2001ab83016"].into(), - ], - // Root - // 5CwWu8QwK8hdHcC5JHWWVSbxAFcLD4eUPsWY1BEy48LxjjMf - hex!["26c0a10c263cf2583936ff9714a645de855e39090765a0a23fe8a2001ab83016"].into(), - // Zero treasury account - // 5EeG87W6f5X39SUeTLM6oBT8M5BZ4ApQbncKw78QFvgkGnqd - hex!["72102ee7e9bd0170c9829054bf8aaab65ea2555b1c30b04747160fe4a86d5b47"].into(), - // Gamedao treasury account - // 5EnLtQYf87Kab8vR8CyGmFXjo1HjYLUbFAdCsK5rFMAhfT4R - hex!["783a2eb5d5b4f1f3a7b49bea0c82119cccb366fd7b05d4c44b21ea160b52b160"].into(), - // Game3 treasury account - // 5DtGqwDh1rgcGYX2QxqxBs5S7VsNFbowX7cUiGiLEQ2aP9UV - hex!["5083d014500f360fa17ec74d50f0b8336e205f11d7a9e4cfc4bb42a7a3da4c6d"].into(), - // Org Prime - // 5GWchgf4qbaJZTBbmKTGWDCVPJt1XPLQfxaKsDe3Y3LqyHbT - hex!["c4b3f61d4f896a660d35bdf6a78c54cf2aa2af48ba0945f568dc67674247e136"].into(), - DEFAULT_PARA_ID.into(), - ) - }, - vec![ - "/dns/collator-1/tcp/30333/p2p/12D3KooWBQB9MUka9nMcqXi3ANLUdu4FweQpMvw9VHpHveiYhsPx" - .parse() - .unwrap(), - ], - // Telemetry - None, - // Protocol ID - Some("subzero-dev"), - // Fork ID - None, - Some(properties), - Extensions { - relay_chain: "rococo-local".into(), // You MUST set this to the correct network! - para_id: DEFAULT_PARA_ID, - }, - ) -} - -pub fn staging_subzero_config() -> ChainSpec { - let properties = get_properties(); - - ChainSpec::from_genesis( - // Name - "Subzero Staging", - // ID - "subzero-stage", - ChainType::Local, - // SECRET="..." - // docker run --rm parity/subkey inspect "$SECRET//subzero//root" - // docker run --rm parity/subkey inspect "$SECRET//subzero//1//collator" - // docker run --rm parity/subkey inspect "$SECRET//subzero//1//aura" - // docker run --rm parity/subkey inspect "$SECRET//subzero//2//collator" - // docker run --rm parity/subkey inspect "$SECRET//subzero//2//aura" - // docker run --rm parity/subkey inspect "$SECRET//subzero//3//collator" - // docker run --rm parity/subkey inspect "$SECRET//subzero//3//aura" - // docker run --rm parity/subkey inspect "$SECRET//subzero//4//collator" - // docker run --rm parity/subkey inspect "$SECRET//subzero//4//aura" - // docker run --rm parity/subkey inspect "$SECRET//subzero//zero-treasury" - // docker run --rm parity/subkey inspect "$SECRET//subzero//gamedao-treasury" - // docker run --rm parity/subkey inspect "$SECRET//subzero//game3-treasury" - // docker run --rm parity/subkey inspect "$SECRET//subzero//prime" - move || { - subzero_genesis( - // Initial collators - vec![ - ( - // 5EJVzfYgcPEncpwNoQp7ryzfJRjNfxQs4b4gUUdT7ya2Hg16 - hex!["62fdf8994e59cf79ef96338ccf1fa6fffd37c1a843841db0d3963efef0e4d31d"].into(), - hex!["90bf7542167747bcceb0614d4e461df631a8557cf9a7009899bacb203479f642"].unchecked_into(), - ), - ( - // 5GH83LCgSC6Kp5WZtF7pvaBiyqY22ZeH2gr1vCAh3TxpM83i - hex!["ba6949eb864d92d360bf997043b4229b7f54a6df5136af5b4f885a1ce89fd462"].into(), - hex!["eab75e30bd998c79befb81938daf6189f983273b0aeb292b15667d01245bfa6c"].unchecked_into(), - ), - ( - // 5EZZFSPHc2myoFFPFoM7k7Cy1p3niGoXCP8iG4qAKWcDMVVM - hex!["6e799bc5437690e6bd86aa0df8451eaf605ae7b2ec0266f9899905265572b018"].into(), - hex!["a2d2896c87b1db42b952835a775ff7418375ef4dc171b92640b4c11c22a2250f"].unchecked_into(), - ), - ( - // 5FKnYx26KziwtQeXmR6gaD1LwgMUUjCFjG5YAQQES1RfHFbV - hex!["90352f3b6f33a62c3f43cfe08726724d48cbc4919e27a5d1e55efa6881bad229"].into(), - hex!["96750acce3e01bedb5b2ffd7706f2e7b4a83c5e2f8714257d9d2ab95fb61da0d"].unchecked_into(), - ), - ], - vec![ - // Faucet Bot - // 5Ef24TjfGNPnxrALTsPN3wJ9XoTTY4coMvryNed4MkZmqKaL - hex!["72a416a9270487e9fa301883780fe22edfac394bcf018b5da4444dff38937574"].into(), - // Org Prime - // 5GeBJnjVxueXj5PsTFLTBoPQzt5scehWkKL84JLJ8hXWexaP - hex!["ca7870338715348c17ffb5a299c4ae9e2ceec0726d8d72a2f502060942af045d"].into(), - // Root - // 5HdZAx6ieBdLPdeQjj778ST7oq6poUkhr7nZ32mWzEjWGwQa - hex!["f63b07ad8610dcbdff485d2497fb359077ec8bfef9d9ffdb38022d7cdc986318"].into(), - ], - // Root - // 5HdZAx6ieBdLPdeQjj778ST7oq6poUkhr7nZ32mWzEjWGwQa - hex!["f63b07ad8610dcbdff485d2497fb359077ec8bfef9d9ffdb38022d7cdc986318"].into(), - // Zero treasury account - // 5EXAdVUvu3dyDb4Wn55XUdxWBv3fPhvf9Vzf76LsFBe72WA4 - hex!["6ca6f9057fa6374afd5c0b92a40905340f56e96f4905b36a0526917016f48667"].into(), - // Gamedao treasury account - // 5CSM7WW5icde1aqCK4xfbhBXCVqE76dZX2tvMtntaVvEBuFv - hex!["10819164c87b9f4dc70e64879d170d52378358b538b80fdabc0e90028a66f570"].into(), - // Game3 treasury account - // 5GNFNuNAJbD4ECDVHjYKHZibPUfGXHdFqKRoqVDbopsSGAim - hex!["be52373f74b5fa074de8edaa76e288305f200a6831d3550c0ebe4e02da9fa52d"].into(), - // Org Prime - // 5GeBJnjVxueXj5PsTFLTBoPQzt5scehWkKL84JLJ8hXWexaP - hex!["ca7870338715348c17ffb5a299c4ae9e2ceec0726d8d72a2f502060942af045d"].into(), - DEFAULT_PARA_ID.into(), - ) - }, - vec![ - "/dns/collator-1/tcp/30333/p2p/12D3KooWBQB9MUka9nMcqXi3ANLUdu4FweQpMvw9VHpHveiYhsPx" - .parse() - .unwrap(), - ], - // Telemetry - None, - // Protocol ID - Some("subzero-stage"), - // Fork ID - None, - Some(properties), - Extensions { - relay_chain: "rococo-local".into(), // You MUST set this to the correct network! - para_id: DEFAULT_PARA_ID, - }, - ) -} - -fn subzero_genesis( - invulnerables: Vec<(AccountId, AuraId)>, - endowed_accounts: Vec, - root_key: AccountId, - zero_treasury: AccountId, - gamedao_treasury: AccountId, - game3_treasury: AccountId, - org_prime: AccountId, - id: ParaId, -) -> subzero_runtime::GenesisConfig { - subzero_runtime::GenesisConfig { - system: subzero_runtime::SystemConfig { - code: subzero_runtime::WASM_BINARY - .expect("WASM binary was not build, please build it!") - .to_vec(), - }, - sudo: SudoConfig { key: Some(root_key) }, - balances: subzero_runtime::BalancesConfig { - balances: balances_config(endowed_accounts.clone(), zero_treasury.clone(), game3_treasury.clone(), gamedao_treasury.clone()), - }, - parachain_info: subzero_runtime::ParachainInfoConfig { parachain_id: id }, - collator_selection: subzero_runtime::CollatorSelectionConfig { - invulnerables: invulnerables.iter().cloned().map(|(acc, _)| acc).collect(), - candidacy_bond: cent(ZERO) * 16, - ..Default::default() - }, - session: subzero_runtime::SessionConfig { - keys: invulnerables - .into_iter() - .map(|(acc, aura)| { - ( - acc.clone(), // account id - acc, // validator id - subzero_session_keys(aura), // session keys - ) - }) - .collect(), - }, - // no need to pass anything to aura, in fact it will panic if we do. Session will take care - // of this. - aura: Default::default(), - aura_ext: Default::default(), - parachain_system: Default::default(), - polkadot_xcm: subzero_runtime::PolkadotXcmConfig { - safe_xcm_version: Some(SAFE_XCM_VERSION), - }, - council: Default::default(), - treasury: Default::default(), - tokens: orml_tokens::GenesisConfig { - balances: tokens_config(endowed_accounts.clone(), zero_treasury.clone(), game3_treasury.clone(), gamedao_treasury.clone()), - }, - democracy: Default::default(), - technical_committee: Default::default(), - elections: Default::default(), - technical_membership: Default::default(), - control: gamedao_control::GenesisConfig { - orgs: vec![ - // Zero Network - (org_prime.clone(), org_prime.clone(), zero_treasury, BoundedVec::truncate_from(b"Zero Network".to_vec()), - BoundedVec::truncate_from(b"QmUWu6zoFM4j1fwT6fHGEjiuCSft2sNcbmJtT23R9su3Bk".to_vec()), - OrgType::Individual, AccessModel::Open, FeeModel::NoFees, Zero::zero(), - GAME, PLAY, 1000, 1 * dollar(GAME) - ), - // GameDao - (org_prime.clone(), org_prime.clone(), gamedao_treasury, BoundedVec::truncate_from(b"GameDao".to_vec()), - BoundedVec::truncate_from(b"QmcNp8hsRaxVDhKgbgo6Jtcb8papyPnKbqjzFtqzqxDE7j".to_vec()), - OrgType::Individual, AccessModel::Open, FeeModel::NoFees, Zero::zero(), - GAME, PLAY, 1000, 1 * dollar(GAME) - ), - // Game3 Foundation - (org_prime.clone(), org_prime.clone(), game3_treasury, BoundedVec::truncate_from(b"Game3 Foundation".to_vec()), - BoundedVec::truncate_from(b"QmNYVx6bhRUGbMp6UEPHKhaLRwFfpsbsP4sFT9XCvMxgfz".to_vec()), - OrgType::Individual, AccessModel::Open, FeeModel::NoFees, Zero::zero(), - GAME, PLAY, 1000, 1 * dollar(GAME) - ), - ] - }, asset_registry: Default::default(), } } - -fn balances_config(accounts: Vec, zero_treasury: AccountId, - game3_treasury: AccountId, gamedao_treasury: AccountId) -> Vec<(AccountId, Balance)> { - // Zero Network Treasury owns ZERO issuance: - let mut zero_issuance = 1_000_000_000 * dollar(ZERO); - // Game3 Foundation Treasury: - let game3_zero = 1_000_000 * dollar(ZERO); - // GameDAO Treasury: - let gamedao_zero = 1_000_000 * dollar(ZERO); - - let account_balances = accounts.iter().cloned().map(|x| (x, 1_000_000 * dollar(ZERO))) - .fold( - BTreeMap::::new(), - |mut acc, (account_id, amount)| { - if let Some(balance) = acc.get_mut(&account_id) { - *balance = balance - .checked_add(amount) - .expect("balance overflow"); - } else { - zero_issuance = zero_issuance.saturating_sub(amount); - acc.insert(account_id.clone(), amount); - } - acc - }, - ) - .into_iter() - .collect::>(); - - zero_issuance = zero_issuance.saturating_sub(game3_zero).saturating_sub(gamedao_zero); - let mut balances = vec![ - (zero_treasury, zero_issuance), - (gamedao_treasury, gamedao_zero), - (game3_treasury, game3_zero), - ]; - balances.extend(account_balances); - balances -} - -fn tokens_config(accounts: Vec, zero_treasury: AccountId, - game3_treasury: AccountId, gamedao_treasury: AccountId) -> Vec<(AccountId, CurrencyId, Balance)> { - // Game3 Foundation Treasury owns GAME & PLAY issuance: - let mut game_issuance = 100_000_000 * dollar(GAME); - let mut play_issuance = 10_000_000 * dollar(PLAY); - - // Zero Network Treasury: - let zeronet_game = 100_000 * dollar(GAME); - let zeronet_play = 1_000_000 * dollar(PLAY); - - // GameDAO: - let gamedao_game = 100_000 * dollar(GAME); - let gamedao_play = 1_000_000 * dollar(PLAY); - - let account_balances = accounts - .iter().cloned() - .flat_map(|x| vec![(x.clone(), GAME, 1_000_000 * dollar(GAME)), (x.clone(), PLAY, 1_000_000 * dollar(PLAY))]) - .fold( - Vec::new(), - |mut vec, (account_id, currency_id, amount)| { - match currency_id { - GAME => { game_issuance = game_issuance.saturating_sub(amount); }, - PLAY => { play_issuance = play_issuance.saturating_sub(amount); }, - _ => () - }; - vec.push((account_id.clone(), currency_id, amount)); - vec - }, - ) - .into_iter() - .collect::>(); - - game_issuance = game_issuance.saturating_sub(zeronet_game).saturating_sub(gamedao_game); - play_issuance = play_issuance.saturating_sub(zeronet_play).saturating_sub(gamedao_play); - - let mut token_balances = vec![ - (zero_treasury.clone(), GAME, zeronet_game), - (zero_treasury, PLAY, zeronet_play), - (game3_treasury.clone(), GAME, game_issuance), - (game3_treasury, PLAY, play_issuance), - (gamedao_treasury.clone(), GAME, gamedao_game), - (gamedao_treasury, PLAY, gamedao_play), - ]; - token_balances.extend(account_balances); - token_balances -} diff --git a/bin/subzero/node/src/command.rs b/bin/subzero/node/src/command.rs index ebb62fa5a9..22b9af09e2 100644 --- a/bin/subzero/node/src/command.rs +++ b/bin/subzero/node/src/command.rs @@ -26,8 +26,6 @@ use crate::{ fn load_spec(id: &str) -> std::result::Result, String> { Ok(match id { "dev" => Box::new(chain_spec::development_config()), - "subzero-dev" => Box::new(chain_spec::development_subzero_config()), - "subzero-stage" => Box::new(chain_spec::staging_subzero_config()), "template-rococo" => Box::new(chain_spec::local_testnet_config()), "" | "local" => Box::new(chain_spec::local_testnet_config()), path => Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?), diff --git a/bin/subzero/runtime/Cargo.toml b/bin/subzero/runtime/Cargo.toml index 7d96a75722..ddb2f5adf7 100644 --- a/bin/subzero/runtime/Cargo.toml +++ b/bin/subzero/runtime/Cargo.toml @@ -75,20 +75,21 @@ xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.28" } # Cumulus -cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28", default-features = false } -cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28", default-features = false } -cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28", default-features = false } -cumulus-pallet-session-benchmarking = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28", default-features = false} -cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28", default-features = false } -cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28", default-features = false } -cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28", default-features = false } -cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28", default-features = false } -cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28", default-features = false } -pallet-collator-selection = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28", default-features = false } -parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28", default-features = false } +cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.28" } +cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.28" } +cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.28" } +cumulus-pallet-session-benchmarking = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.28", version = "3.0.0"} +cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.28" } +cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.28" } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.28" } +cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.28" } +cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.28" } +pallet-collator-selection = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.28" } +parachain-info = { git = "https://github.com/paritytech/cumulus", default-features = false, branch = "polkadot-v0.9.28" } primitives = { version = "2.0.0", package = "zero-primitives", default-features = false, path = "../../../modules/primitives" } +# ORML orml-asset-registry = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch= "polkadot-v0.9.28", default-features = false } orml-currencies = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch= "polkadot-v0.9.28", default-features = false } orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch= "polkadot-v0.9.28", default-features = false } @@ -98,18 +99,13 @@ orml-xcm = { git = "https://github.com/open-web3-stack/open-runtime-module-libra orml-xcm-support = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch= "polkadot-v0.9.28", default-features = false } orml-xtokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch= "polkadot-v0.9.28", default-features = false } +# RMRK pallet-rmrk-core = { git = "https://github.com/rmrk-team/rmrk-substrate", default-features = false, branch = "polkadot-v0.9.28" } pallet-rmrk-equip = { git = "https://github.com/rmrk-team/rmrk-substrate", default-features = false, branch = "polkadot-v0.9.28" } pallet-rmrk-market = { git = "https://github.com/rmrk-team/rmrk-substrate", default-features = false, branch = "polkadot-v0.9.28" } rmrk-traits = { git = "https://github.com/rmrk-team/rmrk-substrate", default-features = false, branch = "polkadot-v0.9.28" } pallet-rmrk-rpc-runtime-api = { git = "https://github.com/rmrk-team/rmrk-substrate", default-features = false, branch = "polkadot-v0.9.28" } -gamedao-traits = { path = "../../../modules/gamedao-protocol/traits", default-features = false } -gamedao-flow = { path = "../../../modules/gamedao-protocol/flow", default-features = false } -gamedao-control = { path = "../../../modules/gamedao-protocol/control", default-features = false } -gamedao-signal = { path = "../../../modules/gamedao-protocol/signal", default-features = false } -gamedao-sense = { path = "../../../modules/gamedao-protocol/sense", default-features = false } - [features] default = [ "std", @@ -191,12 +187,6 @@ std = [ "pallet-rmrk-equip/std", "rmrk-traits/std", "pallet-rmrk-rpc-runtime-api/std", - - "gamedao-sense/std", - "gamedao-traits/std", - "gamedao-flow/std", - "gamedao-control/std", - "gamedao-signal/std", ] runtime-benchmarks = [ @@ -210,7 +200,6 @@ runtime-benchmarks = [ "pallet-collator-selection/runtime-benchmarks", "pallet-collective/runtime-benchmarks", "pallet-child-bounties/runtime-benchmarks", - "pallet-democracy/runtime-benchmarks", "pallet-identity/runtime-benchmarks", "pallet-treasury/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", @@ -219,12 +208,6 @@ runtime-benchmarks = [ "xcm-builder/runtime-benchmarks", "cumulus-pallet-session-benchmarking/runtime-benchmarks", "cumulus-pallet-xcmp-queue/runtime-benchmarks", - - "gamedao-traits/runtime-benchmarks", - "gamedao-sense/runtime-benchmarks", - "gamedao-control/runtime-benchmarks", - "gamedao-flow/runtime-benchmarks", - "gamedao-signal/runtime-benchmarks", ] try-runtime = [ diff --git a/bin/subzero/runtime/src/lib.rs b/bin/subzero/runtime/src/lib.rs index ecf9c35a8f..9ac2d32d55 100644 --- a/bin/subzero/runtime/src/lib.rs +++ b/bin/subzero/runtime/src/lib.rs @@ -6,9 +6,9 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -pub mod constants; mod weights; pub mod xcm_config; +pub mod constants; use codec::{Decode, Encode, MaxEncodedLen}; use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; @@ -39,11 +39,12 @@ use frame_support::{ weights::{ constants::WEIGHT_PER_SECOND, ConstantMultiplier, DispatchClass, Weight, }, - BoundedVec, PalletId, + BoundedVec, + PalletId, }; use frame_system::{ limits::{BlockLength, BlockWeights}, - EnsureRoot, EnsureSigned, + EnsureRoot, EnsureSigned }; pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; pub use sp_runtime::{DispatchError, MultiAddress, Perbill, Permill}; @@ -61,11 +62,9 @@ use xcm::latest::prelude::BodyId; pub use constants::{fee::*, time::*}; pub use primitives::{ - cent, - currency::{ - AssetIdMapping, AssetIds, CurrencyId, CustomMetadata, ForeignAssetId, TokenSymbol, DOT, GAME, PLAY, ZERO, - }, - dollar, millicent, Amount, ReserveIdentifier, + currency::{ZERO, PLAY, GAME, DOT, AssetIds, CurrencyId, CustomMetadata, ForeignAssetId, TokenSymbol}, + dollar, cent, millicent, + Amount, ReserveIdentifier }; use orml_asset_registry::SequentialId; @@ -129,8 +128,13 @@ pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; /// Executive: handles dispatch to the various modules. -pub type Executive = - frame_executive::Executive, Runtime, AllPalletsWithSystem>; +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + AllPalletsWithSystem, +>; /// Opaque types. These are used by the CLI to instantiate machinery that don't need to know /// the specifics of the runtime. They can then be made to be agnostic over specific formats @@ -158,7 +162,7 @@ impl_opaque_keys! { #[sp_version::runtime_version] pub const VERSION: RuntimeVersion = RuntimeVersion { spec_name: create_runtime_str!("subzero"), - impl_name: create_runtime_str!("dev"), + impl_name: create_runtime_str!("live"), authoring_version: 75, spec_version: 63, impl_version: 0, @@ -189,10 +193,7 @@ const MAXIMUM_BLOCK_WEIGHT: Weight = WEIGHT_PER_SECOND / 2; /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] pub fn native_version() -> NativeVersion { - NativeVersion { - runtime_version: VERSION, - can_author_with: Default::default(), - } + NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } } parameter_types! { @@ -231,22 +232,22 @@ impl Contains for BaseFilter { // Disable direct calls to pallet_uniques !matches!( call, - Call::Uniques(pallet_uniques::Call::approve_transfer { .. }) - | Call::Uniques(pallet_uniques::Call::burn { .. }) - | Call::Uniques(pallet_uniques::Call::cancel_approval { .. }) - | Call::Uniques(pallet_uniques::Call::clear_collection_metadata { .. }) - | Call::Uniques(pallet_uniques::Call::clear_metadata { .. }) - | Call::Uniques(pallet_uniques::Call::create { .. }) - | Call::Uniques(pallet_uniques::Call::destroy { .. }) - | Call::Uniques(pallet_uniques::Call::force_item_status { .. }) - | Call::Uniques(pallet_uniques::Call::force_create { .. }) - | Call::Uniques(pallet_uniques::Call::freeze_collection { .. }) - | Call::Uniques(pallet_uniques::Call::mint { .. }) - | Call::Uniques(pallet_uniques::Call::redeposit { .. }) - | Call::Uniques(pallet_uniques::Call::set_collection_metadata { .. }) - | Call::Uniques(pallet_uniques::Call::thaw_collection { .. }) - | Call::Uniques(pallet_uniques::Call::transfer { .. }) - | Call::Uniques(pallet_uniques::Call::transfer_ownership { .. }) + Call::Uniques(pallet_uniques::Call::approve_transfer { .. }) | + Call::Uniques(pallet_uniques::Call::burn { .. }) | + Call::Uniques(pallet_uniques::Call::cancel_approval { .. }) | + Call::Uniques(pallet_uniques::Call::clear_collection_metadata { .. }) | + Call::Uniques(pallet_uniques::Call::clear_metadata { .. }) | + Call::Uniques(pallet_uniques::Call::create { .. }) | + Call::Uniques(pallet_uniques::Call::destroy { .. }) | + Call::Uniques(pallet_uniques::Call::force_item_status { .. }) | + Call::Uniques(pallet_uniques::Call::force_create { .. }) | + Call::Uniques(pallet_uniques::Call::freeze_collection { .. }) | + Call::Uniques(pallet_uniques::Call::mint { .. }) | + Call::Uniques(pallet_uniques::Call::redeposit { .. }) | + Call::Uniques(pallet_uniques::Call::set_collection_metadata { .. }) | + Call::Uniques(pallet_uniques::Call::thaw_collection { .. }) | + Call::Uniques(pallet_uniques::Call::transfer { .. }) | + Call::Uniques(pallet_uniques::Call::transfer_ownership { .. }) ) } } @@ -552,7 +553,6 @@ impl pallet_sudo::Config for Runtime { } parameter_types! { - pub const BountyCuratorDeposit: Permill = Permill::from_percent(50); pub BountyValueMinimum: Balance = 5 * dollar(ZERO); pub BountyDepositBase: Balance = 1 * dollar(ZERO); pub const CuratorDepositMultiplier: Permill = Permill::from_percent(50); @@ -766,9 +766,6 @@ parameter_types! { pub ProposalBondMinimum: Balance = 1 * dollar(ZERO); pub const SpendPeriod: BlockNumber = 1 * DAYS; pub const Burn: Permill = Permill::from_percent(50); - // pub const TipCountdown: BlockNumber = 1 * DAYS; - // pub const TipFindersFee: Percent = Percent::from_percent(20); - // pub TipReportDepositBase: Balance = 1 * dollar(ZERO); pub DataDepositPerByte: Balance = 1 * cent(ZERO); pub const MaximumReasonLength: u32 = 300; } @@ -799,9 +796,9 @@ impl pallet_treasury::Config for Runtime { } parameter_types! { - pub BasicDeposit: Balance = 10 * dollar(ZERO); // 258 bytes on-chain - pub FieldDeposit: Balance = 250 * cent(ZERO); // 66 bytes on-chain - pub SubAccountDeposit: Balance = 2 * dollar(ZERO); // 53 bytes on-chain + pub BasicDeposit: Balance = 10 * dollar(ZERO); // 258 bytes on-chain + pub FieldDeposit: Balance = 250 * cent(ZERO); // 66 bytes on-chain + pub SubAccountDeposit: Balance = 2 * dollar(ZERO); // 53 bytes on-chain } impl pallet_identity::Config for Runtime { @@ -876,8 +873,6 @@ parameter_types! { } // We allow root only to execute privileged collator selection operations. -// SBP-M2 review: you should have an entity like a council -// instead of providing the whole power to the single user (Root account) pub type CollatorSelectionUpdateOrigin = EnsureRoot; impl pallet_collator_selection::Config for Runtime { @@ -932,8 +927,6 @@ parameter_type_with_key! { } /// Allow asset registration only from root origin -// SBP-M2 review: root account has too much power -// Need for a council pub struct AssetAuthority; impl EnsureOriginWithArg> for AssetAuthority { type Success = (); @@ -995,86 +988,6 @@ impl orml_currencies::Config for Runtime { type WeightInfo = (); } -parameter_types! { - pub MinProposalDeposit: Balance = 100 * dollar(GAME); - pub SlashingMajority: Permill = Permill::from_rational(2u32, 3u32); - pub GameDAOGetsFromSlashing: Permill = Permill::from_rational(1u32, 10u32); - pub const MaxMembersPerOrg: u32 = 1000; - pub const ProposalDurationLimits: (BlockNumber, BlockNumber) = (100, 864000); -} - -impl gamedao_signal::Config for Runtime { - type WeightInfo = gamedao_signal::weights::SubstrateWeight; - type Event = Event; - type Currency = Currencies; - type CurrencyId = CurrencyId; - type PaymentTokenId = GetStableCurrencyId; - type ProtocolTokenId = GetProtocolCurrencyId; - type Balance = Balance; - type Flow = Flow; - type Control = Control; - type MinProposalDeposit = MinProposalDeposit; - type GameDAOTreasury = GameDAOTreasuryAccountId; - type SlashingMajority = SlashingMajority; - type GameDAOGetsFromSlashing = GameDAOGetsFromSlashing; - type MaxMembers = MaxMembersPerOrg; - type ProposalDurationLimits = ProposalDurationLimits; - type MaxProposalsPerBlock = ConstU32<100>; - type StringLimit = StringLimit; -} - -parameter_types! { - pub OrgMinimumDeposit: Balance = 1 * dollar(GAME); -} - -impl gamedao_control::Config for Runtime { - type Balance = Balance; - type CurrencyId = CurrencyId; - type WeightInfo = gamedao_control::weights::SubstrateWeight; - type Event = Event; - type Currency = Currencies; - type MaxMembers = MaxMembersPerOrg; - type ProtocolTokenId = GetProtocolCurrencyId; - type PaymentTokenId = GetStableCurrencyId; - type MinimumDeposit = OrgMinimumDeposit; - type PalletId = ControlPalletId; - type StringLimit = StringLimit; -} - -parameter_types! { - pub MinContribution: Balance = 1 * dollar(PLAY); - pub CampaignFee: Permill = Permill::from_rational(3u32, 1000u32); // 0.3% - pub MinCampaignDeposit: Permill = Permill::from_rational(1u32, 10u32); // 10% - pub const CampaignDurationLimits: (BlockNumber, BlockNumber) = (24 * HOURS, 60 * DAYS); -} - -impl gamedao_flow::Config for Runtime { - type Event = Event; - type Balance = Balance; - type CurrencyId = CurrencyId; - type WeightInfo = gamedao_flow::weights::SubstrateWeight; - type Currency = Currencies; - type Control = Control; - type GameDAOTreasury = GameDAOTreasuryAccountId; - type MinNameLength = ConstU32<4>; - type MaxCampaignsPerBlock = ConstU32<10>; - type MaxCampaignContributors = ConstU32<10000>; - type MaxContributorsProcessing = ConstU32<100>; - type MinContribution = MinContribution; - type MinCampaignDeposit = MinCampaignDeposit; - type ProtocolTokenId = GetProtocolCurrencyId; - type PaymentTokenId = GetStableCurrencyId; - type CampaignFee = CampaignFee; - type StringLimit = StringLimit; - type CampaignDurationLimits = CampaignDurationLimits; -} - -impl gamedao_sense::Config for Runtime { - type Event = Event; - type WeightInfo = gamedao_sense::weights::SubstrateWeight; - type StringLimit = StringLimit; -} - // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime where @@ -1084,6 +997,9 @@ construct_runtime!( { // System support stuff. System: frame_system::{Pallet, Call, Config, Storage, Event} = 0, + ParachainSystem: cumulus_pallet_parachain_system::{ + Pallet, Call, Config, Storage, Inherent, Event, ValidateUnsigned, + } = 1, Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 2, Utility: pallet_utility::{Pallet, Call, Storage, Event} = 3, Multisig: pallet_multisig = 4, @@ -1126,10 +1042,6 @@ construct_runtime!( CumulusXcm: cumulus_pallet_xcm::{Pallet, Event, Origin} = 52, DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event} = 53, - ParachainSystem: cumulus_pallet_parachain_system::{ - Pallet, Call, Config, Storage, Inherent, Event, - } = 1, - // ORML: AssetRegistry: orml_asset_registry::{Pallet, Storage, Call, Event, Config} = 60, Currencies: orml_currencies::{Pallet, Call} = 61, @@ -1137,12 +1049,6 @@ construct_runtime!( Tokens: orml_tokens::{Pallet, Storage, Call, Event, Config} = 63, UnknownTokens: orml_unknown_tokens::{Pallet, Storage, Event} = 64, XTokens: orml_xtokens::{Pallet, Storage, Call, Event} = 65, - - // GameDAO protocol: - Flow: gamedao_flow = 70, - Sense: gamedao_sense = 71, - Control: gamedao_control = 72, - Signal: gamedao_signal = 73, } ); @@ -1169,16 +1075,14 @@ fn option_filter_keys_to_set>( Some(filter_keys) => { let tree = filter_keys .into_iter() - .map( - |filter_keys| -> pallet_rmrk_rpc_runtime_api::Result> { - filter_keys - .try_into() - .map_err(|_| DispatchError::Other("Can't read filter key")) - }, - ) + .map(|filter_keys| -> pallet_rmrk_rpc_runtime_api::Result> { + filter_keys + .try_into() + .map_err(|_| DispatchError::Other("Can't read filter key")) + }) .collect::>>()?; Ok(Some(tree)) - } + }, None => Ok(None), } } @@ -1470,12 +1374,13 @@ impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { .read_slot() .expect("Could not read the relay chain slot from the proof"); - let inherent_data = cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( - relay_chain_slot, - sp_std::time::Duration::from_secs(6), - ) - .create_inherent_data() - .expect("Could not create the timestamp inherent data"); + let inherent_data = + cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( + relay_chain_slot, + sp_std::time::Duration::from_secs(6), + ) + .create_inherent_data() + .expect("Could not create the timestamp inherent data"); inherent_data.check_extrinsics(block) } diff --git a/bin/subzero/runtime/src/xcm_config.rs b/bin/subzero/runtime/src/xcm_config.rs index a7e373b320..00b738e4f9 100644 --- a/bin/subzero/runtime/src/xcm_config.rs +++ b/bin/subzero/runtime/src/xcm_config.rs @@ -16,8 +16,8 @@ use frame_support::{ weights::Weight, }; use sp_runtime::{ - traits::ConstU32, - WeakBoundedVec + traits::ConstU32, + WeakBoundedVec }; use pallet_xcm::XcmPassthrough; use polkadot_parachain::primitives::Sibling; @@ -97,7 +97,6 @@ pub type Barrier = ( AllowSubscriptionsFrom ); -// todo: move this to common runtimes module pub fn local_currency_location(key: CurrencyId) -> MultiLocation { MultiLocation::new( 0, @@ -247,12 +246,12 @@ pub type LocalAssetTransactor = MultiCurrencyAdapter< pub fn native_currency_location(para_id: u32, id: CurrencyId) -> MultiLocation { MultiLocation::new( - 1, - X2( - Parachain(para_id), GeneralKey( - WeakBoundedVec::>::force_from(id.encode(), None) - ) - ) + 1, + X2( + Parachain(para_id), GeneralKey( + WeakBoundedVec::>::force_from(id.encode(), None) + ) + ) ) } @@ -272,8 +271,8 @@ impl Convert> for CurrencyIdConvert { fn convert(location: MultiLocation) -> Option { fn decode_currency_id(key: WeakBoundedVec::>) -> Option { - let key = &key.into_inner()[..]; - if let Ok(currency_id) = CurrencyId::decode(&mut &*key) { + let key = &key.into_inner()[..]; + if let Ok(currency_id) = CurrencyId::decode(&mut &*key) { // check `currency_id` is cross-chain asset match currency_id { ZERO | GAME | PLAY => Some(currency_id), From f11dcb1c7d84f29a588991c84da6e1b78a1c689f Mon Sep 17 00:00:00 2001 From: vasylenko-yevhen Date: Thu, 24 Nov 2022 15:32:48 +0200 Subject: [PATCH 2/2] Move old `subzero` to `subzero-dev`. --- bin/subzero-dev/node/Cargo.toml | 105 ++ bin/subzero-dev/node/build.rs | 7 + bin/subzero-dev/node/src/chain_spec.rs | 595 +++++++ bin/subzero-dev/node/src/cli.rs | 93 ++ bin/subzero-dev/node/src/command.rs | 450 +++++ bin/subzero-dev/node/src/main.rs | 14 + bin/subzero-dev/node/src/rpc.rs | 58 + bin/subzero-dev/node/src/service.rs | 534 ++++++ bin/subzero-dev/runtime/Cargo.toml | 233 +++ bin/subzero-dev/runtime/build.rs | 9 + bin/subzero-dev/runtime/src/constants.rs | 101 ++ bin/subzero-dev/runtime/src/lib.rs | 1488 +++++++++++++++++ .../runtime/src/weights/block_weights.rs | 46 + .../runtime/src/weights/extrinsic_weights.rs | 46 + bin/subzero-dev/runtime/src/weights/mod.rs | 28 + .../runtime/src/weights/paritydb_weights.rs | 63 + .../runtime/src/weights/rocksdb_weights.rs | 63 + bin/subzero-dev/runtime/src/xcm_config.rs | 368 ++++ 18 files changed, 4301 insertions(+) create mode 100644 bin/subzero-dev/node/Cargo.toml create mode 100644 bin/subzero-dev/node/build.rs create mode 100644 bin/subzero-dev/node/src/chain_spec.rs create mode 100644 bin/subzero-dev/node/src/cli.rs create mode 100644 bin/subzero-dev/node/src/command.rs create mode 100644 bin/subzero-dev/node/src/main.rs create mode 100644 bin/subzero-dev/node/src/rpc.rs create mode 100644 bin/subzero-dev/node/src/service.rs create mode 100644 bin/subzero-dev/runtime/Cargo.toml create mode 100644 bin/subzero-dev/runtime/build.rs create mode 100644 bin/subzero-dev/runtime/src/constants.rs create mode 100644 bin/subzero-dev/runtime/src/lib.rs create mode 100644 bin/subzero-dev/runtime/src/weights/block_weights.rs create mode 100644 bin/subzero-dev/runtime/src/weights/extrinsic_weights.rs create mode 100644 bin/subzero-dev/runtime/src/weights/mod.rs create mode 100644 bin/subzero-dev/runtime/src/weights/paritydb_weights.rs create mode 100644 bin/subzero-dev/runtime/src/weights/rocksdb_weights.rs create mode 100644 bin/subzero-dev/runtime/src/xcm_config.rs diff --git a/bin/subzero-dev/node/Cargo.toml b/bin/subzero-dev/node/Cargo.toml new file mode 100644 index 0000000000..e22ad96a39 --- /dev/null +++ b/bin/subzero-dev/node/Cargo.toml @@ -0,0 +1,105 @@ +[package] +name = "subzero-dev-node" +version = "3.2.63" +authors = ["ZERO "] +description = "A substrate node for video games and beyond." +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +homepage = "https://zero.io" +repository = "https://github.com/playzero/zero-network/" +edition = "2021" +build = "build.rs" + +[[bin]] +name = "subzero-dev" +path = "src/main.rs" + +[dependencies] +clap = { version = "3.2.17", features = ["derive"] } +derive_more = "0.99.2" +log = "0.4.17" +codec = { package = "parity-scale-codec", version = "3.0.0" } +serde = { version = "1.0.143", features = ["derive"] } +hex-literal = "0.3.4" +jsonrpsee = { version = "0.15.1", features = ["server"] } + +# Local +subzero-dev-runtime = { path = "../runtime" } + +# Substrate +frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +frame-benchmarking-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +pallet-transaction-payment-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sc-basic-authorship = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sc-chain-spec = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sc-cli = { git = "https://github.com/paritytech/substrate", features = ["wasmtime"] , branch = "polkadot-v0.9.28" } +sc-client-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sc-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sc-executor = { git = "https://github.com/paritytech/substrate", features = ["wasmtime"] , branch = "polkadot-v0.9.28" } +sc-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sc-network = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sc-network-common = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sc-rpc = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sc-rpc-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sc-service = { git = "https://github.com/paritytech/substrate", features = ["wasmtime"] , branch = "polkadot-v0.9.28" } +sc-sysinfo = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sc-telemetry = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sc-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sc-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sc-transaction-pool-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sp-block-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sp-consensus = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sp-consensus-aura = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sp-keystore = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sp-offchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sp-session = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sp-transaction-pool = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +substrate-frame-rpc-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +substrate-prometheus-endpoint = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +try-runtime-cli = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } + +# Polkadot +polkadot-cli = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28", features = [ + # Set of features fixes next error: + # Invalid input: `rococo-local` only supported with `rococo-native` feature enabled. + # Includes default features + rococo. + "wasmtime", "db", "cli", "full-node", "trie-memory-tracker", "polkadot-native", "rococo-native" +] } +polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } +polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } +polkadot-service = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.28" } +xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.28" } + +# Cumulus +cumulus-client-cli = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-client-collator = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-client-consensus-aura = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-client-consensus-common = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-client-network = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-client-service = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-primitives-parachain-inherent = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-relay-chain-inprocess-interface = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-relay-chain-interface = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } +cumulus-relay-chain-rpc-interface = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28" } + +primitives = { version = "2.0.0", package = "zero-primitives", default-features = false, path = "../../../modules/primitives" } +gamedao-control = { path = "../../../modules/gamedao-protocol/control", default-features = false } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch= "polkadot-v0.9.28", default-features = false } + +[build-dependencies] +substrate-build-script-utils = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } + +[features] +default = [] +runtime-benchmarks = [ + "subzero-dev-runtime/runtime-benchmarks", + "polkadot-cli/runtime-benchmarks", +] +try-runtime = ["subzero-dev-runtime/try-runtime"] diff --git a/bin/subzero-dev/node/build.rs b/bin/subzero-dev/node/build.rs new file mode 100644 index 0000000000..e3bfe3116b --- /dev/null +++ b/bin/subzero-dev/node/build.rs @@ -0,0 +1,7 @@ +use substrate_build_script_utils::{generate_cargo_keys, rerun_if_git_head_changed}; + +fn main() { + generate_cargo_keys(); + + rerun_if_git_head_changed(); +} diff --git a/bin/subzero-dev/node/src/chain_spec.rs b/bin/subzero-dev/node/src/chain_spec.rs new file mode 100644 index 0000000000..92468431e4 --- /dev/null +++ b/bin/subzero-dev/node/src/chain_spec.rs @@ -0,0 +1,595 @@ +use cumulus_primitives_core::ParaId; +use subzero_dev_runtime::{AccountId, AuraId, SS58Prefix, Signature, SudoConfig}; +use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup, Properties}; +use sc_service::ChainType; +use serde::{Deserialize, Serialize}; +use sp_core::{sr25519, Pair, Public, crypto::UncheckedInto}; +use sp_runtime::{BoundedVec, traits::{IdentifyAccount, Verify, Zero}}; +use sp_std::collections::btree_map::BTreeMap; +use hex_literal::hex; + +use gamedao_control::types::{OrgType, AccessModel, FeeModel}; +use orml_tokens; + +use primitives::{ + currency::{ZERO, PLAY, GAME, DOT, TokenInfo, CurrencyId}, + cent, dollar, Balance +}; + +/// Specialized `ChainSpec` for the normal parachain runtime. +pub type ChainSpec = + sc_service::GenericChainSpec; + +/// The default XCM version to set in genesis config. +const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION; +const DEFAULT_PARA_ID: u32 = 2000; + +/// Helper function to generate a crypto pair from seed +pub fn get_from_seed(seed: &str) -> ::Public { + TPublic::Pair::from_string(&format!("//{}", seed), None) + .expect("static values are valid; qed") + .public() +} + +/// The extensions for the [`ChainSpec`]. +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)] +#[serde(deny_unknown_fields)] +pub struct Extensions { + /// The relay chain of the Parachain. + pub relay_chain: String, + /// The id of the Parachain. + pub para_id: u32, +} + +impl Extensions { + /// Try to get the extension from the given `ChainSpec`. + pub fn try_get(chain_spec: &dyn sc_service::ChainSpec) -> Option<&Self> { + sc_chain_spec::get_extension(chain_spec.extensions()) + } +} + +type AccountPublic = ::Signer; + +/// Generate collator keys from seed. +/// +/// This function's return type must always match the session keys of the chain in tuple format. +pub fn get_collator_keys_from_seed(seed: &str) -> AuraId { + get_from_seed::(seed) +} + +/// Helper function to generate an account ID from seed +pub fn get_account_id_from_seed(seed: &str) -> AccountId +where + AccountPublic: From<::Public>, +{ + AccountPublic::from(get_from_seed::(seed)).into_account() +} + +/// Generate the session keys from individual elements. +/// +/// The input must be a tuple of individual keys (a single arg for now since we have just one key). +pub fn subzero_session_keys(keys: AuraId) -> subzero_dev_runtime::SessionKeys { + subzero_dev_runtime::SessionKeys { aura: keys } +} + +/// Give your currencies a unit name and decimal places +pub fn get_properties() -> Properties { + let mut properties = Properties::new(); + let mut token_symbol: Vec = vec![]; + let mut token_decimals: Vec = vec![]; + [ZERO, PLAY, GAME, DOT].iter().for_each(|token| { + token_symbol.push(token.symbol().unwrap().to_string()); + token_decimals.push(token.decimals().unwrap() as u32); + }); + properties.insert("tokenSymbol".into(), token_symbol.into()); + properties.insert("tokenDecimals".into(), token_decimals.into()); + properties.insert("ss58Format".into(), SS58Prefix::get().into()); + properties +} + +pub fn development_config() -> ChainSpec { + // Give your base currency a unit name and decimal places + let properties = get_properties(); + ChainSpec::from_genesis( + // Name + "Development", + // ID + "dev", + ChainType::Development, + move || { + testnet_genesis( + // initial collators. + vec![ + ( + get_account_id_from_seed::("Alice"), + get_collator_keys_from_seed("Alice"), + ), + ( + get_account_id_from_seed::("Bob"), + get_collator_keys_from_seed("Bob"), + ), + ], + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Charlie"), + get_account_id_from_seed::("Dave"), + get_account_id_from_seed::("Eve"), + get_account_id_from_seed::("Ferdie"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + get_account_id_from_seed::("Charlie//stash"), + get_account_id_from_seed::("Dave//stash"), + get_account_id_from_seed::("Eve//stash"), + get_account_id_from_seed::("Ferdie//stash"), + ], + get_account_id_from_seed::("Alice"), + DEFAULT_PARA_ID.into(), + ) + }, + Vec::new(), + None, + None, + None, + Some(properties), + Extensions { + relay_chain: "rococo-local".into(), // You MUST set this to the correct network! + para_id: DEFAULT_PARA_ID, + }, + ) +} + +pub fn local_testnet_config() -> ChainSpec { + let properties = get_properties(); + + ChainSpec::from_genesis( + // Name + "Local Testnet", + // ID + "local_testnet", + ChainType::Local, + move || { + testnet_genesis( + // initial collators. + vec![ + ( + get_account_id_from_seed::("Alice"), + get_collator_keys_from_seed("Alice"), + ), + ( + get_account_id_from_seed::("Bob"), + get_collator_keys_from_seed("Bob"), + ), + ], + vec![ + get_account_id_from_seed::("Alice"), + get_account_id_from_seed::("Bob"), + get_account_id_from_seed::("Charlie"), + get_account_id_from_seed::("Dave"), + get_account_id_from_seed::("Eve"), + get_account_id_from_seed::("Ferdie"), + get_account_id_from_seed::("Alice//stash"), + get_account_id_from_seed::("Bob//stash"), + get_account_id_from_seed::("Charlie//stash"), + get_account_id_from_seed::("Dave//stash"), + get_account_id_from_seed::("Eve//stash"), + get_account_id_from_seed::("Ferdie//stash"), + ], + get_account_id_from_seed::("Alice"), + DEFAULT_PARA_ID.into(), + ) + }, + // Bootnodes + Vec::new(), + // Telemetry + None, + // Protocol ID + Some("subzero-local"), + // Fork ID + None, + // Properties + Some(properties), + // Extensions + Extensions { + relay_chain: "rococo-local".into(), // You MUST set this to the correct network! + para_id: DEFAULT_PARA_ID, + }, + ) +} + +fn testnet_genesis( + invulnerables: Vec<(AccountId, AuraId)>, + endowed_accounts: Vec, + root_key: AccountId, + id: ParaId, +) -> subzero_dev_runtime::GenesisConfig { + subzero_dev_runtime::GenesisConfig { + system: subzero_dev_runtime::SystemConfig { + code: subzero_dev_runtime::WASM_BINARY + .expect("WASM binary was not build, please build it!") + .to_vec(), + }, + sudo: SudoConfig { key: Some(root_key) }, + balances: subzero_dev_runtime::BalancesConfig { + balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), + }, + parachain_info: subzero_dev_runtime::ParachainInfoConfig { parachain_id: id }, + collator_selection: subzero_dev_runtime::CollatorSelectionConfig { + invulnerables: invulnerables.iter().cloned().map(|(acc, _)| acc).collect(), + candidacy_bond: cent(ZERO) * 16, + ..Default::default() + }, + session: subzero_dev_runtime::SessionConfig { + keys: invulnerables + .into_iter() + .map(|(acc, aura)| { + ( + acc.clone(), // account id + acc, // validator id + subzero_session_keys(aura), // session keys + ) + }) + .collect(), + }, + // no need to pass anything to aura, in fact it will panic if we do. Session will take care + // of this. + aura: Default::default(), + aura_ext: Default::default(), + parachain_system: Default::default(), + polkadot_xcm: subzero_dev_runtime::PolkadotXcmConfig { + safe_xcm_version: Some(SAFE_XCM_VERSION), + }, + council: Default::default(), + treasury: Default::default(), + tokens: Default::default(), + democracy: Default::default(), + technical_committee: Default::default(), + elections: Default::default(), + technical_membership: Default::default(), + control: Default::default(), + asset_registry: Default::default(), + } +} + +pub fn development_subzero_config() -> ChainSpec { + let properties = get_properties(); + + ChainSpec::from_genesis( + // Name + "Subzero Development", + // ID + "subzero-dev", + ChainType::Local, + // SECRET="..." + // docker run --rm parity/subkey inspect "$SECRET//subzero//root" + // docker run --rm parity/subkey inspect "$SECRET//subzero//1//collator" + // docker run --rm parity/subkey inspect "$SECRET//subzero//1//aura" + // docker run --rm parity/subkey inspect "$SECRET//subzero//2//collator" + // docker run --rm parity/subkey inspect "$SECRET//subzero//2//aura" + // docker run --rm parity/subkey inspect "$SECRET//subzero//zero-treasury" + // docker run --rm parity/subkey inspect "$SECRET//subzero//gamedao-treasury" + // docker run --rm parity/subkey inspect "$SECRET//subzero//game3-treasury" + // docker run --rm parity/subkey inspect "$SECRET//subzero//prime" + move || { + subzero_genesis( + // Initial collators + vec![ + ( + // 5FyCQF345qawarNwSoUgg5ankQt1g4J4wHwryMsEiUHi592W + hex!["acbd8ce2c37263c4964f4babcc6eaedd5276006c448e046290d366318c3b0016"].into(), + hex!["d081d0b6ee6fe89fca7ed9ee7a927da7462389798a2ed1a62caa456de487f574"].unchecked_into(), + ), + ( + // 5FP7zjy4uZ46uGSTrXBhkk6L7RkKtS8emD9BLAFAXBDS5nD2 + hex!["92c0609c5bc85053246436c99e5474163e2f73f59adef926bc0897502eca1945"].into(), + hex!["d008cd73618b8bce15531f693516635800ec1ee69f19e43f25f32129c5d5fd39"].unchecked_into(), + ), + ], + vec![ + // Faucet Bot + // 5Ef24TjfGNPnxrALTsPN3wJ9XoTTY4coMvryNed4MkZmqKaL + hex!["72a416a9270487e9fa301883780fe22edfac394bcf018b5da4444dff38937574"].into(), + // Org Prime + // 5GWchgf4qbaJZTBbmKTGWDCVPJt1XPLQfxaKsDe3Y3LqyHbT + hex!["c4b3f61d4f896a660d35bdf6a78c54cf2aa2af48ba0945f568dc67674247e136"].into(), + // Root + // 5CwWu8QwK8hdHcC5JHWWVSbxAFcLD4eUPsWY1BEy48LxjjMf + hex!["26c0a10c263cf2583936ff9714a645de855e39090765a0a23fe8a2001ab83016"].into(), + ], + // Root + // 5CwWu8QwK8hdHcC5JHWWVSbxAFcLD4eUPsWY1BEy48LxjjMf + hex!["26c0a10c263cf2583936ff9714a645de855e39090765a0a23fe8a2001ab83016"].into(), + // Zero treasury account + // 5EeG87W6f5X39SUeTLM6oBT8M5BZ4ApQbncKw78QFvgkGnqd + hex!["72102ee7e9bd0170c9829054bf8aaab65ea2555b1c30b04747160fe4a86d5b47"].into(), + // Gamedao treasury account + // 5EnLtQYf87Kab8vR8CyGmFXjo1HjYLUbFAdCsK5rFMAhfT4R + hex!["783a2eb5d5b4f1f3a7b49bea0c82119cccb366fd7b05d4c44b21ea160b52b160"].into(), + // Game3 treasury account + // 5DtGqwDh1rgcGYX2QxqxBs5S7VsNFbowX7cUiGiLEQ2aP9UV + hex!["5083d014500f360fa17ec74d50f0b8336e205f11d7a9e4cfc4bb42a7a3da4c6d"].into(), + // Org Prime + // 5GWchgf4qbaJZTBbmKTGWDCVPJt1XPLQfxaKsDe3Y3LqyHbT + hex!["c4b3f61d4f896a660d35bdf6a78c54cf2aa2af48ba0945f568dc67674247e136"].into(), + DEFAULT_PARA_ID.into(), + ) + }, + vec![ + "/dns/collator-1/tcp/30333/p2p/12D3KooWBQB9MUka9nMcqXi3ANLUdu4FweQpMvw9VHpHveiYhsPx" + .parse() + .unwrap(), + ], + // Telemetry + None, + // Protocol ID + Some("subzero-dev"), + // Fork ID + None, + Some(properties), + Extensions { + relay_chain: "rococo-local".into(), // You MUST set this to the correct network! + para_id: DEFAULT_PARA_ID, + }, + ) +} + +pub fn staging_subzero_config() -> ChainSpec { + let properties = get_properties(); + + ChainSpec::from_genesis( + // Name + "Subzero Staging", + // ID + "subzero-stage", + ChainType::Local, + // SECRET="..." + // docker run --rm parity/subkey inspect "$SECRET//subzero//root" + // docker run --rm parity/subkey inspect "$SECRET//subzero//1//collator" + // docker run --rm parity/subkey inspect "$SECRET//subzero//1//aura" + // docker run --rm parity/subkey inspect "$SECRET//subzero//2//collator" + // docker run --rm parity/subkey inspect "$SECRET//subzero//2//aura" + // docker run --rm parity/subkey inspect "$SECRET//subzero//3//collator" + // docker run --rm parity/subkey inspect "$SECRET//subzero//3//aura" + // docker run --rm parity/subkey inspect "$SECRET//subzero//4//collator" + // docker run --rm parity/subkey inspect "$SECRET//subzero//4//aura" + // docker run --rm parity/subkey inspect "$SECRET//subzero//zero-treasury" + // docker run --rm parity/subkey inspect "$SECRET//subzero//gamedao-treasury" + // docker run --rm parity/subkey inspect "$SECRET//subzero//game3-treasury" + // docker run --rm parity/subkey inspect "$SECRET//subzero//prime" + move || { + subzero_genesis( + // Initial collators + vec![ + ( + // 5EJVzfYgcPEncpwNoQp7ryzfJRjNfxQs4b4gUUdT7ya2Hg16 + hex!["62fdf8994e59cf79ef96338ccf1fa6fffd37c1a843841db0d3963efef0e4d31d"].into(), + hex!["90bf7542167747bcceb0614d4e461df631a8557cf9a7009899bacb203479f642"].unchecked_into(), + ), + ( + // 5GH83LCgSC6Kp5WZtF7pvaBiyqY22ZeH2gr1vCAh3TxpM83i + hex!["ba6949eb864d92d360bf997043b4229b7f54a6df5136af5b4f885a1ce89fd462"].into(), + hex!["eab75e30bd998c79befb81938daf6189f983273b0aeb292b15667d01245bfa6c"].unchecked_into(), + ), + ( + // 5EZZFSPHc2myoFFPFoM7k7Cy1p3niGoXCP8iG4qAKWcDMVVM + hex!["6e799bc5437690e6bd86aa0df8451eaf605ae7b2ec0266f9899905265572b018"].into(), + hex!["a2d2896c87b1db42b952835a775ff7418375ef4dc171b92640b4c11c22a2250f"].unchecked_into(), + ), + ( + // 5FKnYx26KziwtQeXmR6gaD1LwgMUUjCFjG5YAQQES1RfHFbV + hex!["90352f3b6f33a62c3f43cfe08726724d48cbc4919e27a5d1e55efa6881bad229"].into(), + hex!["96750acce3e01bedb5b2ffd7706f2e7b4a83c5e2f8714257d9d2ab95fb61da0d"].unchecked_into(), + ), + ], + vec![ + // Faucet Bot + // 5Ef24TjfGNPnxrALTsPN3wJ9XoTTY4coMvryNed4MkZmqKaL + hex!["72a416a9270487e9fa301883780fe22edfac394bcf018b5da4444dff38937574"].into(), + // Org Prime + // 5GeBJnjVxueXj5PsTFLTBoPQzt5scehWkKL84JLJ8hXWexaP + hex!["ca7870338715348c17ffb5a299c4ae9e2ceec0726d8d72a2f502060942af045d"].into(), + // Root + // 5HdZAx6ieBdLPdeQjj778ST7oq6poUkhr7nZ32mWzEjWGwQa + hex!["f63b07ad8610dcbdff485d2497fb359077ec8bfef9d9ffdb38022d7cdc986318"].into(), + ], + // Root + // 5HdZAx6ieBdLPdeQjj778ST7oq6poUkhr7nZ32mWzEjWGwQa + hex!["f63b07ad8610dcbdff485d2497fb359077ec8bfef9d9ffdb38022d7cdc986318"].into(), + // Zero treasury account + // 5EXAdVUvu3dyDb4Wn55XUdxWBv3fPhvf9Vzf76LsFBe72WA4 + hex!["6ca6f9057fa6374afd5c0b92a40905340f56e96f4905b36a0526917016f48667"].into(), + // Gamedao treasury account + // 5CSM7WW5icde1aqCK4xfbhBXCVqE76dZX2tvMtntaVvEBuFv + hex!["10819164c87b9f4dc70e64879d170d52378358b538b80fdabc0e90028a66f570"].into(), + // Game3 treasury account + // 5GNFNuNAJbD4ECDVHjYKHZibPUfGXHdFqKRoqVDbopsSGAim + hex!["be52373f74b5fa074de8edaa76e288305f200a6831d3550c0ebe4e02da9fa52d"].into(), + // Org Prime + // 5GeBJnjVxueXj5PsTFLTBoPQzt5scehWkKL84JLJ8hXWexaP + hex!["ca7870338715348c17ffb5a299c4ae9e2ceec0726d8d72a2f502060942af045d"].into(), + DEFAULT_PARA_ID.into(), + ) + }, + vec![ + "/dns/collator-1/tcp/30333/p2p/12D3KooWBQB9MUka9nMcqXi3ANLUdu4FweQpMvw9VHpHveiYhsPx" + .parse() + .unwrap(), + ], + // Telemetry + None, + // Protocol ID + Some("subzero-stage"), + // Fork ID + None, + Some(properties), + Extensions { + relay_chain: "rococo-local".into(), // You MUST set this to the correct network! + para_id: DEFAULT_PARA_ID, + }, + ) +} + +fn subzero_genesis( + invulnerables: Vec<(AccountId, AuraId)>, + endowed_accounts: Vec, + root_key: AccountId, + zero_treasury: AccountId, + gamedao_treasury: AccountId, + game3_treasury: AccountId, + org_prime: AccountId, + id: ParaId, +) -> subzero_dev_runtime::GenesisConfig { + subzero_dev_runtime::GenesisConfig { + system: subzero_dev_runtime::SystemConfig { + code: subzero_dev_runtime::WASM_BINARY + .expect("WASM binary was not build, please build it!") + .to_vec(), + }, + sudo: SudoConfig { key: Some(root_key) }, + balances: subzero_dev_runtime::BalancesConfig { + balances: balances_config(endowed_accounts.clone(), zero_treasury.clone(), game3_treasury.clone(), gamedao_treasury.clone()), + }, + parachain_info: subzero_dev_runtime::ParachainInfoConfig { parachain_id: id }, + collator_selection: subzero_dev_runtime::CollatorSelectionConfig { + invulnerables: invulnerables.iter().cloned().map(|(acc, _)| acc).collect(), + candidacy_bond: cent(ZERO) * 16, + ..Default::default() + }, + session: subzero_dev_runtime::SessionConfig { + keys: invulnerables + .into_iter() + .map(|(acc, aura)| { + ( + acc.clone(), // account id + acc, // validator id + subzero_session_keys(aura), // session keys + ) + }) + .collect(), + }, + // no need to pass anything to aura, in fact it will panic if we do. Session will take care + // of this. + aura: Default::default(), + aura_ext: Default::default(), + parachain_system: Default::default(), + polkadot_xcm: subzero_dev_runtime::PolkadotXcmConfig { + safe_xcm_version: Some(SAFE_XCM_VERSION), + }, + council: Default::default(), + treasury: Default::default(), + tokens: orml_tokens::GenesisConfig { + balances: tokens_config(endowed_accounts.clone(), zero_treasury.clone(), game3_treasury.clone(), gamedao_treasury.clone()), + }, + democracy: Default::default(), + technical_committee: Default::default(), + elections: Default::default(), + technical_membership: Default::default(), + control: gamedao_control::GenesisConfig { + orgs: vec![ + // Zero Network + (org_prime.clone(), org_prime.clone(), zero_treasury, BoundedVec::truncate_from(b"Zero Network".to_vec()), + BoundedVec::truncate_from(b"QmUWu6zoFM4j1fwT6fHGEjiuCSft2sNcbmJtT23R9su3Bk".to_vec()), + OrgType::Individual, AccessModel::Open, FeeModel::NoFees, Zero::zero(), + GAME, PLAY, 1000, 1 * dollar(GAME) + ), + // GameDao + (org_prime.clone(), org_prime.clone(), gamedao_treasury, BoundedVec::truncate_from(b"GameDao".to_vec()), + BoundedVec::truncate_from(b"QmcNp8hsRaxVDhKgbgo6Jtcb8papyPnKbqjzFtqzqxDE7j".to_vec()), + OrgType::Individual, AccessModel::Open, FeeModel::NoFees, Zero::zero(), + GAME, PLAY, 1000, 1 * dollar(GAME) + ), + // Game3 Foundation + (org_prime.clone(), org_prime.clone(), game3_treasury, BoundedVec::truncate_from(b"Game3 Foundation".to_vec()), + BoundedVec::truncate_from(b"QmNYVx6bhRUGbMp6UEPHKhaLRwFfpsbsP4sFT9XCvMxgfz".to_vec()), + OrgType::Individual, AccessModel::Open, FeeModel::NoFees, Zero::zero(), + GAME, PLAY, 1000, 1 * dollar(GAME) + ), + ] + }, + asset_registry: Default::default(), + } +} + +fn balances_config(accounts: Vec, zero_treasury: AccountId, + game3_treasury: AccountId, gamedao_treasury: AccountId) -> Vec<(AccountId, Balance)> { + // Zero Network Treasury owns ZERO issuance: + let mut zero_issuance = 1_000_000_000 * dollar(ZERO); + // Game3 Foundation Treasury: + let game3_zero = 1_000_000 * dollar(ZERO); + // GameDAO Treasury: + let gamedao_zero = 1_000_000 * dollar(ZERO); + + let account_balances = accounts.iter().cloned().map(|x| (x, 1_000_000 * dollar(ZERO))) + .fold( + BTreeMap::::new(), + |mut acc, (account_id, amount)| { + if let Some(balance) = acc.get_mut(&account_id) { + *balance = balance + .checked_add(amount) + .expect("balance overflow"); + } else { + zero_issuance = zero_issuance.saturating_sub(amount); + acc.insert(account_id.clone(), amount); + } + acc + }, + ) + .into_iter() + .collect::>(); + + zero_issuance = zero_issuance.saturating_sub(game3_zero).saturating_sub(gamedao_zero); + let mut balances = vec![ + (zero_treasury, zero_issuance), + (gamedao_treasury, gamedao_zero), + (game3_treasury, game3_zero), + ]; + balances.extend(account_balances); + balances +} + +fn tokens_config(accounts: Vec, zero_treasury: AccountId, + game3_treasury: AccountId, gamedao_treasury: AccountId) -> Vec<(AccountId, CurrencyId, Balance)> { + // Game3 Foundation Treasury owns GAME & PLAY issuance: + let mut game_issuance = 100_000_000 * dollar(GAME); + let mut play_issuance = 10_000_000 * dollar(PLAY); + + // Zero Network Treasury: + let zeronet_game = 100_000 * dollar(GAME); + let zeronet_play = 1_000_000 * dollar(PLAY); + + // GameDAO: + let gamedao_game = 100_000 * dollar(GAME); + let gamedao_play = 1_000_000 * dollar(PLAY); + + let account_balances = accounts + .iter().cloned() + .flat_map(|x| vec![(x.clone(), GAME, 1_000_000 * dollar(GAME)), (x.clone(), PLAY, 1_000_000 * dollar(PLAY))]) + .fold( + Vec::new(), + |mut vec, (account_id, currency_id, amount)| { + match currency_id { + GAME => { game_issuance = game_issuance.saturating_sub(amount); }, + PLAY => { play_issuance = play_issuance.saturating_sub(amount); }, + _ => () + }; + vec.push((account_id.clone(), currency_id, amount)); + vec + }, + ) + .into_iter() + .collect::>(); + + game_issuance = game_issuance.saturating_sub(zeronet_game).saturating_sub(gamedao_game); + play_issuance = play_issuance.saturating_sub(zeronet_play).saturating_sub(gamedao_play); + + let mut token_balances = vec![ + (zero_treasury.clone(), GAME, zeronet_game), + (zero_treasury, PLAY, zeronet_play), + (game3_treasury.clone(), GAME, game_issuance), + (game3_treasury, PLAY, play_issuance), + (gamedao_treasury.clone(), GAME, gamedao_game), + (gamedao_treasury, PLAY, gamedao_play), + ]; + token_balances.extend(account_balances); + token_balances +} diff --git a/bin/subzero-dev/node/src/cli.rs b/bin/subzero-dev/node/src/cli.rs new file mode 100644 index 0000000000..949ce489d6 --- /dev/null +++ b/bin/subzero-dev/node/src/cli.rs @@ -0,0 +1,93 @@ +use std::path::PathBuf; + +/// Sub-commands supported by the collator. +#[derive(Debug, clap::Subcommand)] +pub enum Subcommand { + /// Build a chain specification. + BuildSpec(sc_cli::BuildSpecCmd), + + /// Validate blocks. + CheckBlock(sc_cli::CheckBlockCmd), + + /// Export blocks. + ExportBlocks(sc_cli::ExportBlocksCmd), + + /// Export the state of a given block into a chain spec. + ExportState(sc_cli::ExportStateCmd), + + /// Import blocks. + ImportBlocks(sc_cli::ImportBlocksCmd), + + /// Revert the chain to a previous state. + Revert(sc_cli::RevertCmd), + + /// Remove the whole chain. + PurgeChain(cumulus_client_cli::PurgeChainCmd), + + /// Export the genesis state of the parachain. + ExportGenesisState(cumulus_client_cli::ExportGenesisStateCommand), + + /// Export the genesis wasm of the parachain. + ExportGenesisWasm(cumulus_client_cli::ExportGenesisWasmCommand), + + /// Sub-commands concerned with benchmarking. + /// The pallet benchmarking moved to the `pallet` sub-command. + #[clap(subcommand)] + Benchmark(frame_benchmarking_cli::BenchmarkCmd), + + /// Try some testing command against a specified runtime state. + TryRuntime(try_runtime_cli::TryRuntimeCmd), +} + +#[derive(Debug, clap::Parser)] +#[clap( + propagate_version = true, + args_conflicts_with_subcommands = true, + subcommand_negates_reqs = true +)] +pub struct Cli { + #[clap(subcommand)] + pub subcommand: Option, + + #[clap(flatten)] + pub run: cumulus_client_cli::RunCmd, + + /// Disable automatic hardware benchmarks. + /// + /// By default these benchmarks are automatically ran at startup and measure + /// the CPU speed, the memory bandwidth and the disk speed. + /// + /// The results are then printed out in the logs, and also sent as part of + /// telemetry, if telemetry is enabled. + #[clap(long)] + pub no_hardware_benchmarks: bool, + + /// Relay chain arguments + #[clap(raw = true)] + pub relay_chain_args: Vec, +} + +#[derive(Debug)] +pub struct RelayChainCli { + /// The actual relay chain cli object. + pub base: polkadot_cli::RunCmd, + + /// Optional chain id that should be passed to the relay chain. + pub chain_id: Option, + + /// The base path that should be used by the relay chain. + pub base_path: Option, +} + +impl RelayChainCli { + /// Parse the relay chain CLI parameters using the para chain `Configuration`. + pub fn new<'a>( + para_config: &sc_service::Configuration, + relay_chain_args: impl Iterator, + ) -> Self { + let extension = crate::chain_spec::Extensions::try_get(&*para_config.chain_spec); + let chain_id = extension.map(|e| e.relay_chain.clone()); + let base_path = para_config.base_path.as_ref().map(|x| x.path().join("polkadot")); + Self { base_path, chain_id, base: clap::Parser::parse_from(relay_chain_args) } + } +} diff --git a/bin/subzero-dev/node/src/command.rs b/bin/subzero-dev/node/src/command.rs new file mode 100644 index 0000000000..0780b01057 --- /dev/null +++ b/bin/subzero-dev/node/src/command.rs @@ -0,0 +1,450 @@ +use std::net::SocketAddr; + +use codec::Encode; +use cumulus_client_cli::generate_genesis_block; +use cumulus_primitives_core::ParaId; +use frame_benchmarking_cli::{BenchmarkCmd, SUBSTRATE_REFERENCE_HARDWARE}; +use log::info; +use subzero_dev_runtime::{Block, RuntimeApi}; +use sc_cli::{ + ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, + NetworkParams, Result, RuntimeVersion, SharedParams, SubstrateCli, +}; +use sc_service::{ + config::{BasePath, PrometheusConfig}, + TaskManager, +}; +use sp_core::hexdisplay::HexDisplay; +use sp_runtime::traits::{AccountIdConversion, Block as BlockT}; + +use crate::{ + chain_spec, + cli::{Cli, RelayChainCli, Subcommand}, + service::{new_partial, SubzeroDevRuntimeExecutor}, +}; + +fn load_spec(id: &str) -> std::result::Result, String> { + Ok(match id { + "dev" => Box::new(chain_spec::development_config()), + "subzero-dev" => Box::new(chain_spec::development_subzero_config()), + "subzero-stage" => Box::new(chain_spec::staging_subzero_config()), + "template-rococo" => Box::new(chain_spec::local_testnet_config()), + "" | "local" => Box::new(chain_spec::local_testnet_config()), + path => Box::new(chain_spec::ChainSpec::from_json_file(std::path::PathBuf::from(path))?), + }) +} + +impl SubstrateCli for Cli { + fn impl_name() -> String { + "Subzero Dev Collator".into() + } + + fn impl_version() -> String { + env!("SUBSTRATE_CLI_IMPL_VERSION").into() + } + + fn description() -> String { + format!( + "Subzero Dev Collator\n\nThe command-line arguments provided first will be \ + passed to the parachain node, while the arguments provided after -- will be passed \ + to the relay chain node.\n\n\ + {} -- ", + Self::executable_name() + ) + } + + fn author() -> String { + env!("CARGO_PKG_AUTHORS").into() + } + + fn support_url() -> String { + "https://github.com/playzero/zero-network/issues/new".into() + } + + fn copyright_start_year() -> i32 { + 2022 + } + + fn load_spec(&self, id: &str) -> std::result::Result, String> { + load_spec(id) + } + + fn native_runtime_version(_: &Box) -> &'static RuntimeVersion { + &subzero_dev_runtime::VERSION + } +} + +impl SubstrateCli for RelayChainCli { + fn impl_name() -> String { + "Subzero Dev Collator".into() + } + + fn impl_version() -> String { + env!("SUBSTRATE_CLI_IMPL_VERSION").into() + } + + fn description() -> String { + format!( + "Subzero Dev Collator\n\nThe command-line arguments provided first will be \ + passed to the parachain node, while the arguments provided after -- will be passed \ + to the relay chain node.\n\n\ + {} -- ", + Self::executable_name() + ) + } + + fn author() -> String { + env!("CARGO_PKG_AUTHORS").into() + } + + fn support_url() -> String { + "https://github.com/playzero/zero-network/issues/new".into() + } + + fn copyright_start_year() -> i32 { + 2022 + } + + fn load_spec(&self, id: &str) -> std::result::Result, String> { + polkadot_cli::Cli::from_iter([RelayChainCli::executable_name()].iter()).load_spec(id) + } + + fn native_runtime_version(chain_spec: &Box) -> &'static RuntimeVersion { + polkadot_cli::Cli::native_runtime_version(chain_spec) + } +} + +macro_rules! construct_async_run { + (|$components:ident, $cli:ident, $cmd:ident, $config:ident| $( $code:tt )* ) => {{ + let runner = $cli.create_runner($cmd)?; + runner.async_run(|$config| { + let $components = new_partial::< + RuntimeApi, + SubzeroDevRuntimeExecutor, + _ + >( + &$config, + crate::service::parachain_build_import_queue, + )?; + let task_manager = $components.task_manager; + { $( $code )* }.map(|v| (v, task_manager)) + }) + }} +} + +/// Parse command line arguments into service configuration. +pub fn run() -> Result<()> { + let cli = Cli::from_args(); + + match &cli.subcommand { + Some(Subcommand::BuildSpec(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|config| cmd.run(config.chain_spec, config.network)) + }, + Some(Subcommand::CheckBlock(cmd)) => { + construct_async_run!(|components, cli, cmd, config| { + Ok(cmd.run(components.client, components.import_queue)) + }) + }, + Some(Subcommand::ExportBlocks(cmd)) => { + construct_async_run!(|components, cli, cmd, config| { + Ok(cmd.run(components.client, config.database)) + }) + }, + Some(Subcommand::ExportState(cmd)) => { + construct_async_run!(|components, cli, cmd, config| { + Ok(cmd.run(components.client, config.chain_spec)) + }) + }, + Some(Subcommand::ImportBlocks(cmd)) => { + construct_async_run!(|components, cli, cmd, config| { + Ok(cmd.run(components.client, components.import_queue)) + }) + }, + Some(Subcommand::Revert(cmd)) => { + construct_async_run!(|components, cli, cmd, config| { + Ok(cmd.run(components.client, components.backend, None)) + }) + }, + Some(Subcommand::PurgeChain(cmd)) => { + let runner = cli.create_runner(cmd)?; + + runner.sync_run(|config| { + let polkadot_cli = RelayChainCli::new( + &config, + [RelayChainCli::executable_name()].iter().chain(cli.relay_chain_args.iter()), + ); + + let polkadot_config = SubstrateCli::create_configuration( + &polkadot_cli, + &polkadot_cli, + config.tokio_handle.clone(), + ) + .map_err(|err| format!("Relay chain argument error: {}", err))?; + + cmd.run(config, polkadot_config) + }) + }, + Some(Subcommand::ExportGenesisState(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|_config| { + let spec = cli.load_spec(&cmd.shared_params.chain.clone().unwrap_or_default())?; + let state_version = Cli::native_runtime_version(&spec).state_version(); + cmd.run::(&*spec, state_version) + }) + }, + Some(Subcommand::ExportGenesisWasm(cmd)) => { + let runner = cli.create_runner(cmd)?; + runner.sync_run(|_config| { + let spec = cli.load_spec(&cmd.shared_params.chain.clone().unwrap_or_default())?; + cmd.run(&*spec) + }) + }, + Some(Subcommand::Benchmark(cmd)) => { + let runner = cli.create_runner(cmd)?; + // Switch on the concrete benchmark sub-command- + match cmd { + BenchmarkCmd::Pallet(cmd) => + if cfg!(feature = "runtime-benchmarks") { + runner.sync_run(|config| cmd.run::(config)) + } else { + Err("Benchmarking wasn't enabled when building the node. \ + You can enable it with `--features runtime-benchmarks`." + .into()) + }, + BenchmarkCmd::Block(cmd) => runner.sync_run(|config| { + let partials = new_partial::( + &config, + crate::service::parachain_build_import_queue, + )?; + cmd.run(partials.client) + }), + BenchmarkCmd::Storage(cmd) => runner.sync_run(|config| { + let partials = new_partial::( + &config, + crate::service::parachain_build_import_queue, + )?; + let db = partials.backend.expose_db(); + let storage = partials.backend.expose_storage(); + + cmd.run(config, partials.client.clone(), db, storage) + }), + BenchmarkCmd::Machine(cmd) => + runner.sync_run(|config| cmd.run(&config, SUBSTRATE_REFERENCE_HARDWARE.clone())), + // NOTE: this allows the Client to leniently implement + // new benchmark commands without requiring a companion MR. + #[allow(unreachable_patterns)] + _ => Err("Benchmarking sub-command unsupported".into()), + } + }, + Some(Subcommand::TryRuntime(cmd)) => { + if cfg!(feature = "try-runtime") { + let runner = cli.create_runner(cmd)?; + + // grab the task manager. + let registry = &runner.config().prometheus_config.as_ref().map(|cfg| &cfg.registry); + let task_manager = + TaskManager::new(runner.config().tokio_handle.clone(), *registry) + .map_err(|e| format!("Error: {:?}", e))?; + + runner.async_run(|config| { + Ok((cmd.run::(config), task_manager)) + }) + } else { + Err("Try-runtime must be enabled by `--features try-runtime`.".into()) + } + }, + None => { + let runner = cli.create_runner(&cli.run.normalize())?; + let collator_options = cli.run.collator_options(); + + runner.run_node_until_exit(|config| async move { + let hwbench = if !cli.no_hardware_benchmarks { + config.database.path().map(|database_path| { + let _ = std::fs::create_dir_all(&database_path); + sc_sysinfo::gather_hwbench(Some(database_path)) + }) + } else { + None + }; + + let para_id = chain_spec::Extensions::try_get(&*config.chain_spec) + .map(|e| e.para_id) + .ok_or_else(|| "Could not find parachain ID in chain-spec.")?; + + let polkadot_cli = RelayChainCli::new( + &config, + [RelayChainCli::executable_name()].iter().chain(cli.relay_chain_args.iter()), + ); + + let id = ParaId::from(para_id); + + let parachain_account = + AccountIdConversion::::into_account_truncating(&id); + + let state_version = Cli::native_runtime_version(&config.chain_spec).state_version(); + let block: Block = generate_genesis_block(&*config.chain_spec, state_version) + .map_err(|e| format!("{:?}", e))?; + let genesis_state = format!("0x{:?}", HexDisplay::from(&block.header().encode())); + + let tokio_handle = config.tokio_handle.clone(); + let polkadot_config = + SubstrateCli::create_configuration(&polkadot_cli, &polkadot_cli, tokio_handle) + .map_err(|err| format!("Relay chain argument error: {}", err))?; + + info!("Parachain id: {:?}", id); + info!("Parachain Account: {}", parachain_account); + info!("Parachain genesis state: {}", genesis_state); + info!("Is collating: {}", if config.role.is_authority() { "yes" } else { "no" }); + + crate::service::start_parachain_node( + config, + polkadot_config, + collator_options, + id, + hwbench, + ) + .await + .map(|r| r.0) + .map_err(Into::into) + }) + }, + } +} + +impl DefaultConfigurationValues for RelayChainCli { + fn p2p_listen_port() -> u16 { + 30334 + } + + fn rpc_ws_listen_port() -> u16 { + 9945 + } + + fn rpc_http_listen_port() -> u16 { + 9934 + } + + fn prometheus_listen_port() -> u16 { + 9616 + } +} + +impl CliConfiguration for RelayChainCli { + fn shared_params(&self) -> &SharedParams { + self.base.base.shared_params() + } + + fn import_params(&self) -> Option<&ImportParams> { + self.base.base.import_params() + } + + fn network_params(&self) -> Option<&NetworkParams> { + self.base.base.network_params() + } + + fn keystore_params(&self) -> Option<&KeystoreParams> { + self.base.base.keystore_params() + } + + fn base_path(&self) -> Result> { + Ok(self + .shared_params() + .base_path() + .or_else(|| self.base_path.clone().map(Into::into))) + } + + fn rpc_http(&self, default_listen_port: u16) -> Result> { + self.base.base.rpc_http(default_listen_port) + } + + fn rpc_ipc(&self) -> Result> { + self.base.base.rpc_ipc() + } + + fn rpc_ws(&self, default_listen_port: u16) -> Result> { + self.base.base.rpc_ws(default_listen_port) + } + + fn prometheus_config( + &self, + default_listen_port: u16, + chain_spec: &Box, + ) -> Result> { + self.base.base.prometheus_config(default_listen_port, chain_spec) + } + + fn init( + &self, + _support_url: &String, + _impl_version: &String, + _logger_hook: F, + _config: &sc_service::Configuration, + ) -> Result<()> + where + F: FnOnce(&mut sc_cli::LoggerBuilder, &sc_service::Configuration), + { + unreachable!("PolkadotCli is never initialized; qed"); + } + + fn chain_id(&self, is_dev: bool) -> Result { + let chain_id = self.base.base.chain_id(is_dev)?; + + Ok(if chain_id.is_empty() { self.chain_id.clone().unwrap_or_default() } else { chain_id }) + } + + fn role(&self, is_dev: bool) -> Result { + self.base.base.role(is_dev) + } + + fn transaction_pool(&self, is_dev: bool) -> Result { + self.base.base.transaction_pool(is_dev) + } + + fn state_cache_child_ratio(&self) -> Result> { + self.base.base.state_cache_child_ratio() + } + + fn rpc_methods(&self) -> Result { + self.base.base.rpc_methods() + } + + fn rpc_ws_max_connections(&self) -> Result> { + self.base.base.rpc_ws_max_connections() + } + + fn rpc_cors(&self, is_dev: bool) -> Result>> { + self.base.base.rpc_cors(is_dev) + } + + fn default_heap_pages(&self) -> Result> { + self.base.base.default_heap_pages() + } + + fn force_authoring(&self) -> Result { + self.base.base.force_authoring() + } + + fn disable_grandpa(&self) -> Result { + self.base.base.disable_grandpa() + } + + fn max_runtime_instances(&self) -> Result> { + self.base.base.max_runtime_instances() + } + + fn announce_block(&self) -> Result { + self.base.base.announce_block() + } + + fn telemetry_endpoints( + &self, + chain_spec: &Box, + ) -> Result> { + self.base.base.telemetry_endpoints(chain_spec) + } + + fn node_name(&self) -> Result { + self.base.base.node_name() + } +} diff --git a/bin/subzero-dev/node/src/main.rs b/bin/subzero-dev/node/src/main.rs new file mode 100644 index 0000000000..ba9f28b354 --- /dev/null +++ b/bin/subzero-dev/node/src/main.rs @@ -0,0 +1,14 @@ +//! Substrate Parachain Node Template CLI + +#![warn(missing_docs)] + +mod chain_spec; +#[macro_use] +mod service; +mod cli; +mod command; +mod rpc; + +fn main() -> sc_cli::Result<()> { + command::run() +} diff --git a/bin/subzero-dev/node/src/rpc.rs b/bin/subzero-dev/node/src/rpc.rs new file mode 100644 index 0000000000..6f8c6664d9 --- /dev/null +++ b/bin/subzero-dev/node/src/rpc.rs @@ -0,0 +1,58 @@ +//! A collection of node-specific RPC methods. +//! Substrate provides the `sc-rpc` crate, which defines the core RPC layer +//! used by Substrate nodes. This file extends those RPC definitions with +//! capabilities that are specific to this project's runtime configuration. + +#![warn(missing_docs)] + +use std::sync::Arc; + +use subzero_dev_runtime::{opaque::Block, AccountId, Balance, Index as Nonce}; + +use sc_client_api::AuxStore; +pub use sc_rpc::{DenyUnsafe, SubscriptionTaskExecutor}; +use sc_transaction_pool_api::TransactionPool; +use sp_api::ProvideRuntimeApi; +use sp_block_builder::BlockBuilder; +use sp_blockchain::{Error as BlockChainError, HeaderBackend, HeaderMetadata}; + +/// A type representing all RPC extensions. +pub type RpcExtension = jsonrpsee::RpcModule<()>; + +/// Full client dependencies +pub struct FullDeps { + /// The client instance to use. + pub client: Arc, + /// Transaction pool instance. + pub pool: Arc

, + /// Whether to deny unsafe calls + pub deny_unsafe: DenyUnsafe, +} + +/// Instantiate all RPC extensions. +pub fn create_full( + deps: FullDeps, +) -> Result> +where + C: ProvideRuntimeApi + + HeaderBackend + + AuxStore + + HeaderMetadata + + Send + + Sync + + 'static, + C::Api: pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi, + C::Api: substrate_frame_rpc_system::AccountNonceApi, + C::Api: BlockBuilder, + P: TransactionPool + Sync + Send + 'static, +{ + use pallet_transaction_payment_rpc::{TransactionPayment, TransactionPaymentApiServer}; + use substrate_frame_rpc_system::{System, SystemApiServer}; + + let mut module = RpcExtension::new(()); + let FullDeps { client, pool, deny_unsafe } = deps; + + module.merge(System::new(client.clone(), pool, deny_unsafe).into_rpc())?; + module.merge(TransactionPayment::new(client).into_rpc())?; + Ok(module) +} diff --git a/bin/subzero-dev/node/src/service.rs b/bin/subzero-dev/node/src/service.rs new file mode 100644 index 0000000000..bd529e4cec --- /dev/null +++ b/bin/subzero-dev/node/src/service.rs @@ -0,0 +1,534 @@ +//! Service and ServiceFactory implementation. Specialized wrapper over substrate service. + +// std +use std::{sync::Arc, time::Duration}; + +// rpc +use jsonrpsee::RpcModule; + +use cumulus_client_cli::CollatorOptions; +// Local Runtime Types +use subzero_dev_runtime::{ + opaque::Block, AccountId, Balance, Hash, Index as Nonce, RuntimeApi, +}; + +// Cumulus Imports +use cumulus_client_consensus_aura::{AuraConsensus, BuildAuraConsensusParams, SlotProportion}; +use cumulus_client_consensus_common::ParachainConsensus; +use cumulus_client_network::BlockAnnounceValidator; +use cumulus_client_service::{ + prepare_node_config, start_collator, start_full_node, StartCollatorParams, StartFullNodeParams, +}; +use cumulus_primitives_core::ParaId; +use cumulus_relay_chain_inprocess_interface::build_inprocess_relay_chain; +use cumulus_relay_chain_interface::{RelayChainError, RelayChainInterface, RelayChainResult}; +use cumulus_relay_chain_rpc_interface::{create_client_and_start_worker, RelayChainRpcInterface}; + +// Substrate Imports +use sc_client_api::ExecutorProvider; +use sc_executor::NativeElseWasmExecutor; +use sc_network::NetworkService; +use sc_network_common::service::NetworkBlock; +use sc_service::{Configuration, PartialComponents, TFullBackend, TFullClient, TaskManager}; +use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle}; +use sp_api::ConstructRuntimeApi; +use sp_keystore::SyncCryptoStorePtr; +use sp_runtime::traits::BlakeTwo256; +use substrate_prometheus_endpoint::Registry; + +use polkadot_service::CollatorPair; + +/// Native executor instance. +pub struct SubzeroDevRuntimeExecutor; + +impl sc_executor::NativeExecutionDispatch for SubzeroDevRuntimeExecutor { + type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; + + fn dispatch(method: &str, data: &[u8]) -> Option> { + subzero_dev_runtime::api::dispatch(method, data) + } + + fn native_version() -> sc_executor::NativeVersion { + subzero_dev_runtime::native_version() + } +} + +/// Starts a `ServiceBuilder` for a full service. +/// +/// Use this macro if you don't actually need the full service, but just the builder in order to +/// be able to perform chain operations. +#[allow(clippy::type_complexity)] +pub fn new_partial( + config: &Configuration, + build_import_queue: BIQ, +) -> Result< + PartialComponents< + TFullClient>, + TFullBackend, + (), + sc_consensus::DefaultImportQueue< + Block, + TFullClient>, + >, + sc_transaction_pool::FullPool< + Block, + TFullClient>, + >, + (Option, Option), + >, + sc_service::Error, +> +where + RuntimeApi: ConstructRuntimeApi>> + + Send + + Sync + + 'static, + RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue + + sp_api::Metadata + + sp_session::SessionKeys + + sp_api::ApiExt< + Block, + StateBackend = sc_client_api::StateBackendFor, Block>, + > + sp_offchain::OffchainWorkerApi + + sp_block_builder::BlockBuilder, + sc_client_api::StateBackendFor, Block>: sp_api::StateBackend, + Executor: sc_executor::NativeExecutionDispatch + 'static, + BIQ: FnOnce( + Arc>>, + &Configuration, + Option, + &TaskManager, + ) -> Result< + sc_consensus::DefaultImportQueue< + Block, + TFullClient>, + >, + sc_service::Error, + >, +{ + let telemetry = config + .telemetry_endpoints + .clone() + .filter(|x| !x.is_empty()) + .map(|endpoints| -> Result<_, sc_telemetry::Error> { + let worker = TelemetryWorker::new(16)?; + let telemetry = worker.handle().new_telemetry(endpoints); + Ok((worker, telemetry)) + }) + .transpose()?; + + let executor = sc_executor::NativeElseWasmExecutor::::new( + config.wasm_method, + config.default_heap_pages, + config.max_runtime_instances, + config.runtime_cache_size, + ); + + let (client, backend, keystore_container, task_manager) = + sc_service::new_full_parts::( + config, + telemetry.as_ref().map(|(_, telemetry)| telemetry.handle()), + executor, + )?; + let client = Arc::new(client); + + let telemetry_worker_handle = telemetry.as_ref().map(|(worker, _)| worker.handle()); + + let telemetry = telemetry.map(|(worker, telemetry)| { + task_manager.spawn_handle().spawn("telemetry", None, worker.run()); + telemetry + }); + + let transaction_pool = sc_transaction_pool::BasicPool::new_full( + config.transaction_pool.clone(), + config.role.is_authority().into(), + config.prometheus_registry(), + task_manager.spawn_essential_handle(), + client.clone(), + ); + + let import_queue = build_import_queue( + client.clone(), + config, + telemetry.as_ref().map(|telemetry| telemetry.handle()), + &task_manager, + )?; + + let params = PartialComponents { + backend, + client, + import_queue, + keystore_container, + task_manager, + transaction_pool, + select_chain: (), + other: (telemetry, telemetry_worker_handle), + }; + + Ok(params) +} + +async fn build_relay_chain_interface( + polkadot_config: Configuration, + parachain_config: &Configuration, + telemetry_worker_handle: Option, + task_manager: &mut TaskManager, + collator_options: CollatorOptions, + hwbench: Option, +) -> RelayChainResult<(Arc<(dyn RelayChainInterface + 'static)>, Option)> { + match collator_options.relay_chain_rpc_url { + Some(relay_chain_url) => { + let client = create_client_and_start_worker(relay_chain_url, task_manager).await?; + Ok((Arc::new(RelayChainRpcInterface::new(client)) as Arc<_>, None)) + }, + None => build_inprocess_relay_chain( + polkadot_config, + parachain_config, + telemetry_worker_handle, + task_manager, + hwbench, + ), + } +} + +/// Start a node with the given parachain `Configuration` and relay chain `Configuration`. +/// +/// This is the actual implementation that is abstract over the executor and the runtime api. +#[sc_tracing::logging::prefix_logs_with("Parachain")] +async fn start_node_impl( + parachain_config: Configuration, + polkadot_config: Configuration, + collator_options: CollatorOptions, + id: ParaId, + _rpc_ext_builder: RB, + build_import_queue: BIQ, + build_consensus: BIC, + hwbench: Option, +) -> sc_service::error::Result<( + TaskManager, + Arc>>, +)> +where + RuntimeApi: ConstructRuntimeApi>> + + Send + + Sync + + 'static, + RuntimeApi::RuntimeApi: sp_transaction_pool::runtime_api::TaggedTransactionQueue + + sp_api::Metadata + + sp_session::SessionKeys + + sp_api::ApiExt< + Block, + StateBackend = sc_client_api::StateBackendFor, Block>, + > + sp_offchain::OffchainWorkerApi + + sp_block_builder::BlockBuilder + + cumulus_primitives_core::CollectCollationInfo + + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi + + substrate_frame_rpc_system::AccountNonceApi, + sc_client_api::StateBackendFor, Block>: sp_api::StateBackend, + Executor: sc_executor::NativeExecutionDispatch + 'static, + RB: Fn( + Arc>, + ) -> Result, sc_service::Error> + + Send + + 'static, + BIQ: FnOnce( + Arc>>, + &Configuration, + Option, + &TaskManager, + ) -> Result< + sc_consensus::DefaultImportQueue< + Block, + TFullClient>, + >, + sc_service::Error, + > + 'static, + BIC: FnOnce( + Arc>>, + Option<&Registry>, + Option, + &TaskManager, + Arc, + Arc< + sc_transaction_pool::FullPool< + Block, + TFullClient>, + >, + >, + Arc>, + SyncCryptoStorePtr, + bool, + ) -> Result>, sc_service::Error>, +{ + let parachain_config = prepare_node_config(parachain_config); + + let params = new_partial::(¶chain_config, build_import_queue)?; + let (mut telemetry, telemetry_worker_handle) = params.other; + + let client = params.client.clone(); + let backend = params.backend.clone(); + let mut task_manager = params.task_manager; + + let (relay_chain_interface, collator_key) = build_relay_chain_interface( + polkadot_config, + ¶chain_config, + telemetry_worker_handle, + &mut task_manager, + collator_options.clone(), + hwbench.clone(), + ) + .await + .map_err(|e| match e { + RelayChainError::ServiceError(polkadot_service::Error::Sub(x)) => x, + s => s.to_string().into(), + })?; + + let block_announce_validator = BlockAnnounceValidator::new(relay_chain_interface.clone(), id); + + let force_authoring = parachain_config.force_authoring; + let validator = parachain_config.role.is_authority(); + let prometheus_registry = parachain_config.prometheus_registry().cloned(); + let transaction_pool = params.transaction_pool.clone(); + let import_queue = cumulus_client_service::SharedImportQueue::new(params.import_queue); + let (network, system_rpc_tx, start_network) = + sc_service::build_network(sc_service::BuildNetworkParams { + config: ¶chain_config, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + spawn_handle: task_manager.spawn_handle(), + import_queue: import_queue.clone(), + block_announce_validator_builder: Some(Box::new(|_| { + Box::new(block_announce_validator) + })), + warp_sync: None, + })?; + + let rpc_builder = { + let client = client.clone(); + let transaction_pool = transaction_pool.clone(); + + Box::new(move |deny_unsafe, _| { + let deps = crate::rpc::FullDeps { + client: client.clone(), + pool: transaction_pool.clone(), + deny_unsafe, + }; + + crate::rpc::create_full(deps).map_err(Into::into) + }) + }; + + sc_service::spawn_tasks(sc_service::SpawnTasksParams { + rpc_builder, + client: client.clone(), + transaction_pool: transaction_pool.clone(), + task_manager: &mut task_manager, + config: parachain_config, + keystore: params.keystore_container.sync_keystore(), + backend: backend.clone(), + network: network.clone(), + system_rpc_tx, + telemetry: telemetry.as_mut(), + })?; + + if let Some(hwbench) = hwbench { + sc_sysinfo::print_hwbench(&hwbench); + + if let Some(ref mut telemetry) = telemetry { + let telemetry_handle = telemetry.handle(); + task_manager.spawn_handle().spawn( + "telemetry_hwbench", + None, + sc_sysinfo::initialize_hwbench_telemetry(telemetry_handle, hwbench), + ); + } + } + + let announce_block = { + let network = network.clone(); + Arc::new(move |hash, data| network.announce_block(hash, data)) + }; + + let relay_chain_slot_duration = Duration::from_secs(6); + + if validator { + let parachain_consensus = build_consensus( + client.clone(), + prometheus_registry.as_ref(), + telemetry.as_ref().map(|t| t.handle()), + &task_manager, + relay_chain_interface.clone(), + transaction_pool, + network, + params.keystore_container.sync_keystore(), + force_authoring, + )?; + + let spawner = task_manager.spawn_handle(); + + let params = StartCollatorParams { + para_id: id, + block_status: client.clone(), + announce_block, + client: client.clone(), + task_manager: &mut task_manager, + relay_chain_interface, + spawner, + parachain_consensus, + import_queue, + collator_key: collator_key.expect("Command line arguments do not allow this. qed"), + relay_chain_slot_duration, + }; + + start_collator(params).await?; + } else { + let params = StartFullNodeParams { + client: client.clone(), + announce_block, + task_manager: &mut task_manager, + para_id: id, + relay_chain_interface, + relay_chain_slot_duration, + import_queue, + collator_options, + }; + + start_full_node(params)?; + } + + start_network.start_network(); + + Ok((task_manager, client)) +} + +/// Build the import queue for the parachain runtime. +#[allow(clippy::type_complexity)] +pub fn parachain_build_import_queue( + client: Arc>>, + config: &Configuration, + telemetry: Option, + task_manager: &TaskManager, +) -> Result< + sc_consensus::DefaultImportQueue< + Block, + TFullClient>, + >, + sc_service::Error, +> { + let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; + + cumulus_client_consensus_aura::import_queue::< + sp_consensus_aura::sr25519::AuthorityPair, + _, + _, + _, + _, + _, + _, + >(cumulus_client_consensus_aura::ImportQueueParams { + block_import: client.clone(), + client: client.clone(), + create_inherent_data_providers: move |_, _| async move { + let time = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *time, + slot_duration, + ); + + Ok((time, slot)) + }, + registry: config.prometheus_registry(), + can_author_with: sp_consensus::CanAuthorWithNativeVersion::new(client.executor().clone()), + spawner: &task_manager.spawn_essential_handle(), + telemetry, + }) + .map_err(Into::into) +} + +/// Start a parachain node. +pub async fn start_parachain_node( + parachain_config: Configuration, + polkadot_config: Configuration, + collator_options: CollatorOptions, + id: ParaId, + hwbench: Option, +) -> sc_service::error::Result<( + TaskManager, + Arc>>, +)> { + start_node_impl::( + parachain_config, + polkadot_config, + collator_options, + id, + |_| Ok(RpcModule::new(())), + parachain_build_import_queue, + |client, + prometheus_registry, + telemetry, + task_manager, + relay_chain_interface, + transaction_pool, + sync_oracle, + keystore, + force_authoring| { + let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; + + let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( + task_manager.spawn_handle(), + client.clone(), + transaction_pool, + prometheus_registry, + telemetry.clone(), + ); + + Ok(AuraConsensus::build::( + BuildAuraConsensusParams { + proposer_factory, + create_inherent_data_providers: move |_, (relay_parent, validation_data)| { + let relay_chain_interface = relay_chain_interface.clone(); + async move { + let parachain_inherent = + cumulus_primitives_parachain_inherent::ParachainInherentData::create_at( + relay_parent, + &relay_chain_interface, + &validation_data, + id, + ).await; + let time = sp_timestamp::InherentDataProvider::from_system_time(); + + let slot = + sp_consensus_aura::inherents::InherentDataProvider::from_timestamp_and_slot_duration( + *time, + slot_duration, + ); + + let parachain_inherent = parachain_inherent.ok_or_else(|| { + Box::::from( + "Failed to create parachain inherent", + ) + })?; + Ok((time, slot, parachain_inherent)) + } + }, + block_import: client.clone(), + para_client: client, + backoff_authoring_blocks: Option::<()>::None, + sync_oracle, + keystore, + force_authoring, + slot_duration, + // We got around 500ms for proposing + block_proposal_slot_portion: SlotProportion::new(1f32 / 24f32), + // And a maximum of 750ms if slots are skipped + max_block_proposal_slot_portion: Some(SlotProportion::new(1f32 / 16f32)), + telemetry, + }, + )) + }, + hwbench, + ) + .await +} diff --git a/bin/subzero-dev/runtime/Cargo.toml b/bin/subzero-dev/runtime/Cargo.toml new file mode 100644 index 0000000000..2f84372d2e --- /dev/null +++ b/bin/subzero-dev/runtime/Cargo.toml @@ -0,0 +1,233 @@ +[package] +name = "subzero-dev-runtime" +version = "3.2.63" +authors = ["ZERO "] +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" +homepage = "https://zero.io" +repository = "https://github.com/playzero/zero-network/" +edition = "2021" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[build-dependencies] +substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } +hex-literal = { version = "0.3.4", optional = true } +log = { version = "0.4.17", default-features = false } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +serde = { version = "1.0.143", optional = true, features = ["derive"] } +smallvec = "1.9.0" +static_assertions = "1.1.0" + +# Substrate +frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "polkadot-v0.9.28" } +frame-executive = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +frame-support = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +frame-system = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +frame-system-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "polkadot-v0.9.28" } +frame-system-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +frame-try-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "polkadot-v0.9.28" } +pallet-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +pallet-authorship = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +pallet-balances = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +pallet-bounties = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +pallet-child-bounties = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +pallet-collective = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +pallet-democracy = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +pallet-elections-phragmen = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.28" } +pallet-identity = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +pallet-membership = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +pallet-multisig = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +pallet-preimage = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +pallet-proxy = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +pallet-scheduler = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +pallet-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +pallet-sudo = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +pallet-timestamp = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +pallet-tips = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +pallet-transaction-payment-rpc-runtime-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +pallet-treasury = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +pallet-uniques = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +pallet-utility = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +sp-api = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +sp-block-builder = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +sp-consensus-aura = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +sp-inherents = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +sp-io = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +sp-offchain = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +sp-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +sp-std = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +sp-transaction-pool = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } +sp-version = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.28" } + +# Polkadot +pallet-xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.28" } +polkadot-parachain = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.28" } +polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.28" } +xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.28" } +xcm-builder = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.28" } +xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.28" } + +# Cumulus +cumulus-pallet-aura-ext = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28", default-features = false } +cumulus-pallet-dmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28", default-features = false } +cumulus-pallet-parachain-system = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28", default-features = false } +cumulus-pallet-session-benchmarking = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28", default-features = false} +cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28", default-features = false } +cumulus-pallet-xcmp-queue = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28", default-features = false } +cumulus-primitives-core = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28", default-features = false } +cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28", default-features = false } +cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28", default-features = false } +pallet-collator-selection = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28", default-features = false } +parachain-info = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.28", default-features = false } + +primitives = { version = "2.0.0", package = "zero-primitives", default-features = false, path = "../../../modules/primitives" } + +orml-asset-registry = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch= "polkadot-v0.9.28", default-features = false } +orml-currencies = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch= "polkadot-v0.9.28", default-features = false } +orml-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch= "polkadot-v0.9.28", default-features = false } +orml-traits = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch= "polkadot-v0.9.28", default-features = false } +orml-unknown-tokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch= "polkadot-v0.9.28", default-features = false } +orml-xcm = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch= "polkadot-v0.9.28", default-features = false } +orml-xcm-support = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch= "polkadot-v0.9.28", default-features = false } +orml-xtokens = { git = "https://github.com/open-web3-stack/open-runtime-module-library", branch= "polkadot-v0.9.28", default-features = false } + +pallet-rmrk-core = { git = "https://github.com/rmrk-team/rmrk-substrate", default-features = false, branch = "polkadot-v0.9.28" } +pallet-rmrk-equip = { git = "https://github.com/rmrk-team/rmrk-substrate", default-features = false, branch = "polkadot-v0.9.28" } +pallet-rmrk-market = { git = "https://github.com/rmrk-team/rmrk-substrate", default-features = false, branch = "polkadot-v0.9.28" } +rmrk-traits = { git = "https://github.com/rmrk-team/rmrk-substrate", default-features = false, branch = "polkadot-v0.9.28" } +pallet-rmrk-rpc-runtime-api = { git = "https://github.com/rmrk-team/rmrk-substrate", default-features = false, branch = "polkadot-v0.9.28" } + +gamedao-traits = { path = "../../../modules/gamedao-protocol/traits", default-features = false } +gamedao-flow = { path = "../../../modules/gamedao-protocol/flow", default-features = false } +gamedao-control = { path = "../../../modules/gamedao-protocol/control", default-features = false } +gamedao-signal = { path = "../../../modules/gamedao-protocol/signal", default-features = false } +gamedao-sense = { path = "../../../modules/gamedao-protocol/sense", default-features = false } + +[features] +default = [ + "std", +] +std = [ + "codec/std", + "log/std", + "scale-info/std", + "serde", + "cumulus-pallet-aura-ext/std", + "cumulus-pallet-dmp-queue/std", + "cumulus-pallet-parachain-system/std", + "cumulus-pallet-xcm/std", + "cumulus-pallet-xcmp-queue/std", + "cumulus-primitives-core/std", + "cumulus-primitives-timestamp/std", + "cumulus-primitives-utility/std", + "frame-executive/std", + "frame-support/std", + "frame-system-rpc-runtime-api/std", + "frame-system/std", + "pallet-aura/std", + "pallet-authorship/std", + "pallet-balances/std", + "pallet-bounties/std", + "pallet-collator-selection/std", + "pallet-child-bounties/std", + "pallet-collective/std", + "pallet-democracy/std", + "pallet-elections-phragmen/std", + "pallet-identity/std", + "pallet-membership/std", + "pallet-multisig/std", + "pallet-preimage/std", + "pallet-proxy/std", + "pallet-scheduler/std", + "pallet-session/std", + "pallet-sudo/std", + "pallet-timestamp/std", + "pallet-tips/std", + "pallet-transaction-payment-rpc-runtime-api/std", + "pallet-transaction-payment/std", + "pallet-treasury/std", + "pallet-uniques/std", + "pallet-utility/std", + "pallet-xcm/std", + "parachain-info/std", + "polkadot-parachain/std", + "polkadot-runtime-common/std", + "sp-api/std", + "sp-block-builder/std", + "sp-consensus-aura/std", + "sp-core/std", + "sp-inherents/std", + "sp-io/std", + "sp-offchain/std", + "sp-runtime/std", + "sp-session/std", + "sp-std/std", + "sp-transaction-pool/std", + "sp-version/std", + "xcm-builder/std", + "xcm-executor/std", + "xcm/std", + + "primitives/std", + + "orml-asset-registry/std", + "orml-currencies/std", + "orml-tokens/std", + "orml-traits/std", + "orml-unknown-tokens/std", + "orml-xcm-support/std", + "orml-xcm/std", + "orml-xtokens/std", + + "pallet-rmrk-core/std", + "pallet-rmrk-market/std", + "pallet-rmrk-equip/std", + "rmrk-traits/std", + "pallet-rmrk-rpc-runtime-api/std", + + "gamedao-sense/std", + "gamedao-traits/std", + "gamedao-flow/std", + "gamedao-control/std", + "gamedao-signal/std", +] + +runtime-benchmarks = [ + "hex-literal", + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system-benchmarking", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-bounties/runtime-benchmarks", + "pallet-collator-selection/runtime-benchmarks", + "pallet-collective/runtime-benchmarks", + "pallet-child-bounties/runtime-benchmarks", + "pallet-democracy/runtime-benchmarks", + "pallet-identity/runtime-benchmarks", + "pallet-treasury/runtime-benchmarks", + "pallet-timestamp/runtime-benchmarks", + "pallet-xcm/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", + "cumulus-pallet-session-benchmarking/runtime-benchmarks", + "cumulus-pallet-xcmp-queue/runtime-benchmarks", + + "gamedao-traits/runtime-benchmarks", + "gamedao-sense/runtime-benchmarks", + "gamedao-control/runtime-benchmarks", + "gamedao-flow/runtime-benchmarks", + "gamedao-signal/runtime-benchmarks", +] + +try-runtime = [ + "frame-executive/try-runtime", + "frame-try-runtime", +] diff --git a/bin/subzero-dev/runtime/build.rs b/bin/subzero-dev/runtime/build.rs new file mode 100644 index 0000000000..9b53d2457d --- /dev/null +++ b/bin/subzero-dev/runtime/build.rs @@ -0,0 +1,9 @@ +use substrate_wasm_builder::WasmBuilder; + +fn main() { + WasmBuilder::new() + .with_current_project() + .export_heap_base() + .import_memory() + .build() +} diff --git a/bin/subzero-dev/runtime/src/constants.rs b/bin/subzero-dev/runtime/src/constants.rs new file mode 100644 index 0000000000..a4f78f474c --- /dev/null +++ b/bin/subzero-dev/runtime/src/constants.rs @@ -0,0 +1,101 @@ +pub mod time { + use primitives::{ + currency::ZERO, + cent, + Balance, BlockNumber, Moment, + }; + + pub const SECS_PER_BLOCK: Moment = 12; + pub const MILLISECS_PER_BLOCK: Moment = SECS_PER_BLOCK * 1000; + + // These time units are defined in number of blocks. + pub const MINUTES: BlockNumber = 60 / (SECS_PER_BLOCK as BlockNumber); + pub const HOURS: BlockNumber = MINUTES * 60; + pub const DAYS: BlockNumber = HOURS * 24; + + pub const SLOT_DURATION: Moment = MILLISECS_PER_BLOCK; + + pub fn deposit(items: u32, bytes: u32) -> Balance { + items as Balance * 15 * cent(ZERO) + (bytes as Balance) * 6 * cent(ZERO) + } +} + +pub mod fee { + use frame_support::weights::{ + constants::{ExtrinsicBaseWeight, WEIGHT_PER_SECOND}, + WeightToFeePolynomial, + WeightToFeeCoefficients, + WeightToFeeCoefficient + }; + use smallvec::smallvec; + use sp_runtime::Perbill; + use primitives::{ + currency::{TokenSymbol, DOT, ZERO, GAME, PLAY}, + Balance, + cent + }; + + pub fn base_tx_in_token(token: TokenSymbol) -> Balance { + match token { + TokenSymbol::DOT => cent(DOT) * 30 / 10000, + // ZERO:DOT = 6:1 + TokenSymbol::ZERO => cent(ZERO) * 18 / 1000, + // GAME:DOT = 6:1 + TokenSymbol::GAME => cent(GAME) * 18 / 1000, + // PLAY:DOT = 6:1 + TokenSymbol::PLAY => cent(PLAY) * 18 / 1000, + } + } + + pub fn base_tx_per_second() -> u128 { + let base_weight = Balance::from(ExtrinsicBaseWeight::get()); + (WEIGHT_PER_SECOND as u128) / base_weight + } + + pub fn dot_per_second() -> u128 { + base_tx_per_second() * base_tx_in_token(TokenSymbol::DOT) + } + + pub fn zero_per_second() -> u128 { + base_tx_per_second() * base_tx_in_token(TokenSymbol::ZERO) + } + + pub fn game_per_second() -> u128 { + base_tx_per_second() * base_tx_in_token(TokenSymbol::GAME) + } + + pub fn play_per_second() -> u128 { + base_tx_per_second() * base_tx_in_token(TokenSymbol::PLAY) + } + + /// Handles converting a weight scalar to a fee value, based on the scale and granularity of the + /// node's balance type. + /// + /// This should typically create a mapping between the following ranges: + /// - `[0, MAXIMUM_BLOCK_WEIGHT]` + /// - `[Balance::min, Balance::max]` + /// + /// Yet, it can be used for any other sort of change to weight-fee. Some examples being: + /// - Setting it to `0` will essentially disable the weight fee. + /// - Setting it to `1` will cause the literal `#[weight = x]` values to be charged. + pub struct WeightToFee; + impl WeightToFeePolynomial for WeightToFee { + type Balance = Balance; + fn polynomial() -> WeightToFeeCoefficients { + let p = base_tx_in_token(TokenSymbol::ZERO); + let q = Balance::from(ExtrinsicBaseWeight::get()); + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } + } +} + +pub mod parachains { + pub mod acala { + pub const ID: u32 = 2000; + } +} diff --git a/bin/subzero-dev/runtime/src/lib.rs b/bin/subzero-dev/runtime/src/lib.rs new file mode 100644 index 0000000000..ecf9c35a8f --- /dev/null +++ b/bin/subzero-dev/runtime/src/lib.rs @@ -0,0 +1,1488 @@ +#![cfg_attr(not(feature = "std"), no_std)] +// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. +#![recursion_limit = "256"] + +// Make the WASM binary available. +#[cfg(feature = "std")] +include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); + +pub mod constants; +mod weights; +pub mod xcm_config; + +use codec::{Decode, Encode, MaxEncodedLen}; +use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; +use sp_api::impl_runtime_apis; +use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; +use sp_runtime::{ + create_runtime_str, generic, impl_opaque_keys, + traits::{AccountIdConversion, AccountIdLookup, BlakeTwo256, Block as BlockT, Convert, IdentifyAccount, Verify}, + transaction_validity::{TransactionSource, TransactionValidity}, + ApplyExtrinsicResult, MultiSignature, Percent +}; + +use sp_std::{collections::btree_set::BTreeSet, prelude::*}; +#[cfg(feature = "std")] +use sp_version::NativeVersion; +use sp_version::RuntimeVersion; +use static_assertions::const_assert; + +use frame_support::{ + construct_runtime, parameter_types, + pallet_prelude::RuntimeDebug, + traits::{ + tokens::nonfungibles::*, + AsEnsureOriginWithArg, ConstU16, ConstU32, Contains, EitherOfDiverse, + EnsureOrigin, EnsureOriginWithArg, EqualPrivilegeOnly, InstanceFilter, + LockIdentifier, U128CurrencyToVote + }, + weights::{ + constants::WEIGHT_PER_SECOND, ConstantMultiplier, DispatchClass, Weight, + }, + BoundedVec, PalletId, +}; +use frame_system::{ + limits::{BlockLength, BlockWeights}, + EnsureRoot, EnsureSigned, +}; +pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; +pub use sp_runtime::{DispatchError, MultiAddress, Perbill, Permill}; + +#[cfg(any(feature = "std", test))] +pub use sp_runtime::BuildStorage; + +// Polkadot imports +use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; + +use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; + +// XCM Imports +use xcm::latest::prelude::BodyId; + +pub use constants::{fee::*, time::*}; +pub use primitives::{ + cent, + currency::{ + AssetIdMapping, AssetIds, CurrencyId, CustomMetadata, ForeignAssetId, TokenSymbol, DOT, GAME, PLAY, ZERO, + }, + dollar, millicent, Amount, ReserveIdentifier, +}; + +use orml_asset_registry::SequentialId; +use orml_currencies::BasicCurrencyAdapter; +use orml_traits::{parameter_type_with_key, GetByKey}; + +use pallet_rmrk_core::{CollectionInfoOf, InstanceInfoOf, PropertyInfoOf, ResourceInfoOf}; +use pallet_rmrk_equip::{BaseInfoOf, BoundedThemeOf, PartTypeOf}; +use rmrk_traits::{primitives::*, NftChild}; + +/// Alias to 512-bit hash when used in the context of a transaction signature on the chain. +pub type Signature = MultiSignature; + +/// Some way of identifying an account on the chain. We intentionally make it equivalent +/// to the public key of our transaction signing scheme. +pub type AccountId = <::Signer as IdentifyAccount>::AccountId; + +/// Balance of an account. +pub type Balance = u128; + +/// Index of a transaction in the chain. +pub type Index = u32; + +/// A hash of some data used by the chain. +pub type Hash = sp_core::H256; + +/// An index to a block. +pub type BlockNumber = u32; + +/// The address format for describing accounts. +pub type Address = MultiAddress; + +/// Block header type as expected by this runtime. +pub type Header = generic::Header; + +/// Block type as expected by this runtime. +pub type Block = generic::Block; + +/// A Block signed with a Justification +pub type SignedBlock = generic::SignedBlock; + +/// BlockId type as expected by this runtime. +pub type BlockId = generic::BlockId; + +/// The SignedExtension to the basic transaction logic. +pub type SignedExtra = ( + frame_system::CheckNonZeroSender, + frame_system::CheckSpecVersion, + frame_system::CheckTxVersion, + frame_system::CheckGenesis, + frame_system::CheckEra, + frame_system::CheckNonce, + frame_system::CheckWeight, + pallet_transaction_payment::ChargeTransactionPayment, +); + +/// Unchecked extrinsic type as expected by this runtime. +pub type UncheckedExtrinsic = generic::UncheckedExtrinsic; + +/// Extrinsic type that has already been checked. +pub type CheckedExtrinsic = generic::CheckedExtrinsic; + +/// Executive: handles dispatch to the various modules. +pub type Executive = + frame_executive::Executive, Runtime, AllPalletsWithSystem>; + +/// Opaque types. These are used by the CLI to instantiate machinery that don't need to know +/// the specifics of the runtime. They can then be made to be agnostic over specific formats +/// of data like extrinsics, allowing for them to continue syncing the network through upgrades +/// to even the core data structures. +pub mod opaque { + use super::*; + use sp_runtime::{generic, traits::BlakeTwo256}; + + pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; + /// Opaque block header type. + pub type Header = generic::Header; + /// Opaque block type. + pub type Block = generic::Block; + /// Opaque block identifier type. + pub type BlockId = generic::BlockId; +} + +impl_opaque_keys! { + pub struct SessionKeys { + pub aura: Aura, + } +} + +#[sp_version::runtime_version] +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: create_runtime_str!("subzero"), + impl_name: create_runtime_str!("dev"), + authoring_version: 75, + spec_version: 63, + impl_version: 0, + apis: RUNTIME_API_VERSIONS, + transaction_version: 1, + state_version: 1, +}; + +// Unit = the base number of indivisible units for balances +pub const UNIT: Balance = 1_000_000_000_000; +pub const MILLIUNIT: Balance = 1_000_000_000; +pub const MICROUNIT: Balance = 1_000_000; + +/// The existential deposit. Set to 1/10 of the Connected Relay Chain. +pub const EXISTENTIAL_DEPOSIT: Balance = MILLIUNIT; + +/// We assume that ~5% of the block weight is consumed by `on_initialize` handlers. This is +/// used to limit the maximal weight of a single extrinsic. +const AVERAGE_ON_INITIALIZE_RATIO: Perbill = Perbill::from_percent(5); + +/// We allow `Normal` extrinsics to fill up the block up to 75%, the rest can be used by +/// `Operational` extrinsics. +const NORMAL_DISPATCH_RATIO: Perbill = Perbill::from_percent(75); + +/// We allow for 0.5 of a second of compute with a 12 second average block time. +const MAXIMUM_BLOCK_WEIGHT: Weight = WEIGHT_PER_SECOND / 2; + +/// The version information used to identify this runtime when compiled natively. +#[cfg(feature = "std")] +pub fn native_version() -> NativeVersion { + NativeVersion { + runtime_version: VERSION, + can_author_with: Default::default(), + } +} + +parameter_types! { + pub const Version: RuntimeVersion = VERSION; + + // This part is copied from Substrate's `bin/node/runtime/src/lib.rs`. + // The `RuntimeBlockLength` and `RuntimeBlockWeights` exist here because the + // `DeletionWeightLimit` and `DeletionQueueDepth` depend on those to parameterize + // the lazy contract deletion. + pub RuntimeBlockLength: BlockLength = + BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); + pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder() + .base_block(BlockExecutionWeight::get()) + .for_class(DispatchClass::all(), |weights| { + weights.base_extrinsic = ExtrinsicBaseWeight::get(); + }) + .for_class(DispatchClass::Normal, |weights| { + weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); + }) + .for_class(DispatchClass::Operational, |weights| { + weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); + // Operational transactions have some extra reserved space, so that they + // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. + weights.reserved = Some( + MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT + ); + }) + .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) + .build_or_panic(); + pub const SS58Prefix: u16 = 25; +} + +pub struct BaseFilter; +impl Contains for BaseFilter { + fn contains(call: &Call) -> bool { + // Disable direct calls to pallet_uniques + !matches!( + call, + Call::Uniques(pallet_uniques::Call::approve_transfer { .. }) + | Call::Uniques(pallet_uniques::Call::burn { .. }) + | Call::Uniques(pallet_uniques::Call::cancel_approval { .. }) + | Call::Uniques(pallet_uniques::Call::clear_collection_metadata { .. }) + | Call::Uniques(pallet_uniques::Call::clear_metadata { .. }) + | Call::Uniques(pallet_uniques::Call::create { .. }) + | Call::Uniques(pallet_uniques::Call::destroy { .. }) + | Call::Uniques(pallet_uniques::Call::force_item_status { .. }) + | Call::Uniques(pallet_uniques::Call::force_create { .. }) + | Call::Uniques(pallet_uniques::Call::freeze_collection { .. }) + | Call::Uniques(pallet_uniques::Call::mint { .. }) + | Call::Uniques(pallet_uniques::Call::redeposit { .. }) + | Call::Uniques(pallet_uniques::Call::set_collection_metadata { .. }) + | Call::Uniques(pallet_uniques::Call::thaw_collection { .. }) + | Call::Uniques(pallet_uniques::Call::transfer { .. }) + | Call::Uniques(pallet_uniques::Call::transfer_ownership { .. }) + ) + } +} + +// Configure FRAME pallets to include in runtime. + +impl frame_system::Config for Runtime { + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; + /// The aggregated dispatch type that is available for extrinsics. + type Call = Call; + /// The lookup mechanism to get account ID from whatever is passed in dispatchers. + type Lookup = AccountIdLookup; + /// The index type for storing how many extrinsics an account has signed. + type Index = Index; + /// The index type for blocks. + type BlockNumber = BlockNumber; + /// The type for hashing blocks and tries. + type Hash = Hash; + /// The hashing algorithm used. + type Hashing = BlakeTwo256; + /// The header type. + type Header = generic::Header; + /// The ubiquitous event type. + type Event = Event; + /// The ubiquitous origin type. + type Origin = Origin; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; + /// Runtime version. + type Version = Version; + /// Converts a module to an index of this module in the runtime. + type PalletInfo = PalletInfo; + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; + /// What to do if a new account is created. + type OnNewAccount = (); + /// What to do if an account is fully reaped from the system. + type OnKilledAccount = (); + /// The weight of database operations that the runtime can invoke. + type DbWeight = RocksDbWeight; + /// The basic call filter to use in dispatchable. + type BaseCallFilter = BaseFilter; + /// Weight information for the extrinsics of this pallet. + type SystemWeightInfo = (); + /// Block & extrinsics weights: base values and limits. + type BlockWeights = RuntimeBlockWeights; + /// The maximum length of a block (in bytes). + type BlockLength = RuntimeBlockLength; + /// This is used as an identifier of the chain. 42 is the generic substrate prefix. + type SS58Prefix = SS58Prefix; + /// The action to take on a Runtime Upgrade + type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; + type MaxConsumers = ConstU32<16>; +} + +parameter_types! { + pub const MinimumPeriod: u64 = SLOT_DURATION / 2; +} + +impl pallet_timestamp::Config for Runtime { + /// A timestamp: milliseconds since the unix epoch. + type Moment = u64; + type OnTimestampSet = (); + type MinimumPeriod = MinimumPeriod; + type WeightInfo = (); +} + +parameter_types! { + pub const UncleGenerations: u32 = 0; +} + +impl pallet_authorship::Config for Runtime { + type FindAuthor = pallet_session::FindAccountFromAuthorIndex; + type UncleGenerations = UncleGenerations; + type FilterUncle = (); + type EventHandler = (CollatorSelection,); +} + +parameter_types! { + pub ExistentialDeposit: Balance = ExistentialDeposits::get(&ZERO); + pub const MaxLocks: u32 = 50; + pub const MaxReserves: u32 = ReserveIdentifier::Count as u32; +} + +impl pallet_balances::Config for Runtime { + type MaxLocks = MaxLocks; + /// The type for recording an account's balance. + type Balance = Balance; + /// The ubiquitous event type. + type Event = Event; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = pallet_balances::weights::SubstrateWeight; + type MaxReserves = MaxReserves; + type ReserveIdentifier = ReserveIdentifier; +} + +parameter_types! { + /// Relay Chain `TransactionByteFee` / 10 + pub const TransactionByteFee: Balance = 10 * MICROUNIT; + pub const OperationalFeeMultiplier: u8 = 5; +} + +impl pallet_transaction_payment::Config for Runtime { + type Event = Event; + type OnChargeTransaction = pallet_transaction_payment::CurrencyAdapter; + type WeightToFee = WeightToFee; + type LengthToFee = ConstantMultiplier; + type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type OperationalFeeMultiplier = OperationalFeeMultiplier; +} + +parameter_types! { + // One storage item; key size is 32; value is size 4+4+16+32 bytes = 56 bytes. + pub MultisigDepositBase: Balance = deposit(1, 88); + // Additional storage item size of 32 bytes. + pub MultisigDepositFactor: Balance = deposit(0, 32); +} + +impl pallet_multisig::Config for Runtime { + type Event = Event; + type Call = Call; + type Currency = Balances; + type DepositBase = MultisigDepositBase; + type DepositFactor = MultisigDepositFactor; + type MaxSignatories = ConstU16<100>; + type WeightInfo = pallet_multisig::weights::SubstrateWeight; +} + +parameter_types! { + pub MaximumSchedulerWeight: Weight = Perbill::from_percent(80) * + RuntimeBlockWeights::get().max_block; + // Retry a scheduled item every 10 blocks (1 minute) until the preimage exists. + pub const NoPreimagePostponement: Option = Some(10); +} + +impl pallet_scheduler::Config for Runtime { + type Event = Event; + type Origin = Origin; + type PalletsOrigin = OriginCaller; + type Call = Call; + type MaximumWeight = MaximumSchedulerWeight; + type ScheduleOrigin = EnsureRoot; + type MaxScheduledPerBlock = ConstU32<50>; + type WeightInfo = pallet_scheduler::weights::SubstrateWeight; + type OriginPrivilegeCmp = EqualPrivilegeOnly; + type PreimageProvider = Preimage; + type NoPreimagePostponement = NoPreimagePostponement; +} + +parameter_types! { + pub const PreimageMaxSize: u32 = 4096 * 1024; + pub PreimageBaseDeposit: Balance = 1 * dollar(ZERO); + // One cent: $10,000 / MB + pub PreimageByteDeposit: Balance = 1 * cent(ZERO); +} + +impl pallet_preimage::Config for Runtime { + type WeightInfo = pallet_preimage::weights::SubstrateWeight; + type Event = Event; + type Currency = Balances; + type ManagerOrigin = EnsureRoot; + type MaxSize = PreimageMaxSize; + type BaseDeposit = PreimageBaseDeposit; + type ByteDeposit = PreimageByteDeposit; +} + +parameter_types! { + // One storage item; key size 32, value size 8; . + pub ProxyDepositBase: Balance = deposit(1, 8); + // Additional storage item size of 33 bytes. + pub ProxyDepositFactor: Balance = deposit(0, 33); + pub AnnouncementDepositBase: Balance = deposit(1, 8); + pub AnnouncementDepositFactor: Balance = deposit(0, 66); +} + +#[derive(Copy, Clone, Eq, PartialEq, Ord,PartialOrd, Encode, Decode, RuntimeDebug, MaxEncodedLen, scale_info::TypeInfo)] +pub enum ProxyType { + Any, + NonTransfer, + Governance, +} +impl Default for ProxyType { + fn default() -> Self { + Self::Any + } +} +impl InstanceFilter for ProxyType { + fn filter(&self, c: &Call) -> bool { + match self { + ProxyType::Any => true, + ProxyType::NonTransfer => !matches!( + c, + Call::Balances(..) | + Call::Uniques(..) | + Call::Currencies(..) | + Call::Tokens(..) + ), + ProxyType::Governance => matches!( + c, + Call::Democracy(..) | + Call::Council(..) | + Call::TechnicalCommittee(..) | + Call::Treasury(..) | + Call::Bounties(..) | Call::ChildBounties(..) | + Call::Utility(..) | + Call::Elections(..) + ) + } + } + fn is_superset(&self, o: &Self) -> bool { + match (self, o) { + (x, y) if x == y => true, + (ProxyType::Any, _) => true, + (_, ProxyType::Any) => false, + (ProxyType::NonTransfer, _) => true, + _ => false, + } + } +} + +impl pallet_proxy::Config for Runtime { + type Event = Event; + type Call = Call; + type Currency = Balances; + type ProxyType = ProxyType; + type ProxyDepositBase = ProxyDepositBase; + type ProxyDepositFactor = ProxyDepositFactor; + type MaxProxies = ConstU32<32>; + type WeightInfo = pallet_proxy::weights::SubstrateWeight; + type MaxPending = ConstU32<32>; + type CallHasher = BlakeTwo256; + type AnnouncementDepositBase = AnnouncementDepositBase; + type AnnouncementDepositFactor = AnnouncementDepositFactor; +} + +parameter_types! { + pub const LaunchPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; + pub const VotingPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; + pub const FastTrackVotingPeriod: BlockNumber = 3 * 24 * 60 * MINUTES; + pub MinimumDeposit: Balance = 100 * dollar(ZERO); + pub const EnactmentPeriod: BlockNumber = 30 * 24 * 60 * MINUTES; + pub const CooloffPeriod: BlockNumber = 28 * 24 * 60 * MINUTES; + pub const MaxProposals: u32 = 100; +} + +impl pallet_democracy::Config for Runtime { + type Proposal = Call; + type Event = Event; + type Currency = Balances; + type EnactmentPeriod = EnactmentPeriod; + type LaunchPeriod = LaunchPeriod; + type VotingPeriod = VotingPeriod; + type VoteLockingPeriod = EnactmentPeriod; // Same as EnactmentPeriod + type MinimumDeposit = MinimumDeposit; + /// A straight majority of the council can decide what their next motion is. + type ExternalOrigin = + pallet_collective::EnsureProportionAtLeast; + /// A super-majority can have the next scheduled referendum be a straight majority-carries vote. + type ExternalMajorityOrigin = + pallet_collective::EnsureProportionAtLeast; + /// A unanimous council can have the next scheduled referendum be a straight default-carries + /// (NTB) vote. + type ExternalDefaultOrigin = + pallet_collective::EnsureProportionAtLeast; + /// Two thirds of the technical committee can have an ExternalMajority/ExternalDefault vote + /// be tabled immediately and with a shorter voting/enactment period. + type FastTrackOrigin = + pallet_collective::EnsureProportionAtLeast; + type InstantOrigin = + pallet_collective::EnsureProportionAtLeast; + type InstantAllowed = frame_support::traits::ConstBool; + type FastTrackVotingPeriod = FastTrackVotingPeriod; + // To cancel a proposal which has been passed, 2/3 of the council must agree to it. + type CancellationOrigin = + pallet_collective::EnsureProportionAtLeast; + // To cancel a proposal before it has been passed, the technical committee must be unanimous or + // Root must agree. + type CancelProposalOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionAtLeast, + >; + type BlacklistOrigin = EnsureRoot; + // Any single technical committee member may veto a coming council proposal, however they can + // only do it once and it lasts only for the cool-off period. + type VetoOrigin = pallet_collective::EnsureMember; + type CooloffPeriod = CooloffPeriod; + type PreimageByteDeposit = PreimageByteDeposit; + type OperationalPreimageOrigin = pallet_collective::EnsureMember; + type Slash = Treasury; + type Scheduler = Scheduler; + type PalletsOrigin = OriginCaller; + type MaxVotes = ConstU32<100>; + type WeightInfo = pallet_democracy::weights::SubstrateWeight; + type MaxProposals = MaxProposals; +} + +impl pallet_sudo::Config for Runtime { + type Event = Event; + type Call = Call; +} + +parameter_types! { + pub const BountyCuratorDeposit: Permill = Permill::from_percent(50); + pub BountyValueMinimum: Balance = 5 * dollar(ZERO); + pub BountyDepositBase: Balance = 1 * dollar(ZERO); + pub const CuratorDepositMultiplier: Permill = Permill::from_percent(50); + pub CuratorDepositMin: Balance = 1 * dollar(ZERO); + pub CuratorDepositMax: Balance = 100 * dollar(ZERO); + pub const BountyDepositPayoutDelay: BlockNumber = 1 * DAYS; + pub const BountyUpdatePeriod: BlockNumber = 14 * DAYS; +} + +impl pallet_bounties::Config for Runtime { + type Event = Event; + type BountyDepositBase = BountyDepositBase; + type BountyDepositPayoutDelay = BountyDepositPayoutDelay; + type BountyUpdatePeriod = BountyUpdatePeriod; + type CuratorDepositMultiplier = CuratorDepositMultiplier; + type CuratorDepositMin = CuratorDepositMin; + type CuratorDepositMax = CuratorDepositMax; + type BountyValueMinimum = BountyValueMinimum; + type DataDepositPerByte = DataDepositPerByte; + type MaximumReasonLength = MaximumReasonLength; + type WeightInfo = pallet_bounties::weights::SubstrateWeight; + type ChildBountyManager = ChildBounties; +} + +parameter_types! { + pub ChildBountyValueMinimum: Balance = 1 * dollar(ZERO); +} + +impl pallet_child_bounties::Config for Runtime { + type Event = Event; + type MaxActiveChildBountyCount = ConstU32<5>; + type ChildBountyValueMinimum = ChildBountyValueMinimum; + type WeightInfo = pallet_child_bounties::weights::SubstrateWeight; +} + +parameter_types! { + pub const CouncilMotionDuration: BlockNumber = 5 * DAYS; + pub const CouncilMaxMembers: u32 = 100; +} + +type EnsureRootOrHalfCouncil = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionMoreThan, +>; + +type EnsureRootOrThreeFourthsCouncil = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionMoreThan, +>; + +impl pallet_rmrk_core::Config for Runtime { + type Event = Event; + type ProtocolOrigin = frame_system::EnsureRoot; + type MaxRecursions = ConstU32<10>; + type ResourceSymbolLimit = ConstU32<10>; + type PartsLimit = ConstU32<25>; + type MaxPriorities = ConstU32<25>; + type CollectionSymbolLimit = ConstU32<100>; + type MaxResourcesOnMint = ConstU32<100>; +} + +parameter_types! { + pub MinimumOfferAmount: Balance = cent(ZERO) / 10; +} + +impl pallet_rmrk_market::Config for Runtime { + type Event = Event; + type ProtocolOrigin = EnsureRoot; + type Currency = Balances; + type MinimumOfferAmount = MinimumOfferAmount; +} + +impl pallet_rmrk_equip::Config for Runtime { + type Event = Event; + type MaxPropertiesPerTheme = ConstU32<100>; + type MaxCollectionsEquippablePerPart = ConstU32<100>; +} + +parameter_types! { + pub CollectionDeposit: Balance = cent(ZERO) * 10; + pub ItemDeposit: Balance = dollar(ZERO); + pub MetadataDepositBase: Balance = cent(ZERO) * 10; + pub MetadataDepositPerByte: Balance = cent(ZERO); +} + +impl pallet_uniques::Config for Runtime { + type Event = Event; + type CollectionId = u32; + type ItemId = u32; + type Currency = Balances; + type ForceOrigin = EnsureRoot; + type CollectionDeposit = CollectionDeposit; + type ItemDeposit = ItemDeposit; + type MetadataDepositBase = MetadataDepositBase; + type AttributeDepositBase = MetadataDepositBase; + type DepositPerByte = MetadataDepositPerByte; + type StringLimit = StringLimit; + type KeyLimit = ConstU32<32>; + type ValueLimit = ConstU32<256>; + type WeightInfo = pallet_uniques::weights::SubstrateWeight; + #[cfg(feature = "runtime-benchmarks")] + type Helper = (); + type CreateOrigin = AsEnsureOriginWithArg>; + type Locker = pallet_rmrk_core::Pallet; +} + +impl pallet_utility::Config for Runtime { + type Event = Event; + type Call = Call; + type PalletsOrigin = OriginCaller; + type WeightInfo = (); +} + +type CouncilCollective = pallet_collective::Instance1; +impl pallet_collective::Config for Runtime { + type Origin = Origin; + type Proposal = Call; + type Event = Event; + type MotionDuration = CouncilMotionDuration; + type MaxProposals = ConstU32<100>; + type MaxMembers = CouncilMaxMembers; + type DefaultVote = pallet_collective::PrimeDefaultVote; + type WeightInfo = pallet_collective::weights::SubstrateWeight; +} + +parameter_types! { + pub const TechnicalMotionDuration: BlockNumber = 5 * DAYS; + pub const TechnicalMaxMembers: u32 = 100; +} + +type TechnicalCollective = pallet_collective::Instance2; +impl pallet_collective::Config for Runtime { + type Origin = Origin; + type Proposal = Call; + type Event = Event; + type MotionDuration = TechnicalMotionDuration; + type MaxProposals = ConstU32<100>; + type MaxMembers = TechnicalMaxMembers; + type DefaultVote = pallet_collective::PrimeDefaultVote; + type WeightInfo = pallet_collective::weights::SubstrateWeight; +} + +impl pallet_membership::Config for Runtime { + type Event = Event; + type AddOrigin = EnsureRootOrHalfCouncil; + type RemoveOrigin = EnsureRootOrHalfCouncil; + type SwapOrigin = EnsureRootOrHalfCouncil; + type ResetOrigin = EnsureRootOrHalfCouncil; + type PrimeOrigin = EnsureRootOrHalfCouncil; + type MembershipInitialized = TechnicalCommittee; + type MembershipChanged = TechnicalCommittee; + type MaxMembers = TechnicalMaxMembers; + type WeightInfo = pallet_membership::weights::SubstrateWeight; +} + +parameter_types! { + pub CandidacyBond: Balance = 10 * dollar(ZERO); + // 1 storage item created, key size is 32 bytes, value size is 16+16. + pub VotingBondBase: Balance = deposit(1, 64); + // additional data per vote is 32 bytes (account id). + pub VotingBondFactor: Balance = deposit(0, 32); + pub const TermDuration: BlockNumber = 7 * DAYS; + pub const DesiredMembers: u32 = 13; + pub const ElectionsPhragmenPalletId: LockIdentifier = *b"phrelect"; +} + +// Make sure that there are no more than `MaxMembers` members elected via elections-phragmen. +const_assert!(DesiredMembers::get() <= CouncilMaxMembers::get()); + +impl pallet_elections_phragmen::Config for Runtime { + type Event = Event; + type PalletId = ElectionsPhragmenPalletId; + type Currency = Balances; + type ChangeMembers = Council; + // NOTE: this implies that council's genesis members cannot be set directly and must come from + // this module. + type InitializeMembers = Council; + type CurrencyToVote = U128CurrencyToVote; + type CandidacyBond = CandidacyBond; + type VotingBondBase = VotingBondBase; + type VotingBondFactor = VotingBondFactor; + type LoserCandidate = Treasury; + type KickedMember = Treasury; + type DesiredMembers = DesiredMembers; + type DesiredRunnersUp = ConstU32<7>; + type TermDuration = TermDuration; + type MaxVoters = ConstU32<{10 * 1000}>; + type MaxCandidates = ConstU32<1000>; + type WeightInfo = pallet_elections_phragmen::weights::SubstrateWeight; +} + +parameter_types! { + pub const TipCountdown: BlockNumber = 1 * DAYS; + pub const TipFindersFee: Percent = Percent::from_percent(20); + pub TipReportDepositBase: Balance = 1 * dollar(ZERO); +} + +impl pallet_tips::Config for Runtime { + type Event = Event; + type DataDepositPerByte = DataDepositPerByte; + type MaximumReasonLength = MaximumReasonLength; + type Tippers = Elections; + type TipCountdown = TipCountdown; + type TipFindersFee = TipFindersFee; + type TipReportDepositBase = TipReportDepositBase; + type WeightInfo = pallet_tips::weights::SubstrateWeight; +} + +parameter_types! { + pub const ProposalBond: Permill = Permill::from_percent(5); + pub ProposalBondMinimum: Balance = 1 * dollar(ZERO); + pub const SpendPeriod: BlockNumber = 1 * DAYS; + pub const Burn: Permill = Permill::from_percent(50); + // pub const TipCountdown: BlockNumber = 1 * DAYS; + // pub const TipFindersFee: Percent = Percent::from_percent(20); + // pub TipReportDepositBase: Balance = 1 * dollar(ZERO); + pub DataDepositPerByte: Balance = 1 * cent(ZERO); + pub const MaximumReasonLength: u32 = 300; +} + +impl pallet_treasury::Config for Runtime { + type PalletId = TreasuryPalletId; + type Currency = Balances; + type ApproveOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionAtLeast, + >; + type RejectOrigin = EitherOfDiverse< + EnsureRoot, + pallet_collective::EnsureProportionMoreThan, + >; + type Event = Event; + type OnSlash = (); + type ProposalBond = ProposalBond; + type ProposalBondMinimum = ProposalBondMinimum; + type ProposalBondMaximum = (); + type SpendPeriod = SpendPeriod; + type Burn = Burn; + type BurnDestination = (); + type SpendFunds = Bounties; + type WeightInfo = pallet_treasury::weights::SubstrateWeight; + type MaxApprovals = ConstU32<100>; + type SpendOrigin = frame_support::traits::NeverEnsureOrigin; +} + +parameter_types! { + pub BasicDeposit: Balance = 10 * dollar(ZERO); // 258 bytes on-chain + pub FieldDeposit: Balance = 250 * cent(ZERO); // 66 bytes on-chain + pub SubAccountDeposit: Balance = 2 * dollar(ZERO); // 53 bytes on-chain +} + +impl pallet_identity::Config for Runtime { + type Event = Event; + type Currency = Balances; + type BasicDeposit = BasicDeposit; + type FieldDeposit = FieldDeposit; + type SubAccountDeposit = SubAccountDeposit; + type MaxSubAccounts = ConstU32<100>; + type MaxAdditionalFields = ConstU32<100>; + type MaxRegistrars = ConstU32<20>; + type Slashed = Treasury; + type ForceOrigin = EnsureRootOrHalfCouncil; + type RegistrarOrigin = EnsureRootOrHalfCouncil; + type WeightInfo = pallet_identity::weights::SubstrateWeight; +} + +parameter_types! { + pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4; + pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT / 4; +} + +impl cumulus_pallet_parachain_system::Config for Runtime { + type Event = Event; + type OnSystemEvent = (); + type SelfParaId = parachain_info::Pallet; + type OutboundXcmpMessageSource = XcmpQueue; + type DmpMessageHandler = DmpQueue; + type ReservedDmpWeight = ReservedDmpWeight; + type XcmpMessageHandler = XcmpQueue; + type ReservedXcmpWeight = ReservedXcmpWeight; + type CheckAssociatedRelayNumber = RelayNumberStrictlyIncreases; +} + +impl parachain_info::Config for Runtime {} + +impl cumulus_pallet_aura_ext::Config for Runtime {} + +parameter_types! { + pub const Period: u32 = 6 * HOURS; + pub const Offset: u32 = 0; + pub const MaxAuthorities: u32 = 100_000; +} + +impl pallet_session::Config for Runtime { + type Event = Event; + type ValidatorId = ::AccountId; + // we don't have stash and controller, thus we don't need the convert as well. + type ValidatorIdOf = pallet_collator_selection::IdentityCollator; + type ShouldEndSession = pallet_session::PeriodicSessions; + type NextSessionRotation = pallet_session::PeriodicSessions; + type SessionManager = CollatorSelection; + // Essentially just Aura, but lets be pedantic. + type SessionHandler = ::KeyTypeIdProviders; + type Keys = SessionKeys; + type WeightInfo = (); +} + +impl pallet_aura::Config for Runtime { + type AuthorityId = AuraId; + type DisabledValidators = (); + type MaxAuthorities = MaxAuthorities; +} + +parameter_types! { + pub const PotId: PalletId = PalletId(*b"PotStake"); + pub const MaxCandidates: u32 = 1000; + pub const MinCandidates: u32 = 5; + pub const SessionLength: BlockNumber = 6 * HOURS; + pub const MaxInvulnerables: u32 = 100; + pub const ExecutiveBody: BodyId = BodyId::Executive; +} + +// We allow root only to execute privileged collator selection operations. +// SBP-M2 review: you should have an entity like a council +// instead of providing the whole power to the single user (Root account) +pub type CollatorSelectionUpdateOrigin = EnsureRoot; + +impl pallet_collator_selection::Config for Runtime { + type Event = Event; + type Currency = Balances; + type UpdateOrigin = CollatorSelectionUpdateOrigin; + type PotId = PotId; + type MaxCandidates = MaxCandidates; + type MinCandidates = MinCandidates; + type MaxInvulnerables = MaxInvulnerables; + // should be a multiple of session or things will get inconsistent + type KickThreshold = Period; + type ValidatorId = ::AccountId; + type ValidatorIdOf = pallet_collator_selection::IdentityCollator; + type ValidatorRegistration = Session; + type WeightInfo = (); +} + +// Pallet accounts of runtime +parameter_types! { + pub const TreasuryPalletId: PalletId = PalletId(*b"zr/zrtrs"); + pub const ControlPalletId: PalletId = PalletId(*b"gd/cntrl"); + pub TreasuryAccountId: AccountId = TreasuryPalletId::get().into_account_truncating(); + pub Game3FoundationTreasuryAccountId: AccountId = PalletId(*b"gd/g3trs").into_account_truncating(); + pub GameDAOTreasuryAccountId: AccountId = PalletId(*b"gd/gdtrs").into_account_truncating(); +} + +pub fn get_all_module_accounts() -> Vec { + vec![ + TreasuryAccountId::get(), + ControlPalletId::get().into_account_truncating(), + Game3FoundationTreasuryAccountId::get(), + GameDAOTreasuryAccountId::get(), + ] +} + +parameter_type_with_key! { + pub ExistentialDeposits: |currency_id: CurrencyId| -> Balance { + match currency_id { + CurrencyId::Token(symbol) => match symbol { + TokenSymbol::ZERO => cent(*currency_id), + TokenSymbol::PLAY => 10 * cent(*currency_id), + TokenSymbol::GAME => 10 * cent(*currency_id), + TokenSymbol::DOT => cent(*currency_id), + }, + CurrencyId::ForeignAsset(id) => { + AssetRegistry::metadata(&id) + .map_or(Balance::max_value(), |metadata| metadata.existential_deposit) + }, + } + }; +} + +/// Allow asset registration only from root origin +// SBP-M2 review: root account has too much power +// Need for a council +pub struct AssetAuthority; +impl EnsureOriginWithArg> for AssetAuthority { + type Success = (); + + fn try_origin(origin: Origin, _asset_id: &Option) -> Result { + EnsureRoot::try_origin(origin) + } + + #[cfg(feature = "runtime-benchmarks")] + fn successful_origin(_asset_id: &Option) -> Origin { + EnsureRoot::successful_origin() + } +} + +impl orml_asset_registry::Config for Runtime { + type Event = Event; + type Balance = Balance; + type CustomMetadata = CustomMetadata; + type AssetProcessor = SequentialId; + type AssetId = ForeignAssetId; + type AuthorityOrigin = AssetAuthority; + type WeightInfo = (); +} + +pub struct DustRemovalWhitelist; +impl Contains for DustRemovalWhitelist { + fn contains(a: &AccountId) -> bool { + get_all_module_accounts().contains(a) + } +} + +parameter_types! { + pub const GetNativeCurrencyId: CurrencyId = ZERO; + pub const GetStableCurrencyId: CurrencyId = PLAY; + pub const GetProtocolCurrencyId: CurrencyId = GAME; + pub const StringLimit: u32 = 64; +} + +impl orml_tokens::Config for Runtime { + type Event = Event; + type Balance = Balance; + type Amount = Amount; + type CurrencyId = CurrencyId; + type WeightInfo = (); + type ExistentialDeposits = ExistentialDeposits; + type OnDust = orml_tokens::TransferDust; + type MaxLocks = MaxLocks; + type MaxReserves = MaxReserves; + type ReserveIdentifier = ReserveIdentifier; + type DustRemovalWhitelist = DustRemovalWhitelist; + type OnNewTokenAccount = (); + type OnKilledTokenAccount = (); +} + +impl orml_currencies::Config for Runtime { + type MultiCurrency = Tokens; + type NativeCurrency = BasicCurrencyAdapter; + type GetNativeCurrencyId = GetNativeCurrencyId; + type WeightInfo = (); +} + +parameter_types! { + pub MinProposalDeposit: Balance = 100 * dollar(GAME); + pub SlashingMajority: Permill = Permill::from_rational(2u32, 3u32); + pub GameDAOGetsFromSlashing: Permill = Permill::from_rational(1u32, 10u32); + pub const MaxMembersPerOrg: u32 = 1000; + pub const ProposalDurationLimits: (BlockNumber, BlockNumber) = (100, 864000); +} + +impl gamedao_signal::Config for Runtime { + type WeightInfo = gamedao_signal::weights::SubstrateWeight; + type Event = Event; + type Currency = Currencies; + type CurrencyId = CurrencyId; + type PaymentTokenId = GetStableCurrencyId; + type ProtocolTokenId = GetProtocolCurrencyId; + type Balance = Balance; + type Flow = Flow; + type Control = Control; + type MinProposalDeposit = MinProposalDeposit; + type GameDAOTreasury = GameDAOTreasuryAccountId; + type SlashingMajority = SlashingMajority; + type GameDAOGetsFromSlashing = GameDAOGetsFromSlashing; + type MaxMembers = MaxMembersPerOrg; + type ProposalDurationLimits = ProposalDurationLimits; + type MaxProposalsPerBlock = ConstU32<100>; + type StringLimit = StringLimit; +} + +parameter_types! { + pub OrgMinimumDeposit: Balance = 1 * dollar(GAME); +} + +impl gamedao_control::Config for Runtime { + type Balance = Balance; + type CurrencyId = CurrencyId; + type WeightInfo = gamedao_control::weights::SubstrateWeight; + type Event = Event; + type Currency = Currencies; + type MaxMembers = MaxMembersPerOrg; + type ProtocolTokenId = GetProtocolCurrencyId; + type PaymentTokenId = GetStableCurrencyId; + type MinimumDeposit = OrgMinimumDeposit; + type PalletId = ControlPalletId; + type StringLimit = StringLimit; +} + +parameter_types! { + pub MinContribution: Balance = 1 * dollar(PLAY); + pub CampaignFee: Permill = Permill::from_rational(3u32, 1000u32); // 0.3% + pub MinCampaignDeposit: Permill = Permill::from_rational(1u32, 10u32); // 10% + pub const CampaignDurationLimits: (BlockNumber, BlockNumber) = (24 * HOURS, 60 * DAYS); +} + +impl gamedao_flow::Config for Runtime { + type Event = Event; + type Balance = Balance; + type CurrencyId = CurrencyId; + type WeightInfo = gamedao_flow::weights::SubstrateWeight; + type Currency = Currencies; + type Control = Control; + type GameDAOTreasury = GameDAOTreasuryAccountId; + type MinNameLength = ConstU32<4>; + type MaxCampaignsPerBlock = ConstU32<10>; + type MaxCampaignContributors = ConstU32<10000>; + type MaxContributorsProcessing = ConstU32<100>; + type MinContribution = MinContribution; + type MinCampaignDeposit = MinCampaignDeposit; + type ProtocolTokenId = GetProtocolCurrencyId; + type PaymentTokenId = GetStableCurrencyId; + type CampaignFee = CampaignFee; + type StringLimit = StringLimit; + type CampaignDurationLimits = CampaignDurationLimits; +} + +impl gamedao_sense::Config for Runtime { + type Event = Event; + type WeightInfo = gamedao_sense::weights::SubstrateWeight; + type StringLimit = StringLimit; +} + +// Create the runtime by composing the FRAME pallets that were previously configured. +construct_runtime!( + pub enum Runtime where + Block = Block, + NodeBlock = opaque::Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + // System support stuff. + System: frame_system::{Pallet, Call, Config, Storage, Event} = 0, + Timestamp: pallet_timestamp::{Pallet, Call, Storage, Inherent} = 2, + Utility: pallet_utility::{Pallet, Call, Storage, Event} = 3, + Multisig: pallet_multisig = 4, + ParachainInfo: parachain_info::{Pallet, Storage, Config} = 5, + Council: pallet_collective:: = 6, + TechnicalCommittee: pallet_collective:: = 7, + Identity: pallet_identity = 8, + Bounties: pallet_bounties = 9, + ChildBounties: pallet_child_bounties = 10, + Scheduler: pallet_scheduler = 11, + Preimage: pallet_preimage = 12, + Sudo: pallet_sudo = 13, + Proxy: pallet_proxy = 14, + Democracy: pallet_democracy = 15, + Elections: pallet_elections_phragmen::{Pallet, Call, Storage, Config, Event} = 16, + TechnicalMembership: pallet_membership:: = 17, + + // Monetary stuff. + Treasury: pallet_treasury = 20, + Tips: pallet_tips = 21, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event} = 22, + TransactionPayment: pallet_transaction_payment::{Pallet, Storage, Event} = 23, + + // NFT + RmrkEquip: pallet_rmrk_equip::{Pallet, Call, Event, Storage} = 30, + RmrkCore: pallet_rmrk_core::{Pallet, Call, Event, Storage} = 31, + RmrkMarket: pallet_rmrk_market::{Pallet, Call, Storage, Event} = 32, + Uniques: pallet_uniques::{Pallet, Call, Storage, Event} = 33, + + // Collator support. The order of these 4 are important and shall not change. + Authorship: pallet_authorship::{Pallet, Call, Storage} = 40, + CollatorSelection: pallet_collator_selection::{Pallet, Call, Storage, Event, Config} = 41, + Session: pallet_session::{Pallet, Call, Storage, Event, Config} = 42, + Aura: pallet_aura::{Pallet, Storage, Config} = 43, + AuraExt: cumulus_pallet_aura_ext::{Pallet, Storage, Config} = 44, + + // XCM helpers. + XcmpQueue: cumulus_pallet_xcmp_queue::{Pallet, Call, Storage, Event} = 50, + PolkadotXcm: pallet_xcm::{Pallet, Call, Event, Origin, Config} = 51, + CumulusXcm: cumulus_pallet_xcm::{Pallet, Event, Origin} = 52, + DmpQueue: cumulus_pallet_dmp_queue::{Pallet, Call, Storage, Event} = 53, + + ParachainSystem: cumulus_pallet_parachain_system::{ + Pallet, Call, Config, Storage, Inherent, Event, + } = 1, + + // ORML: + AssetRegistry: orml_asset_registry::{Pallet, Storage, Call, Event, Config} = 60, + Currencies: orml_currencies::{Pallet, Call} = 61, + OrmlXcm: orml_xcm::{Pallet, Call, Event} = 62, + Tokens: orml_tokens::{Pallet, Storage, Call, Event, Config} = 63, + UnknownTokens: orml_unknown_tokens::{Pallet, Storage, Event} = 64, + XTokens: orml_xtokens::{Pallet, Storage, Call, Event} = 65, + + // GameDAO protocol: + Flow: gamedao_flow = 70, + Sense: gamedao_sense = 71, + Control: gamedao_control = 72, + Signal: gamedao_signal = 73, + } +); + +#[cfg(feature = "runtime-benchmarks")] +#[macro_use] +extern crate frame_benchmarking; + +#[cfg(feature = "runtime-benchmarks")] +mod benches { + define_benchmarks!( + [frame_system, SystemBench::] + [pallet_balances, Balances] + [pallet_session, SessionBench::] + [pallet_timestamp, Timestamp] + [pallet_collator_selection, CollatorSelection] + [cumulus_pallet_xcmp_queue, XcmpQueue] + ); +} + +fn option_filter_keys_to_set>( + filter_keys: Option>, +) -> pallet_rmrk_rpc_runtime_api::Result>>> { + match filter_keys { + Some(filter_keys) => { + let tree = filter_keys + .into_iter() + .map( + |filter_keys| -> pallet_rmrk_rpc_runtime_api::Result> { + filter_keys + .try_into() + .map_err(|_| DispatchError::Other("Can't read filter key")) + }, + ) + .collect::>>()?; + Ok(Some(tree)) + } + None => Ok(None), + } +} + +impl_runtime_apis! { + impl sp_consensus_aura::AuraApi for Runtime { + fn slot_duration() -> sp_consensus_aura::SlotDuration { + sp_consensus_aura::SlotDuration::from_millis(Aura::slot_duration()) + } + + fn authorities() -> Vec { + Aura::authorities().into_inner() + } + } + + impl sp_api::Core for Runtime { + fn version() -> RuntimeVersion { + VERSION + } + + fn execute_block(block: Block) { + Executive::execute_block(block) + } + + fn initialize_block(header: &::Header) { + Executive::initialize_block(header) + } + } + + impl sp_api::Metadata for Runtime { + fn metadata() -> OpaqueMetadata { + OpaqueMetadata::new(Runtime::metadata().into()) + } + } + + impl sp_block_builder::BlockBuilder for Runtime { + fn apply_extrinsic(extrinsic: ::Extrinsic) -> ApplyExtrinsicResult { + Executive::apply_extrinsic(extrinsic) + } + + fn finalize_block() -> ::Header { + Executive::finalize_block() + } + + fn inherent_extrinsics(data: sp_inherents::InherentData) -> Vec<::Extrinsic> { + data.create_extrinsics() + } + + fn check_inherents( + block: Block, + data: sp_inherents::InherentData, + ) -> sp_inherents::CheckInherentsResult { + data.check_extrinsics(&block) + } + } + + impl sp_transaction_pool::runtime_api::TaggedTransactionQueue for Runtime { + fn validate_transaction( + source: TransactionSource, + tx: ::Extrinsic, + block_hash: ::Hash, + ) -> TransactionValidity { + Executive::validate_transaction(source, tx, block_hash) + } + } + + impl sp_offchain::OffchainWorkerApi for Runtime { + fn offchain_worker(header: &::Header) { + Executive::offchain_worker(header) + } + } + + impl sp_session::SessionKeys for Runtime { + fn generate_session_keys(seed: Option>) -> Vec { + SessionKeys::generate(seed) + } + + fn decode_session_keys( + encoded: Vec, + ) -> Option, KeyTypeId)>> { + SessionKeys::decode_into_raw_public_keys(&encoded) + } + } + + impl frame_system_rpc_runtime_api::AccountNonceApi for Runtime { + fn account_nonce(account: AccountId) -> Index { + System::account_nonce(account) + } + } + + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi for Runtime { + fn query_info( + uxt: ::Extrinsic, + len: u32, + ) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo { + TransactionPayment::query_info(uxt, len) + } + fn query_fee_details( + uxt: ::Extrinsic, + len: u32, + ) -> pallet_transaction_payment::FeeDetails { + TransactionPayment::query_fee_details(uxt, len) + } + } + + impl cumulus_primitives_core::CollectCollationInfo for Runtime { + fn collect_collation_info(header: &::Header) -> cumulus_primitives_core::CollationInfo { + ParachainSystem::collect_collation_info(header) + } + } + + #[cfg(feature = "try-runtime")] + impl frame_try_runtime::TryRuntime for Runtime { + fn on_runtime_upgrade() -> (Weight, Weight) { + log::info!("try-runtime::on_runtime_upgrade parachain-subzero."); + let weight = Executive::try_runtime_upgrade().unwrap(); + (weight, RuntimeBlockWeights::get().max_block) + } + + fn execute_block_no_check(block: Block) -> Weight { + Executive::execute_block_no_check(block) + } + } + + #[cfg(feature = "runtime-benchmarks")] + impl frame_benchmarking::Benchmark for Runtime { + fn benchmark_metadata(extra: bool) -> ( + Vec, + Vec, + ) { + use frame_benchmarking::{Benchmarking, BenchmarkList}; + use frame_support::traits::StorageInfoTrait; + use frame_system_benchmarking::Pallet as SystemBench; + use cumulus_pallet_session_benchmarking::Pallet as SessionBench; + + let mut list = Vec::::new(); + list_benchmarks!(list, extra); + + let storage_info = AllPalletsWithSystem::storage_info(); + return (list, storage_info) + } + + fn dispatch_benchmark( + config: frame_benchmarking::BenchmarkConfig + ) -> Result, sp_runtime::RuntimeString> { + use frame_benchmarking::{Benchmarking, BenchmarkBatch, TrackedStorageKey}; + + use frame_system_benchmarking::Pallet as SystemBench; + impl frame_system_benchmarking::Config for Runtime {} + + use cumulus_pallet_session_benchmarking::Pallet as SessionBench; + impl cumulus_pallet_session_benchmarking::Config for Runtime {} + + let whitelist: Vec = vec![ + // Block Number + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), + // Total Issuance + hex_literal::hex!("c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80").to_vec().into(), + // Execution Phase + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef7ff553b5a9862a516939d82b3d3d8661a").to_vec().into(), + // Event Count + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef70a98fdbe9ce6c55837576c60c7af3850").to_vec().into(), + // System Events + hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef780d41e5e16056765bc8461851072c9d7").to_vec().into(), + ]; + + let mut batches = Vec::::new(); + let params = (&config, &whitelist); + add_benchmarks!(params, batches); + + if batches.is_empty() { return Err("Benchmark not found for this pallet.".into()) } + Ok(batches) + } + } + + impl pallet_rmrk_rpc_runtime_api::RmrkApi< + Block, + AccountId, + CollectionInfoOf, + InstanceInfoOf, + ResourceInfoOf, + PropertyInfoOf, + BaseInfoOf, + PartTypeOf, + BoundedThemeOf + > for Runtime + { + fn last_collection_idx() -> pallet_rmrk_rpc_runtime_api::Result { + Ok(RmrkCore::collection_index()) + } + + fn collection_by_id(id: CollectionId) -> pallet_rmrk_rpc_runtime_api::Result>> { + Ok(RmrkCore::collections(id)) + } + + fn nft_by_id(collection_id: CollectionId, nft_id: NftId) -> pallet_rmrk_rpc_runtime_api::Result>> { + Ok(RmrkCore::nfts(collection_id, nft_id)) + } + + fn account_tokens(account_id: AccountId, collection_id: CollectionId) -> pallet_rmrk_rpc_runtime_api::Result> { + Ok(Uniques::owned_in_collection(&collection_id, &account_id).collect()) + } + + fn nft_children(collection_id: CollectionId, nft_id: NftId) -> pallet_rmrk_rpc_runtime_api::Result> { + let children = RmrkCore::iterate_nft_children(collection_id, nft_id).collect(); + + Ok(children) + } + + fn collection_properties( + collection_id: CollectionId, + filter_keys: Option> + ) -> pallet_rmrk_rpc_runtime_api::Result>> { + let nft_id = None; + + let filter_keys = option_filter_keys_to_set::<::KeyLimit>( + filter_keys + )?; + + Ok(RmrkCore::query_properties(collection_id, nft_id, filter_keys).collect()) + } + + fn nft_properties( + collection_id: CollectionId, + nft_id: NftId, + filter_keys: Option> + ) -> pallet_rmrk_rpc_runtime_api::Result>> { + let filter_keys = option_filter_keys_to_set::<::KeyLimit>( + filter_keys + )?; + + Ok(RmrkCore::query_properties(collection_id, Some(nft_id), filter_keys).collect()) + } + + fn nft_resources(collection_id: CollectionId, nft_id: NftId) -> pallet_rmrk_rpc_runtime_api::Result>> { + Ok(RmrkCore::iterate_resources(collection_id, nft_id).collect()) + } + + fn nft_resource_priority(collection_id: CollectionId, nft_id: NftId, resource_id: ResourceId) -> pallet_rmrk_rpc_runtime_api::Result> { + let priority = RmrkCore::priorities((collection_id, nft_id, resource_id)); + + Ok(priority) + } + + fn base(base_id: BaseId) -> pallet_rmrk_rpc_runtime_api::Result>> { + Ok(RmrkEquip::bases(base_id)) + } + + fn base_parts(base_id: BaseId) -> pallet_rmrk_rpc_runtime_api::Result>> { + Ok(RmrkEquip::iterate_part_types(base_id).collect()) + } + + fn theme_names(base_id: BaseId) -> pallet_rmrk_rpc_runtime_api::Result> { + let names = RmrkEquip::iterate_theme_names(base_id) + .map(|name| name.into()) + .collect(); + + Ok(names) + } + + fn theme( + base_id: BaseId, + theme_name: pallet_rmrk_rpc_runtime_api::ThemeName, + filter_keys: Option> + ) -> pallet_rmrk_rpc_runtime_api::Result>> { + use pallet_rmrk_equip::StringLimitOf; + + let theme_name: StringLimitOf = theme_name.try_into() + .map_err(|_| DispatchError::Other("Can't read theme_name"))?; + + let filter_keys = option_filter_keys_to_set::<::StringLimit>( + filter_keys + )?; + + let theme = RmrkEquip::get_theme(base_id, theme_name, filter_keys)?; + Ok(theme) + } + } +} + +struct CheckInherents; + +impl cumulus_pallet_parachain_system::CheckInherents for CheckInherents { + fn check_inherents( + block: &Block, + relay_state_proof: &cumulus_pallet_parachain_system::RelayChainStateProof, + ) -> sp_inherents::CheckInherentsResult { + let relay_chain_slot = relay_state_proof + .read_slot() + .expect("Could not read the relay chain slot from the proof"); + + let inherent_data = cumulus_primitives_timestamp::InherentDataProvider::from_relay_chain_slot_and_duration( + relay_chain_slot, + sp_std::time::Duration::from_secs(6), + ) + .create_inherent_data() + .expect("Could not create the timestamp inherent data"); + + inherent_data.check_extrinsics(block) + } +} + +cumulus_pallet_parachain_system::register_validate_block! { + Runtime = Runtime, + BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, + CheckInherents = CheckInherents, +} diff --git a/bin/subzero-dev/runtime/src/weights/block_weights.rs b/bin/subzero-dev/runtime/src/weights/block_weights.rs new file mode 100644 index 0000000000..4db90f0c02 --- /dev/null +++ b/bin/subzero-dev/runtime/src/weights/block_weights.rs @@ -0,0 +1,46 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +pub mod constants { + use frame_support::{ + parameter_types, + weights::{constants, Weight}, + }; + + parameter_types! { + /// Importing a block with 0 Extrinsics. + pub const BlockExecutionWeight: Weight = 5_000_000 * constants::WEIGHT_PER_NANOS; + } + + #[cfg(test)] + mod test_weights { + use frame_support::weights::constants; + + /// Checks that the weight exists and is sane. + // NOTE: If this test fails but you are sure that the generated values are fine, + // you can delete it. + #[test] + fn sane() { + let w = super::constants::BlockExecutionWeight::get(); + + // At least 100 µs. + assert!(w >= 100 * constants::WEIGHT_PER_MICROS, "Weight should be at least 100 µs."); + // At most 50 ms. + assert!(w <= 50 * constants::WEIGHT_PER_MILLIS, "Weight should be at most 50 ms."); + } + } +} diff --git a/bin/subzero-dev/runtime/src/weights/extrinsic_weights.rs b/bin/subzero-dev/runtime/src/weights/extrinsic_weights.rs new file mode 100644 index 0000000000..158ba99c6a --- /dev/null +++ b/bin/subzero-dev/runtime/src/weights/extrinsic_weights.rs @@ -0,0 +1,46 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +pub mod constants { + use frame_support::{ + parameter_types, + weights::{constants, Weight}, + }; + + parameter_types! { + /// Executing a NO-OP `System::remarks` Extrinsic. + pub const ExtrinsicBaseWeight: Weight = 125_000 * constants::WEIGHT_PER_NANOS; + } + + #[cfg(test)] + mod test_weights { + use frame_support::weights::constants; + + /// Checks that the weight exists and is sane. + // NOTE: If this test fails but you are sure that the generated values are fine, + // you can delete it. + #[test] + fn sane() { + let w = super::constants::ExtrinsicBaseWeight::get(); + + // At least 10 µs. + assert!(w >= 10 * constants::WEIGHT_PER_MICROS, "Weight should be at least 10 µs."); + // At most 1 ms. + assert!(w <= constants::WEIGHT_PER_MILLIS, "Weight should be at most 1 ms."); + } + } +} diff --git a/bin/subzero-dev/runtime/src/weights/mod.rs b/bin/subzero-dev/runtime/src/weights/mod.rs new file mode 100644 index 0000000000..ed0b4dbcd4 --- /dev/null +++ b/bin/subzero-dev/runtime/src/weights/mod.rs @@ -0,0 +1,28 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Expose the auto generated weight files. + +pub mod block_weights; +pub mod extrinsic_weights; +pub mod paritydb_weights; +pub mod rocksdb_weights; + +pub use block_weights::constants::BlockExecutionWeight; +pub use extrinsic_weights::constants::ExtrinsicBaseWeight; +pub use paritydb_weights::constants::ParityDbWeight; +pub use rocksdb_weights::constants::RocksDbWeight; diff --git a/bin/subzero-dev/runtime/src/weights/paritydb_weights.rs b/bin/subzero-dev/runtime/src/weights/paritydb_weights.rs new file mode 100644 index 0000000000..843823c1bf --- /dev/null +++ b/bin/subzero-dev/runtime/src/weights/paritydb_weights.rs @@ -0,0 +1,63 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +pub mod constants { + use frame_support::{ + parameter_types, + weights::{constants, RuntimeDbWeight}, + }; + + parameter_types! { + /// `ParityDB` can be enabled with a feature flag, but is still experimental. These weights + /// are available for brave runtime engineers who may want to try this out as default. + pub const ParityDbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 8_000 * constants::WEIGHT_PER_NANOS, + write: 50_000 * constants::WEIGHT_PER_NANOS, + }; + } + + #[cfg(test)] + mod test_db_weights { + use super::constants::ParityDbWeight as W; + use frame_support::weights::constants; + + /// Checks that all weights exist and have sane values. + // NOTE: If this test fails but you are sure that the generated values are fine, + // you can delete it. + #[test] + fn sane() { + // At least 1 µs. + assert!( + W::get().reads(1) >= constants::WEIGHT_PER_MICROS, + "Read weight should be at least 1 µs." + ); + assert!( + W::get().writes(1) >= constants::WEIGHT_PER_MICROS, + "Write weight should be at least 1 µs." + ); + // At most 1 ms. + assert!( + W::get().reads(1) <= constants::WEIGHT_PER_MILLIS, + "Read weight should be at most 1 ms." + ); + assert!( + W::get().writes(1) <= constants::WEIGHT_PER_MILLIS, + "Write weight should be at most 1 ms." + ); + } + } +} diff --git a/bin/subzero-dev/runtime/src/weights/rocksdb_weights.rs b/bin/subzero-dev/runtime/src/weights/rocksdb_weights.rs new file mode 100644 index 0000000000..05e06b0eab --- /dev/null +++ b/bin/subzero-dev/runtime/src/weights/rocksdb_weights.rs @@ -0,0 +1,63 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +pub mod constants { + use frame_support::{ + parameter_types, + weights::{constants, RuntimeDbWeight}, + }; + + parameter_types! { + /// By default, Substrate uses `RocksDB`, so this will be the weight used throughout + /// the runtime. + pub const RocksDbWeight: RuntimeDbWeight = RuntimeDbWeight { + read: 25_000 * constants::WEIGHT_PER_NANOS, + write: 100_000 * constants::WEIGHT_PER_NANOS, + }; + } + + #[cfg(test)] + mod test_db_weights { + use super::constants::RocksDbWeight as W; + use frame_support::weights::constants; + + /// Checks that all weights exist and have sane values. + // NOTE: If this test fails but you are sure that the generated values are fine, + // you can delete it. + #[test] + fn sane() { + // At least 1 µs. + assert!( + W::get().reads(1) >= constants::WEIGHT_PER_MICROS, + "Read weight should be at least 1 µs." + ); + assert!( + W::get().writes(1) >= constants::WEIGHT_PER_MICROS, + "Write weight should be at least 1 µs." + ); + // At most 1 ms. + assert!( + W::get().reads(1) <= constants::WEIGHT_PER_MILLIS, + "Read weight should be at most 1 ms." + ); + assert!( + W::get().writes(1) <= constants::WEIGHT_PER_MILLIS, + "Write weight should be at most 1 ms." + ); + } + } +} diff --git a/bin/subzero-dev/runtime/src/xcm_config.rs b/bin/subzero-dev/runtime/src/xcm_config.rs new file mode 100644 index 0000000000..a7e373b320 --- /dev/null +++ b/bin/subzero-dev/runtime/src/xcm_config.rs @@ -0,0 +1,368 @@ +use super::{ + constants::{fee::*, parachains}, + AccountId, AssetRegistry, Balance, Call, Convert, + CurrencyId::{self, ForeignAsset}, Currencies, + EnsureRootOrHalfCouncil, EnsureRootOrThreeFourthsCouncil, + Event, Origin, ParachainInfo, ParachainSystem, PolkadotXcm, + Runtime, TreasuryAccountId, UnknownTokens, XcmpQueue, + ZERO, PLAY, GAME, DOT, +}; +use codec::{Decode, Encode}; +use cumulus_primitives_core::ParaId; +use frame_support::{ + match_types, + parameter_types, + traits::{Everything, Get, Nothing}, + weights::Weight, +}; +use sp_runtime::{ + traits::ConstU32, + WeakBoundedVec +}; +use pallet_xcm::XcmPassthrough; +use polkadot_parachain::primitives::Sibling; +use xcm::latest::prelude::*; +use xcm_builder::{ + AccountId32Aliases, AllowKnownQueryResponses, AllowTopLevelPaidExecutionFrom, + AllowSubscriptionsFrom, AllowUnpaidExecutionFrom, EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, + LocationInverter, NativeAsset, ParentIsPreset, RelayChainAsNative, + SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, TakeRevenue, TakeWeightCredit, +}; +use xcm_executor::XcmExecutor; +use orml_asset_registry::{AssetRegistryTrader, FixedRateAssetRegistryTrader}; +use orml_traits::{location::AbsoluteReserveProvider, FixedConversionRateProvider, MultiCurrency, parameter_type_with_key}; +use orml_xcm_support::{DepositToAlternative, IsNativeConcrete, MultiCurrencyAdapter, MultiNativeAsset}; + + +parameter_types! { + pub const DotLocation: MultiLocation = MultiLocation::parent(); + pub const RelayNetwork: NetworkId = NetworkId::Polkadot; + pub RelayChainOrigin: Origin = cumulus_pallet_xcm::Origin::Relay.into(); + pub Ancestry: MultiLocation = Parachain(ParachainInfo::parachain_id().into()).into(); +} + +/// Type for specifying how a `MultiLocation` can be converted into an `AccountId`. This is used +/// when determining ownership of accounts for asset transacting and when attempting to use XCM +/// `Transact` in order to determine the dispatch Origin. +pub type LocationToAccountId = ( + // The parent (Relay-chain) origin converts to the default `AccountId`. + ParentIsPreset, + // Sibling parachain origins convert to AccountId via the `ParaId::into`. + SiblingParachainConvertsVia, + // Straight up local `AccountId32` origins just alias directly to `AccountId`. + AccountId32Aliases, +); + +/// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, +/// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can +/// biases the kind of local `Origin` it will become. +pub type XcmOriginToCallOrigin = ( + // Sovereign account converter; this attempts to derive an `AccountId` from the origin location + // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for + // foreign chains who want to have a local sovereign account on this chain which they control. + SovereignSignedViaLocation, + // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when + // recognized. + RelayChainAsNative, + // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when + // recognized. + SiblingParachainAsNative, + // Native signed account converter; this just converts an `AccountId32` origin into a normal + // `Origin::Signed` origin of the same 32-byte value. + SignedAccountId32AsNative, + // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. + XcmPassthrough, +); + +match_types! { + pub type ParentOrParentsExecutivePlurality: impl Contains = { + MultiLocation { parents: 1, interior: Here } | + MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Executive, .. }) } + }; +} + +match_types! { + pub type SpecParachain: impl Contains = { + MultiLocation { parents: 1, interior: X1(Parachain(parachains::acala::ID)) } + }; +} + +pub type Barrier = ( + TakeWeightCredit, + AllowTopLevelPaidExecutionFrom, + AllowKnownQueryResponses, + AllowUnpaidExecutionFrom, + AllowUnpaidExecutionFrom, + AllowSubscriptionsFrom +); + +// todo: move this to common runtimes module +pub fn local_currency_location(key: CurrencyId) -> MultiLocation { + MultiLocation::new( + 0, + X1(GeneralKey(WeakBoundedVec::>::force_from( + key.encode(), + None, + ))), + ) +} + +parameter_types! { + pub UnitWeightCost: Weight = 200_000_000; + pub const MaxInstructions: u32 = 100; + pub DotPerSecond: (AssetId, u128) = ( + MultiLocation::parent().into(), + dot_per_second() + ); + pub ZeroPerSecond: (AssetId, u128) = ( + local_currency_location(ZERO).into(), + zero_per_second() + ); + pub PlayPerSecond: (AssetId, u128) = ( + local_currency_location(PLAY).into(), + play_per_second() + ); + pub GamePerSecond: (AssetId, u128) = ( + local_currency_location(GAME).into(), + game_per_second() + ); +} + +pub struct ToAuthor; +impl TakeRevenue for ToAuthor { + fn take_revenue(revenue: MultiAsset) { + if let MultiAsset { + id: Concrete(location), + fun: Fungible(amount), + } = revenue + { + if let Some(currency_id) = CurrencyIdConvert::convert(location) { + if let Some(author) = pallet_authorship::Pallet::::author() { + let _ = Currencies::deposit(currency_id, &author, amount); + } else { + let _ = Currencies::deposit(currency_id, &TreasuryAccountId::get(), amount); + } + } + } + } +} + +pub struct ChainFixedConversionRateProvider; +impl FixedConversionRateProvider for ChainFixedConversionRateProvider { + fn get_fee_per_second(location: &MultiLocation) -> Option { + let metadata = AssetRegistry::fetch_metadata_by_location(location)?; + Some(metadata.additional.fee_per_second) + } +} + +pub type Trader = ( + FixedRateOfFungible, + FixedRateOfFungible, + FixedRateOfFungible, + FixedRateOfFungible, + AssetRegistryTrader, ToAuthor>, +); + +pub struct XcmConfig; +impl xcm_executor::Config for XcmConfig { + type Call = Call; + type XcmSender = XcmRouter; + // How to withdraw and deposit an asset. + type AssetTransactor = LocalAssetTransactor; + type OriginConverter = XcmOriginToCallOrigin; + type IsReserve = MultiNativeAsset; + type IsTeleporter = NativeAsset; + type LocationInverter = LocationInverter; + type Barrier = Barrier; + type Weigher = FixedWeightBounds; + type Trader = Trader; + type ResponseHandler = PolkadotXcm; + type AssetTrap = PolkadotXcm; + type AssetClaims = PolkadotXcm; + type SubscriptionService = PolkadotXcm; +} + +/// No local origins on this chain are allowed to dispatch XCM sends/executions. +pub type LocalOriginToLocation = (SignedToAccountId32,); + +/// The means for routing XCM messages which are not for local execution into the right message +/// queues. +pub type XcmRouter = ( + // Two routers - use UMP to communicate with the relay chain: + cumulus_primitives_utility::ParentAsUmp, + // ..and XCMP to communicate with the sibling chains. + XcmpQueue, +); + +impl pallet_xcm::Config for Runtime { + type Event = Event; + type Call = Call; + type Origin = Origin; + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = EnsureXcmOrigin; + type XcmExecuteFilter = Nothing; + type XcmExecutor = XcmExecutor; + type XcmTeleportFilter = Everything; + type XcmReserveTransferFilter = Everything; + type Weigher = FixedWeightBounds; + type LocationInverter = LocationInverter; + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; + const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; +} + +impl cumulus_pallet_xcm::Config for Runtime { + type Event = Event; + type XcmExecutor = XcmExecutor; +} + +impl cumulus_pallet_xcmp_queue::Config for Runtime { + type Event = Event; + type XcmExecutor = XcmExecutor; + type ChannelInfo = ParachainSystem; + type VersionWrapper = PolkadotXcm; + type ExecuteOverweightOrigin = EnsureRootOrHalfCouncil; + type ControllerOrigin = EnsureRootOrHalfCouncil; + type ControllerOriginConverter = XcmOriginToCallOrigin; + type WeightInfo = (); +} + +impl cumulus_pallet_dmp_queue::Config for Runtime { + type Event = Event; + type XcmExecutor = XcmExecutor; + type ExecuteOverweightOrigin = EnsureRootOrHalfCouncil; +} + +pub type LocalAssetTransactor = MultiCurrencyAdapter< + Currencies, + UnknownTokens, + IsNativeConcrete, + AccountId, + LocationToAccountId, + CurrencyId, + CurrencyIdConvert, + DepositToAlternative, +>; + +pub fn native_currency_location(para_id: u32, id: CurrencyId) -> MultiLocation { + MultiLocation::new( + 1, + X2( + Parachain(para_id), GeneralKey( + WeakBoundedVec::>::force_from(id.encode(), None) + ) + ) + ) +} + +pub struct CurrencyIdConvert; +impl Convert> for CurrencyIdConvert { + fn convert(id: CurrencyId) -> Option { + match id { + DOT => Some(MultiLocation::parent()), + ZERO | GAME | PLAY + => Some(native_currency_location(ParachainInfo::get().into(), id)), + ForeignAsset(id) + => AssetRegistry::multilocation(&id).unwrap_or_default(), + } + } +} +impl Convert> for CurrencyIdConvert { + fn convert(location: MultiLocation) -> Option { + + fn decode_currency_id(key: WeakBoundedVec::>) -> Option { + let key = &key.into_inner()[..]; + if let Ok(currency_id) = CurrencyId::decode(&mut &*key) { + // check `currency_id` is cross-chain asset + match currency_id { + ZERO | GAME | PLAY => Some(currency_id), + _ => None, + } + } else { + None + } + } + + match location.clone() { + x if x == MultiLocation::parent() => Some(DOT), + MultiLocation { + parents: 1, + interior: X2(Parachain(id), GeneralKey(key)), + } if ParaId::from(id) == ParachainInfo::get() => decode_currency_id(key), + MultiLocation { + parents: 0, + interior: X1(GeneralKey(key)), + } => decode_currency_id(key), + _ => None, + } + .or_else(|| AssetRegistry::location_to_asset_id(&location) + .map(|id| CurrencyId::ForeignAsset(id))) + } +} +impl Convert> for CurrencyIdConvert { + fn convert(asset: MultiAsset) -> Option { + if let MultiAsset { + id: Concrete(location), .. + } = asset + { + Self::convert(location) + } else { + None + } + } +} + +parameter_types! { + pub SelfLocation: MultiLocation = MultiLocation::new(1, X1(Parachain(ParachainInfo::get().into()))); +} + +pub struct AccountIdToMultiLocation; +impl Convert for AccountIdToMultiLocation { + fn convert(account: AccountId) -> MultiLocation { + X1(AccountId32 { + network: NetworkId::Any, + id: account.into(), + }) + .into() + } +} + +parameter_types! { + pub const MaxAssetsForTransfer: usize = 2; +} + +parameter_type_with_key! { + pub ParachainMinFee: |location: MultiLocation| -> Option { + match (location.parents, location.first_interior()) { + (1, Some(Parachain(parachains::acala::ID))) => Some(200_000_000), + _ => None, + } + }; +} + +impl orml_xtokens::Config for Runtime { + type Event = Event; + type Balance = Balance; + type CurrencyId = CurrencyId; + type CurrencyIdConvert = CurrencyIdConvert; + type AccountIdToMultiLocation = AccountIdToMultiLocation; + type SelfLocation = SelfLocation; + type XcmExecutor = XcmExecutor; + type Weigher = FixedWeightBounds; + type BaseXcmWeight = UnitWeightCost; + type LocationInverter = ::LocationInverter; + type MaxAssetsForTransfer = MaxAssetsForTransfer; + type MinXcmFee = ParachainMinFee; + type MultiLocationsFilter = Everything; + type ReserveProvider = AbsoluteReserveProvider; +} + +impl orml_unknown_tokens::Config for Runtime { + type Event = Event; +} + +impl orml_xcm::Config for Runtime { + type Event = Event; + type SovereignOrigin = EnsureRootOrThreeFourthsCouncil; +}