diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c82d1b9f..d43fb075 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -28,7 +28,7 @@ jobs: contents: write strategy: matrix: - runtime: [ "devnet", "testnet" ] + runtime: [ "devnet", "testnet", "mainnet" ] steps: - name: Checkout sources uses: actions/checkout@v4 diff --git a/Cargo.lock b/Cargo.lock index 9f217ed1..caf6c1d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4995,6 +4995,7 @@ dependencies = [ "polkadot-runtime-parachains", "pop-runtime-common", "pop-runtime-devnet", + "pop-runtime-mainnet", "sp-authority-discovery", "sp-consensus-aura", "sp-consensus-babe", @@ -10294,12 +10295,14 @@ dependencies = [ "futures", "jsonrpsee", "log", + "pallet-multisig", "pallet-transaction-payment-rpc", "parity-scale-codec", "polkadot-cli", "polkadot-primitives", "pop-runtime-common", "pop-runtime-devnet", + "pop-runtime-mainnet", "pop-runtime-testnet", "sc-basic-authorship", "sc-chain-spec", @@ -10434,6 +10437,73 @@ dependencies = [ "substrate-wasm-builder", ] +[[package]] +name = "pop-runtime-mainnet" +version = "0.1.0" +dependencies = [ + "cumulus-pallet-aura-ext", + "cumulus-pallet-parachain-system", + "cumulus-pallet-session-benchmarking", + "cumulus-pallet-xcm", + "cumulus-pallet-xcmp-queue", + "cumulus-primitives-aura", + "cumulus-primitives-core", + "cumulus-primitives-storage-weight-reclaim", + "cumulus-primitives-utility", + "enumflags2", + "env_logger 0.11.5", + "frame-benchmarking", + "frame-executive", + "frame-metadata-hash-extension", + "frame-support", + "frame-system", + "frame-system-benchmarking", + "frame-system-rpc-runtime-api", + "frame-try-runtime", + "hex", + "pallet-aura", + "pallet-authorship", + "pallet-balances", + "pallet-collator-selection", + "pallet-message-queue", + "pallet-multisig", + "pallet-preimage", + "pallet-proxy", + "pallet-scheduler", + "pallet-session", + "pallet-sudo", + "pallet-timestamp", + "pallet-transaction-payment", + "pallet-transaction-payment-rpc-runtime-api", + "pallet-utility", + "pallet-xcm", + "parachains-common", + "parity-scale-codec", + "polkadot-parachain-primitives", + "polkadot-runtime-common", + "pop-runtime-common", + "scale-info", + "smallvec", + "sp-api", + "sp-block-builder", + "sp-consensus-aura", + "sp-core", + "sp-genesis-builder", + "sp-inherents", + "sp-io", + "sp-offchain", + "sp-runtime", + "sp-session", + "sp-std", + "sp-transaction-pool", + "sp-version", + "staging-parachain-info", + "staging-xcm", + "staging-xcm-builder", + "staging-xcm-executor", + "substrate-wasm-builder", +] + [[package]] name = "pop-runtime-testnet" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index 8cd3f269..cc4fa5b1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,6 +21,7 @@ members = [ "node", "primitives", "runtime/devnet", + "runtime/mainnet", "runtime/testnet", ] @@ -54,6 +55,7 @@ substrate-wasm-builder = "23.0.0" pop-primitives = { path = "./primitives", default-features = false } pop-runtime-common = { path = "runtime/common", default-features = false } pop-runtime-devnet = { path = "runtime/devnet", default-features = true } # default-features=true required for `-p pop-node` builds +pop-runtime-mainnet = { path = "runtime/mainnet", default-features = true } # default-features=true required for `-p pop-node` builds pop-runtime-testnet = { path = "runtime/testnet", default-features = true } # default-features=true required for `-p pop-node` builds # Substrate diff --git a/integration-tests/Cargo.toml b/integration-tests/Cargo.toml index db94f2f0..0bbdc053 100644 --- a/integration-tests/Cargo.toml +++ b/integration-tests/Cargo.toml @@ -48,9 +48,11 @@ paseo-runtime-constants.workspace = true # Local pop-runtime-common.workspace = true pop-runtime-devnet.workspace = true +pop-runtime-mainnet.workspace = true [features] default = [ "std" ] +mainnet = [ "pop-runtime-mainnet/default" ] std = [ "asset-hub-paseo-runtime/std", "cumulus-primitives-core/std", @@ -65,6 +67,7 @@ std = [ "polkadot-runtime-parachains/std", "pop-runtime-common/std", "pop-runtime-devnet/std", + "pop-runtime-mainnet/std", "sp-authority-discovery/std", "sp-consensus-aura/std", "sp-consensus-babe/std", @@ -87,6 +90,7 @@ runtime-benchmarks = [ "polkadot-primitives/runtime-benchmarks", "pop-runtime-common/runtime-benchmarks", "pop-runtime-devnet/runtime-benchmarks", + "pop-runtime-mainnet/runtime-benchmarks", "sp-runtime/runtime-benchmarks", "xcm-executor/runtime-benchmarks", ] @@ -99,5 +103,6 @@ try-runtime = [ "pallet-message-queue/try-runtime", "paseo-runtime/try-runtime", "pop-runtime-devnet/try-runtime", + "pop-runtime-mainnet/try-runtime", "sp-runtime/try-runtime", ] diff --git a/integration-tests/src/chains/pop_network/mod.rs b/integration-tests/src/chains/pop_network/mod.rs index 043800e2..41daed27 100644 --- a/integration-tests/src/chains/pop_network/mod.rs +++ b/integration-tests/src/chains/pop_network/mod.rs @@ -2,29 +2,31 @@ pub(crate) mod genesis; use emulated_integration_tests_common::{ impl_accounts_helpers_for_parachain, impl_assert_events_helpers_for_parachain, - impl_assets_helpers_for_parachain, impl_xcm_helpers_for_parachain, impls::Parachain, - xcm_emulator::decl_test_parachains, + impl_xcm_helpers_for_parachain, impls::Parachain, xcm_emulator::decl_test_parachains, }; use frame_support::traits::OnInitialize; +#[cfg(not(feature = "mainnet"))] +use pop_runtime_devnet as runtime; +#[cfg(feature = "mainnet")] +use pop_runtime_mainnet as runtime; // PopNetwork Parachain declaration decl_test_parachains! { pub struct PopNetwork { genesis = genesis::genesis(), on_init = { - pop_runtime_devnet::AuraExt::on_initialize(1); + runtime::AuraExt::on_initialize(1); }, - runtime = pop_runtime_devnet, + runtime = runtime, core = { - XcmpMessageHandler: pop_runtime_devnet::XcmpQueue, - LocationToAccountId: pop_runtime_devnet::config::xcm::LocationToAccountId, - ParachainInfo: pop_runtime_devnet::ParachainInfo, + XcmpMessageHandler: runtime::XcmpQueue, + LocationToAccountId: runtime::config::xcm::LocationToAccountId, + ParachainInfo: runtime::ParachainInfo, MessageOrigin: cumulus_primitives_core::AggregateMessageOrigin, }, pallets = { - PolkadotXcm: pop_runtime_devnet::PolkadotXcm, - Assets: pop_runtime_devnet::Assets, - Balances: pop_runtime_devnet::Balances, + PolkadotXcm: runtime::PolkadotXcm, + Balances: runtime::Balances, } }, } @@ -32,5 +34,4 @@ decl_test_parachains! { // PopNetwork implementation impl_accounts_helpers_for_parachain!(PopNetwork); impl_assert_events_helpers_for_parachain!(PopNetwork); -impl_assets_helpers_for_parachain!(PopNetwork); impl_xcm_helpers_for_parachain!(PopNetwork); diff --git a/networks/mainnet.toml b/networks/mainnet.toml new file mode 100644 index 00000000..dc1fda4b --- /dev/null +++ b/networks/mainnet.toml @@ -0,0 +1,40 @@ +# pop up parachain -f ./networks/mainnet.toml + +[relaychain] +chain = "paseo-local" + +[relaychain.runtime_genesis_patch.balances] +balances = [ + # Pop sovereign account + ["5Ec4AhPKXY9B4ayGshkz2wFMh7N8gP7XKfAvtt1cigpG9FkJ", 60000000000000000], +] + +[[relaychain.nodes]] +name = "alice" +rpc_port = 8833 +validator = true + +[[relaychain.nodes]] +name = "bob" +validator = true + +[[parachains]] +id = 4001 +chain = "mainnet" +default_command = "./target/release/pop-node" + +[parachains.genesis_overrides.balances] +balances = [ + # Dev accounts + ["5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY", 10000000000000000], + ["5FHneW46xGXgs5mUiveU4sbTyGBzmstUspZC92UhjJM694ty", 10000000000000000], + ["5FLSigC9HGRKVhB9FiEo4Y3koPsNmBmLJbpXg2mp1hXcS59Y", 10000000000000000], + ["5DAAnrj7VHTznn2AWBemMuyBwZWs6FNFjdyVXUeYum3PTXFy", 10000000000000000], + ["5HGjWAeFDfFCWPsjFQdVV2Msvz2XtMktvgocEZcCj68kUMaw", 10000000000000000], + ["5CiPPseXPECbkjWCa6MnjNokrgYjMqmKndv2rSnekmSK2DjL", 10000000000000000], +] + +[[parachains.collators]] +name = "pop" +rpc_port = 9944 +args = ["-lruntime::contracts=debug", "-lpopapi::extension=debug"] \ No newline at end of file diff --git a/node/Cargo.toml b/node/Cargo.toml index adcd4b2b..05d17a51 100644 --- a/node/Cargo.toml +++ b/node/Cargo.toml @@ -22,6 +22,7 @@ serde_json.workspace = true # Local pop-runtime-common.workspace = true pop-runtime-devnet.workspace = true +pop-runtime-mainnet.workspace = true pop-runtime-testnet.workspace = true # Substrate @@ -80,6 +81,9 @@ cumulus-relay-chain-interface.workspace = true [build-dependencies] substrate-build-script-utils.workspace = true +[dev-dependencies] +pallet-multisig.workspace = true + [features] runtime-benchmarks = [ "cumulus-primitives-core/runtime-benchmarks", @@ -89,6 +93,7 @@ runtime-benchmarks = [ "polkadot-primitives/runtime-benchmarks", "pop-runtime-common/runtime-benchmarks", "pop-runtime-devnet/runtime-benchmarks", + "pop-runtime-mainnet/runtime-benchmarks", "pop-runtime-testnet/runtime-benchmarks", "sc-service/runtime-benchmarks", "sp-runtime/runtime-benchmarks", @@ -96,6 +101,7 @@ runtime-benchmarks = [ try-runtime = [ "polkadot-cli/try-runtime", "pop-runtime-devnet/try-runtime", + "pop-runtime-mainnet/try-runtime", "pop-runtime-testnet/try-runtime", "sp-runtime/try-runtime", ] diff --git a/node/src/chain_spec.rs b/node/src/chain_spec.rs index 2d208eb1..b41ea8aa 100644 --- a/node/src/chain_spec.rs +++ b/node/src/chain_spec.rs @@ -1,5 +1,6 @@ use cumulus_primitives_core::ParaId; use pop_runtime_common::{AccountId, AuraId, Signature}; +use pop_runtime_mainnet::SudoAddress; use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup}; use sc_service::ChainType; use serde::{Deserialize, Serialize}; @@ -12,12 +13,16 @@ pub type DevnetChainSpec = sc_service::GenericChainSpec; /// Specialized `ChainSpec` for the testnet parachain runtime. pub type TestnetChainSpec = sc_service::GenericChainSpec; +/// Specialized `ChainSpec` for the mainnet parachain runtime. +pub type MainnetChainSpec = sc_service::GenericChainSpec; + /// The default XCM version to set in genesis config. const SAFE_XCM_VERSION: u32 = xcm::prelude::XCM_VERSION; pub(crate) enum Relay { Paseo, PaseoLocal, + Polkadot, } /// Helper function to generate a crypto pair from seed @@ -74,12 +79,17 @@ pub fn pop_devnet_session_keys(keys: AuraId) -> pop_runtime_devnet::SessionKeys pub fn pop_testnet_session_keys(keys: AuraId) -> pop_runtime_testnet::SessionKeys { pop_runtime_testnet::SessionKeys { aura: keys } } +/// 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 pop_mainnet_session_keys(keys: AuraId) -> pop_runtime_mainnet::SessionKeys { + pop_runtime_mainnet::SessionKeys { aura: keys } +} fn configure_for_relay( relay: Relay, properties: &mut sc_chain_spec::Properties, ) -> (Extensions, u32) { - properties.insert("ss58Format".into(), 42.into()); let para_id; match relay { @@ -88,10 +98,22 @@ fn configure_for_relay( properties.insert("tokenSymbol".into(), "PAS".into()); properties.insert("tokenDecimals".into(), 10.into()); - let relay_chain = - if let Relay::Paseo = relay { "paseo".into() } else { "paseo-local".into() }; + let relay_chain = if let Relay::Paseo = relay { + properties.insert("ss58Format".into(), 0.into()); + "paseo".into() + } else { + properties.insert("ss58Format".into(), 42.into()); + "paseo-local".into() + }; (Extensions { relay_chain, para_id }, para_id) }, + Relay::Polkadot => { + para_id = 3395; + properties.insert("ss58Format".into(), 0.into()); + properties.insert("tokenSymbol".into(), "DOT".into()); + properties.insert("tokenDecimals".into(), 10.into()); + (Extensions { relay_chain: "polkadot".into(), para_id }, para_id) + }, } } @@ -173,6 +195,83 @@ pub fn testnet_config(relay: Relay) -> TestnetChainSpec { .build() } +pub fn mainnet_config(relay: Relay) -> MainnetChainSpec { + let mut properties = sc_chain_spec::Properties::new(); + let (extensions, para_id) = configure_for_relay(relay, &mut properties); + + let collator_0_account_id: AccountId = + AccountId::from_ss58check("15B6eUkXgoLA3dWruCRYWeBGNC8SCwuqiMtMTM1Zh2auSg3w").unwrap(); + let collator_0_aura_id: AuraId = + AuraId::from_ss58check("15B6eUkXgoLA3dWruCRYWeBGNC8SCwuqiMtMTM1Zh2auSg3w").unwrap(); + + // Multisig account for sudo, generated from the following signatories: + // - 15VPagCVayS6XvT5RogPYop3BJTJzwqR2mCGR1kVn3w58ygg + // - 142zako1kfvrpQ7pJKYR8iGUD58i4wjb78FUsmJ9WcXmkM5z + // - 15k9niqckMg338cFBoz9vWFGwnCtwPBquKvqJEfHApijZkDz + // - 14G3CUFnZUBnHZUhahexSZ6AgemaW9zMHBnGccy3df7actf4 + // - Threshold 2 + let sudo_account_id: AccountId = SudoAddress::get(); + + #[allow(deprecated)] + MainnetChainSpec::builder( + pop_runtime_mainnet::WASM_BINARY.expect("WASM binary was not built, please build it!"), + extensions, + ) + .with_name("Pop Network") + .with_id("pop") + .with_chain_type(ChainType::Live) + .with_genesis_config_patch(mainnet_genesis( + // initial collators. + vec![ + // POP COLLATOR 0 + (collator_0_account_id, collator_0_aura_id), + ], + sudo_account_id, + para_id.into(), + )) + .with_protocol_id("pop") + .with_properties(properties) + .build() +} + +fn mainnet_genesis( + invulnerables: Vec<(AccountId, AuraId)>, + root: AccountId, + id: ParaId, +) -> serde_json::Value { + use pop_runtime_mainnet::EXISTENTIAL_DEPOSIT; + + serde_json::json!({ + "balances": { + "balances": [], + }, + "parachainInfo": { + "parachainId": id, + }, + "collatorSelection": { + "invulnerables": invulnerables.iter().cloned().map(|(acc, _)| acc).collect::>(), + "candidacyBond": EXISTENTIAL_DEPOSIT * 16, + "desiredCandidates": 0, + }, + "session": { + "keys": invulnerables + .into_iter() + .map(|(acc, aura)| { + ( + acc.clone(), // account id + acc, // validator id + pop_mainnet_session_keys(aura), // session keys + ) + }) + .collect::>(), + }, + "polkadotXcm": { + "safeXcmVersion": Some(SAFE_XCM_VERSION), + }, + "sudo": { "key": Some(root) } + }) +} + fn testnet_genesis( invulnerables: Vec<(AccountId, AuraId)>, root: AccountId, @@ -246,3 +345,43 @@ fn devnet_genesis( "sudo": { "key": Some(root) } }) } + +#[test] +fn sudo_key_valid() { + // Source: https://github.com/paritytech/extended-parachain-template/blob/d08cec37117731953119ecaed79522a0812b46f5/node/src/chain_spec.rs#L79 + fn get_multisig_sudo_key(mut authority_set: Vec, threshold: u16) -> AccountId { + assert!(threshold > 0, "Threshold for sudo multisig cannot be 0"); + assert!(!authority_set.is_empty(), "Sudo authority set cannot be empty"); + assert!( + authority_set.len() >= threshold.into(), + "Threshold must be less than or equal to authority set members" + ); + // Sorting is done to deterministically order the multisig set + // So that a single authority set (A, B, C) may generate only a single unique multisig key + // Otherwise, (B, A, C) or (C, A, B) could produce different keys and cause chaos + authority_set.sort(); + + // Define a multisig threshold for `threshold / authority_set.len()` members + pallet_multisig::Pallet::::multi_account_id( + &authority_set[..], + threshold, + ) + } + + assert_eq!( + get_multisig_sudo_key( + vec![ + AccountId::from_ss58check("15VPagCVayS6XvT5RogPYop3BJTJzwqR2mCGR1kVn3w58ygg") + .unwrap(), + AccountId::from_ss58check("142zako1kfvrpQ7pJKYR8iGUD58i4wjb78FUsmJ9WcXmkM5z") + .unwrap(), + AccountId::from_ss58check("15k9niqckMg338cFBoz9vWFGwnCtwPBquKvqJEfHApijZkDz") + .unwrap(), + AccountId::from_ss58check("14G3CUFnZUBnHZUhahexSZ6AgemaW9zMHBnGccy3df7actf4") + .unwrap(), + ], + 2 + ), + SudoAddress::get() + ) +} diff --git a/node/src/command.rs b/node/src/command.rs index a6ebd620..9da4052d 100644 --- a/node/src/command.rs +++ b/node/src/command.rs @@ -23,6 +23,7 @@ use crate::{ enum Runtime { Devnet, Testnet, + Mainnet, } trait RuntimeResolver { @@ -35,6 +36,8 @@ fn runtime(id: &str) -> Runtime { Runtime::Devnet } else if id.starts_with("test") || id.ends_with("testnet") { Runtime::Testnet + } else if id.eq("pop") || id.ends_with("mainnet") { + Runtime::Mainnet } else { log::warn!( "No specific runtime was recognized for ChainSpec's Id: '{}', so Runtime::Devnet will \ @@ -72,12 +75,15 @@ fn load_spec(id: &str) -> std::result::Result, String> { "dev" | "devnet" | "dev-paseo" => Box::new(chain_spec::development_config(Relay::PaseoLocal)), "test" | "testnet" | "pop-paseo" => Box::new(chain_spec::testnet_config(Relay::Paseo)), + "pop" | "mainnet" | "pop-polkadot" | "pop-network" => + Box::new(chain_spec::mainnet_config(Relay::Polkadot)), "" | "local" => Box::new(chain_spec::development_config(Relay::PaseoLocal)), path => { let path: PathBuf = path.into(); match path.runtime() { Runtime::Devnet => Box::new(chain_spec::DevnetChainSpec::from_json_file(path)?), Runtime::Testnet => Box::new(chain_spec::TestnetChainSpec::from_json_file(path)?), + Runtime::Mainnet => Box::new(chain_spec::MainnetChainSpec::from_json_file(path)?), } }, }) @@ -175,6 +181,15 @@ macro_rules! construct_async_run { { $( $code )* }.map(|v| (v, task_manager)) }) } + Runtime::Mainnet => { + runner.async_run(|$config| { + let $components = new_partial::( + &$config + )?; + let task_manager = $components.task_manager; + { $( $code )* }.map(|v| (v, task_manager)) + }) + } } }} } @@ -190,6 +205,10 @@ macro_rules! construct_benchmark_partials { let $partials = new_partial::(&$config)?; $code }, + Runtime::Mainnet => { + let $partials = new_partial::(&$config)?; + $code + }, } }; } @@ -362,6 +381,21 @@ pub fn run() -> Result<()> { .map(|r| r.0) .map_err(Into::into) }, + Runtime::Mainnet => { + sp_core::crypto::set_default_ss58_version( + pop_runtime_mainnet::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/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index f7f7ddb7..f20ea377 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -45,8 +45,8 @@ pub const MAXIMUM_BLOCK_WEIGHT: Weight = // Unit = the base number of indivisible units for balances pub const UNIT: Balance = 10_000_000_000; // 10 decimals -pub const MILLIUNIT: Balance = UNIT / 1_000; -pub const MICROUNIT: Balance = UNIT / 1_000_000; +pub const MILLIUNIT: Balance = UNIT / 1_000; // 10_000_000 +pub const MICROUNIT: Balance = UNIT / 1_000_000; // 10_000 // Deposits pub const fn deposit(items: u32, bytes: u32) -> Balance { diff --git a/runtime/mainnet/Cargo.toml b/runtime/mainnet/Cargo.toml new file mode 100644 index 00000000..a3ddf745 --- /dev/null +++ b/runtime/mainnet/Cargo.toml @@ -0,0 +1,220 @@ +[package] +authors.workspace = true +description.workspace = true +edition.workspace = true +homepage.workspace = true +license.workspace = true +name = "pop-runtime-mainnet" +repository.workspace = true +version = "0.1.0" + +[package.metadata.docs.rs] +targets = [ "x86_64-unknown-linux-gnu" ] + +[build-dependencies] +substrate-wasm-builder.workspace = true + +[dependencies] +codec.workspace = true +scale-info.workspace = true +smallvec.workspace = true + +# Local +pop-runtime-common = { workspace = true, default-features = false } + +# Substrate +frame-benchmarking.workspace = true +frame-executive.workspace = true +frame-metadata-hash-extension.workspace = true +frame-support.workspace = true +frame-system.workspace = true +frame-system-benchmarking.workspace = true +frame-system-rpc-runtime-api.workspace = true +frame-try-runtime.workspace = true +pallet-aura.workspace = true +pallet-authorship.workspace = true +pallet-balances.workspace = true +pallet-message-queue.workspace = true +pallet-multisig.workspace = true +pallet-preimage.workspace = true +pallet-proxy.workspace = true +pallet-scheduler.workspace = true +pallet-session.workspace = true +pallet-sudo.workspace = true +pallet-timestamp.workspace = true +pallet-transaction-payment.workspace = true +pallet-transaction-payment-rpc-runtime-api.workspace = true +pallet-utility.workspace = true +sp-api.workspace = true +sp-block-builder.workspace = true +sp-consensus-aura.workspace = true +sp-core.workspace = true +sp-genesis-builder.workspace = true +sp-inherents.workspace = true +sp-io.workspace = true +sp-offchain.workspace = true +sp-runtime.workspace = true +sp-session.workspace = true +sp-std.workspace = true +sp-transaction-pool.workspace = true +sp-version.workspace = true + +# Polkadot +pallet-xcm.workspace = true +polkadot-parachain-primitives.workspace = true +polkadot-runtime-common.workspace = true +xcm.workspace = true +xcm-builder.workspace = true +xcm-executor.workspace = true + +# Cumulus +cumulus-pallet-aura-ext.workspace = true +cumulus-pallet-parachain-system.workspace = true +cumulus-pallet-session-benchmarking.workspace = true +cumulus-pallet-xcm.workspace = true +cumulus-pallet-xcmp-queue.workspace = true +cumulus-primitives-aura.workspace = true +cumulus-primitives-core.workspace = true +cumulus-primitives-storage-weight-reclaim.workspace = true +cumulus-primitives-utility.workspace = true +pallet-collator-selection.workspace = true +parachain-info.workspace = true +parachains-common.workspace = true + +[dev-dependencies] +enumflags2 = "0.7.9" +env_logger = "0.11.2" +hex = "0.4.3" + +[features] +default = [ "std" ] +std = [ + "codec/std", + "cumulus-pallet-aura-ext/std", + "cumulus-pallet-parachain-system/std", + "cumulus-pallet-session-benchmarking/std", + "cumulus-pallet-xcm/std", + "cumulus-pallet-xcmp-queue/std", + "cumulus-primitives-aura/std", + "cumulus-primitives-core/std", + "cumulus-primitives-storage-weight-reclaim/std", + "cumulus-primitives-utility/std", + "frame-benchmarking/std", + "frame-executive/std", + "frame-metadata-hash-extension/std", + "frame-support/std", + "frame-system-benchmarking/std", + "frame-system-rpc-runtime-api/std", + "frame-system/std", + "frame-try-runtime/std", + "pallet-aura/std", + "pallet-authorship/std", + "pallet-balances/std", + "pallet-collator-selection/std", + "pallet-message-queue/std", + "pallet-multisig/std", + "pallet-preimage/std", + "pallet-proxy/std", + "pallet-scheduler/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", + "parachains-common/std", + "polkadot-parachain-primitives/std", + "polkadot-runtime-common/std", + "pop-runtime-common/std", + "scale-info/std", + "sp-api/std", + "sp-block-builder/std", + "sp-consensus-aura/std", + "sp-core/std", + "sp-genesis-builder/std", + "sp-inherents/std", + "sp-io/std", + "sp-offchain/std", + "sp-runtime/std", + "sp-session/std", + "sp-std/std", + "sp-transaction-pool/std", + "sp-version/std", + "xcm-builder/std", + "xcm-executor/std", + "xcm/std", +] + +runtime-benchmarks = [ + "cumulus-pallet-parachain-system/runtime-benchmarks", + "cumulus-pallet-session-benchmarking/runtime-benchmarks", + "cumulus-pallet-xcmp-queue/runtime-benchmarks", + "cumulus-primitives-core/runtime-benchmarks", + "cumulus-primitives-utility/runtime-benchmarks", + "frame-benchmarking/runtime-benchmarks", + "frame-support/runtime-benchmarks", + "frame-system-benchmarking/runtime-benchmarks", + "frame-system/runtime-benchmarks", + "pallet-balances/runtime-benchmarks", + "pallet-collator-selection/runtime-benchmarks", + "pallet-message-queue/runtime-benchmarks", + "pallet-multisig/runtime-benchmarks", + "pallet-preimage/runtime-benchmarks", + "pallet-proxy/runtime-benchmarks", + "pallet-scheduler/runtime-benchmarks", + "pallet-sudo/runtime-benchmarks", + "pallet-timestamp/runtime-benchmarks", + "pallet-utility/runtime-benchmarks", + "pallet-xcm/runtime-benchmarks", + "parachains-common/runtime-benchmarks", + "polkadot-parachain-primitives/runtime-benchmarks", + "polkadot-runtime-common/runtime-benchmarks", + "pop-runtime-common/runtime-benchmarks", + "sp-runtime/runtime-benchmarks", + "xcm-builder/runtime-benchmarks", + "xcm-executor/runtime-benchmarks", +] + +try-runtime = [ + "cumulus-pallet-aura-ext/try-runtime", + "cumulus-pallet-parachain-system/try-runtime", + "cumulus-pallet-xcm/try-runtime", + "cumulus-pallet-xcmp-queue/try-runtime", + "frame-executive/try-runtime", + "frame-support/try-runtime", + "frame-system/try-runtime", + "frame-try-runtime/try-runtime", + "pallet-aura/try-runtime", + "pallet-authorship/try-runtime", + "pallet-balances/try-runtime", + "pallet-collator-selection/try-runtime", + "pallet-message-queue/try-runtime", + "pallet-multisig/try-runtime", + "pallet-preimage/try-runtime", + "pallet-proxy/try-runtime", + "pallet-scheduler/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", + "polkadot-runtime-common/try-runtime", + "sp-runtime/try-runtime", +] + +# Enable the metadata hash generation. +# +# This is hidden behind a feature because it increases the compile time. +# The wasm binary needs to be compiled twice, once to fetch the metadata, +# generate the metadata hash and then a second time with the +# `RUNTIME_METADATA_HASH` environment variable set for the `CheckMetadataHash` +# extension. +metadata-hash = [ "substrate-wasm-builder/metadata-hash" ] + +# A convenience feature for enabling things when doing a build +# for an on-chain release. +on-chain-release-build = [ "metadata-hash" ] diff --git a/runtime/mainnet/build.rs b/runtime/mainnet/build.rs new file mode 100644 index 00000000..ecc5fb01 --- /dev/null +++ b/runtime/mainnet/build.rs @@ -0,0 +1,16 @@ +#[cfg(all(feature = "std", feature = "metadata-hash"))] +fn main() { + substrate_wasm_builder::WasmBuilder::init_with_defaults() + .enable_metadata_hash("DOT", 10) + .build() +} + +#[cfg(all(feature = "std", not(feature = "metadata-hash")))] +fn main() { + substrate_wasm_builder::WasmBuilder::build_using_defaults() +} + +/// 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/mainnet/src/config/mod.rs b/runtime/mainnet/src/config/mod.rs new file mode 100644 index 00000000..913d0352 --- /dev/null +++ b/runtime/mainnet/src/config/mod.rs @@ -0,0 +1,2 @@ +mod proxy; +pub mod xcm; diff --git a/runtime/mainnet/src/config/proxy.rs b/runtime/mainnet/src/config/proxy.rs new file mode 100644 index 00000000..0b8ab9b9 --- /dev/null +++ b/runtime/mainnet/src/config/proxy.rs @@ -0,0 +1,57 @@ +use frame_support::traits::InstanceFilter; +use pop_runtime_common::proxy::{ + AnnouncementDepositBase, AnnouncementDepositFactor, MaxPending, MaxProxies, ProxyDepositBase, + ProxyDepositFactor, ProxyType, +}; +use sp_runtime::traits::BlakeTwo256; + +use crate::{Balances, Runtime, RuntimeCall, RuntimeEvent}; + +impl InstanceFilter for ProxyType { + fn filter(&self, c: &RuntimeCall) -> bool { + match self { + ProxyType::Any => true, + ProxyType::NonTransfer => !matches!(c, RuntimeCall::Balances { .. }), + ProxyType::CancelProxy => matches!( + c, + RuntimeCall::Proxy(pallet_proxy::Call::reject_announcement { .. }) | + RuntimeCall::Utility { .. } | + RuntimeCall::Multisig { .. } + ), + ProxyType::Assets => { + matches!(c, RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. }) + }, + ProxyType::AssetOwner => { + matches!(c, RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. }) + }, + ProxyType::AssetManager => { + matches!(c, RuntimeCall::Utility { .. } | RuntimeCall::Multisig { .. }) + }, + ProxyType::Collator => matches!( + c, + RuntimeCall::CollatorSelection { .. } | + RuntimeCall::Utility { .. } | + RuntimeCall::Multisig { .. } + ), + } + } + + fn is_superset(&self, o: &Self) -> bool { + ProxyType::is_superset(self, o) + } +} + +impl pallet_proxy::Config for Runtime { + type AnnouncementDepositBase = AnnouncementDepositBase; + type AnnouncementDepositFactor = AnnouncementDepositFactor; + type CallHasher = BlakeTwo256; + type Currency = Balances; + type MaxPending = MaxPending; + type MaxProxies = MaxProxies; + type ProxyDepositBase = ProxyDepositBase; + type ProxyDepositFactor = ProxyDepositFactor; + type ProxyType = ProxyType; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = pallet_proxy::weights::SubstrateWeight; +} diff --git a/runtime/mainnet/src/config/xcm.rs b/runtime/mainnet/src/config/xcm.rs new file mode 100644 index 00000000..0b5863a7 --- /dev/null +++ b/runtime/mainnet/src/config/xcm.rs @@ -0,0 +1,213 @@ +use core::marker::PhantomData; + +use frame_support::{ + parameter_types, + traits::{tokens::imbalance::ResolveTo, ConstU32, ContainsPair, Everything, Get, Nothing}, + weights::Weight, +}; +use frame_system::EnsureRoot; +use pallet_xcm::XcmPassthrough; +use parachains_common::xcm_config::{ + AllSiblingSystemParachains, ParentRelayOrSiblingParachains, RelayOrOtherSystemParachains, +}; +use polkadot_parachain_primitives::primitives::Sibling; +use xcm::latest::prelude::*; +use xcm_builder::{ + AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, + FrameTransactionalProcessor, FungibleAdapter, IsConcrete, NativeAsset, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + TrailingSetTopicAsId, UsingComponents, WithComputedOrigin, WithUniqueTopic, + XcmFeeManagerFromComponents, XcmFeeToAccount, +}; +use xcm_executor::XcmExecutor; + +use crate::{ + fee::WeightToFee, AccountId, AllPalletsWithSystem, Balances, ParachainInfo, ParachainSystem, + PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, SudoAddress, XcmpQueue, +}; + +parameter_types! { + pub const RelayLocation: Location = Location::parent(); + pub AssetHub: Location = Location::new(1, [Parachain(1000)]); + pub const RelayNetwork: Option = Some(Polkadot); + pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); + pub UniversalLocation: InteriorLocation = [GlobalConsensus(RelayNetwork::get().unwrap()), Parachain(ParachainInfo::parachain_id().into())].into(); +} + +/// Type for specifying how a `Location` 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 = FungibleAdapter< + // 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 Location 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 convert 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; +} + +pub type Barrier = TrailingSetTopicAsId<( + TakeWeightCredit, + AllowKnownQueryResponses, + WithComputedOrigin< + ( + AllowTopLevelPaidExecutionFrom, + AllowSubscriptionsFrom, + ), + UniversalLocation, + ConstU32<8>, + >, +)>; + +/// Asset filter that allows native/relay asset if coming from a certain location. +// Borrowed from https://github.com/paritytech/polkadot-sdk/blob/ea458d0b95d819d31683a8a09ca7973ae10b49be/cumulus/parachains/runtimes/testing/penpal/src/xcm_config.rs#L239 for now +pub struct NativeAssetFrom(PhantomData); +impl> ContainsPair for NativeAssetFrom { + fn contains(asset: &Asset, origin: &Location) -> bool { + let loc = T::get(); + &loc == origin && + matches!(asset, Asset { id: AssetId(asset_loc), fun: Fungible(_a) } + if *asset_loc == Location::from(Parent)) + } +} +pub type TrustedReserves = (NativeAsset, NativeAssetFrom); + +/// Locations that will not be charged fees in the executor, +/// either execution or delivery. +/// We only waive fees for system functions, which these locations represent. +pub type WaivedLocations = (RelayOrOtherSystemParachains,); + +pub struct XcmConfig; +impl xcm_executor::Config for XcmConfig { + type Aliasers = Nothing; + type AssetClaims = PolkadotXcm; + type AssetExchanger = (); + type AssetLocker = (); + // How to withdraw and deposit an asset. + type AssetTransactor = LocalAssetTransactor; + type AssetTrap = PolkadotXcm; + type Barrier = Barrier; + type CallDispatcher = RuntimeCall; + type FeeManager = XcmFeeManagerFromComponents< + WaivedLocations, + XcmFeeToAccount, + >; + type HrmpChannelAcceptedHandler = (); + type HrmpChannelClosingHandler = (); + type HrmpNewChannelOpenRequestHandler = (); + type IsReserve = TrustedReserves; + type IsTeleporter = (); + type MaxAssetsIntoHolding = MaxAssetsIntoHolding; + type MessageExporter = (); + type OriginConverter = XcmOriginToTransactDispatchOrigin; + type PalletInstancesInfo = AllPalletsWithSystem; + type ResponseHandler = PolkadotXcm; + type RuntimeCall = RuntimeCall; + type SafeCallFilter = Everything; + type SubscriptionService = PolkadotXcm; + type Trader = UsingComponents< + WeightToFee, + RelayLocation, + AccountId, + Balances, + ResolveTo, + >; + type TransactionalProcessor = FrameTransactionalProcessor; + type UniversalAliases = Nothing; + type UniversalLocation = UniversalLocation; + type Weigher = FixedWeightBounds; + type XcmRecorder = PolkadotXcm; + type XcmSender = XcmRouter; +} + +/// 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 = WithUniqueTopic<( + // Two routers - use UMP to communicate with the relay chain: + cumulus_primitives_utility::ParentAsUmp, + // ..and XCMP to communicate with the sibling chains. + XcmpQueue, +)>; + +impl pallet_xcm::Config for Runtime { + type AdminOrigin = EnsureRoot; + // ^ Override for AdvertisedXcmVersion default. + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; + type Currency = Balances; + type CurrencyMatcher = (); + type ExecuteXcmOrigin = EnsureXcmOrigin; + type MaxLockers = ConstU32<8>; + type MaxRemoteLockConsumers = ConstU32<0>; + type RemoteLockConsumerIdentifier = (); + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type SendXcmOrigin = EnsureXcmOrigin; + type SovereignAccountOf = LocationToAccountId; + type TrustedLockers = (); + type UniversalLocation = UniversalLocation; + type Weigher = FixedWeightBounds; + type WeightInfo = pallet_xcm::TestWeightInfo; + type XcmExecuteFilter = Nothing; + // ^ Disable dispatchable execute on the XCM pallet. + // Needs to be `Everything` for local testing. + type XcmExecutor = XcmExecutor; + // TODO: add filter to only allow reserve transfers of native to relay/asset hub + type XcmReserveTransferFilter = Everything; + type XcmRouter = XcmRouter; + type XcmTeleportFilter = Nothing; + + const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; +} + +impl cumulus_pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} diff --git a/runtime/mainnet/src/lib.rs b/runtime/mainnet/src/lib.rs new file mode 100644 index 00000000..536396af --- /dev/null +++ b/runtime/mainnet/src/lib.rs @@ -0,0 +1,1015 @@ +#![cfg_attr(not(feature = "std"), no_std)] +// `construct_runtime!` does a lot of recursion and requires us to increase the limit to 256. +#![recursion_limit = "256"] + +// Make the WASM binary available. +#[cfg(feature = "std")] +include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); + +pub mod config; +mod weights; + +use config::xcm::{RelayLocation, XcmOriginToTransactDispatchOrigin}; +use cumulus_pallet_parachain_system::RelayNumberMonotonicallyIncreases; +use cumulus_primitives_core::{AggregateMessageOrigin, ParaId}; +use frame_support::{ + derive_impl, + dispatch::DispatchClass, + genesis_builder_helper::{build_state, get_preset}, + parameter_types, + traits::{ + fungible::HoldConsideration, tokens::imbalance::ResolveTo, ConstBool, ConstU32, ConstU64, + ConstU8, Contains, EitherOfDiverse, EqualPrivilegeOnly, EverythingBut, LinearStoragePrice, + TransformOrigin, VariantCountOf, + }, + weights::{ConstantMultiplier, Weight}, + PalletId, +}; +use frame_system::{ + limits::{BlockLength, BlockWeights}, + EnsureRoot, +}; +use pallet_balances::Call as BalancesCall; +use pallet_xcm::{EnsureXcm, IsVoiceOfBody}; +use parachains_common::message_queue::{NarrowOriginToSibling, ParaIdToSibling}; +use polkadot_runtime_common::xcm_sender::NoPriceForMessageDelivery; +// Polkadot imports +use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; +pub use pop_runtime_common::{ + AuraId, Balance, BlockNumber, Hash, Nonce, Signature, AVERAGE_ON_INITIALIZE_RATIO, + BLOCK_PROCESSING_VELOCITY, DAYS, EXISTENTIAL_DEPOSIT, HOURS, MAXIMUM_BLOCK_WEIGHT, MICROUNIT, + MILLIUNIT, MINUTES, NORMAL_DISPATCH_RATIO, RELAY_CHAIN_SLOT_DURATION_MILLIS, SLOT_DURATION, + UNINCLUDED_SEGMENT_CAPACITY, UNIT, +}; +use sp_api::impl_runtime_apis; +use sp_core::{ + crypto::{KeyTypeId, Ss58Codec}, + OpaqueMetadata, +}; +#[cfg(any(feature = "std", test))] +pub use sp_runtime::BuildStorage; +use sp_runtime::{ + create_runtime_str, generic, impl_opaque_keys, + traits::{BlakeTwo256, Block as BlockT, IdentifyAccount, Verify}, + transaction_validity::{TransactionSource, TransactionValidity}, + ApplyExtrinsicResult, +}; +pub use sp_runtime::{ExtrinsicInclusionMode, MultiAddress, Perbill, Permill}; +use sp_std::prelude::*; +#[cfg(feature = "std")] +use sp_version::NativeVersion; +use sp_version::RuntimeVersion; +use weights::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight}; +// XCM Imports +use xcm::latest::prelude::BodyId; + +/// 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; + +/// 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, + cumulus_primitives_storage_weight_reclaim::StorageWeightReclaim, + frame_metadata_hash_extension::CheckMetadataHash, +); + +/// Unchecked extrinsic type as expected by this runtime. +pub type UncheckedExtrinsic = + generic::UncheckedExtrinsic; + +/// Migrations to apply on runtime upgrade. +pub type Migrations = (); + +/// Executive: handles dispatch to the various modules. +pub type Executive = frame_executive::Executive< + Runtime, + Block, + frame_system::ChainContext, + Runtime, + AllPalletsWithSystem, + Migrations, +>; + +pub const fn deposit(items: u32, bytes: u32) -> Balance { + // src: https://github.com/polkadot-fellows/runtimes/blob/main/system-parachains/constants/src/polkadot.rs#L70 + (items as Balance * 20 * UNIT + (bytes as Balance) * 100 * fee::MILLICENTS) / 100 +} + +/// Constants related to Polkadot fee payment. +/// Source: https://github.com/polkadot-fellows/runtimes/blob/main/system-parachains/constants/src/polkadot.rs#L65C47-L65C58 +pub mod fee { + use frame_support::{ + pallet_prelude::Weight, + weights::{ + constants::ExtrinsicBaseWeight, FeePolynomial, WeightToFeeCoefficient, + WeightToFeeCoefficients, WeightToFeePolynomial, + }, + }; + use pop_runtime_common::{Balance, MILLIUNIT}; + use smallvec::smallvec; + pub use sp_runtime::Perbill; + + pub const CENTS: Balance = MILLIUNIT * 10; // 100_000_000 + pub const MILLICENTS: Balance = CENTS / 1_000; // 100_000 + + /// Cost of every transaction byte at Polkadot system parachains. + /// + /// It is the Relay Chain (Polkadot) `TransactionByteFee` / 20. + pub const TRANSACTION_BYTE_FEE: Balance = MILLICENTS / 2; + + /// 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 time_poly: FeePolynomial = RefTimeToFee::polynomial().into(); + let proof_poly: FeePolynomial = ProofSizeToFee::polynomial().into(); + + // Take the maximum instead of the sum to charge by the more scarce resource. + time_poly.eval(weight.ref_time()).max(proof_poly.eval(weight.proof_size())) + } + } + + /// Maps the reference time component of `Weight` to a fee. + pub struct RefTimeToFee; + impl WeightToFeePolynomial for RefTimeToFee { + type Balance = Balance; + + fn polynomial() -> WeightToFeeCoefficients { + // In Polkadot, extrinsic base weight (smallest non-zero weight) is mapped to 1/10 CENT: + // The standard system parachain configuration is 1/20 of that, as in 1/200 CENT. + let p = CENTS; + let q = 200 * 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 20kb proof to 1 CENT. + let p = CENTS; + let q = 20_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 { + pub use sp_runtime::OpaqueExtrinsic as UncheckedExtrinsic; + use sp_runtime::{ + generic, + traits::{BlakeTwo256, Hash as HashT}, + }; + + use super::*; + /// 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; + /// Opaque block hash type. + pub type Hash = ::Output; +} + +impl_opaque_keys! { + pub struct SessionKeys { + pub aura: Aura, + } +} + +#[sp_version::runtime_version] +pub const VERSION: RuntimeVersion = RuntimeVersion { + spec_name: create_runtime_str!("pop"), + impl_name: create_runtime_str!("pop"), + authoring_version: 1, + #[allow(clippy::zero_prefixed_literal)] + spec_version: 00_01_00, + impl_version: 0, + apis: RUNTIME_API_VERSIONS, + transaction_version: 1, + state_version: 1, +}; + +/// The version information used to identify this runtime when compiled natively. +#[cfg(feature = "std")] +pub fn native_version() -> NativeVersion { + NativeVersion { runtime_version: VERSION, can_author_with: Default::default() } +} + +parameter_types! { + pub const Version: RuntimeVersion = VERSION; + + // This part is copied from Substrate's `bin/node/runtime/src/lib.rs`. + // The `RuntimeBlockLength` and `RuntimeBlockWeights` exist here because the + // `DeletionWeightLimit` and `DeletionQueueDepth` depend on those to parameterize + // the lazy contract deletion. + pub RuntimeBlockLength: BlockLength = + BlockLength::max_with_normal_ratio(5 * 1024 * 1024, NORMAL_DISPATCH_RATIO); + pub RuntimeBlockWeights: BlockWeights = BlockWeights::builder() + .base_block(BlockExecutionWeight::get()) + .for_class(DispatchClass::all(), |weights| { + weights.base_extrinsic = ExtrinsicBaseWeight::get(); + }) + .for_class(DispatchClass::Normal, |weights| { + weights.max_total = Some(NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT); + }) + .for_class(DispatchClass::Operational, |weights| { + weights.max_total = Some(MAXIMUM_BLOCK_WEIGHT); + // Operational transactions have some extra reserved space, so that they + // are included even if block reached `MAXIMUM_BLOCK_WEIGHT`. + weights.reserved = Some( + MAXIMUM_BLOCK_WEIGHT - NORMAL_DISPATCH_RATIO * MAXIMUM_BLOCK_WEIGHT + ); + }) + .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) + .build_or_panic(); + pub const SS58Prefix: u16 = 0; +} + +/// A type to identify filtered calls. +pub struct FilteredCalls; +impl Contains for FilteredCalls { + fn contains(c: &RuntimeCall) -> bool { + use BalancesCall::*; + matches!( + c, + RuntimeCall::Balances( + force_adjust_total_issuance { .. } | + force_set_balance { .. } | + force_transfer { .. } | + force_unreserve { .. } + ) + ) + } +} + +/// The default types are being injected by [`derive_impl`](`frame_support::derive_impl`) from +/// [`ParaChainDefaultConfig`](`struct@frame_system::config_preludes::ParaChainDefaultConfig`), +/// but overridden as needed. +#[derive_impl(frame_system::config_preludes::ParaChainDefaultConfig)] +impl frame_system::Config for Runtime { + /// The data to be stored in an account. + type AccountData = pallet_balances::AccountData; + /// The identifier used to distinguish between accounts. + type AccountId = AccountId; + /// The basic call filter to use in dispatchable. Supports everything as the default. + type BaseCallFilter = EverythingBut; + /// The block type. + type Block = Block; + /// Maximum number of block number to block hash mappings to keep (oldest pruned first). + type BlockHashCount = BlockHashCount; + /// The maximum length of a block (in bytes). + type BlockLength = RuntimeBlockLength; + /// Block & extrinsics weights: base values and limits. + type BlockWeights = RuntimeBlockWeights; + /// The weight of database operations that the runtime can invoke. + type DbWeight = RocksDbWeight; + /// The type for hashing blocks and tries. + type Hash = Hash; + type MaxConsumers = frame_support::traits::ConstU32<16>; + /// The index type for storing how many extrinsics an account has signed. + type Nonce = Nonce; + /// The action to take on a Runtime Upgrade + type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode; + /// This is used as an identifier of the chain. 42 is the generic substrate prefix. + type SS58Prefix = SS58Prefix; + /// Runtime version. + type Version = Version; +} + +impl pallet_timestamp::Config for Runtime { + type MinimumPeriod = ConstU64<0>; + /// A timestamp: milliseconds since the unix epoch. + type Moment = u64; + type OnTimestampSet = Aura; + type WeightInfo = (); +} + +impl pallet_authorship::Config for Runtime { + type EventHandler = (CollatorSelection,); + type FindAuthor = pallet_session::FindAccountFromAuthorIndex; +} + +parameter_types! { + // increase ED 100 times to match system chains: 1_000_000_000 + pub const ExistentialDeposit: Balance = EXISTENTIAL_DEPOSIT * 100; +} + +impl pallet_balances::Config for Runtime { + type AccountStore = System; + /// The type for recording an account's balance. + type Balance = Balance; + type DustRemoval = (); + type ExistentialDeposit = ExistentialDeposit; + type FreezeIdentifier = RuntimeFreezeReason; + type MaxFreezes = VariantCountOf; + type MaxLocks = ConstU32<50>; + type MaxReserves = ConstU32<50>; + type ReserveIdentifier = [u8; 8]; + /// The ubiquitous event type. + type RuntimeEvent = RuntimeEvent; + type RuntimeFreezeReason = RuntimeFreezeReason; + type RuntimeHoldReason = RuntimeHoldReason; + type WeightInfo = pallet_balances::weights::SubstrateWeight; +} + +parameter_types! { + /// Relay Chain `TransactionByteFee` / 10 + pub const TransactionByteFee: Balance = fee::TRANSACTION_BYTE_FEE; + pub SudoAddress: AccountId = AccountId::from_ss58check("15NMV2JX1NeMwarQiiZvuJ8ixUcvayFDcu1F9Wz1HNpSc8gP").expect("sudo address is valid SS58"); +} + +impl pallet_transaction_payment::Config for Runtime { + type FeeMultiplierUpdate = SlowAdjustingFeeUpdate; + type LengthToFee = ConstantMultiplier; + type OnChargeTransaction = + pallet_transaction_payment::FungibleAdapter>; + type OperationalFeeMultiplier = ConstU8<5>; + type RuntimeEvent = RuntimeEvent; + type WeightToFee = fee::WeightToFee; +} + +impl pallet_sudo::Config for Runtime { + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = (); +} + +parameter_types! { + pub const ReservedXcmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); + pub const ReservedDmpWeight: Weight = MAXIMUM_BLOCK_WEIGHT.saturating_div(4); + pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent; +} + +type ConsensusHook = cumulus_pallet_aura_ext::FixedVelocityConsensusHook< + Runtime, + RELAY_CHAIN_SLOT_DURATION_MILLIS, + BLOCK_PROCESSING_VELOCITY, + UNINCLUDED_SEGMENT_CAPACITY, +>; + +impl cumulus_pallet_parachain_system::Config for Runtime { + type CheckAssociatedRelayNumber = RelayNumberMonotonicallyIncreases; + type ConsensusHook = ConsensusHook; + type DmpQueue = frame_support::traits::EnqueueWithOrigin; + type OnSystemEvent = (); + type OutboundXcmpMessageSource = XcmpQueue; + type ReservedDmpWeight = ReservedDmpWeight; + type ReservedXcmpWeight = ReservedXcmpWeight; + type RuntimeEvent = RuntimeEvent; + type SelfParaId = parachain_info::Pallet; + type WeightInfo = (); + type XcmpMessageHandler = XcmpQueue; +} + +impl parachain_info::Config for Runtime {} + +parameter_types! { + pub MessageQueueServiceWeight: Weight = Perbill::from_percent(35) * RuntimeBlockWeights::get().max_block; + pub MessageQueueIdleServiceWeight: Weight = Perbill::from_percent(20) * RuntimeBlockWeights::get().max_block; +} + +impl pallet_message_queue::Config for Runtime { + type HeapSize = ConstU32<{ 64 * 1024 }>; + type IdleMaxServiceWeight = MessageQueueIdleServiceWeight; + type MaxStale = ConstU32<8>; + #[cfg(feature = "runtime-benchmarks")] + type MessageProcessor = + pallet_message_queue::mock_helpers::NoopMessageProcessor; + #[cfg(not(feature = "runtime-benchmarks"))] + type MessageProcessor = xcm_builder::ProcessXcmMessage< + AggregateMessageOrigin, + xcm_executor::XcmExecutor, + RuntimeCall, + >; + // The XCMP queue pallet is only ever able to handle the `Sibling(ParaId)` origin: + type QueueChangeHandler = NarrowOriginToSibling; + type QueuePausedQuery = NarrowOriginToSibling; + type RuntimeEvent = RuntimeEvent; + type ServiceWeight = MessageQueueServiceWeight; + type Size = u32; + type WeightInfo = (); +} + +impl cumulus_pallet_aura_ext::Config for Runtime {} + +impl cumulus_pallet_xcmp_queue::Config for Runtime { + type ChannelInfo = ParachainSystem; + type ControllerOrigin = EnsureRoot; + type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; + // Limit the number of messages and signals a HRMP channel can have at most + type MaxActiveOutboundChannels = ConstU32<128>; + type MaxInboundSuspended = ConstU32<1_000>; + // Limit the number of HRMP channels + type MaxPageSize = ConstU32<{ 103 * 1024 }>; + type PriceForSiblingDelivery = NoPriceForMessageDelivery; + type RuntimeEvent = RuntimeEvent; + type VersionWrapper = PolkadotXcm; + type WeightInfo = (); + // Enqueue XCMP messages from siblings for later processing. + type XcmpQueue = TransformOrigin; +} + +parameter_types! { + pub const Period: u32 = 6 * HOURS; + pub const Offset: u32 = 0; +} + +impl pallet_session::Config for Runtime { + type Keys = SessionKeys; + type NextSessionRotation = pallet_session::PeriodicSessions; + type RuntimeEvent = RuntimeEvent; + // Essentially just Aura, but let's be pedantic. + type SessionHandler = ::KeyTypeIdProviders; + type SessionManager = CollatorSelection; + type ShouldEndSession = pallet_session::PeriodicSessions; + 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 WeightInfo = (); +} + +impl pallet_aura::Config for Runtime { + type AllowMultipleBlocksPerSlot = ConstBool; + type AuthorityId = AuraId; + type DisabledValidators = (); + type MaxAuthorities = ConstU32<100_000>; + type SlotDuration = ConstU64; +} + +parameter_types! { + pub const PotId: PalletId = PalletId(*b"PotStake"); + // 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 Currency = Balances; + // should be a multiple of session or things will get inconsistent + type KickThreshold = Period; + type MaxCandidates = ConstU32<0>; + type MaxInvulnerables = ConstU32<20>; + type MinEligibleCollators = ConstU32<3>; + type PotId = PotId; + type RuntimeEvent = RuntimeEvent; + type UpdateOrigin = CollatorSelectionUpdateOrigin; + type ValidatorId = ::AccountId; + type ValidatorIdOf = pallet_collator_selection::IdentityCollator; + type ValidatorRegistration = Session; + type WeightInfo = (); +} + +parameter_types! { + pub MaximumSchedulerWeight: Weight = Perbill::from_percent(60) * + RuntimeBlockWeights::get().max_block; +} + +impl pallet_scheduler::Config for Runtime { + #[cfg(feature = "runtime-benchmarks")] + type MaxScheduledPerBlock = ConstU32<512>; + #[cfg(not(feature = "runtime-benchmarks"))] + type MaxScheduledPerBlock = ConstU32<50>; + type MaximumWeight = MaximumSchedulerWeight; + type OriginPrivilegeCmp = EqualPrivilegeOnly; + type PalletsOrigin = OriginCaller; + type Preimages = Preimage; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type RuntimeOrigin = RuntimeOrigin; + type ScheduleOrigin = EnsureRoot; + type WeightInfo = pallet_scheduler::weights::SubstrateWeight; +} + +parameter_types! { + pub const PreimageHoldReason: RuntimeHoldReason = RuntimeHoldReason::Preimage(pallet_preimage::HoldReason::Preimage); + pub const PreimageBaseDeposit: Balance = deposit(2, 64); + pub const PreimageByteDeposit: Balance = deposit(0, 1); +} + +impl pallet_preimage::Config for Runtime { + type Consideration = HoldConsideration< + AccountId, + Balances, + PreimageHoldReason, + LinearStoragePrice, + >; + type Currency = Balances; + type ManagerOrigin = EnsureRoot; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = pallet_preimage::weights::SubstrateWeight; +} + +parameter_types! { + // One storage item; key size is 32; value is size 4+4+16+32 bytes = 56 bytes. + pub const DepositBase: Balance = deposit(1, 88); + // Additional storage item size of 32 bytes. + pub const DepositFactor: Balance = deposit(0, 32); + pub const MaxSignatories: u32 = 100; +} + +impl pallet_multisig::Config for Runtime { + type Currency = Balances; + type DepositBase = DepositBase; + type DepositFactor = DepositFactor; + type MaxSignatories = MaxSignatories; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = pallet_multisig::weights::SubstrateWeight; +} + +impl pallet_utility::Config for Runtime { + type PalletsOrigin = OriginCaller; + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; + type WeightInfo = pallet_utility::weights::SubstrateWeight; +} + +#[frame_support::runtime] +mod runtime { + // Create the runtime by composing the FRAME pallets that were previously configured. + #[runtime::runtime] + #[runtime::derive( + RuntimeCall, + RuntimeEvent, + RuntimeError, + RuntimeOrigin, + RuntimeFreezeReason, + RuntimeHoldReason, + RuntimeSlashReason, + RuntimeLockId, + RuntimeTask + )] + pub struct Runtime; + + // System support stuff. + #[runtime::pallet_index(0)] + pub type System = frame_system::Pallet; + #[runtime::pallet_index(1)] + pub type ParachainSystem = cumulus_pallet_parachain_system::Pallet; + #[runtime::pallet_index(2)] + pub type Timestamp = pallet_timestamp::Pallet; + #[runtime::pallet_index(3)] + pub type ParachainInfo = parachain_info::Pallet; + + // Monetary stuff. + #[runtime::pallet_index(10)] + pub type Balances = pallet_balances::Pallet; + #[runtime::pallet_index(11)] + pub type TransactionPayment = pallet_transaction_payment::Pallet; + + // Governance + #[runtime::pallet_index(15)] + pub type Sudo = pallet_sudo; + + // Collator support. The order of these 4 are important and shall not change. + #[runtime::pallet_index(20)] + pub type Authorship = pallet_authorship::Pallet; + #[runtime::pallet_index(21)] + pub type CollatorSelection = pallet_collator_selection::Pallet; + #[runtime::pallet_index(22)] + pub type Session = pallet_session::Pallet; + #[runtime::pallet_index(23)] + pub type Aura = pallet_aura::Pallet; + #[runtime::pallet_index(24)] + pub type AuraExt = cumulus_pallet_aura_ext; + + // Scheduler + #[runtime::pallet_index(28)] + pub type Scheduler = pallet_scheduler; + + // Preimage + #[runtime::pallet_index(29)] + pub type Preimage = pallet_preimage; + + // XCM helpers. + #[runtime::pallet_index(30)] + pub type XcmpQueue = cumulus_pallet_xcmp_queue::Pallet; + #[runtime::pallet_index(31)] + pub type PolkadotXcm = pallet_xcm::Pallet; + #[runtime::pallet_index(32)] + pub type CumulusXcm = cumulus_pallet_xcm::Pallet; + #[runtime::pallet_index(33)] + pub type MessageQueue = pallet_message_queue::Pallet; + + // Proxy + #[runtime::pallet_index(41)] + pub type Proxy = pallet_proxy::Pallet; + // Multisig + #[runtime::pallet_index(42)] + pub type Multisig = pallet_multisig::Pallet; + // Utility + #[runtime::pallet_index(43)] + pub type Utility = pallet_utility::Pallet; +} + +#[cfg(feature = "runtime-benchmarks")] +mod benches { + frame_benchmarking::define_benchmarks!( + [frame_system, SystemBench::] + [pallet_balances, Balances] + [pallet_session, SessionBench::] + [pallet_timestamp, Timestamp] + [pallet_message_queue, MessageQueue] + [pallet_sudo, Sudo] + [pallet_collator_selection, CollatorSelection] + [cumulus_pallet_parachain_system, ParachainSystem] + [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(SLOT_DURATION) + } + + fn authorities() -> Vec { + pallet_aura::Authorities::::get().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) -> ExtrinsicInclusionMode{ + 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) -> Nonce { + 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_aura::AuraUnincludedSegmentApi for Runtime { + fn can_build_upon( + included_hash: ::Hash, + slot: cumulus_primitives_aura::Slot, + ) -> bool { + ConsensusHook::can_build_upon(included_hash, slot) + } + } + + 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 { + // NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to + // have a backtrace here. + 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(); + (list, storage_info) + } + + fn dispatch_benchmark( + config: frame_benchmarking::BenchmarkConfig + ) -> Result, sp_runtime::RuntimeString> { + use frame_benchmarking::{BenchmarkError, Benchmarking, BenchmarkBatch}; + + use frame_system_benchmarking::Pallet as SystemBench; + impl frame_system_benchmarking::Config for Runtime { + fn setup_set_code_requirements(code: &sp_std::vec::Vec) -> Result<(), BenchmarkError> { + ParachainSystem::initialize_for_set_code_benchmark(code.len() as u32); + Ok(()) + } + + fn verify_set_code() { + System::assert_last_event(cumulus_pallet_parachain_system::Event::::ValidationFunctionStored.into()); + } + } + + 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) + } + } + + impl sp_genesis_builder::GenesisBuilder for Runtime { + fn build_state(config: Vec) -> sp_genesis_builder::Result { + build_state::(config) + } + + fn get_preset(id: &Option) -> Option> { + get_preset::(id, |_| None) + } + + fn preset_names() -> Vec { + Default::default() + } + } +} + +cumulus_pallet_parachain_system::register_validate_block! { + Runtime = Runtime, + BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, +} + +#[cfg(test)] +mod tests { + use std::any::TypeId; + + use pallet_balances::AdjustmentDirection; + use BalancesCall::*; + use RuntimeCall::Balances; + + use super::*; + #[test] + fn filtering_force_adjust_total_issuance_works() { + assert!(FilteredCalls::contains(&Balances(force_adjust_total_issuance { + direction: AdjustmentDirection::Increase, + delta: 0 + }))); + } + + #[test] + fn filtering_force_set_balance_works() { + assert!(FilteredCalls::contains(&Balances(force_set_balance { + who: MultiAddress::Address32([0u8; 32]), + new_free: 0, + }))); + } + + #[test] + fn filtering_force_transfer_works() { + assert!(FilteredCalls::contains(&Balances(force_transfer { + source: MultiAddress::Address32([0u8; 32]), + dest: MultiAddress::Address32([0u8; 32]), + value: 0, + }))); + } + + #[test] + fn filtering_force_unreserve_works() { + assert!(FilteredCalls::contains(&Balances(force_unreserve { + who: MultiAddress::Address32([0u8; 32]), + amount: 0 + }))); + } + + #[test] + fn filtering_configured() { + assert_eq!( + TypeId::of::<::BaseCallFilter>(), + TypeId::of::>(), + ); + } + + #[test] + fn ed_is_correct() { + assert_eq!(ExistentialDeposit::get(), EXISTENTIAL_DEPOSIT * 100); + assert_eq!(ExistentialDeposit::get(), 1_000_000_000); + } + + #[test] + fn units_are_correct() { + // UNIT should have 10 decimals + assert_eq!(UNIT, 10_000_000_000); + assert_eq!(MILLIUNIT, 10_000_000); + assert_eq!(MICROUNIT, 10_000); + + // fee specific units + assert_eq!(fee::CENTS, 100_000_000); + assert_eq!(fee::MILLICENTS, 100_000); + } + + #[test] + fn transaction_byte_fee_is_correct() { + assert_eq!(fee::TRANSACTION_BYTE_FEE, 50_000); + } + + #[test] + fn deposit_works() { + const UNITS: Balance = 10_000_000_000; + const DOLLARS: Balance = UNITS; // 10_000_000_000 + const CENTS: Balance = DOLLARS / 100; // 100_000_000 + const MILLICENTS: Balance = CENTS / 1_000; // 100_000 + + // https://github.com/polkadot-fellows/runtimes/blob/e220854a081f30183999848ce6c11ca62647bcfa/relay/polkadot/constants/src/lib.rs#L36 + fn relay_deposit(items: u32, bytes: u32) -> Balance { + items as Balance * 20 * DOLLARS + (bytes as Balance) * 100 * MILLICENTS + } + + // https://github.com/polkadot-fellows/runtimes/blob/e220854a081f30183999848ce6c11ca62647bcfa/system-parachains/constants/src/polkadot.rs#L70 + fn system_para_deposit(items: u32, bytes: u32) -> Balance { + relay_deposit(items, bytes) / 100 + } + + assert_eq!(deposit(2, 64), system_para_deposit(2, 64)) + } +} diff --git a/runtime/mainnet/src/weights/block_weights.rs b/runtime/mainnet/src/weights/block_weights.rs new file mode 100644 index 00000000..e7fdb2aa --- /dev/null +++ b/runtime/mainnet/src/weights/block_weights.rs @@ -0,0 +1,53 @@ +// This file is part of Substrate. + +// Copyright (C) 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 00000000..1a4adb96 --- /dev/null +++ b/runtime/mainnet/src/weights/extrinsic_weights.rs @@ -0,0 +1,53 @@ +// This file is part of Substrate. + +// Copyright (C) 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 00000000..b473d49e --- /dev/null +++ b/runtime/mainnet/src/weights/mod.rs @@ -0,0 +1,27 @@ +// This file is part of Substrate. + +// Copyright (C) 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 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 00000000..27f7f1b0 --- /dev/null +++ b/runtime/mainnet/src/weights/paritydb_weights.rs @@ -0,0 +1,64 @@ +// This file is part of Substrate. + +// Copyright (C) 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 frame_support::weights::constants; + + use super::constants::ParityDbWeight as W; + + /// 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 00000000..bacad98c --- /dev/null +++ b/runtime/mainnet/src/weights/rocksdb_weights.rs @@ -0,0 +1,64 @@ +// This file is part of Substrate. + +// Copyright (C) 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 frame_support::weights::constants; + + use super::constants::RocksDbWeight as W; + + /// 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/testnet/src/lib.rs b/runtime/testnet/src/lib.rs index ab52c9ab..eccde36c 100644 --- a/runtime/testnet/src/lib.rs +++ b/runtime/testnet/src/lib.rs @@ -233,7 +233,7 @@ parameter_types! { }) .avg_block_initialization(AVERAGE_ON_INITIALIZE_RATIO) .build_or_panic(); - pub const SS58Prefix: u16 = 42; + pub const SS58Prefix: u16 = 0; } /// A type to identify filtered calls.