diff --git a/Cargo.lock b/Cargo.lock index 422504b..7f04a0d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2191,6 +2191,66 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "devnet-runtime" +version = "0.1.0" +dependencies = [ + "cumulus-pallet-aura-ext", + "cumulus-pallet-dmp-queue", + "cumulus-pallet-parachain-system", + "cumulus-pallet-session-benchmarking", + "cumulus-pallet-xcm", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-core", + "cumulus-primitives-timestamp", + "cumulus-primitives-utility", + "frame-benchmarking", + "frame-executive", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "frame-try-runtime", + "hex-literal", + "log", + "pallet-assets", + "pallet-aura", + "pallet-authorship", + "pallet-balances", + "pallet-collator-selection", + "pallet-collective", + "pallet-motion", + "pallet-session", + "pallet-sudo", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "pallet-utility", + "pallet-xcm", + "parachain-info", + "parity-scale-codec", + "polkadot-parachain", + "polkadot-runtime-common", + "runtime-common", + "scale-info", + "smallvec", + "sp-api", + "sp-block-builder", + "sp-consensus-aura", + "sp-core", + "sp-inherents", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-std", + "sp-transaction-pool", + "sp-version", + "substrate-wasm-builder", + "xcm", + "xcm-builder", + "xcm-executor", +] + [[package]] name = "difflib" version = "0.4.0" @@ -3333,9 +3393,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "globset" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1391ab1f92ffcc08911957149833e682aa3fe252b9f45f966d2ef972274c97df" +checksum = "aca8bbd8e0707c1887a8bbb7e6b40e228f251ff5d62c8220a4a7a53c73aff006" dependencies = [ "aho-corasick", "bstr", @@ -4759,9 +4819,9 @@ dependencies = [ [[package]] name = "libz-sys" -version = "1.1.10" +version = "1.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24e6ab01971eb092ffe6a7d42f49f9ff42662f17604681e2843ad65077ba47dc" +checksum = "d97137b25e321a73eef1418d1d5d2eda4d77e12813f8e6dead84bc52c5870a7b" dependencies = [ "cc", "pkg-config", @@ -4891,6 +4951,66 @@ dependencies = [ "libc", ] +[[package]] +name = "mainnet-runtime" +version = "0.1.0" +dependencies = [ + "cumulus-pallet-aura-ext", + "cumulus-pallet-dmp-queue", + "cumulus-pallet-parachain-system", + "cumulus-pallet-session-benchmarking", + "cumulus-pallet-xcm", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-core", + "cumulus-primitives-timestamp", + "cumulus-primitives-utility", + "frame-benchmarking", + "frame-executive", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "frame-try-runtime", + "hex-literal", + "log", + "pallet-assets", + "pallet-aura", + "pallet-authorship", + "pallet-balances", + "pallet-collator-selection", + "pallet-collective", + "pallet-motion", + "pallet-session", + "pallet-sudo", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "pallet-utility", + "pallet-xcm", + "parachain-info", + "parity-scale-codec", + "polkadot-parachain", + "polkadot-runtime-common", + "runtime-common", + "scale-info", + "smallvec", + "sp-api", + "sp-block-builder", + "sp-consensus-aura", + "sp-core", + "sp-inherents", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-std", + "sp-transaction-pool", + "sp-version", + "substrate-wasm-builder", + "xcm", + "xcm-builder", + "xcm-executor", +] + [[package]] name = "maplit" version = "1.0.2" @@ -6626,16 +6746,18 @@ dependencies = [ "cumulus-relay-chain-interface", "cumulus-relay-chain-minimal-node", "cumulus-relay-chain-rpc-interface", + "devnet-runtime", "frame-benchmarking", "frame-benchmarking-cli", "jsonrpsee", "log", + "mainnet-runtime", "pallet-transaction-payment-rpc", - "parachain-template-runtime", "parity-scale-codec", "polkadot-cli", "polkadot-primitives", "polkadot-service", + "runtime-common", "sc-basic-authorship", "sc-chain-spec", "sc-cli", @@ -6661,6 +6783,7 @@ dependencies = [ "sp-keystore", "sp-offchain", "sp-runtime", + "sp-serializer", "sp-session", "sp-timestamp", "sp-transaction-pool", @@ -6671,66 +6794,6 @@ dependencies = [ "xcm", ] -[[package]] -name = "parachain-template-runtime" -version = "0.1.0" -dependencies = [ - "cumulus-pallet-aura-ext", - "cumulus-pallet-dmp-queue", - "cumulus-pallet-parachain-system", - "cumulus-pallet-session-benchmarking", - "cumulus-pallet-xcm", - "cumulus-pallet-xcmp-queue", - "cumulus-primitives-core", - "cumulus-primitives-timestamp", - "cumulus-primitives-utility", - "frame-benchmarking", - "frame-executive", - "frame-support", - "frame-system", - "frame-system-benchmarking", - "frame-system-rpc-runtime-api", - "frame-try-runtime", - "hex-literal", - "log", - "pallet-assets", - "pallet-aura", - "pallet-authorship", - "pallet-balances", - "pallet-collator-selection", - "pallet-collective", - "pallet-motion", - "pallet-session", - "pallet-sudo", - "pallet-timestamp", - "pallet-transaction-payment", - "pallet-transaction-payment-rpc-runtime-api", - "pallet-utility", - "pallet-xcm", - "parachain-info", - "parachains-common", - "parity-scale-codec", - "polkadot-parachain", - "polkadot-runtime-common", - "scale-info", - "smallvec", - "sp-api", - "sp-block-builder", - "sp-consensus-aura", - "sp-core", - "sp-inherents", - "sp-offchain", - "sp-runtime", - "sp-session", - "sp-std", - "sp-transaction-pool", - "sp-version", - "substrate-wasm-builder", - "xcm", - "xcm-builder", - "xcm-executor", -] - [[package]] name = "parachains-common" version = "1.0.0" @@ -9064,6 +9127,19 @@ dependencies = [ "webrtc-util", ] +[[package]] +name = "runtime-common" +version = "1.0.0" +dependencies = [ + "frame-support", + "parachains-common", + "parity-scale-codec", + "polkadot-primitives", + "scale-info", + "sp-runtime", + "sp-std", +] + [[package]] name = "rustc-demangle" version = "0.1.23" @@ -10579,18 +10655,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.175" +version = "1.0.176" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d25439cd7397d044e2748a6fe2432b5e85db703d6d097bd014b3c0ad1ebff0b" +checksum = "76dc28c9523c5d70816e393136b86d48909cfb27cecaa902d338c19ed47164dc" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.175" +version = "1.0.176" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b23f7ade6f110613c0d63858ddb8b94c1041f550eab58a16b371bdf2c9c80ab4" +checksum = "a4e7b8c5dc823e3b90651ff1d3808419cd14e5ad76de04feaf37da114e7a306f" dependencies = [ "proc-macro2", "quote", @@ -10599,9 +10675,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.103" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d03b412469450d4404fe8499a268edd7f8b79fecb074b0d812ad64ca21f4031b" +checksum = "076066c5f1078eac5b722a31827a8832fe108bed65dfa75e233c89f8206e976c" dependencies = [ "itoa", "ryu", @@ -11358,6 +11434,15 @@ dependencies = [ "syn 2.0.27", ] +[[package]] +name = "sp-serializer" +version = "4.0.0-dev" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-v0.9.42#ff24c60ac7d9f87727ecdd0ded9a80c56e4f4b65" +dependencies = [ + "serde", + "serde_json", +] + [[package]] name = "sp-session" version = "4.0.0-dev" diff --git a/Cargo.toml b/Cargo.toml index f95719d..cda3590 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,8 @@ panic = "unwind" [workspace] members = [ - "node", - "pallets/*", - "runtime", + "node", + "pallets/*", + "runtime/mainnet", + "runtime/devnet", ] diff --git a/node/Cargo.toml b/node/Cargo.toml index 4b581ed..bc1e6cb 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -18,7 +18,9 @@ serde = {version = "1.0.160", features = ["derive"]} color-print = "0.3.4" # Local -parachain-template-runtime = {path = "../runtime"} +devnet-runtime = {path = "../runtime/devnet"} +mainnet-runtime = {path = "../runtime/mainnet"} +runtime-common = {path = "../runtime/common"} # Substrate frame-benchmarking = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42"} @@ -49,6 +51,7 @@ sp-keystore = {git = "https://github.com/paritytech/substrate", branch = "polkad sp-offchain = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42"} sp-runtime = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42"} sp-session = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42"} +sp-serializer = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42"} sp-timestamp = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42"} sp-transaction-pool = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42"} substrate-frame-rpc-system = {git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.42"} @@ -80,11 +83,13 @@ substrate-build-script-utils = {git = "https://github.com/paritytech/substrate", default = [] runtime-benchmarks = [ "try-runtime-cli/try-runtime", - "parachain-template-runtime/runtime-benchmarks", + "mainnet-runtime/runtime-benchmarks", + "devnet-runtime/runtime-benchmarks", "polkadot-cli/runtime-benchmarks", ] try-runtime = [ "try-runtime-cli/try-runtime", - "parachain-template-runtime/try-runtime", + "mainnet-runtime/try-runtime", + "devnet-runtime/try-runtime", "dep:sp-io", ] diff --git a/node/src/chain_spec.rs b/node/src/chain_spec.rs index 5ebc717..8389b04 100644 --- a/node/src/chain_spec.rs +++ b/node/src/chain_spec.rs @@ -1,5 +1,5 @@ use cumulus_primitives_core::ParaId; -use parachain_template_runtime::{AccountId, AuraId, Signature, EXISTENTIAL_DEPOSIT}; +use runtime_common::{AccountId, AuraId, Signature}; use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup}; use sc_service::ChainType; use serde::{Deserialize, Serialize}; @@ -7,12 +7,16 @@ use sp_core::{sr25519, Pair, Public}; use sp_runtime::traits::{IdentifyAccount, Verify}; /// Specialized `ChainSpec` for the normal parachain runtime. -pub type ChainSpec = - sc_service::GenericChainSpec; +pub type MainChainSpec = sc_service::GenericChainSpec; + +/// Specialized `ChainSpec` for the development parachain runtime. +pub type DevnetChainSpec = sc_service::GenericChainSpec; /// The default XCM version to set in genesis config. const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION; +const 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) @@ -57,190 +61,394 @@ where /// 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 template_session_keys(keys: AuraId) -> parachain_template_runtime::SessionKeys { - parachain_template_runtime::SessionKeys { aura: keys } +pub fn mainnet_session_keys(keys: AuraId) -> mainnet_runtime::SessionKeys { + mainnet_runtime::SessionKeys { aura: keys } +} + +pub fn devnet_session_keys(keys: AuraId) -> devnet_runtime::SessionKeys { + devnet_runtime::SessionKeys { aura: keys } } -pub fn development_config() -> ChainSpec { - // Give your base currency a unit name and decimal places - let mut properties = sc_chain_spec::Properties::new(); - properties.insert("tokenSymbol".into(), "UNIT".into()); - properties.insert("tokenDecimals".into(), 12.into()); - properties.insert("ss58Format".into(), 42.into()); - - ChainSpec::from_genesis( - // Name - "Development", - // ID - "dev", - ChainType::Development, - move || { - testnet_genesis( - // initial collators. - vec![ - ( +pub mod devnet { + use super::*; + pub fn development_config() -> DevnetChainSpec { + // Give your base currency a unit name and decimal places + let mut properties = sc_chain_spec::Properties::new(); + properties.insert("tokenSymbol".into(), "DEV".into()); + properties.insert("tokenDecimals".into(), 12.into()); + properties.insert("ss58Format".into(), 42.into()); + + DevnetChainSpec::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"), + ], + Some(get_account_id_from_seed::("Alice")), + PARA_ID.into(), + ) + }, + Vec::new(), + None, + None, + None, + None, + Extensions { + relay_chain: "rococo-local".into(), // You MUST set this to the correct network! + para_id: PARA_ID, + }, + ) + } + + pub fn local_testnet_config() -> DevnetChainSpec { + // Give your base currency a unit name and decimal places + let mut properties = sc_chain_spec::Properties::new(); + properties.insert("tokenSymbol".into(), "UNIT".into()); + properties.insert("tokenDecimals".into(), 12.into()); + properties.insert("ss58Format".into(), 42.into()); + + DevnetChainSpec::from_genesis( + // Name + "Development Local Testnet", + // ID + "dev_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_collator_keys_from_seed("Alice"), - ), - ( get_account_id_from_seed::("Bob"), - get_collator_keys_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"), + ], + Some(get_account_id_from_seed::("Alice")), + PARA_ID.into(), + ) + }, + // Bootnodes + Vec::new(), + // Telemetry + None, + // Protocol ID + Some("devnet-local"), + // Fork ID + None, + // Properties + Some(properties), + // Extensions + Extensions { + relay_chain: "rococo-local".into(), // You MUST set this to the correct network! + para_id: PARA_ID, + }, + ) + } + + fn testnet_genesis( + invulnerables: Vec<(AccountId, AuraId)>, + endowed_accounts: Vec, + root_key: Option, + id: ParaId, + ) -> devnet_runtime::GenesisConfig { + use devnet_runtime::EXISTENTIAL_DEPOSIT; + let alice = get_from_seed::("Alice"); + let bob = get_from_seed::("Bob"); + + devnet_runtime::GenesisConfig { + system: devnet_runtime::SystemConfig { + code: devnet_runtime::WASM_BINARY + .expect("WASM binary was not build, please build it!") + .to_vec(), + }, + balances: devnet_runtime::BalancesConfig { + balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), + }, + // Configure two assets ALT1 & ALT2 with two owners, alice and bob respectively + assets: devnet_runtime::AssetsConfig { + assets: vec![ + (1, alice.into(), true, 100_000_000_000), + (2, bob.into(), true, 100_000_000_000), + ], + // Genesis metadata: Vec<(id, name, symbol, decimals)> + metadata: vec![ + (1, "asset-1".into(), "ALT1".into(), 10), + (2, "asset-2".into(), "ALT2".into(), 10), ], - 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"), + // Genesis accounts: Vec<(id, account_id, balance)> + accounts: vec![ + (1, alice.into(), 500_000_000_000), + (2, bob.into(), 500_000_000_000), ], - Some(get_account_id_from_seed::("Alice")), - 1000.into(), - ) - }, - Vec::new(), - None, - None, - None, - None, - Extensions { - relay_chain: "rococo-local".into(), // You MUST set this to the correct network! - para_id: 1000, - }, - ) + }, + parachain_info: devnet_runtime::ParachainInfoConfig { parachain_id: id }, + collator_selection: devnet_runtime::CollatorSelectionConfig { + invulnerables: invulnerables.iter().cloned().map(|(acc, _)| acc).collect(), + candidacy_bond: EXISTENTIAL_DEPOSIT * 16, + ..Default::default() + }, + session: devnet_runtime::SessionConfig { + keys: invulnerables + .into_iter() + .map(|(acc, aura)| { + ( + acc.clone(), // account id + acc, // validator id + devnet_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(), + sudo: devnet_runtime::SudoConfig { key: root_key }, + council: devnet_runtime::CouncilConfig { + phantom: std::marker::PhantomData, + members: endowed_accounts.iter().take(4).cloned().collect(), + }, + parachain_system: Default::default(), + polkadot_xcm: devnet_runtime::PolkadotXcmConfig { + safe_xcm_version: Some(SAFE_XCM_VERSION), + }, + transaction_payment: Default::default(), + } + } } -pub fn local_testnet_config() -> ChainSpec { - // Give your base currency a unit name and decimal places - let mut properties = sc_chain_spec::Properties::new(); - properties.insert("tokenSymbol".into(), "UNIT".into()); - properties.insert("tokenDecimals".into(), 12.into()); - properties.insert("ss58Format".into(), 42.into()); - - ChainSpec::from_genesis( - // Name - "Local Testnet", - // ID - "local_testnet", - ChainType::Local, - move || { - testnet_genesis( - // initial collators. - vec![ - ( +pub mod mainnet { + use super::*; + pub fn development_config() -> MainChainSpec { + // Give your base currency a unit name and decimal places + let mut properties = sc_chain_spec::Properties::new(); + properties.insert("tokenSymbol".into(), "UNIT".into()); + properties.insert("tokenDecimals".into(), 12.into()); + properties.insert("ss58Format".into(), 42.into()); + + MainChainSpec::from_genesis( + // Name + "Mainnet Development", + // ID + "main_dev", + ChainType::Development, + move || { + mainnet_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"), + ], + Some(get_account_id_from_seed::("Alice")), + PARA_ID.into(), + ) + }, + Vec::new(), + None, + None, + None, + None, + Extensions { + relay_chain: "rococo-local".into(), // You MUST set this to the correct network! + para_id: PARA_ID, + }, + ) + } + + pub fn local_testnet_config() -> MainChainSpec { + // Give your base currency a unit name and decimal places + let mut properties = sc_chain_spec::Properties::new(); + properties.insert("tokenSymbol".into(), "UNIT".into()); + properties.insert("tokenDecimals".into(), 12.into()); + properties.insert("ss58Format".into(), 42.into()); + + MainChainSpec::from_genesis( + // Name + "Mainnet Local Testnet", + // ID + "main_local_testnet", + ChainType::Local, + move || { + mainnet_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_collator_keys_from_seed("Alice"), - ), - ( get_account_id_from_seed::("Bob"), - get_collator_keys_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"), + ], + Some(get_account_id_from_seed::("Alice")), + PARA_ID.into(), + ) + }, + // Bootnodes + Vec::new(), + // Telemetry + None, + // Protocol ID + Some("mainnet-local"), + // Fork ID + None, + // Properties + Some(properties), + // Extensions + Extensions { + relay_chain: "rococo-local".into(), // You MUST set this to the correct network! + para_id: PARA_ID, + }, + ) + } + + fn mainnet_genesis( + invulnerables: Vec<(AccountId, AuraId)>, + endowed_accounts: Vec, + root_key: Option, + id: ParaId, + ) -> mainnet_runtime::GenesisConfig { + use mainnet_runtime::EXISTENTIAL_DEPOSIT; + let alice = get_from_seed::("Alice"); + let bob = get_from_seed::("Bob"); + + mainnet_runtime::GenesisConfig { + system: mainnet_runtime::SystemConfig { + code: mainnet_runtime::WASM_BINARY + .expect("WASM binary was not build, please build it!") + .to_vec(), + }, + balances: mainnet_runtime::BalancesConfig { + balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), + }, + // Configure two assets ALT1 & ALT2 with two owners, alice and bob respectively + assets: mainnet_runtime::AssetsConfig { + assets: vec![ + (1, alice.into(), true, 100_000_000_000), + (2, bob.into(), true, 100_000_000_000), ], - 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"), + // Genesis metadata: Vec<(id, name, symbol, decimals)> + metadata: vec![ + (1, "asset-1".into(), "ALT1".into(), 10), + (2, "asset-2".into(), "ALT2".into(), 10), ], - Some(get_account_id_from_seed::("Alice")), - 2000.into(), - ) - }, - // Bootnodes - Vec::new(), - // Telemetry - None, - // Protocol ID - Some("template-local"), - // Fork ID - None, - // Properties - Some(properties), - // Extensions - Extensions { - relay_chain: "rococo-local".into(), // You MUST set this to the correct network! - para_id: 2000, - }, - ) -} - -fn testnet_genesis( - invulnerables: Vec<(AccountId, AuraId)>, - endowed_accounts: Vec, - root_key: Option, - id: ParaId, -) -> parachain_template_runtime::GenesisConfig { - let alice = get_from_seed::("Alice"); - let bob = get_from_seed::("Bob"); - parachain_template_runtime::GenesisConfig { - system: parachain_template_runtime::SystemConfig { - code: parachain_template_runtime::WASM_BINARY - .expect("WASM binary was not build, please build it!") - .to_vec(), - }, - balances: parachain_template_runtime::BalancesConfig { - balances: endowed_accounts.iter().cloned().map(|k| (k, 1 << 60)).collect(), - }, - // Configure two assets ALT1 & ALT2 with two owners, alice and bob respectively - assets: parachain_template_runtime::AssetsConfig { - assets: vec![ - (1, alice.into(), true, 100_000_000_000), - (2, bob.into(), true, 100_000_000_000), - ], - // Genesis metadata: Vec<(id, name, symbol, decimals)> - metadata: vec![ - (1, "asset-1".into(), "ALT1".into(), 10), - (2, "asset-2".into(), "ALT2".into(), 10), - ], - // Genesis accounts: Vec<(id, account_id, balance)> - accounts: vec![(1, alice.into(), 500_000_000_000), (2, bob.into(), 500_000_000_000)], - }, - parachain_info: parachain_template_runtime::ParachainInfoConfig { parachain_id: id }, - collator_selection: parachain_template_runtime::CollatorSelectionConfig { - invulnerables: invulnerables.iter().cloned().map(|(acc, _)| acc).collect(), - candidacy_bond: EXISTENTIAL_DEPOSIT * 16, - ..Default::default() - }, - session: parachain_template_runtime::SessionConfig { - keys: invulnerables - .into_iter() - .map(|(acc, aura)| { - ( - acc.clone(), // account id - acc, // validator id - template_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(), - sudo: parachain_template_runtime::SudoConfig { key: root_key }, - council: parachain_template_runtime::CouncilConfig { - phantom: std::marker::PhantomData, - members: endowed_accounts.iter().take(4).map(|acc| acc.clone()).collect::>(), - }, - parachain_system: Default::default(), - polkadot_xcm: parachain_template_runtime::PolkadotXcmConfig { - safe_xcm_version: Some(SAFE_XCM_VERSION), - }, - transaction_payment: Default::default(), + // Genesis accounts: Vec<(id, account_id, balance)> + accounts: vec![ + (1, alice.into(), 500_000_000_000), + (2, bob.into(), 500_000_000_000), + ], + }, + parachain_info: mainnet_runtime::ParachainInfoConfig { parachain_id: id }, + collator_selection: mainnet_runtime::CollatorSelectionConfig { + invulnerables: invulnerables.iter().cloned().map(|(acc, _)| acc).collect(), + candidacy_bond: EXISTENTIAL_DEPOSIT * 16, + ..Default::default() + }, + session: mainnet_runtime::SessionConfig { + keys: invulnerables + .into_iter() + .map(|(acc, aura)| { + ( + acc.clone(), // account id + acc, // validator id + mainnet_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(), + sudo: mainnet_runtime::SudoConfig { key: root_key }, + council: mainnet_runtime::CouncilConfig { + phantom: std::marker::PhantomData, + members: endowed_accounts.iter().take(4).cloned().collect(), + }, + parachain_system: Default::default(), + polkadot_xcm: mainnet_runtime::PolkadotXcmConfig { + safe_xcm_version: Some(SAFE_XCM_VERSION), + }, + transaction_payment: Default::default(), + } } } diff --git a/node/src/cli.rs b/node/src/cli.rs index 14d5e20..5abd25a 100644 --- a/node/src/cli.rs +++ b/node/src/cli.rs @@ -2,6 +2,7 @@ use std::path::PathBuf; /// Sub-commands supported by the collator. #[derive(Debug, clap::Subcommand)] +#[allow(clippy::large_enum_variant)] pub enum Subcommand { /// Build a chain specification. BuildSpec(sc_cli::BuildSpecCmd), diff --git a/node/src/command.rs b/node/src/command.rs index 5698745..33ca2af 100644 --- a/node/src/command.rs +++ b/node/src/command.rs @@ -1,11 +1,11 @@ -use std::net::SocketAddr; +use std::{net::SocketAddr, path::PathBuf}; 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, warn}; -use parachain_template_runtime::Block; +use runtime_common::Block; use sc_cli::{ ChainSpec, CliConfiguration, DefaultConfigurationValues, ImportParams, KeystoreParams, NetworkParams, Result, RuntimeVersion, SharedParams, SubstrateCli, @@ -17,15 +17,73 @@ use sp_runtime::traits::{AccountIdConversion, Block as BlockT}; use crate::{ chain_spec, cli::{Cli, RelayChainCli, Subcommand}, - service::{new_partial, ParachainNativeExecutor}, + service::{new_partial, DevnetRuntimeExecutor, MainnetRuntimeExecutor}, }; +/// Helper enum that is used for better distinction of different parachain/runtime configuration +/// (it is based/calculated on ChainSpec's 'chain_spec' attribute) +#[derive(Debug, PartialEq, Default)] +enum Runtime { + /// This is the default runtime (actually based on rococo) + #[default] + Default, + Devnet, + Mainnet, +} + +trait RuntimeResolver { + fn runtime(&self) -> Runtime; +} +/// Private helper that pattern matches on the input (which is expected to be a ChainSpec ID) +/// and returns the Runtime accordingly. +fn runtime(id: &str) -> Runtime { + if id.starts_with("dev") { + Runtime::Devnet + } else if id.starts_with("main") { + Runtime::Mainnet + } else { + log::warn!("No specific runtime was recognized for ChainSpec's Id: '{}', so Runtime::Default will be used", id); + Runtime::default() + } +} +/// Resolve runtime from ChainSpec ID +impl RuntimeResolver for dyn ChainSpec { + fn runtime(&self) -> Runtime { + runtime(self.id()) + } +} +/// Implementation, that can resolve [`Runtime`] from any json configuration file +impl RuntimeResolver for PathBuf { + fn runtime(&self) -> Runtime { + #[derive(Debug, serde::Deserialize)] + struct EmptyChainSpecWithId { + id: String, + } + + let file = std::fs::File::open(self).expect("Failed to open file"); + let reader = std::io::BufReader::new(file); + let chain_spec: EmptyChainSpecWithId = sp_serializer::from_reader(reader) + .expect("Failed to read 'json' file with ChainSpec configuration"); + + runtime(&chain_spec.id) + } +} + fn load_spec(id: &str) -> std::result::Result, String> { Ok(match id { - "dev" => Box::new(chain_spec::development_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))?), + "dev" => Box::new(chain_spec::devnet::development_config()), + "" | "devnet-local" | "local" => Box::new(chain_spec::devnet::local_testnet_config()), + "main" | "mainnet-dev" => Box::new(chain_spec::mainnet::development_config()), + "mainnet-local" => Box::new(chain_spec::mainnet::local_testnet_config()), + path => { + let path: PathBuf = path.into(); + match path.runtime() { + Runtime::Devnet | Runtime::Default => { + Box::new(chain_spec::DevnetChainSpec::from_json_file(path)?) + }, + Runtime::Mainnet => Box::new(chain_spec::MainChainSpec::from_json_file(path)?), + } + }, }) } @@ -64,8 +122,11 @@ impl SubstrateCli for Cli { load_spec(id) } - fn native_runtime_version(_: &Box) -> &'static RuntimeVersion { - ¶chain_template_runtime::VERSION + fn native_runtime_version(chain_spec: &Box) -> &'static RuntimeVersion { + match chain_spec.runtime() { + Runtime::Devnet | Runtime::Default => &devnet_runtime::VERSION, + Runtime::Mainnet => &mainnet_runtime::VERSION, + } } } @@ -112,14 +173,53 @@ impl SubstrateCli for RelayChainCli { 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(&$config)?; - let task_manager = $components.task_manager; - { $( $code )* }.map(|v| (v, task_manager)) - }) + match runner.config().chain_spec.runtime() { + Runtime::Devnet | Runtime::Default => { + runner.async_run(|$config| { + let $components = new_partial::( + &$config, + crate::service::build_import_queue::, + )?; + let task_manager = $components.task_manager; + { $( $code )* }.map(|v| (v, task_manager)) + }) + } + Runtime::Mainnet => { + runner.async_run(|$config| { + let $components = new_partial::( + &$config, + crate::service::build_import_queue::, + )?; + let task_manager = $components.task_manager; + { $( $code )* }.map(|v| (v, task_manager)) + }) + } + } }} } +macro_rules! construct_benchmark_partials { + ($config:expr, |$partials:ident| $code:expr) => { + match $config.chain_spec.runtime() { + Runtime::Devnet | Runtime::Default => { + let $partials = new_partial::( + &$config, + crate::service::build_import_queue::<_, DevnetRuntimeExecutor>, + )?; + $code + }, + Runtime::Mainnet => { + let $partials = + new_partial::( + &$config, + crate::service::build_import_queue::<_, MainnetRuntimeExecutor>, + )?; + $code + }, + } + }; +} + /// Parse command line arguments into service configuration. pub fn run() -> Result<()> { let cli = Cli::from_args(); @@ -194,16 +294,21 @@ pub fn run() -> Result<()> { match cmd { BenchmarkCmd::Pallet(cmd) => { if cfg!(feature = "runtime-benchmarks") { - runner.sync_run(|config| cmd.run::(config)) + runner.sync_run(|config| match config.chain_spec.runtime() { + Runtime::Devnet | Runtime::Default => { + cmd.run::(config) + }, + Runtime::Mainnet => 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)?; - cmd.run(partials.client) + construct_benchmark_partials!(config, |partials| cmd.run(partials.client)) }), #[cfg(not(feature = "runtime-benchmarks"))] BenchmarkCmd::Storage(_) => Err(sc_cli::Error::Input( @@ -213,10 +318,12 @@ pub fn run() -> Result<()> { )), #[cfg(feature = "runtime-benchmarks")] BenchmarkCmd::Storage(cmd) => runner.sync_run(|config| { - let partials = new_partial(&config)?; - let db = partials.backend.expose_db(); - let storage = partials.backend.expose_storage(); - cmd.run(config, partials.client.clone(), db, storage) + construct_benchmark_partials!(config, |partials| { + 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())) @@ -229,7 +336,7 @@ pub fn run() -> Result<()> { }, #[cfg(feature = "try-runtime")] Some(Subcommand::TryRuntime(cmd)) => { - use parachain_template_runtime::MILLISECS_PER_BLOCK; + use runtime_common::MILLISECS_PER_BLOCK; use sc_executor::{sp_wasm_interface::ExtendedHostFunctions, NativeExecutionDispatch}; use try_runtime_cli::block_building_info::timestamp_with_aura_info; @@ -248,14 +355,24 @@ pub fn run() -> Result<()> { let info_provider = timestamp_with_aura_info(MILLISECS_PER_BLOCK); - runner.async_run(|_| { - Ok(( - cmd.run::, _>(Some( - info_provider, - )), - task_manager, - )) - }) + match runner.config().chain_spec.runtime() { + Runtime::Devnet | Runtime::Default => runner.async_run(|_config| { + Ok(( + cmd.run::, _>(Some( + info_provider, + )), + task_manager, + )) + }), + Runtime::Mainnet => runner.async_run(|_config| { + Ok(( + cmd.run::, _>(Some( + info_provider, + )), + task_manager, + )) + }), + } }, #[cfg(not(feature = "try-runtime"))] Some(Subcommand::TryRuntime) => Err("Try-runtime was not enabled when building the node. \ @@ -304,17 +421,29 @@ pub fn run() -> Result<()> { if !collator_options.relay_chain_rpc_urls.is_empty() && !cli.relay_chain_args.is_empty() { warn!("Detected relay chain node arguments together with --relay-chain-rpc-url. This command starts a minimal Polkadot node that only uses a network-related subset of all relay chain CLI options."); } + match config.chain_spec.runtime() { + Runtime::Default | Runtime::Devnet => { + // If you want to support a custom SS58 prefix (that isn’t yet registered in the ss58-registry), + // you are required to call this function with your desired prefix [Ss58AddressFormat::custom]. + // This will enable the node to decode ss58 addresses with this prefix. + // This SS58 version/format is also only used by the node and not by the runtime. + sp_core::crypto::set_default_ss58_version(devnet_runtime::SS58Prefix::get().into()); + crate::service::start_parachain_node:: + (config, polkadot_config, collator_options, id, hwbench) + .await + .map(|r| r.0) + .map_err(Into::into) - crate::service::start_parachain_node( - config, - polkadot_config, - collator_options, - id, - hwbench, - ) - .await - .map(|r| r.0) - .map_err(Into::into) + } + Runtime::Mainnet => { + sp_core::crypto::set_default_ss58_version(mainnet_runtime::SS58Prefix::get().into()); + crate::service::start_parachain_node:: + (config, polkadot_config, collator_options, id, hwbench) + .await + .map(|r| r.0) + .map_err(Into::into) + } + } }) }, } diff --git a/node/src/rpc.rs b/node/src/rpc.rs index 2bc5ccc..7e90749 100644 --- a/node/src/rpc.rs +++ b/node/src/rpc.rs @@ -7,7 +7,7 @@ use std::sync::Arc; -use parachain_template_runtime::{opaque::Block, AccountId, Balance, Index as Nonce}; +use runtime_common::{AccountId, Balance, Block, Index as Nonce}; use sc_client_api::AuxStore; pub use sc_rpc::{DenyUnsafe, SubscriptionTaskExecutor}; diff --git a/node/src/service.rs b/node/src/service.rs index 1d258a6..cb0f626 100644 --- a/node/src/service.rs +++ b/node/src/service.rs @@ -3,11 +3,8 @@ // std use std::{sync::Arc, time::Duration}; -use cumulus_client_cli::CollatorOptions; -// Local Runtime Types -use parachain_template_runtime::{opaque::Block, RuntimeApi}; - // Cumulus Imports +use cumulus_client_cli::CollatorOptions; use cumulus_client_consensus_aura::{AuraConsensus, BuildAuraConsensusParams, SlotProportion}; use cumulus_client_consensus_common::{ ParachainBlockImport as TParachainBlockImport, ParachainConsensus, @@ -23,56 +20,109 @@ use cumulus_relay_chain_interface::RelayChainInterface; use frame_benchmarking_cli::SUBSTRATE_REFERENCE_HARDWARE; use sc_consensus::ImportQueue; use sc_executor::{ - HeapAllocStrategy, NativeElseWasmExecutor, WasmExecutor, DEFAULT_HEAP_ALLOC_STRATEGY, + HeapAllocStrategy, NativeElseWasmExecutor, NativeExecutionDispatch, WasmExecutor, + DEFAULT_HEAP_ALLOC_STRATEGY, }; use sc_network::NetworkBlock; use sc_network_sync::SyncingService; use sc_service::{Configuration, PartialComponents, TFullBackend, TFullClient, TaskManager}; use sc_telemetry::{Telemetry, TelemetryHandle, TelemetryWorker, TelemetryWorkerHandle}; +use sp_api::ConstructRuntimeApi; +use sp_core::Pair; use sp_keystore::KeystorePtr; +use sp_runtime::{app_crypto::AppCrypto, traits::BlakeTwo256}; use substrate_prometheus_endpoint::Registry; -/// Native executor type. -pub struct ParachainNativeExecutor; +// Local Runtime types +use runtime_common::{AccountId, AuraId, Balance, Block, Index as Nonce}; + +/// Devnet Native executor type. +pub struct DevnetRuntimeExecutor; + +impl NativeExecutionDispatch for DevnetRuntimeExecutor { + type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; + + fn dispatch(method: &str, data: &[u8]) -> Option> { + devnet_runtime::api::dispatch(method, data) + } + + fn native_version() -> sc_executor::NativeVersion { + devnet_runtime::native_version() + } +} + +/// Mainnet Native executor type. +pub struct MainnetRuntimeExecutor; -impl sc_executor::NativeExecutionDispatch for ParachainNativeExecutor { +impl NativeExecutionDispatch for MainnetRuntimeExecutor { type ExtendHostFunctions = frame_benchmarking::benchmarking::HostFunctions; fn dispatch(method: &str, data: &[u8]) -> Option> { - parachain_template_runtime::api::dispatch(method, data) + mainnet_runtime::api::dispatch(method, data) } fn native_version() -> sc_executor::NativeVersion { - parachain_template_runtime::native_version() + mainnet_runtime::native_version() } } -type ParachainExecutor = NativeElseWasmExecutor; +type ParachainExecutor = NativeElseWasmExecutor; -type ParachainClient = TFullClient; +type ParachainClient = + TFullClient>; type ParachainBackend = TFullBackend; -type ParachainBlockImport = TParachainBlockImport, ParachainBackend>; +type ParachainBlockImport = + TParachainBlockImport>, ParachainBackend>; /// 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( +pub fn new_partial( config: &Configuration, + build_import_queue: BIQ, ) -> Result< PartialComponents< - ParachainClient, + ParachainClient, ParachainBackend, (), - sc_consensus::DefaultImportQueue, - sc_transaction_pool::FullPool, - (ParachainBlockImport, Option, Option), + sc_consensus::DefaultImportQueue>, + sc_transaction_pool::FullPool>, + ( + ParachainBlockImport, + 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: NativeExecutionDispatch + 'static, + BIQ: FnOnce( + Arc>, + ParachainBlockImport, + &Configuration, + Option, + &TaskManager, + ) -> Result< + sc_consensus::DefaultImportQueue>, + sc_service::Error, + >, +{ let telemetry = config .telemetry_endpoints .clone() @@ -96,7 +146,7 @@ pub fn new_partial( .with_runtime_cache_size(config.runtime_cache_size) .build(); - let executor = ParachainExecutor::new_with_wasm_executor(wasm); + let executor = NativeElseWasmExecutor::::new_with_wasm_executor(wasm); let (client, backend, keystore_container, task_manager) = sc_service::new_full_parts::( @@ -121,7 +171,8 @@ pub fn new_partial( client.clone(), ); - let block_import = ParachainBlockImport::new(client.clone(), backend.clone()); + let block_import = + ParachainBlockImport::::new(client.clone(), backend.clone()); let import_queue = build_import_queue( client.clone(), @@ -147,16 +198,62 @@ pub fn new_partial( /// /// 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( +#[allow(clippy::too_many_arguments)] +async fn start_node_impl( parachain_config: Configuration, polkadot_config: Configuration, collator_options: CollatorOptions, para_id: ParaId, + build_import_queue: BIQ, + build_consensus: BIC, hwbench: Option, -) -> sc_service::error::Result<(TaskManager, Arc)> { +) -> 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: NativeExecutionDispatch + 'static, + + BIQ: FnOnce( + Arc>, + ParachainBlockImport, + &Configuration, + Option, + &TaskManager, + ) -> Result< + sc_consensus::DefaultImportQueue>, + sc_service::Error, + > + 'static, + BIC: FnOnce( + Arc>, + ParachainBlockImport, + Option<&Registry>, + Option, + &TaskManager, + Arc, + Arc>>, + Arc>, + KeystorePtr, + bool, + ParaId, + ) -> Result>, sc_service::Error>, +{ let parachain_config = prepare_node_config(parachain_config); - let params = new_partial(¶chain_config)?; + let params = new_partial::(¶chain_config, build_import_queue)?; let (block_import, mut telemetry, telemetry_worker_handle) = params.other; let client = params.client.clone(); @@ -318,13 +415,31 @@ async fn start_node_impl( } /// Build the import queue for the parachain runtime. -fn build_import_queue( - client: Arc, - block_import: ParachainBlockImport, +#[allow(clippy::type_complexity)] +pub(crate) fn build_import_queue( + client: Arc>, + block_import: ParachainBlockImport, config: &Configuration, telemetry: Option, task_manager: &TaskManager, -) -> Result, sc_service::Error> { +) -> Result< + sc_consensus::DefaultImportQueue>, + 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 + + sp_consensus_aura::AuraApi::Pair as Pair>::Public> + + substrate_frame_rpc_system::AccountNonceApi, +{ let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; cumulus_client_consensus_aura::import_queue::< @@ -356,19 +471,39 @@ fn build_import_queue( } #[allow(clippy::too_many_arguments)] -fn build_consensus( - client: Arc, - block_import: ParachainBlockImport, + +fn build_consensus( + client: Arc>, + block_import: ParachainBlockImport, prometheus_registry: Option<&Registry>, telemetry: Option, task_manager: &TaskManager, relay_chain_interface: Arc, - transaction_pool: Arc>, + transaction_pool: Arc< + sc_transaction_pool::FullPool>, + >, sync_oracle: Arc>, keystore: KeystorePtr, force_authoring: bool, para_id: ParaId, -) -> Result>, sc_service::Error> { +) -> Result>, 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 + + sp_consensus_aura::AuraApi::Pair as Pair>::Public> + + cumulus_primitives_core::CollectCollationInfo + + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi + + substrate_frame_rpc_system::AccountNonceApi, + Executor: NativeExecutionDispatch + 'static, +{ let slot_duration = cumulus_client_consensus_aura::slot_duration(&*client)?; let proposer_factory = sc_basic_authorship::ProposerFactory::with_proof_recording( @@ -426,12 +561,38 @@ fn build_consensus( } /// Start a parachain node. -pub async fn start_parachain_node( +pub async fn start_parachain_node( parachain_config: Configuration, polkadot_config: Configuration, collator_options: CollatorOptions, para_id: ParaId, hwbench: Option, -) -> sc_service::error::Result<(TaskManager, Arc)> { - start_node_impl(parachain_config, polkadot_config, collator_options, para_id, hwbench).await +) -> sc_service::error::Result<(TaskManager, Arc>)> +where + Executor: NativeExecutionDispatch + 'static, + 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 + + sp_consensus_aura::AuraApi::Pair as Pair>::Public> + + pallet_transaction_payment_rpc::TransactionPaymentRuntimeApi + + substrate_frame_rpc_system::AccountNonceApi, +{ + start_node_impl::( + parachain_config, + polkadot_config, + collator_options, + para_id, + build_import_queue::, + build_consensus::, + hwbench, + ) + .await } diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml new file mode 100644 index 0000000..e4f23e4 --- /dev/null +++ b/runtime/common/Cargo.toml @@ -0,0 +1,38 @@ +[package] +authors = ["Anonymous"] +description = "Runtime Common" +edition = "2021" +license = "Unlicense" +name = "runtime-common" +repository = "https://github.com/paritytech/extended-parachain-template" +version = "1.0.0" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + + +[dependencies] +codec = {package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"]} +scale-info = {version = "2.5.0", default-features = false, features = ["derive"]} + +# Substrate +frame-support = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +sp-runtime = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +sp-std = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} + +parachains-common = {git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.42", default-features = false} +polkadot-primitives = {git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.42", default-features = false} + +[features] +default = [ + "std", +] +std = [ + "frame-support/std", + "sp-runtime/std", +] + +runtime-benchmarks = [ + "frame-support/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", +] diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs new file mode 100644 index 0000000..217ea45 --- /dev/null +++ b/runtime/common/src/lib.rs @@ -0,0 +1,42 @@ +#![cfg_attr(not(feature = "std"), no_std)] +use sp_runtime::Perbill; + +use frame_support::weights::{constants::WEIGHT_REF_TIME_PER_SECOND, Weight}; + +// Cumulus types re-export +// These types are shared between the mainnet and devnet runtimes +//https://github.com/paritytech/cumulus/tree/master/parachains/common +pub use parachains_common::{ + impls::DealWithFees, AccountId, AuraId, Balance, Block, BlockNumber, Hash, Index, Signature, +}; + +/// This determines the average expected block time that we are targeting. +/// Blocks will be produced at a minimum duration defined by `SLOT_DURATION`. +/// `SLOT_DURATION` is picked up by `pallet_timestamp` which is in turn picked +/// up by `pallet_aura` to implement `fn slot_duration()`. +/// +/// Change this to adjust the block time. +pub const MILLISECS_PER_BLOCK: u64 = 12000; + +// NOTE: Currently it is not possible to change the slot duration after the chain has started. +// Attempting to do so will brick block production. +pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; + +// Time is measured by number of blocks. +pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); +pub const HOURS: BlockNumber = MINUTES * 60; +pub const DAYS: BlockNumber = HOURS * 24; + +/// 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. +pub 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. +pub 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. +pub const MAXIMUM_BLOCK_WEIGHT: Weight = Weight::from_parts( + WEIGHT_REF_TIME_PER_SECOND.saturating_div(2), + polkadot_primitives::v4::MAX_POV_SIZE as u64, +); diff --git a/runtime/Cargo.toml b/runtime/devnet/Cargo.toml similarity index 97% rename from runtime/Cargo.toml rename to runtime/devnet/Cargo.toml index 5c903d4..00262d2 100644 --- a/runtime/Cargo.toml +++ b/runtime/devnet/Cargo.toml @@ -1,12 +1,12 @@ [package] +name = "devnet-runtime" +version = "0.1.0" authors = ["Anonymous"] description = "A Cumulus FRAME-based Substrate Runtime, ready for hacking together a parachain." edition = "2021" homepage = "https://substrate.io" license = "Unlicense" -name = "parachain-template-runtime" repository = "https://github.com/paritytech/extended-parachain-template/" -version = "0.1.0" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] @@ -22,7 +22,8 @@ scale-info = { version = "2.5.0", default-features = false, features = ["derive" smallvec = "1.10.0" # Local -pallet-motion = {path = "../pallets/motion", default-features = false} +pallet-motion = { path = "../../pallets/motion", default-features = false } +runtime-common = {path = "../common", default-features = false} # Substrate frame-benchmarking = { git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "polkadot-v0.9.42" } @@ -75,7 +76,6 @@ cumulus-primitives-timestamp = { git = "https://github.com/paritytech/cumulus.gi cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus.git", branch = "polkadot-v0.9.42", default-features = false } pallet-collator-selection = { git = "https://github.com/paritytech/cumulus.git", branch = "polkadot-v0.9.42", default-features = false } parachain-info = { git = "https://github.com/paritytech/cumulus.git", branch = "polkadot-v0.9.42", default-features = false } -parachains-common = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.42", default-features = false } [features] default = [ diff --git a/runtime/build.rs b/runtime/devnet/build.rs similarity index 100% rename from runtime/build.rs rename to runtime/devnet/build.rs diff --git a/runtime/devnet/src/lib.rs b/runtime/devnet/src/lib.rs new file mode 100644 index 0000000..6b7fe1d --- /dev/null +++ b/runtime/devnet/src/lib.rs @@ -0,0 +1,824 @@ +#![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")); + +mod weights; +pub mod xcm_config; +pub use fee::WeightToFee; + +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::{AccountIdLookup, BlakeTwo256, Block as BlockT}, + transaction_validity::{TransactionSource, TransactionValidity}, + ApplyExtrinsicResult, +}; + +use sp_std::prelude::*; +#[cfg(feature = "std")] +use sp_version::NativeVersion; +use sp_version::RuntimeVersion; + +use frame_support::{ + construct_runtime, + dispatch::DispatchClass, + parameter_types, + traits::{AsEnsureOriginWithArg, ConstU32, ConstU64, ConstU8, EitherOfDiverse, Everything}, + weights::{ConstantMultiplier, Weight}, + PalletId, +}; +use frame_system::{ + limits::{BlockLength, BlockWeights}, + EnsureRoot, EnsureSigned, +}; +use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; +pub use runtime_common::{ + AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS, MAXIMUM_BLOCK_WEIGHT, MILLISECS_PER_BLOCK, MINUTES, + NORMAL_DISPATCH_RATIO, SLOT_DURATION, +}; +pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; +pub use sp_runtime::{MultiAddress, Perbill, Permill}; +use xcm_config::{RelayLocation, XcmConfig, XcmOriginToTransactDispatchOrigin}; + +#[cfg(any(feature = "std", test))] +pub use sp_runtime::BuildStorage; + +// Polkadot imports +use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; + +pub use runtime_common::{AccountId, Balance, BlockNumber, DealWithFees, Hash, Index, Signature}; + +use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; + +// XCM Imports +use xcm::latest::prelude::BodyId; +use xcm_executor::XcmExecutor; + +/// 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, + Block, + frame_system::ChainContext, + Runtime, + AllPalletsWithSystem, +>; + +pub mod fee { + use super::{Balance, ExtrinsicBaseWeight, MILLIUNIT}; + use frame_support::weights::{ + FeePolynomial, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, + WeightToFeePolynomial, + }; + use smallvec::smallvec; + use sp_runtime::Perbill; + + /// 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 frame_support::weights::WeightToFee for WeightToFee { + type Balance = Balance; + + fn weight_to_fee(weight: &Weight) -> Self::Balance { + let ref_polynomial: FeePolynomial = RefTimeToFee::polynomial().into(); + let proof_polynomial: FeePolynomial = ProofSizeToFee::polynomial().into(); + + // Get fee amount from ref_time based on the RefTime polynomial + let ref_fee: Balance = ref_polynomial.eval(weight.ref_time()); + + // Get fee amount from proof_size based on the ProofSize polynomial + let proof_fee: Balance = proof_polynomial.eval(weight.proof_size()); + + // Take the maximum instead of the sum to charge by the more scarce resource. + ref_fee.max(proof_fee) + } + } + + /// Maps the Ref time component of `Weight` to a fee. + pub struct RefTimeToFee; + impl WeightToFeePolynomial for RefTimeToFee { + type Balance = Balance; + fn polynomial() -> WeightToFeeCoefficients { + // in Rococo, extrinsic base weight (smallest non-zero weight) is mapped to 1 MILLIUNIT: + // in our template, we map to 1/10 of that, or 1/10 MILLIUNIT + let p = MILLIUNIT / 10; + let q = 100 * Balance::from(ExtrinsicBaseWeight::get().ref_time()); + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } + } + + /// Maps the proof size component of `Weight` to a fee. + pub struct ProofSizeToFee; + impl WeightToFeePolynomial for ProofSizeToFee { + type Balance = Balance; + fn polynomial() -> WeightToFeeCoefficients { + // Map 10kb proof to 1 CENT. + let p = MILLIUNIT / 10; + let q = 10_000; + + smallvec![WeightToFeeCoefficient { + degree: 1, + negative: false, + coeff_frac: Perbill::from_rational(p % q, q), + coeff_integer: p / q, + }] + } + } +} +/// 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!("devnet"), + impl_name: create_runtime_str!("devnet"), + authoring_version: 1, + spec_version: 1000, + impl_version: 0, + apis: RUNTIME_API_VERSIONS, + transaction_version: 1, + state_version: 1, +}; + +pub const MICROUNIT: Balance = 1_000_000; +pub const MILLIUNIT: Balance = 1_000 * MICROUNIT; +pub const UNIT: Balance = 1_000 * MILLIUNIT; + +pub const EXISTENTIAL_DEPOSIT: Balance = MILLIUNIT; + +pub const fn deposit(items: u32, bytes: u32) -> Balance { + (items as Balance * 20 * UNIT + (bytes as Balance) * 100 * MICROUNIT) / 100 +} + +/// 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 MaxCollectivesProposalWeight: Weight = Perbill::from_percent(50) * RuntimeBlockWeights::get().max_block; + pub const SS58Prefix: u16 = 42; +} + +// 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 RuntimeCall = RuntimeCall; + /// 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 RuntimeEvent = RuntimeEvent; + /// The ubiquitous origin type. + type RuntimeOrigin = RuntimeOrigin; + /// 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 = Everything; + /// 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 = frame_support::traits::ConstU32<16>; +} + +impl pallet_timestamp::Config for Runtime { + /// A timestamp: milliseconds since the unix epoch. + type Moment = u64; + type OnTimestampSet = Aura; + type MinimumPeriod = ConstU64<{ SLOT_DURATION / 2 }>; + type WeightInfo = (); +} + +parameter_types! { + pub const UncleGenerations: u32 = 0; +} + +impl pallet_authorship::Config for Runtime { + type FindAuthor = pallet_session::FindAccountFromAuthorIndex; + type EventHandler = (CollatorSelection,); +} + +parameter_types! { + pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT; +} + +impl pallet_balances::Config for Runtime { + type MaxLocks = ConstU32<50>; + /// The type for recording an account's balance. + type Balance = Balance; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type MaxReserves = ConstU32<50>; + type MaxHolds = ConstU32<0>; + type MaxFreezes = ConstU32<0>; + type HoldIdentifier = (); + type FreezeIdentifier = (); + type ReserveIdentifier = [u8; 8]; + type WeightInfo = pallet_balances::weights::SubstrateWeight; +} + +parameter_types! { + pub const AssetDeposit: Balance = 10 * UNIT; + pub const AssetAccountDeposit: Balance = deposit(1, 16); + pub const ApprovalDeposit: Balance = EXISTENTIAL_DEPOSIT; + pub const StringLimit: u32 = 50; + pub const MetadataDepositBase: Balance = deposit(1, 68); + pub const MetadataDepositPerByte: Balance = deposit(0, 1); +} + +impl pallet_assets::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = u32; + type AssetIdParameter = codec::Compact; + type Currency = Balances; + type CreateOrigin = AsEnsureOriginWithArg>; + type CallbackHandle = (); + type ForceOrigin = EnsureRoot; + type AssetDeposit = AssetDeposit; + type AssetAccountDeposit = AssetAccountDeposit; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type ApprovalDeposit = ApprovalDeposit; + type StringLimit = StringLimit; + type Freezer = (); + type Extra = (); + type RemoveItemsLimit = ConstU32<1000>; + type WeightInfo = pallet_assets::weights::SubstrateWeight; + #[cfg(feature = "runtime-benchmarks")] + type BenchmarkHelper = (); +} + +parameter_types! { + /// Relay Chain `TransactionByteFee` / 10 + pub const TransactionByteFee: Balance = 10 * MICROUNIT; +} + +impl pallet_transaction_payment::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type OnChargeTransaction = + pallet_transaction_payment::CurrencyAdapter>; + type WeightToFee = WeightToFee; + type LengthToFee = ConstantMultiplier; + type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type OperationalFeeMultiplier = ConstU8<5>; +} + +impl pallet_utility::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type PalletsOrigin = OriginCaller; + + type WeightInfo = pallet_utility::weights::SubstrateWeight; +} + +parameter_types! { + pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); + pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); +} + +impl cumulus_pallet_parachain_system::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + 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 {} + +impl cumulus_pallet_xcmp_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; + type ChannelInfo = ParachainSystem; + type VersionWrapper = (); + type ExecuteOverweightOrigin = EnsureRoot; + type ControllerOrigin = EnsureRoot; + type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; + type WeightInfo = (); + type PriceForSiblingDelivery = (); +} + +impl cumulus_pallet_dmp_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; + type ExecuteOverweightOrigin = EnsureRoot; +} + +parameter_types! { + pub const Period: u32 = 6 * HOURS; + pub const Offset: u32 = 0; +} + +impl pallet_session::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + 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_sudo::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; +} + +parameter_types! { + pub const CouncilMotionDuration: BlockNumber = 7 * DAYS; + pub const CouncilMaxProposals: u32 = 10; + pub const CouncilMaxMembers: u32 = 25; +} + +type CouncilCollective = pallet_collective::Instance1; +impl pallet_collective::Config for Runtime { + type RuntimeOrigin = RuntimeOrigin; + type RuntimeEvent = RuntimeEvent; + type Proposal = RuntimeCall; + type SetMembersOrigin = EnsureRoot; + type MotionDuration = CouncilMotionDuration; + type MaxProposals = CouncilMaxProposals; + type MaxMembers = CouncilMaxMembers; + type DefaultVote = pallet_collective::PrimeDefaultVote; + type MaxProposalWeight = MaxCollectivesProposalWeight; + type WeightInfo = pallet_collective::weights::SubstrateWeight; +} + +impl pallet_motion::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type SimpleMajorityOrigin = + pallet_collective::EnsureProportionMoreThan; + type SuperMajorityOrigin = + pallet_collective::EnsureProportionAtLeast; + type UnanimousOrigin = + pallet_collective::EnsureProportionAtLeast; + type WeightInfo = pallet_motion::weights::SubstrateWeight; +} + +impl pallet_aura::Config for Runtime { + type AuthorityId = AuraId; + type DisabledValidators = (); + type MaxAuthorities = ConstU32<100_000>; +} + +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; + // StakingAdmin pluralistic body. + pub const StakingAdminBodyId: BodyId = BodyId::Defense; +} + +/// We allow root and the StakingAdmin to execute privileged collator selection operations. +pub type CollatorSelectionUpdateOrigin = EitherOfDiverse< + EnsureRoot, + EnsureXcm>, +>; + +impl pallet_collator_selection::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + 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 = (); +} + +// Create the runtime by composing the FRAME pallets that were previously configured. +construct_runtime!( + pub struct Runtime where + Block = Block, + NodeBlock = opaque::Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + // System support stuff. + System: frame_system = 0, + ParachainSystem: cumulus_pallet_parachain_system = 1, + Timestamp: pallet_timestamp = 2, + ParachainInfo: parachain_info = 3, + + // Utility + Utility: pallet_utility = 4, + + // Monetary stuff. + Balances: pallet_balances = 10, + TransactionPayment: pallet_transaction_payment = 11, + Assets: pallet_assets = 12, + + // Governance + Sudo: pallet_sudo = 15, + Council: pallet_collective:: = 16, + Motion: pallet_motion = 17, + + // Collator support. The order of these 4 are important and shall not change. + Authorship: pallet_authorship = 20, + CollatorSelection: pallet_collator_selection = 21, + Session: pallet_session = 22, + Aura: pallet_aura = 23, + AuraExt: cumulus_pallet_aura_ext = 24, + + // XCM helpers. + XcmpQueue: cumulus_pallet_xcmp_queue = 30, + PolkadotXcm: pallet_xcm = 31, + CumulusXcm: cumulus_pallet_xcm = 32, + DmpQueue: cumulus_pallet_dmp_queue = 33, + } +); + +#[cfg(feature = "runtime-benchmarks")] +mod benches { + frame_benchmarking::define_benchmarks!( + [frame_system, SystemBench::] + [pallet_balances, Balances] + [pallet_assets, Assets] + [pallet_session, SessionBench::] + [pallet_timestamp, Timestamp] + [pallet_collator_selection, CollatorSelection] + [cumulus_pallet_xcmp_queue, XcmpQueue] + ); +} + +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()) + } + fn metadata_at_version(version: u32) -> Option { + Runtime::metadata_at_version(version) + } + + fn metadata_versions() -> sp_std::vec::Vec { + Runtime::metadata_versions() + } + } + + 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) + } + fn query_weight_to_fee(weight: Weight) -> Balance { + TransactionPayment::weight_to_fee(weight) + } + fn query_length_to_fee(length: u32) -> Balance { + TransactionPayment::length_to_fee(length) + } + } + + impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentCallApi + for Runtime + { + fn query_call_info( + call: RuntimeCall, + len: u32, + ) -> pallet_transaction_payment::RuntimeDispatchInfo { + TransactionPayment::query_call_info(call, len) + } + fn query_call_fee_details( + call: RuntimeCall, + len: u32, + ) -> pallet_transaction_payment::FeeDetails { + TransactionPayment::query_call_fee_details(call, len) + } + fn query_weight_to_fee(weight: Weight) -> Balance { + TransactionPayment::weight_to_fee(weight) + } + fn query_length_to_fee(length: u32) -> Balance { + TransactionPayment::length_to_fee(length) + } + } + + 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(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { + let weight = Executive::try_runtime_upgrade(checks).unwrap(); + (weight, RuntimeBlockWeights::get().max_block) + } + + fn execute_block( + block: Block, + state_root_check: bool, + signature_check: bool, + select: frame_try_runtime::TryStateSelect, + ) -> Weight { + Executive::try_execute_block(block, state_root_check, signature_check, select).unwrap() + } + } + + #[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}; + + 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 {} + + use frame_support::traits::WhitelistedStorageKeys; + let whitelist = AllPalletsWithSystem::whitelisted_storage_keys(); + + 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) + } + } +} + +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/runtime/src/weights/block_weights.rs b/runtime/devnet/src/weights/block_weights.rs similarity index 100% rename from runtime/src/weights/block_weights.rs rename to runtime/devnet/src/weights/block_weights.rs diff --git a/runtime/src/weights/extrinsic_weights.rs b/runtime/devnet/src/weights/extrinsic_weights.rs similarity index 100% rename from runtime/src/weights/extrinsic_weights.rs rename to runtime/devnet/src/weights/extrinsic_weights.rs diff --git a/runtime/src/weights/mod.rs b/runtime/devnet/src/weights/mod.rs similarity index 100% rename from runtime/src/weights/mod.rs rename to runtime/devnet/src/weights/mod.rs diff --git a/runtime/src/weights/paritydb_weights.rs b/runtime/devnet/src/weights/paritydb_weights.rs similarity index 100% rename from runtime/src/weights/paritydb_weights.rs rename to runtime/devnet/src/weights/paritydb_weights.rs diff --git a/runtime/src/weights/rocksdb_weights.rs b/runtime/devnet/src/weights/rocksdb_weights.rs similarity index 100% rename from runtime/src/weights/rocksdb_weights.rs rename to runtime/devnet/src/weights/rocksdb_weights.rs diff --git a/runtime/src/xcm_config.rs b/runtime/devnet/src/xcm_config.rs similarity index 100% rename from runtime/src/xcm_config.rs rename to runtime/devnet/src/xcm_config.rs diff --git a/runtime/mainnet/Cargo.toml b/runtime/mainnet/Cargo.toml new file mode 100644 index 0000000..d185878 --- /dev/null +++ b/runtime/mainnet/Cargo.toml @@ -0,0 +1,177 @@ +[package] +authors = ["Anonymous"] +description = "A new Cumulus FRAME-based Substrate Runtime, ready for hacking together a parachain." +edition = "2021" +homepage = "https://substrate.io" +license = "Unlicense" +name = "mainnet-runtime" +repository = "https://github.com/paritytech/extended-parachain-template/" +version = "0.1.0" + +[package.metadata.docs.rs] +targets = ["x86_64-unknown-linux-gnu"] + +[build-dependencies] +substrate-wasm-builder = {git = "https://github.com/paritytech/substrate", optional = true, branch = "polkadot-v0.9.42"} + +[dependencies] +codec = {package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"]} +hex-literal = {version = "0.4.1", optional = true} +log = {version = "0.4.17", default-features = false} +scale-info = {version = "2.5.0", default-features = false, features = ["derive"]} +smallvec = "1.10.0" + +# Local +pallet-motion = {path = "../../pallets/motion", default-features = false} +runtime-common = {path = "../common", default-features = false} + +# Substrate +frame-benchmarking = {git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "polkadot-v0.9.42"} +frame-executive = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +frame-support = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +frame-system = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +frame-system-benchmarking = {git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "polkadot-v0.9.42"} +frame-system-rpc-runtime-api = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +frame-try-runtime = {git = "https://github.com/paritytech/substrate", default-features = false, optional = true, branch = "polkadot-v0.9.42"} +pallet-assets = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +pallet-aura = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +pallet-authorship = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +pallet-balances = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +pallet-collective = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +pallet-session = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +pallet-sudo = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +pallet-timestamp = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +pallet-transaction-payment = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +pallet-transaction-payment-rpc-runtime-api = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +pallet-utility = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +sp-api = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +sp-block-builder = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +sp-consensus-aura = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +sp-core = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +sp-inherents = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +sp-offchain = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +sp-runtime = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +sp-session = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +sp-std = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +sp-transaction-pool = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} +sp-version = {git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-v0.9.42"} + +# Polkadot +pallet-xcm = {git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42"} +polkadot-parachain = {git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42"} +polkadot-runtime-common = {git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42"} +xcm = {git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42"} +xcm-builder = {git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42"} +xcm-executor = {git = "https://github.com/paritytech/polkadot", default-features = false, branch = "release-v0.9.42"} + +# Cumulus +cumulus-pallet-aura-ext = {git = "https://github.com/paritytech/cumulus.git", branch = "polkadot-v0.9.42", default-features = false} +cumulus-pallet-dmp-queue = {git = "https://github.com/paritytech/cumulus.git", branch = "polkadot-v0.9.42", default-features = false} +cumulus-pallet-parachain-system = {git = "https://github.com/paritytech/cumulus.git", branch = "polkadot-v0.9.42", default-features = false} +cumulus-pallet-session-benchmarking = {git = "https://github.com/paritytech/cumulus.git", branch = "polkadot-v0.9.42", default-features = false, version = "3.0.0"} +cumulus-pallet-xcm = {git = "https://github.com/paritytech/cumulus.git", branch = "polkadot-v0.9.42", default-features = false} +cumulus-pallet-xcmp-queue = {git = "https://github.com/paritytech/cumulus.git", branch = "polkadot-v0.9.42", default-features = false} +cumulus-primitives-core = {git = "https://github.com/paritytech/cumulus.git", branch = "polkadot-v0.9.42", default-features = false} +cumulus-primitives-timestamp = {git = "https://github.com/paritytech/cumulus.git", branch = "polkadot-v0.9.42", default-features = false} +cumulus-primitives-utility = {git = "https://github.com/paritytech/cumulus.git", branch = "polkadot-v0.9.42", default-features = false} +pallet-collator-selection = {git = "https://github.com/paritytech/cumulus.git", branch = "polkadot-v0.9.42", default-features = false} +parachain-info = {git = "https://github.com/paritytech/cumulus.git", branch = "polkadot-v0.9.42", default-features = false} + +[features] +default = [ + "std", +] +std = [ + "codec/std", + "log/std", + "scale-info/std", + "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-assets/std", + "pallet-balances/std", + "pallet-collective/std", + "pallet-collator-selection/std", + "pallet-motion/std", + "pallet-session/std", + "pallet-sudo/std", + "pallet-timestamp/std", + "pallet-transaction-payment-rpc-runtime-api/std", + "pallet-transaction-payment/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-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", + "substrate-wasm-builder", +] + +runtime-benchmarks = [ + "hex-literal", + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system-benchmarking/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-assets/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-collator-selection/runtime-benchmarks", + "pallet-collective/runtime-benchmarks", + "pallet-motion/runtime-benchmarks", + "pallet-timestamp/runtime-benchmarks", + "pallet-utility/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", +] + +try-runtime = [ + "cumulus-pallet-aura-ext/try-runtime", + "cumulus-pallet-dmp-queue/try-runtime", + "cumulus-pallet-parachain-system/try-runtime", + "cumulus-pallet-xcm/try-runtime", + "cumulus-pallet-xcmp-queue/try-runtime", + "frame-executive/try-runtime", + "frame-system/try-runtime", + "frame-try-runtime", + "pallet-aura/try-runtime", + "pallet-authorship/try-runtime", + "pallet-assets/try-runtime", + "pallet-balances/try-runtime", + "pallet-collator-selection/try-runtime", + "pallet-collective/try-runtime", + "pallet-motion/try-runtime", + "pallet-session/try-runtime", + "pallet-sudo/try-runtime", + "pallet-timestamp/try-runtime", + "pallet-transaction-payment/try-runtime", + "pallet-utility/try-runtime", + "pallet-xcm/try-runtime", + "parachain-info/try-runtime", +] diff --git a/runtime/mainnet/build.rs b/runtime/mainnet/build.rs new file mode 100644 index 0000000..02d6973 --- /dev/null +++ b/runtime/mainnet/build.rs @@ -0,0 +1,13 @@ +#[cfg(feature = "std")] +fn main() { + substrate_wasm_builder::WasmBuilder::new() + .with_current_project() + .export_heap_base() + .import_memory() + .build() +} + +/// The wasm builder is deactivated when compiling +/// this crate for wasm to speed up the compilation. +#[cfg(not(feature = "std"))] +fn main() {} diff --git a/runtime/src/lib.rs b/runtime/mainnet/src/lib.rs similarity index 92% rename from runtime/src/lib.rs rename to runtime/mainnet/src/lib.rs index 3c21eed..139d7da 100644 --- a/runtime/src/lib.rs +++ b/runtime/mainnet/src/lib.rs @@ -6,11 +6,8 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); -mod currency; mod weights; pub mod xcm_config; - -pub use currency::{deposit, EXISTENTIAL_DEPOSIT, MICROUNIT, MILLIUNIT, UNIT}; pub use fee::WeightToFee; use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; @@ -18,7 +15,7 @@ use sp_api::impl_runtime_apis; use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, - traits::{AccountIdLookup, BlakeTwo256, Block as BlockT, IdentifyAccount, Verify}, + traits::{AccountIdLookup, BlakeTwo256, Block as BlockT}, transaction_validity::{TransactionSource, TransactionValidity}, ApplyExtrinsicResult, }; @@ -33,7 +30,7 @@ use frame_support::{ dispatch::DispatchClass, parameter_types, traits::{AsEnsureOriginWithArg, ConstU32, ConstU64, ConstU8, EitherOfDiverse, Everything}, - weights::{constants::WEIGHT_REF_TIME_PER_SECOND, ConstantMultiplier, Weight}, + weights::{ConstantMultiplier, Weight}, PalletId, }; use frame_system::{ @@ -41,6 +38,10 @@ use frame_system::{ EnsureRoot, EnsureSigned, }; use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; +pub use runtime_common::{ + AVERAGE_ON_INITIALIZE_RATIO, DAYS, HOURS, MAXIMUM_BLOCK_WEIGHT, MILLISECS_PER_BLOCK, MINUTES, + NORMAL_DISPATCH_RATIO, SLOT_DURATION, +}; pub use sp_consensus_aura::sr25519::AuthorityId as AuraId; pub use sp_runtime::{MultiAddress, Perbill, Permill}; use xcm_config::{RelayLocation, XcmConfig, XcmOriginToTransactDispatchOrigin}; @@ -51,12 +52,7 @@ pub use sp_runtime::BuildStorage; // Polkadot imports use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; -// Cumulus imports -//https://github.com/paritytech/cumulus/tree/master/parachains/common -pub use parachains_common::{ - impls::{AccountIdOf, DealWithFees}, - Balance, BlockNumber, Hash, Index, Signature, -}; +pub use runtime_common::{AccountId, Balance, BlockNumber, DealWithFees, Hash, Index, Signature}; use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; @@ -64,10 +60,6 @@ use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; use xcm::latest::prelude::BodyId; use xcm_executor::XcmExecutor; -/// 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; - /// The address format for describing accounts. pub type Address = MultiAddress; @@ -112,7 +104,7 @@ pub type Executive = frame_executive::Executive< >; pub mod fee { - use super::{currency::MILLIUNIT, Balance, ExtrinsicBaseWeight}; + use super::{Balance, ExtrinsicBaseWeight, MILLIUNIT}; use frame_support::weights::{ FeePolynomial, Weight, WeightToFeeCoefficient, WeightToFeeCoefficients, WeightToFeePolynomial, @@ -210,8 +202,8 @@ impl_opaque_keys! { #[sp_version::runtime_version] pub const VERSION: RuntimeVersion = RuntimeVersion { - spec_name: create_runtime_str!("template-parachain"), - impl_name: create_runtime_str!("template-parachain"), + spec_name: create_runtime_str!("mainnet"), + impl_name: create_runtime_str!("mainnet"), authoring_version: 1, spec_version: 1000, impl_version: 0, @@ -220,36 +212,15 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { state_version: 1, }; -/// This determines the average expected block time that we are targeting. -/// Blocks will be produced at a minimum duration defined by `SLOT_DURATION`. -/// `SLOT_DURATION` is picked up by `pallet_timestamp` which is in turn picked -/// up by `pallet_aura` to implement `fn slot_duration()`. -/// -/// Change this to adjust the block time. -pub const MILLISECS_PER_BLOCK: u64 = 12000; - -// NOTE: Currently it is not possible to change the slot duration after the chain has started. -// Attempting to do so will brick block production. -pub const SLOT_DURATION: u64 = MILLISECS_PER_BLOCK; - -// Time is measured by number of blocks. -pub const MINUTES: BlockNumber = 60_000 / (MILLISECS_PER_BLOCK as BlockNumber); -pub const HOURS: BlockNumber = MINUTES * 60; -pub const DAYS: BlockNumber = HOURS * 24; - -/// 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::from_parts( - WEIGHT_REF_TIME_PER_SECOND.saturating_div(2), - cumulus_primitives_core::relay_chain::MAX_POV_SIZE as u64, -); +pub const MICROUNIT: Balance = 1_000_000; +pub const MILLIUNIT: Balance = 1_000 * MICROUNIT; +pub const UNIT: Balance = 1_000 * MILLIUNIT; + +pub const EXISTENTIAL_DEPOSIT: Balance = MILLIUNIT; + +pub const fn deposit(items: u32, bytes: u32) -> Balance { + (items as Balance * 20 * UNIT + (bytes as Balance) * 100 * MICROUNIT) / 100 +} /// The version information used to identify this runtime when compiled natively. #[cfg(feature = "std")] diff --git a/runtime/mainnet/src/weights/block_weights.rs b/runtime/mainnet/src/weights/block_weights.rs new file mode 100644 index 0000000..b2092d8 --- /dev/null +++ b/runtime/mainnet/src/weights/block_weights.rs @@ -0,0 +1,53 @@ +// 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 = + Weight::from_parts(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(5_000_000), 0); + } + + #[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.ref_time() >= 100u64 * constants::WEIGHT_REF_TIME_PER_MICROS, + "Weight should be at least 100 µs." + ); + // At most 50 ms. + assert!( + w.ref_time() <= 50u64 * constants::WEIGHT_REF_TIME_PER_MILLIS, + "Weight should be at most 50 ms." + ); + } + } +} diff --git a/runtime/mainnet/src/weights/extrinsic_weights.rs b/runtime/mainnet/src/weights/extrinsic_weights.rs new file mode 100644 index 0000000..332c3b3 --- /dev/null +++ b/runtime/mainnet/src/weights/extrinsic_weights.rs @@ -0,0 +1,53 @@ +// 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 = + Weight::from_parts(constants::WEIGHT_REF_TIME_PER_NANOS.saturating_mul(125_000), 0); + } + + #[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.ref_time() >= 10u64 * constants::WEIGHT_REF_TIME_PER_MICROS, + "Weight should be at least 10 µs." + ); + // At most 1 ms. + assert!( + w.ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, + "Weight should be at most 1 ms." + ); + } + } +} diff --git a/runtime/mainnet/src/weights/mod.rs b/runtime/mainnet/src/weights/mod.rs new file mode 100644 index 0000000..ed0b4db --- /dev/null +++ b/runtime/mainnet/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/runtime/mainnet/src/weights/paritydb_weights.rs b/runtime/mainnet/src/weights/paritydb_weights.rs new file mode 100644 index 0000000..4338d92 --- /dev/null +++ b/runtime/mainnet/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_REF_TIME_PER_NANOS, + write: 50_000 * constants::WEIGHT_REF_TIME_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).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, + "Read weight should be at least 1 µs." + ); + assert!( + W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, + "Write weight should be at least 1 µs." + ); + // At most 1 ms. + assert!( + W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, + "Read weight should be at most 1 ms." + ); + assert!( + W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, + "Write weight should be at most 1 ms." + ); + } + } +} diff --git a/runtime/mainnet/src/weights/rocksdb_weights.rs b/runtime/mainnet/src/weights/rocksdb_weights.rs new file mode 100644 index 0000000..1d115d9 --- /dev/null +++ b/runtime/mainnet/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_REF_TIME_PER_NANOS, + write: 100_000 * constants::WEIGHT_REF_TIME_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).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, + "Read weight should be at least 1 µs." + ); + assert!( + W::get().writes(1).ref_time() >= constants::WEIGHT_REF_TIME_PER_MICROS, + "Write weight should be at least 1 µs." + ); + // At most 1 ms. + assert!( + W::get().reads(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, + "Read weight should be at most 1 ms." + ); + assert!( + W::get().writes(1).ref_time() <= constants::WEIGHT_REF_TIME_PER_MILLIS, + "Write weight should be at most 1 ms." + ); + } + } +} diff --git a/runtime/mainnet/src/xcm_config.rs b/runtime/mainnet/src/xcm_config.rs new file mode 100644 index 0000000..d431cc6 --- /dev/null +++ b/runtime/mainnet/src/xcm_config.rs @@ -0,0 +1,256 @@ +use super::{ + AccountId, AllPalletsWithSystem, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, + Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, +}; +use core::{marker::PhantomData, ops::ControlFlow}; +use frame_support::{ + log, match_types, parameter_types, + traits::{ConstU32, Everything, Nothing, ProcessMessageError}, + weights::Weight, +}; +use frame_system::EnsureRoot; +use pallet_xcm::XcmPassthrough; +use polkadot_parachain::primitives::Sibling; +use polkadot_runtime_common::impls::ToAuthor; +use xcm::latest::prelude::*; +use xcm_builder::{ + AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowTopLevelPaidExecutionFrom, + CreateMatcher, CurrencyAdapter, EnsureXcmOrigin, FixedWeightBounds, IsConcrete, MatchXcm, + NativeAsset, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, + SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, TakeWeightCredit, UsingComponents, WithComputedOrigin, +}; +use xcm_executor::{traits::ShouldExecute, XcmExecutor}; + +parameter_types! { + pub const RelayLocation: MultiLocation = MultiLocation::parent(); + pub const RelayNetwork: Option = None; + pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); + pub UniversalLocation: InteriorMultiLocation = 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 parent `AccountId`. + ParentIsPreset, + // Sibling parachain origins convert to AccountId via the `ParaId::into`. + SiblingParachainConvertsVia, + // Straight up local `AccountId32` origins just alias directly to `AccountId`. + AccountId32Aliases, +); + +/// Means for transacting assets on this chain. +pub type LocalAssetTransactor = CurrencyAdapter< + // Use this currency: + Balances, + // Use this currency when it is a fungible asset matching the given location or name: + IsConcrete, + // Do a simple punn to convert an AccountId32 MultiLocation into a native chain account ID: + LocationToAccountId, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + // We don't track any teleports. + (), +>; + +/// 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 XcmOriginToTransactDispatchOrigin = ( + // 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 + // `RuntimeOrigin::Signed` origin of the same 32-byte value. + SignedAccountId32AsNative, + // Xcm origins can be represented natively under the Xcm pallet's Xcm origin. + XcmPassthrough, +); + +parameter_types! { + // One XCM operation is 1_000_000_000 weight - almost certainly a conservative estimate. + pub UnitWeightCost: Weight = Weight::from_parts(1_000_000_000, 64 * 1024); + pub const MaxInstructions: u32 = 100; + pub const MaxAssetsIntoHolding: u32 = 64; +} + +match_types! { + pub type ParentOrParentsExecutivePlurality: impl Contains = { + MultiLocation { parents: 1, interior: Here } | + MultiLocation { parents: 1, interior: X1(Plurality { id: BodyId::Executive, .. }) } + }; +} + +//TODO: move DenyThenTry to polkadot's xcm module. +/// Deny executing the xcm message if it matches any of the Deny filter regardless of anything else. +/// If it passes the Deny, and matches one of the Allow cases then it is let through. +pub struct DenyThenTry(PhantomData, PhantomData) +where + Deny: ShouldExecute, + Allow: ShouldExecute; + +impl ShouldExecute for DenyThenTry +where + Deny: ShouldExecute, + Allow: ShouldExecute, +{ + fn should_execute( + origin: &MultiLocation, + message: &mut [Instruction], + max_weight: Weight, + weight_credit: &mut Weight, + ) -> Result<(), ProcessMessageError> { + Deny::should_execute(origin, message, max_weight, weight_credit)?; + Allow::should_execute(origin, message, max_weight, weight_credit) + } +} + +// See issue +pub struct DenyReserveTransferToRelayChain; +impl ShouldExecute for DenyReserveTransferToRelayChain { + fn should_execute( + origin: &MultiLocation, + message: &mut [Instruction], + _max_weight: Weight, + _weight_credit: &mut Weight, + ) -> Result<(), ProcessMessageError> { + message.matcher().match_next_inst_while( + |_| true, + |inst| match inst { + InitiateReserveWithdraw { + reserve: MultiLocation { parents: 1, interior: Here }, + .. + } + | DepositReserveAsset { + dest: MultiLocation { parents: 1, interior: Here }, .. + } + | TransferReserveAsset { + dest: MultiLocation { parents: 1, interior: Here }, .. + } => { + Err(ProcessMessageError::Unsupported) // Deny + }, + // An unexpected reserve transfer has arrived from the Relay Chain. Generally, + // `IsReserve` should not allow this, but we just log it here. + ReserveAssetDeposited { .. } + if matches!(origin, MultiLocation { parents: 1, interior: Here }) => + { + log::warn!( + target: "xcm::barrier", + "Unexpected ReserveAssetDeposited from the Relay Chain", + ); + Ok(ControlFlow::Continue(())) + }, + _ => Ok(ControlFlow::Continue(())), + }, + )?; + + // Permit everything else + Ok(()) + } +} + +pub type Barrier = DenyThenTry< + DenyReserveTransferToRelayChain, + ( + TakeWeightCredit, + WithComputedOrigin< + ( + AllowTopLevelPaidExecutionFrom, + AllowExplicitUnpaidExecutionFrom, + // ^^^ Parent and its exec plurality get free execution + ), + UniversalLocation, + ConstU32<8>, + >, + ), +>; + +pub struct XcmConfig; +impl xcm_executor::Config for XcmConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + // How to withdraw and deposit an asset. + type AssetTransactor = LocalAssetTransactor; + type OriginConverter = XcmOriginToTransactDispatchOrigin; + type IsReserve = NativeAsset; + type IsTeleporter = (); // Teleporting is disabled. + type UniversalLocation = UniversalLocation; + type Barrier = Barrier; + type Weigher = FixedWeightBounds; + type Trader = + UsingComponents>; + type ResponseHandler = PolkadotXcm; + type AssetTrap = PolkadotXcm; + type AssetClaims = PolkadotXcm; + type SubscriptionService = PolkadotXcm; + type PalletInstancesInfo = AllPalletsWithSystem; + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type AssetLocker = (); + type AssetExchanger = (); + type FeeManager = (); + type MessageExporter = (); + type UniversalAliases = Nothing; + type CallDispatcher = RuntimeCall; + type SafeCallFilter = Everything; +} + +/// 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, +); + +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub ReachableDest: Option = Some(Parent.into()); +} + +impl pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type SendXcmOrigin = EnsureXcmOrigin; + type AdminOrigin = EnsureRoot; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = EnsureXcmOrigin; + type XcmExecuteFilter = Nothing; + // ^ Disable dispatchable execute on the XCM pallet. + // Needs to be `Everything` for local testing. + type XcmExecutor = XcmExecutor; + type XcmTeleportFilter = Everything; + type XcmReserveTransferFilter = Nothing; + type Weigher = FixedWeightBounds; + type UniversalLocation = UniversalLocation; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + + const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; + // ^ Override for AdvertisedXcmVersion default + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; + type Currency = Balances; + type CurrencyMatcher = (); + type TrustedLockers = (); + type SovereignAccountOf = LocationToAccountId; + type MaxLockers = ConstU32<8>; + type WeightInfo = pallet_xcm::TestWeightInfo; + #[cfg(feature = "runtime-benchmarks")] + type ReachableDest = ReachableDest; +} + +impl cumulus_pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} diff --git a/runtime/src/currency.rs b/runtime/src/currency.rs deleted file mode 100644 index 5dda6fe..0000000 --- a/runtime/src/currency.rs +++ /dev/null @@ -1,11 +0,0 @@ -use crate::Balance; - -pub const MICROUNIT: Balance = 1_000_000; -pub const MILLIUNIT: Balance = 1_000 * MICROUNIT; // 1_000_000_000 -pub const UNIT: Balance = 1_000 * MILLIUNIT; - -pub const EXISTENTIAL_DEPOSIT: Balance = MILLIUNIT; - -pub const fn deposit(items: u32, bytes: u32) -> Balance { - (items as Balance * 20 * UNIT + (bytes as Balance) * 100 * MICROUNIT) / 100 -}