From 2b0a9ad0724e757b4b40e44d960772286d438436 Mon Sep 17 00:00:00 2001 From: Frank Bell Date: Fri, 6 Jan 2023 13:09:31 +0000 Subject: [PATCH 01/16] feat: add xcm simulator for trappist use cases --- Cargo.toml | 3 +- runtime/trappist/src/lib.rs | 2 +- xcm-simulator/Cargo.toml | 46 + xcm-simulator/src/lib.rs | 352 ++++++++ xcm-simulator/src/parachains/asset_reserve.rs | 786 ++++++++++++++++++ xcm-simulator/src/parachains/mod.rs | 170 ++++ xcm-simulator/src/parachains/parachain.rs | 182 ++++ xcm-simulator/src/parachains/trappist.rs | 221 +++++ xcm-simulator/src/relay_chain.rs | 549 ++++++++++++ 9 files changed, 2309 insertions(+), 2 deletions(-) create mode 100644 xcm-simulator/Cargo.toml create mode 100644 xcm-simulator/src/lib.rs create mode 100644 xcm-simulator/src/parachains/asset_reserve.rs create mode 100644 xcm-simulator/src/parachains/mod.rs create mode 100644 xcm-simulator/src/parachains/parachain.rs create mode 100644 xcm-simulator/src/parachains/trappist.rs create mode 100644 xcm-simulator/src/relay_chain.rs diff --git a/Cargo.toml b/Cargo.toml index 41b2ce5b..930d5c34 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,8 @@ members = [ "primitives/xcm", ] exclude = [ - "contracts" + "contracts", + "xcm-simulator" ] [profile.release] diff --git a/runtime/trappist/src/lib.rs b/runtime/trappist/src/lib.rs index 690aae36..a67c07e6 100644 --- a/runtime/trappist/src/lib.rs +++ b/runtime/trappist/src/lib.rs @@ -23,7 +23,7 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); pub mod constants; mod contracts; -mod xcm_config; +pub mod xcm_config; use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use sp_api::impl_runtime_apis; diff --git a/xcm-simulator/Cargo.toml b/xcm-simulator/Cargo.toml new file mode 100644 index 00000000..e9bdd57b --- /dev/null +++ b/xcm-simulator/Cargo.toml @@ -0,0 +1,46 @@ +[package] +name = "trappist-xcm-simulator" +version = "0.1.0" +authors = ["Parity Technologies "] +description = "Examples of xcm-simulator usage." +edition = "2021" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.0.0" } +scale-info = { version = "2.1.2", features = ["derive"] } + +frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +pallet-assets = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +pallet-asset-registry = { version = "0.0.1", path = "../pallets/asset-registry" } +pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +pallet-sudo = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } +sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } + +xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.30" } +xcm-simulator = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.30" } +xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.30" } +xcm-builder = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.30" } +pallet-xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.30" } + +# Polkadot +polkadot-core-primitives = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.30" } +polkadot-runtime-common = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.30" } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.30" } +polkadot-parachain = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.30" } + +# Cumulus +cumulus-pallet-xcm = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.30" } +cumulus-primitives-utility = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.30" } +pallet-collator-selection = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.30" } +parachains-common = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.30" } + +# Runtimes +rococo-runtime = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.30" } +statemine-runtime = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.30" } +base-runtime = { path = "../runtime/base" } +trappist-runtime = { path = "../runtime/trappist" } \ No newline at end of file diff --git a/xcm-simulator/src/lib.rs b/xcm-simulator/src/lib.rs new file mode 100644 index 00000000..2ddec9c3 --- /dev/null +++ b/xcm-simulator/src/lib.rs @@ -0,0 +1,352 @@ +// Copyright 2021 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +extern crate core; + +mod parachains; +mod relay_chain; + +use frame_support::{sp_tracing, traits::GenesisBuild}; +use parachains::{asset_reserve, parachain, trappist}; +use polkadot_parachain::primitives::Id as ParaId; +use sp_core::Get; +use sp_runtime::traits::AccountIdConversion; + +use xcm_simulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain}; + +pub const ALICE: sp_runtime::AccountId32 = sp_runtime::AccountId32::new([0u8; 32]); +pub const INITIAL_BALANCE: u128 = 1_000_000_000; + +const ASSET_RESERVE_PARA_ID: u32 = 1000; +decl_test_parachain! { + pub struct AssetReserve { + Runtime = asset_reserve::Runtime, + XcmpMessageHandler = asset_reserve::MsgQueue, + DmpMessageHandler = asset_reserve::MsgQueue, + new_ext = { + use asset_reserve::{MsgQueue, Runtime, System}; + + const INITIAL_BALANCE: u128 = ::AssetDeposit::get() * 2; + + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + + pallet_balances::GenesisConfig:: { balances: vec![(ALICE, INITIAL_BALANCE)] } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + sp_tracing::try_init_simple(); + System::set_block_number(1); + MsgQueue::set_para_id(ASSET_RESERVE_PARA_ID.into()); + }); + ext + }, + } +} + +const TRAPPIST_PARA_ID: u32 = 2000; +decl_test_parachain! { + pub struct Trappist { + Runtime = trappist::Runtime, + XcmpMessageHandler = trappist::MsgQueue, + DmpMessageHandler = trappist::MsgQueue, + new_ext = { + use trappist::{MsgQueue, Runtime, System}; + + let asset_deposit: u128 = ::AssetDeposit::get(); + let initial_balance: u128 = asset_deposit * 2; + + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + + pallet_balances::GenesisConfig:: { balances: vec![(ALICE, initial_balance)] } + .assimilate_storage(&mut t) + .unwrap(); + + pallet_sudo::GenesisConfig:: { key: Some(ALICE) } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + sp_tracing::try_init_simple(); + System::set_block_number(1); + MsgQueue::set_para_id(TRAPPIST_PARA_ID.into()); + }); + ext + }, + } +} + +const BASE_PARA_ID: u32 = 3000; +decl_test_parachain! { + pub struct Base { + Runtime = parachains::parachain::Runtime, + XcmpMessageHandler = parachains::parachain::MsgQueue, + DmpMessageHandler = parachains::parachain::MsgQueue, + new_ext = para_ext(BASE_PARA_ID), + } +} + +const A_PARA_ID: u32 = 1; +decl_test_parachain! { + pub struct ParaA { + Runtime = parachains::parachain::Runtime, + XcmpMessageHandler = parachains::parachain::MsgQueue, + DmpMessageHandler = parachains::parachain::MsgQueue, + new_ext = para_ext(A_PARA_ID), + } +} + +decl_test_relay_chain! { + pub struct Relay { + Runtime = relay_chain::Runtime, + XcmConfig = relay_chain::XcmConfig, + new_ext = { + use relay_chain::{Runtime, System}; + + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + + pallet_balances::GenesisConfig:: { + balances: vec![(ALICE, INITIAL_BALANCE), (para_account_id(1), INITIAL_BALANCE)], + } + .assimilate_storage(&mut t) + .unwrap(); + + pallet_sudo::GenesisConfig:: { key: Some(ALICE) } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| System::set_block_number(1)); + ext + }, + } +} + +decl_test_network! { + pub struct MockNet { + relay_chain = Relay, + parachains = vec![ + (A_PARA_ID, ParaA), + (ASSET_RESERVE_PARA_ID, AssetReserve), + (TRAPPIST_PARA_ID, Trappist), + (BASE_PARA_ID, Base), + ], + } +} + +pub fn para_account_id(id: u32) -> relay_chain::AccountId { + ParaId::from(id).into_account_truncating() +} + +fn para_ext(para_id: u32) -> sp_io::TestExternalities { + use parachain::{MsgQueue, Runtime, System}; + + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + + pallet_balances::GenesisConfig:: { balances: vec![(ALICE, INITIAL_BALANCE)] } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + sp_tracing::try_init_simple(); + System::set_block_number(1); + MsgQueue::set_para_id(para_id.into()); + }); + ext +} + +#[cfg(test)] +mod tests { + use super::*; + + use crate::relay_chain::mock_paras_sudo_wrapper; + use codec::Encode; + use frame_support::assert_ok; + use sp_runtime::MultiAddress::Id; + use std::sync::Once; + use xcm::{latest::prelude::*, opaque::VersionedXcm, VersionedMultiAssets::V1}; + use xcm_simulator::TestExt; + + static INIT: Once = Once::new(); + pub fn init() { + INIT.call_once(|| { + // Add test tracing + // todo: filter to only show xcm logs + sp_tracing::init_for_tests(); + }); + } + + const ASSET_RESERVE_PALLET_INDEX: u8 = 50; + + #[test] + fn dmp_teleport_asset_from_relay_chain_asset_reserve_parachain() { + todo!() + } + + #[test] + fn ump_teleport_asset_from_asset_reserve_parachain_to_relay_chain() { + todo!() + } + + #[test] + #[allow(non_upper_case_globals)] + fn hrmp_reserve_transfer_asset_from_asset_reserve_parachain_to_trappist_parachain() { + init(); + + MockNet::reset(); + + const xUSD: u32 = 1; + const txUSD: u32 = 10; + const MIN_BALANCE: asset_reserve::Balance = 1_000_000_000; + const MINT_AMOUNT: u128 = 1_000_000_000_000_000_000; + + AssetReserve::execute_with(|| { + // Create fungible asset on Reserve Parachain + assert_ok!(asset_reserve::Assets::create( + asset_reserve::RuntimeOrigin::signed(ALICE), + xUSD, + Id(ALICE), + MIN_BALANCE + )); + + // Mint fungible asset + assert_ok!(asset_reserve::Assets::mint( + asset_reserve::RuntimeOrigin::signed(ALICE), + xUSD, + Id(ALICE), + MINT_AMOUNT + )); + assert_eq!(asset_reserve::Assets::balance(xUSD, &ALICE), MINT_AMOUNT); + }); + + Relay::execute_with(|| { + // Declare xUSD (on Reserve Parachain) as self-sufficient via Relay Chain + paras_sudo_wrapper_sudo_queue_downward_xcm(asset_reserve::RuntimeCall::Assets( + pallet_assets::Call::::force_asset_status { + id: xUSD, + owner: Id(ALICE), + issuer: Id(ALICE), + admin: Id(ALICE), + freezer: Id(ALICE), + min_balance: MIN_BALANCE, + is_sufficient: true, + is_frozen: false, + }, + )); + }); + + Trappist::execute_with(|| { + // Create derivative asset on Trappist Parachain + assert_ok!(trappist::Assets::create( + trappist::RuntimeOrigin::signed(ALICE), + txUSD, + Id(ALICE), + MIN_BALANCE + )); + + // Map derivative asset (txUSD) to multi-location (xUSD within Assets pallet on Reserve + // Parachain) via Asset Registry + assert_ok!(trappist::Sudo::sudo( + trappist::RuntimeOrigin::signed(ALICE), + Box::new(trappist::RuntimeCall::AssetRegistry(pallet_asset_registry::Call::< + trappist::Runtime, + >::register_reserve_asset { + asset_id: txUSD, + asset_multi_location: ( + Parent, + X3( + Parachain(ASSET_RESERVE_PARA_ID), + PalletInstance(ASSET_RESERVE_PALLET_INDEX), + GeneralIndex(xUSD as u128), + ), + ) + .into(), + })), + )); + assert!(trappist::AssetRegistry::asset_id_multilocation(txUSD).is_some()) + }); + + const SEND_AMOUNT: u128 = 10_000_000_000_000_000; + + AssetReserve::execute_with(|| { + // Reserve parachain should be able to reserve-transfer an asset to Trappist Parachain + assert_ok!(asset_reserve::PolkadotXcm::limited_reserve_transfer_assets( + asset_reserve::RuntimeOrigin::signed(ALICE), + Box::new((Parent, Parachain(TRAPPIST_PARA_ID)).into()), + Box::new(X1(AccountId32 { network: Any, id: ALICE.into() }).into().into()), + Box::new(V1(MultiAssets::from_sorted_and_deduplicated_skip_checks(vec![ + MultiAsset { + id: Concrete( + X2( + PalletInstance(ASSET_RESERVE_PALLET_INDEX), + GeneralIndex(xUSD as u128) + ) + .into(), + ), + fun: Fungible(SEND_AMOUNT), + } + ]))), + 0, + WeightLimit::Unlimited, + )); + + // Check send amount moved to sovereign account + let sovereign_account = asset_reserve::sovereign_account(TRAPPIST_PARA_ID); + assert_eq!(asset_reserve::Assets::balance(xUSD, &sovereign_account), SEND_AMOUNT); + }); + + const FEES: u128 = 1_600_000_000; + Trappist::execute_with(|| { + // Check beneficiary account balance + assert_balance(trappist::Assets::balance(txUSD, &ALICE), SEND_AMOUNT, FEES); + }); + } + + #[test] + #[allow(non_upper_case_globals)] + fn hrmp_two_hop_reserve_transfer_from_trappist_parachain_to_tertiary_parachain() { + todo!() + } + + fn assert_balance(actual: u128, expected: u128, fees: u128) { + assert!( + actual >= (expected - fees) && actual <= expected, + "expected: {expected}, actual: {actual} fees: {fees}" + ) + } + + fn paras_sudo_wrapper_sudo_queue_downward_xcm(call: RuntimeCall) { + let sudo_queue_downward_xcm = + relay_chain::RuntimeCall::ParasSudoWrapper(mock_paras_sudo_wrapper::Call::< + relay_chain::Runtime, + >::sudo_queue_downward_xcm { + id: ParaId::new(ASSET_RESERVE_PARA_ID), + xcm: Box::new(VersionedXcm::V2(Xcm(vec![Transact { + origin_type: OriginKind::Superuser, + require_weight_at_most: 10000000000u64, + call: call.encode().into(), + }]))), + }); + + assert_ok!(relay_chain::Sudo::sudo( + relay_chain::RuntimeOrigin::signed(ALICE), + Box::new(sudo_queue_downward_xcm), + )); + } +} diff --git a/xcm-simulator/src/parachains/asset_reserve.rs b/xcm-simulator/src/parachains/asset_reserve.rs new file mode 100644 index 00000000..a45175f7 --- /dev/null +++ b/xcm-simulator/src/parachains/asset_reserve.rs @@ -0,0 +1,786 @@ +// Copyright 2021 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Asset Reserve Parachain runtime mock. + +use frame_support::{ + construct_runtime, parameter_types, + traits::{Everything, Nothing}, + weights::constants::RocksDbWeight, +}; +use pallet_xcm::XcmPassthrough; +pub use parachains_common::{AccountId, AssetId, Balance, Index}; +use polkadot_runtime_common::BlockHashCount; +use sp_core::H256; +use sp_runtime::traits::{AccountIdLookup, BlakeTwo256, ConvertInto}; +use sp_std::prelude::*; +pub use statemine_runtime::xcm_config::LocationToAccountId; +use statemine_runtime::{ + common::{ + impls::ToStakingPot, xcm_config::AssetFeeAsExistentialDepositMultiplier, BlockNumber, + Header, + }, + constants::fee::WeightToFee, + xcm_config::{ + AssetTransactors, AssetsPalletLocation, Barrier, FungiblesTransactor, KsmLocation, + MaxInstructions, RelayNetwork, XcmAssetFeesReceiver, + }, + ApprovalDeposit, AssetAccountDeposit, AssetDeposit, AssetsForceOrigin, AssetsStringLimit, + CollatorSelectionUpdateOrigin, ExistentialDeposit, MaxCandidates, MaxInvulnerables, MaxLocks, + MaxReserves, MetadataDepositBase, MetadataDepositPerByte, MinCandidates, Period, PotId, + RuntimeBlockLength, RuntimeBlockWeights, SS58Prefix, Session, Version, +}; +use xcm::latest::prelude::*; +use xcm_builder::{ + AsPrefixedGeneralIndex, ConvertedConcreteAssetId, EnsureXcmOrigin, LocationInverter, + NativeAsset, ParentAsSuperuser, RelayChainAsNative, SiblingParachainAsNative, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, UsingComponents, + WeightInfoBounds, +}; +use xcm_executor::{ + traits::{Convert, JustTry}, + XcmExecutor, +}; + +impl frame_system::Config for Runtime { + type BaseCallFilter = Everything; + type BlockWeights = RuntimeBlockWeights; + type BlockLength = RuntimeBlockLength; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Index = Index; + type BlockNumber = BlockNumber; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = AccountIdLookup; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type DbWeight = RocksDbWeight; + type Version = Version; + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = weights::frame_system::WeightInfo; + type SS58Prefix = SS58Prefix; + type OnSetCode = (); //cumulus_pallet_parachain_system::ParachainSetCode; + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +impl super::mock_msg_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +impl pallet_assets::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type Currency = Balances; + type ForceOrigin = AssetsForceOrigin; + type AssetDeposit = AssetDeposit; + type AssetAccountDeposit = AssetAccountDeposit; + type MetadataDepositBase = MetadataDepositBase; + type MetadataDepositPerByte = MetadataDepositPerByte; + type ApprovalDeposit = ApprovalDeposit; + type StringLimit = AssetsStringLimit; + type Freezer = (); + type Extra = (); + type WeightInfo = (); +} + +impl pallet_balances::Config for Runtime { + type Balance = Balance; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = weights::pallet_balances::WeightInfo; + type MaxLocks = MaxLocks; + type MaxReserves = MaxReserves; + type ReserveIdentifier = [u8; 8]; +} + +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; + type KickThreshold = Period; + type ValidatorId = ::AccountId; + type ValidatorIdOf = pallet_collator_selection::IdentityCollator; + type ValidatorRegistration = Session; + type WeightInfo = weights::pallet_collator_selection::WeightInfo; +} + +pub type XcmRouter = crate::ParachainXcmRouter; +pub type LocalOriginToLocation = SignedToAccountId32; + +impl pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = EnsureXcmOrigin; + type XcmExecuteFilter = Nothing; + type XcmExecutor = XcmExecutor; + type XcmTeleportFilter = Everything; + type XcmReserveTransferFilter = Everything; + type Weigher = WeightInfoBounds< + weights::xcm::StatemineXcmWeight, + RuntimeCall, + MaxInstructions, + >; + + type LocationInverter = LocationInverter; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; +} + +impl cumulus_pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +parameter_types! { + pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); + pub Ancestry: MultiLocation = Parachain(MsgQueue::parachain_id().into()).into(); +} + +pub type XcmOriginToTransactDispatchOrigin = ( + SovereignSignedViaLocation, + RelayChainAsNative, + SiblingParachainAsNative, + ParentAsSuperuser, + SignedAccountId32AsNative, + XcmPassthrough, +); + +pub struct XcmConfig; +impl xcm_executor::Config for XcmConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + type AssetTransactor = AssetTransactors; + type OriginConverter = XcmOriginToTransactDispatchOrigin; + type IsReserve = (); + type IsTeleporter = NativeAsset; + type LocationInverter = LocationInverter; + type Barrier = Barrier; + type Weigher = WeightInfoBounds< + weights::xcm::StatemineXcmWeight, + RuntimeCall, + MaxInstructions, + >; + type Trader = ( + UsingComponents>, + cumulus_primitives_utility::TakeFirstAssetTrader< + AccountId, + AssetFeeAsExistentialDepositMultiplier< + Runtime, + WeightToFee, + pallet_assets::BalanceToAssetBalance, + >, + ConvertedConcreteAssetId< + AssetId, + Balance, + AsPrefixedGeneralIndex, + JustTry, + >, + Assets, + cumulus_primitives_utility::XcmFeesTo32ByteAccount< + FungiblesTransactor, + AccountId, + XcmAssetFeesReceiver, + >, + >, + ); + type ResponseHandler = PolkadotXcm; + type AssetTrap = PolkadotXcm; + type AssetClaims = PolkadotXcm; + type SubscriptionService = PolkadotXcm; +} + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +construct_runtime!( + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Storage, Config, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + MsgQueue: super::mock_msg_queue::{Pallet, Storage, Event}, + + // Collator support + CollatorSelection: pallet_collator_selection::{Pallet, Call, Storage, Event, Config} = 21, + + // XCM helpers + PolkadotXcm: pallet_xcm::{Pallet, Call, Event, Origin} = 31, + CumulusXcm: cumulus_pallet_xcm::{Pallet, Event, Origin} = 32, + + Assets: pallet_assets::{Pallet, Call, Storage, Event} = 50, + } +); + +#[allow(dead_code)] +pub(crate) fn sovereign_account(para_id: u32) -> AccountId { + LocationToAccountId::convert_ref(MultiLocation::new(1, X1(Parachain(para_id)))).unwrap() +} + +mod weights { + pub(crate) mod frame_system { + use frame_support::{traits::Get, weights::Weight}; + use sp_std::marker::PhantomData; + + /// Weight functions for `frame_system`. + pub struct WeightInfo(PhantomData); + impl frame_system::WeightInfo for WeightInfo { + /// The range of component `b` is `[0, 3932160]`. + fn remark(_b: u32) -> Weight { + Weight::from_ref_time(0 as u64) + } + /// The range of component `b` is `[0, 3932160]`. + fn remark_with_event(b: u32) -> Weight { + Weight::from_ref_time(0 as u64) + // Standard Error: 0 + .saturating_add(Weight::from_ref_time(1_000 as u64).saturating_mul(b as u64)) + } + // Storage: System Digest (r:1 w:1) + // Storage: unknown [0x3a686561707061676573] (r:0 w:1) + fn set_heap_pages() -> Weight { + Weight::from_ref_time(8_677_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: Skipped Metadata (r:0 w:0) + /// The range of component `i` is `[1, 1000]`. + fn set_storage(i: u32) -> Weight { + Weight::from_ref_time(0 as u64) + // Standard Error: 1_000 + .saturating_add(Weight::from_ref_time(625_000 as u64).saturating_mul(i as u64)) + .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(i as u64))) + } + // Storage: Skipped Metadata (r:0 w:0) + /// The range of component `i` is `[1, 1000]`. + fn kill_storage(i: u32) -> Weight { + Weight::from_ref_time(0 as u64) + // Standard Error: 2_000 + .saturating_add(Weight::from_ref_time(554_000 as u64).saturating_mul(i as u64)) + .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(i as u64))) + } + // Storage: Skipped Metadata (r:0 w:0) + /// The range of component `p` is `[1, 1000]`. + fn kill_prefix(p: u32) -> Weight { + Weight::from_ref_time(0 as u64) + // Standard Error: 2_000 + .saturating_add( + Weight::from_ref_time(1_128_000 as u64).saturating_mul(p as u64), + ) + .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(p as u64))) + } + } + } + + pub(crate) mod pallet_balances { + use frame_support::{traits::Get, weights::Weight}; + use sp_std::marker::PhantomData; + + /// Weight functions for `pallet_balances`. + pub struct WeightInfo(PhantomData); + impl pallet_balances::WeightInfo for WeightInfo { + // Storage: System Account (r:1 w:1) + fn transfer() -> Weight { + Weight::from_ref_time(46_411_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: System Account (r:1 w:1) + fn transfer_keep_alive() -> Weight { + Weight::from_ref_time(34_589_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: System Account (r:1 w:1) + fn set_balance_creating() -> Weight { + Weight::from_ref_time(25_591_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: System Account (r:1 w:1) + fn set_balance_killing() -> Weight { + Weight::from_ref_time(29_471_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: System Account (r:2 w:2) + fn force_transfer() -> Weight { + Weight::from_ref_time(46_550_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: System Account (r:1 w:1) + fn transfer_all() -> Weight { + Weight::from_ref_time(40_804_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: System Account (r:1 w:1) + fn force_unreserve() -> Weight { + Weight::from_ref_time(22_516_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + } + } + + pub(crate) mod pallet_collator_selection { + use frame_support::{traits::Get, weights::Weight}; + use sp_std::marker::PhantomData; + + /// Weight functions for `pallet_collator_selection`. + pub struct WeightInfo(PhantomData); + impl pallet_collator_selection::WeightInfo for WeightInfo { + // Storage: Session NextKeys (r:1 w:0) + // Storage: CollatorSelection Invulnerables (r:0 w:1) + /// The range of component `b` is `[1, 100]`. + fn set_invulnerables(b: u32) -> Weight { + Weight::from_ref_time(23_858_000 as u64) + // Standard Error: 3_000 + .saturating_add( + Weight::from_ref_time(2_412_000 as u64).saturating_mul(b as u64), + ) + .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(b as u64))) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: CollatorSelection DesiredCandidates (r:0 w:1) + fn set_desired_candidates() -> Weight { + Weight::from_ref_time(14_642_000 as u64) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: CollatorSelection CandidacyBond (r:0 w:1) + fn set_candidacy_bond() -> Weight { + Weight::from_ref_time(14_842_000 as u64) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: CollatorSelection Candidates (r:1 w:1) + // Storage: CollatorSelection DesiredCandidates (r:1 w:0) + // Storage: CollatorSelection Invulnerables (r:1 w:0) + // Storage: Session NextKeys (r:1 w:0) + // Storage: CollatorSelection CandidacyBond (r:1 w:0) + // Storage: CollatorSelection LastAuthoredBlock (r:0 w:1) + /// The range of component `c` is `[1, 1000]`. + fn register_as_candidate(c: u32) -> Weight { + Weight::from_ref_time(61_940_000 as u64) + // Standard Error: 0 + .saturating_add(Weight::from_ref_time(170_000 as u64).saturating_mul(c as u64)) + .saturating_add(T::DbWeight::get().reads(5 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: CollatorSelection Candidates (r:1 w:1) + // Storage: CollatorSelection LastAuthoredBlock (r:0 w:1) + /// The range of component `c` is `[6, 1000]`. + fn leave_intent(c: u32) -> Weight { + Weight::from_ref_time(60_018_000 as u64) + // Standard Error: 1_000 + .saturating_add(Weight::from_ref_time(162_000 as u64).saturating_mul(c as u64)) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: System Account (r:2 w:2) + // Storage: System BlockWeight (r:1 w:1) + // Storage: CollatorSelection LastAuthoredBlock (r:0 w:1) + fn note_author() -> Weight { + Weight::from_ref_time(35_100_000 as u64) + .saturating_add(T::DbWeight::get().reads(3 as u64)) + .saturating_add(T::DbWeight::get().writes(4 as u64)) + } + // Storage: CollatorSelection Candidates (r:1 w:1) + // Storage: CollatorSelection LastAuthoredBlock (r:1000 w:1) + // Storage: System Account (r:1 w:1) + // Storage: CollatorSelection Invulnerables (r:1 w:0) + // Storage: System BlockWeight (r:1 w:1) + /// The range of component `r` is `[1, 1000]`. + /// The range of component `c` is `[1, 1000]`. + fn new_session(r: u32, c: u32) -> Weight { + Weight::from_ref_time(0 as u64) + // Standard Error: 1_237_000 + .saturating_add( + Weight::from_ref_time(6_686_000 as u64).saturating_mul(r as u64), + ) + // Standard Error: 1_237_000 + .saturating_add( + Weight::from_ref_time(32_537_000 as u64).saturating_mul(c as u64), + ) + .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(c as u64))) + .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(r as u64))) + .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(c as u64))) + } + } + } + + pub(crate) mod xcm { + + use super::super::Runtime; + use frame_support::weights::Weight; + use pallet_xcm_benchmarks_fungible::WeightInfo as XcmFungibleWeight; + use pallet_xcm_benchmarks_generic::WeightInfo as XcmGeneric; + use sp_std::{cmp, prelude::*}; + use xcm::{ + latest::{prelude::*, Weight as XCMWeight}, + DoubleEncoded, + }; + + trait WeighMultiAssets { + fn weigh_multi_assets(&self, weight: Weight) -> XCMWeight; + } + + const MAX_ASSETS: u32 = 100; + + impl WeighMultiAssets for MultiAssetFilter { + fn weigh_multi_assets(&self, weight: Weight) -> XCMWeight { + let weight = match self { + Definite(assets) => + weight.saturating_mul(assets.inner().into_iter().count() as u64), + Wild(_) => weight.saturating_mul(MAX_ASSETS as u64), + }; + weight.ref_time() + } + } + + impl WeighMultiAssets for MultiAssets { + fn weigh_multi_assets(&self, weight: Weight) -> XCMWeight { + weight.saturating_mul(self.inner().into_iter().count() as u64).ref_time() + } + } + + pub struct StatemineXcmWeight(core::marker::PhantomData); + impl XcmWeightInfo for StatemineXcmWeight { + fn withdraw_asset(assets: &MultiAssets) -> XCMWeight { + assets.weigh_multi_assets(XcmFungibleWeight::::withdraw_asset()) + } + // Currently there is no trusted reserve + fn reserve_asset_deposited(_assets: &MultiAssets) -> XCMWeight { + u64::MAX + } + fn receive_teleported_asset(assets: &MultiAssets) -> XCMWeight { + assets.weigh_multi_assets(XcmFungibleWeight::::receive_teleported_asset()) + } + fn query_response( + _query_id: &u64, + _response: &Response, + _max_weight: &u64, + ) -> XCMWeight { + XcmGeneric::::query_response().ref_time() + } + fn transfer_asset(assets: &MultiAssets, _dest: &MultiLocation) -> XCMWeight { + assets.weigh_multi_assets(XcmFungibleWeight::::transfer_asset()) + } + fn transfer_reserve_asset( + assets: &MultiAssets, + _dest: &MultiLocation, + _xcm: &Xcm<()>, + ) -> XCMWeight { + assets.weigh_multi_assets(XcmFungibleWeight::::transfer_reserve_asset()) + } + fn transact( + _origin_type: &OriginKind, + _require_weight_at_most: &u64, + _call: &DoubleEncoded, + ) -> XCMWeight { + XcmGeneric::::transact().ref_time() + } + fn hrmp_new_channel_open_request( + _sender: &u32, + _max_message_size: &u32, + _max_capacity: &u32, + ) -> XCMWeight { + // XCM Executor does not currently support HRMP channel operations + Weight::MAX.ref_time() + } + fn hrmp_channel_accepted(_recipient: &u32) -> XCMWeight { + // XCM Executor does not currently support HRMP channel operations + Weight::MAX.ref_time() + } + fn hrmp_channel_closing( + _initiator: &u32, + _sender: &u32, + _recipient: &u32, + ) -> XCMWeight { + // XCM Executor does not currently support HRMP channel operations + Weight::MAX.ref_time() + } + fn clear_origin() -> XCMWeight { + XcmGeneric::::clear_origin().ref_time() + } + fn descend_origin(_who: &InteriorMultiLocation) -> XCMWeight { + XcmGeneric::::descend_origin().ref_time() + } + fn report_error( + _query_id: &QueryId, + _dest: &MultiLocation, + _max_response_weight: &u64, + ) -> XCMWeight { + XcmGeneric::::report_error().ref_time() + } + + fn deposit_asset( + assets: &MultiAssetFilter, + _max_assets: &u32, + _dest: &MultiLocation, + ) -> XCMWeight { + // Hardcoded till the XCM pallet is fixed + let hardcoded_weight = Weight::from_ref_time(1_000_000_000 as u64).ref_time(); + let weight = + assets.weigh_multi_assets(XcmFungibleWeight::::deposit_asset()); + cmp::min(hardcoded_weight, weight) + } + fn deposit_reserve_asset( + assets: &MultiAssetFilter, + _max_assets: &u32, + _dest: &MultiLocation, + _xcm: &Xcm<()>, + ) -> XCMWeight { + assets.weigh_multi_assets(XcmFungibleWeight::::deposit_reserve_asset()) + } + fn exchange_asset(_give: &MultiAssetFilter, _receive: &MultiAssets) -> XCMWeight { + Weight::MAX.ref_time() + } + fn initiate_reserve_withdraw( + assets: &MultiAssetFilter, + _reserve: &MultiLocation, + _xcm: &Xcm<()>, + ) -> XCMWeight { + assets.weigh_multi_assets(XcmGeneric::::initiate_reserve_withdraw()) + } + fn initiate_teleport( + assets: &MultiAssetFilter, + _dest: &MultiLocation, + _xcm: &Xcm<()>, + ) -> XCMWeight { + // Hardcoded till the XCM pallet is fixed + let hardcoded_weight = Weight::from_ref_time(200_000_000 as u64).ref_time(); + let weight = + assets.weigh_multi_assets(XcmFungibleWeight::::initiate_teleport()); + cmp::min(hardcoded_weight, weight) + } + fn query_holding( + _query_id: &u64, + _dest: &MultiLocation, + _assets: &MultiAssetFilter, + _max_response_weight: &u64, + ) -> XCMWeight { + XcmGeneric::::query_holding().ref_time() + } + fn buy_execution(_fees: &MultiAsset, _weight_limit: &WeightLimit) -> XCMWeight { + XcmGeneric::::buy_execution().ref_time() + } + fn refund_surplus() -> XCMWeight { + XcmGeneric::::refund_surplus().ref_time() + } + fn set_error_handler(_xcm: &Xcm) -> XCMWeight { + XcmGeneric::::set_error_handler().ref_time() + } + fn set_appendix(_xcm: &Xcm) -> XCMWeight { + XcmGeneric::::set_appendix().ref_time() + } + fn clear_error() -> XCMWeight { + XcmGeneric::::clear_error().ref_time() + } + fn claim_asset(_assets: &MultiAssets, _ticket: &MultiLocation) -> XCMWeight { + XcmGeneric::::claim_asset().ref_time() + } + fn trap(_code: &u64) -> XCMWeight { + XcmGeneric::::trap().ref_time() + } + fn subscribe_version(_query_id: &QueryId, _max_response_weight: &u64) -> XCMWeight { + XcmGeneric::::subscribe_version().ref_time() + } + fn unsubscribe_version() -> XCMWeight { + XcmGeneric::::unsubscribe_version().ref_time() + } + } + + mod pallet_xcm_benchmarks_fungible { + use frame_support::{traits::Get, weights::Weight}; + use sp_std::marker::PhantomData; + + /// Weights for `pallet_xcm_benchmarks::fungible`. + pub struct WeightInfo(PhantomData); + impl WeightInfo { + // Storage: System Account (r:1 w:1) + pub(crate) fn withdraw_asset() -> Weight { + Weight::from_ref_time(35_315_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: System Account (r:2 w:2) + pub(crate) fn transfer_asset() -> Weight { + Weight::from_ref_time(40_541_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: System Account (r:2 w:2) + // Storage: ParachainInfo ParachainId (r:1 w:0) + // Storage: PolkadotXcm SupportedVersion (r:1 w:0) + // Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + // Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + // Storage: ParachainSystem HostConfiguration (r:1 w:0) + // Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + pub(crate) fn transfer_reserve_asset() -> Weight { + Weight::from_ref_time(54_608_000 as u64) + .saturating_add(T::DbWeight::get().reads(8 as u64)) + .saturating_add(T::DbWeight::get().writes(4 as u64)) + } + pub(crate) fn receive_teleported_asset() -> Weight { + Weight::from_ref_time(6_927_000 as u64) + } + // Storage: System Account (r:1 w:1) + pub(crate) fn deposit_asset() -> Weight { + Weight::from_ref_time(35_353_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: System Account (r:1 w:1) + // Storage: ParachainInfo ParachainId (r:1 w:0) + // Storage: PolkadotXcm SupportedVersion (r:1 w:0) + // Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + // Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + // Storage: ParachainSystem HostConfiguration (r:1 w:0) + // Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + pub(crate) fn deposit_reserve_asset() -> Weight { + Weight::from_ref_time(51_366_000 as u64) + .saturating_add(T::DbWeight::get().reads(7 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) + } + // Storage: ParachainInfo ParachainId (r:1 w:0) + // Storage: PolkadotXcm SupportedVersion (r:1 w:0) + // Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + // Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + // Storage: ParachainSystem HostConfiguration (r:1 w:0) + // Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + pub(crate) fn initiate_teleport() -> Weight { + Weight::from_ref_time(27_592_000 as u64) + .saturating_add(T::DbWeight::get().reads(6 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + } + } + + mod pallet_xcm_benchmarks_generic { + use frame_support::{traits::Get, weights::Weight}; + use sp_std::marker::PhantomData; + + /// Weights for `pallet_xcm_benchmarks::generic`. + pub struct WeightInfo(PhantomData); + impl WeightInfo { + // Storage: ParachainInfo ParachainId (r:1 w:0) + // Storage: PolkadotXcm SupportedVersion (r:1 w:0) + // Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + // Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + // Storage: ParachainSystem HostConfiguration (r:1 w:0) + // Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + pub(crate) fn query_holding() -> Weight { + Weight::from_ref_time(679_129_000 as u64) + .saturating_add(T::DbWeight::get().reads(6 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + pub(crate) fn buy_execution() -> Weight { + Weight::from_ref_time(9_337_000 as u64) + } + // Storage: PolkadotXcm Queries (r:1 w:0) + pub(crate) fn query_response() -> Weight { + Weight::from_ref_time(17_924_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + } + pub(crate) fn transact() -> Weight { + Weight::from_ref_time(21_258_000 as u64) + } + pub(crate) fn refund_surplus() -> Weight { + Weight::from_ref_time(9_634_000 as u64) + } + pub(crate) fn set_error_handler() -> Weight { + Weight::from_ref_time(5_616_000 as u64) + } + pub(crate) fn set_appendix() -> Weight { + Weight::from_ref_time(5_627_000 as u64) + } + pub(crate) fn clear_error() -> Weight { + Weight::from_ref_time(5_793_000 as u64) + } + pub(crate) fn descend_origin() -> Weight { + Weight::from_ref_time(6_477_000 as u64) + } + pub(crate) fn clear_origin() -> Weight { + Weight::from_ref_time(5_709_000 as u64) + } + // Storage: PolkadotXcm SupportedVersion (r:1 w:0) + // Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + // Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + // Storage: ParachainSystem HostConfiguration (r:1 w:0) + // Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + pub(crate) fn report_error() -> Weight { + Weight::from_ref_time(16_302_000 as u64) + .saturating_add(T::DbWeight::get().reads(5 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: PolkadotXcm AssetTraps (r:1 w:1) + pub(crate) fn claim_asset() -> Weight { + Weight::from_ref_time(12_324_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + pub(crate) fn trap() -> Weight { + Weight::from_ref_time(5_724_000 as u64) + } + // Storage: PolkadotXcm VersionNotifyTargets (r:1 w:1) + // Storage: PolkadotXcm SupportedVersion (r:1 w:0) + // Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + // Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + // Storage: ParachainSystem HostConfiguration (r:1 w:0) + // Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + pub(crate) fn subscribe_version() -> Weight { + Weight::from_ref_time(19_809_000 as u64) + .saturating_add(T::DbWeight::get().reads(6 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) + } + // Storage: PolkadotXcm VersionNotifyTargets (r:0 w:1) + pub(crate) fn unsubscribe_version() -> Weight { + Weight::from_ref_time(9_008_000 as u64) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: ParachainInfo ParachainId (r:1 w:0) + // Storage: PolkadotXcm SupportedVersion (r:1 w:0) + // Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + // Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + // Storage: ParachainSystem HostConfiguration (r:1 w:0) + // Storage: ParachainSystem PendingUpwardMessages (r:1 w:1) + pub(crate) fn initiate_reserve_withdraw() -> Weight { + Weight::from_ref_time(867_880_000 as u64) + .saturating_add(T::DbWeight::get().reads(6 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + } + } + } +} diff --git a/xcm-simulator/src/parachains/mod.rs b/xcm-simulator/src/parachains/mod.rs new file mode 100644 index 00000000..0982a3b1 --- /dev/null +++ b/xcm-simulator/src/parachains/mod.rs @@ -0,0 +1,170 @@ +// Copyright 2021 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +use polkadot_core_primitives::BlockNumber as RelayBlockNumber; +use polkadot_parachain::primitives::{ + DmpMessageHandler, Id as ParaId, XcmpMessageFormat, XcmpMessageHandler, +}; +use sp_runtime::traits::Hash; +use xcm::{latest::prelude::*, VersionedXcm}; + +pub(crate) mod asset_reserve; +pub(crate) mod parachain; +pub(crate) mod trappist; + +#[frame_support::pallet] +pub mod mock_msg_queue { + use super::*; + use frame_support::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + type XcmExecutor: ExecuteXcm; + } + + #[pallet::call] + impl Pallet {} + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] + pub struct Pallet(_); + + #[pallet::storage] + #[pallet::getter(fn parachain_id)] + pub(crate) type ParachainId = StorageValue<_, ParaId, ValueQuery>; + + #[pallet::storage] + #[pallet::getter(fn received_dmp)] + /// A queue of received DMP messages + pub(crate) type ReceivedDmp = StorageValue<_, Vec>, ValueQuery>; + + impl Get for Pallet { + fn get() -> ParaId { + Self::parachain_id() + } + } + + pub type MessageId = [u8; 32]; + + #[pallet::event] + #[pallet::generate_deposit(pub(super) fn deposit_event)] + pub enum Event { + // XCMP + /// Some XCM was executed OK. + Success(Option), + /// Some XCM failed. + Fail(Option, XcmError), + /// Bad XCM version used. + BadVersion(Option), + /// Bad XCM format used. + BadFormat(Option), + + // DMP + /// Downward message is invalid XCM. + InvalidFormat(MessageId), + /// Downward message is unsupported version of XCM. + UnsupportedVersion(MessageId), + /// Downward message executed with the given outcome. + ExecutedDownward(MessageId, Outcome), + } + + impl Pallet { + pub fn set_para_id(para_id: ParaId) { + ParachainId::::put(para_id); + } + + fn handle_xcmp_message( + sender: ParaId, + _sent_at: RelayBlockNumber, + xcm: VersionedXcm, + max_weight: Weight, + ) -> Result { + let hash = Encode::using_encoded(&xcm, T::Hashing::hash); + let (result, event) = match Xcm::::try_from(xcm) { + Ok(xcm) => { + let location = (1, Parachain(sender.into())); + match T::XcmExecutor::execute_xcm(location, xcm, max_weight.ref_time()) { + Outcome::Error(e) => (Err(e.clone()), Event::Fail(Some(hash), e)), + Outcome::Complete(w) => + (Ok(Weight::from_ref_time(w)), Event::Success(Some(hash))), + // As far as the caller is concerned, this was dispatched without error, so + // we just report the weight used. + Outcome::Incomplete(w, e) => + (Ok(Weight::from_ref_time(w)), Event::Fail(Some(hash), e)), + } + }, + Err(()) => (Err(XcmError::UnhandledXcmVersion), Event::BadVersion(Some(hash))), + }; + Self::deposit_event(event); + result + } + } + + impl XcmpMessageHandler for Pallet { + fn handle_xcmp_messages<'a, I: Iterator>( + iter: I, + max_weight: Weight, + ) -> Weight { + for (sender, sent_at, data) in iter { + let mut data_ref = data; + let _ = XcmpMessageFormat::decode(&mut data_ref) + .expect("Simulator encodes with versioned xcm format; qed"); + + let mut remaining_fragments = &data_ref[..]; + while !remaining_fragments.is_empty() { + if let Ok(xcm) = + VersionedXcm::::decode(&mut remaining_fragments) + { + let _ = Self::handle_xcmp_message(sender, sent_at, xcm, max_weight); + } else { + debug_assert!(false, "Invalid incoming XCMP message data"); + } + } + } + max_weight + } + } + + impl DmpMessageHandler for Pallet { + fn handle_dmp_messages( + iter: impl Iterator)>, + limit: Weight, + ) -> Weight { + for (_i, (_sent_at, data)) in iter.enumerate() { + let id = sp_io::hashing::blake2_256(&data[..]); + let maybe_msg = VersionedXcm::::decode(&mut &data[..]) + .map(Xcm::::try_from); + match maybe_msg { + Err(_) => { + Self::deposit_event(Event::InvalidFormat(id)); + }, + Ok(Err(())) => { + Self::deposit_event(Event::UnsupportedVersion(id)); + }, + Ok(Ok(x)) => { + let outcome = + T::XcmExecutor::execute_xcm(Parent, x.clone(), limit.ref_time()); + >::append(x); + Self::deposit_event(Event::ExecutedDownward(id, outcome)); + }, + } + } + limit + } + } +} diff --git a/xcm-simulator/src/parachains/parachain.rs b/xcm-simulator/src/parachains/parachain.rs new file mode 100644 index 00000000..d571385c --- /dev/null +++ b/xcm-simulator/src/parachains/parachain.rs @@ -0,0 +1,182 @@ +// Copyright 2021 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Parachain runtime mock. + +use frame_support::{ + construct_runtime, parameter_types, + traits::{Everything, Nothing}, + weights::{constants::WEIGHT_PER_SECOND, Weight}, +}; +use pallet_xcm::XcmPassthrough; +use polkadot_parachain::primitives::Sibling; +use sp_core::H256; +use sp_runtime::{testing::Header, traits::IdentityLookup, AccountId32}; +use sp_std::prelude::*; +use statemine_runtime::common::BlockNumber; +use xcm::latest::prelude::*; +use xcm_builder::{ + AccountId32Aliases, AllowUnpaidExecutionFrom, CurrencyAdapter as XcmCurrencyAdapter, + EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, IsConcrete, LocationInverter, + NativeAsset, ParentIsPreset, SiblingParachainConvertsVia, SignedAccountId32AsNative, + SignedToAccountId32, SovereignSignedViaLocation, +}; +use xcm_executor::{Config, XcmExecutor}; + +pub type AccountId = AccountId32; +pub type Balance = u128; + +parameter_types! { + pub const BlockHashCount: BlockNumber = 250; +} + +impl frame_system::Config for Runtime { + type BaseCallFilter = Everything; + type BlockWeights = (); + type BlockLength = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Index = u64; + type BlockNumber = u64; + type Hash = H256; + type Hashing = sp_runtime::traits::BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +parameter_types! { + pub ExistentialDeposit: Balance = 1; + pub const MaxLocks: u32 = 50; + pub const MaxReserves: u32 = 50; +} + +impl pallet_balances::Config for Runtime { + type Balance = Balance; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); + type MaxLocks = MaxLocks; + type MaxReserves = MaxReserves; + type ReserveIdentifier = [u8; 8]; +} + +parameter_types! { + pub const ReservedXcmpWeight: Weight = WEIGHT_PER_SECOND.saturating_div(4); + pub const ReservedDmpWeight: Weight = WEIGHT_PER_SECOND.saturating_div(4); +} + +parameter_types! { + pub const KsmLocation: MultiLocation = MultiLocation::parent(); + pub const RelayNetwork: NetworkId = NetworkId::Kusama; + pub Ancestry: MultiLocation = Parachain(MsgQueue::parachain_id().into()).into(); +} + +pub type LocationToAccountId = ( + ParentIsPreset, + SiblingParachainConvertsVia, + AccountId32Aliases, +); + +pub type XcmOriginToCallOrigin = ( + SovereignSignedViaLocation, + SignedAccountId32AsNative, + XcmPassthrough, +); + +parameter_types! { + pub const UnitWeightCost: u64 = 1; + pub KsmPerSecond: (AssetId, u128) = (Concrete(Parent.into()), 1); + pub const MaxInstructions: u32 = 100; +} + +pub type LocalAssetTransactor = + XcmCurrencyAdapter, LocationToAccountId, AccountId, ()>; + +pub type XcmRouter = crate::ParachainXcmRouter; +pub type Barrier = AllowUnpaidExecutionFrom; + +pub struct XcmConfig; +impl Config for XcmConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + type AssetTransactor = LocalAssetTransactor; + type OriginConverter = XcmOriginToCallOrigin; + type IsReserve = NativeAsset; + type IsTeleporter = (); + type LocationInverter = LocationInverter; + type Barrier = Barrier; + type Weigher = FixedWeightBounds; + type Trader = FixedRateOfFungible; + type ResponseHandler = (); + type AssetTrap = (); + type AssetClaims = (); + type SubscriptionService = (); +} + +impl super::mock_msg_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +pub type LocalOriginToLocation = SignedToAccountId32; + +impl pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = EnsureXcmOrigin; + type XcmExecuteFilter = Everything; + type XcmExecutor = XcmExecutor; + type XcmTeleportFilter = Nothing; + type XcmReserveTransferFilter = Everything; + type Weigher = FixedWeightBounds; + type LocationInverter = LocationInverter; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; +} + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +construct_runtime!( + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Storage, Config, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + MsgQueue: super::mock_msg_queue::{Pallet, Storage, Event}, + PolkadotXcm: pallet_xcm::{Pallet, Call, Event, Origin}, + } +); diff --git a/xcm-simulator/src/parachains/trappist.rs b/xcm-simulator/src/parachains/trappist.rs new file mode 100644 index 00000000..0f0cad3a --- /dev/null +++ b/xcm-simulator/src/parachains/trappist.rs @@ -0,0 +1,221 @@ +// Copyright 2021 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Trappist Parachain runtime mock. + +use frame_support::{ + construct_runtime, parameter_types, + traits::{EitherOfDiverse, Everything, Nothing}, + weights::constants::RocksDbWeight, +}; +use frame_system::EnsureRoot; +use pallet_xcm::{EnsureXcm, IsMajorityOfBody, XcmPassthrough}; +use polkadot_runtime_common::BlockHashCount; +use sp_core::{ConstU128, ConstU16, ConstU32}; +use sp_runtime::traits::{AccountIdLookup, BlakeTwo256}; +use sp_std::prelude::*; +use trappist_runtime::{ + constants::{ + currency::{CENTS, EXISTENTIAL_DEPOSIT, UNITS}, + fee::WeightToFee, + }, + xcm_config::{ + AssetTransactors, Barrier, CollatorSelectionUpdateOrigin, LocationToAccountId, + MaxInstructions, RelayLocation, RelayNetwork, Reserves, SelfReserve, UnitWeightCost, + XUsdPerSecond, + }, + AccountId, AssetId, Balance, BlockNumber, DealWithFees, Hash, Header, Index, Period, PotId, + RuntimeBlockLength, RuntimeBlockWeights, Session, UnitBody, Version, +}; +use xcm::latest::prelude::*; +use xcm_builder::{ + EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, LocationInverter, ParentAsSuperuser, + RelayChainAsNative, SiblingParachainAsNative, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, UsingComponents, +}; +use xcm_executor::{Config, XcmExecutor}; + +impl frame_system::Config for Runtime { + type BaseCallFilter = Everything; + type BlockWeights = RuntimeBlockWeights; + type BlockLength = RuntimeBlockLength; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Index = Index; + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = AccountIdLookup; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type DbWeight = RocksDbWeight; + type Version = Version; + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = frame_system::weights::SubstrateWeight; + type SS58Prefix = ConstU16<42>; + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; +} + +impl super::mock_msg_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +pub type AssetsForceOrigin = + EitherOfDiverse, EnsureXcm>>; + +impl pallet_assets::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type Currency = Balances; + type ForceOrigin = AssetsForceOrigin; + type AssetDeposit = ConstU128; + type AssetAccountDeposit = ConstU128<{ UNITS }>; + type MetadataDepositBase = ConstU128<{ UNITS }>; + type MetadataDepositPerByte = ConstU128<{ 10 * CENTS }>; + type ApprovalDeposit = ConstU128<{ 10 * CENTS }>; + type StringLimit = ConstU32<50>; + type Freezer = (); + type Extra = (); + type WeightInfo = pallet_assets::weights::SubstrateWeight; +} + +impl pallet_asset_registry::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type ReserveAssetModifierOrigin = frame_system::EnsureRoot; + type Assets = Assets; + type WeightInfo = pallet_asset_registry::weights::SubstrateWeight; +} + +impl pallet_balances::Config for Runtime { + type Balance = Balance; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ConstU128; + type AccountStore = System; + type WeightInfo = pallet_balances::weights::SubstrateWeight; + type MaxLocks = ConstU32<50>; + type MaxReserves = ConstU32<50>; + type ReserveIdentifier = [u8; 8]; +} + +impl pallet_collator_selection::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type UpdateOrigin = CollatorSelectionUpdateOrigin; + type PotId = PotId; + type MaxCandidates = ConstU32<1000>; + type MinCandidates = ConstU32<5>; + type MaxInvulnerables = ConstU32<100>; + type KickThreshold = Period; + type ValidatorId = ::AccountId; + type ValidatorIdOf = pallet_collator_selection::IdentityCollator; + type ValidatorRegistration = Session; + type WeightInfo = pallet_collator_selection::weights::SubstrateWeight; +} + +impl pallet_sudo::Config for Runtime { + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; +} + +pub type LocalOriginToLocation = SignedToAccountId32; + +impl pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = EnsureXcmOrigin; + type XcmExecuteFilter = Everything; + type XcmExecutor = XcmExecutor; + type XcmTeleportFilter = Nothing; + type XcmReserveTransferFilter = Everything; + type Weigher = FixedWeightBounds; + type LocationInverter = LocationInverter; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; +} + +impl cumulus_pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +parameter_types! { + pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); + pub Ancestry: MultiLocation = Parachain(MsgQueue::parachain_id().into()).into(); +} + +pub type XcmOriginToTransactDispatchOrigin = ( + SovereignSignedViaLocation, + RelayChainAsNative, + SiblingParachainAsNative, + ParentAsSuperuser, + SignedAccountId32AsNative, + XcmPassthrough, +); +pub type XcmRouter = crate::ParachainXcmRouter; + +pub struct XcmConfig; +impl Config for XcmConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + type AssetTransactor = AssetTransactors; + type OriginConverter = XcmOriginToTransactDispatchOrigin; + type IsReserve = Reserves; + type IsTeleporter = (); + type LocationInverter = LocationInverter; + type Barrier = Barrier; + type Weigher = FixedWeightBounds; + type Trader = ( + FixedRateOfFungible, + UsingComponents>, + ); + type ResponseHandler = PolkadotXcm; + type AssetTrap = PolkadotXcm; + type AssetClaims = PolkadotXcm; + type SubscriptionService = PolkadotXcm; +} + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +construct_runtime!( + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Storage, Config, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + MsgQueue: super::mock_msg_queue::{Pallet, Storage, Event}, + CollatorSelection: pallet_collator_selection::{Pallet, Call, Storage, Event, Config} = 21, + PolkadotXcm: pallet_xcm::{Pallet, Call, Event, Origin} = 31, + CumulusXcm: cumulus_pallet_xcm::{Pallet, Event, Origin} = 32, + Sudo: pallet_sudo = 40, + Assets: pallet_assets = 43, + AssetRegistry: pallet_asset_registry::{Pallet, Call, Storage, Event} = 101, + } +); diff --git a/xcm-simulator/src/relay_chain.rs b/xcm-simulator/src/relay_chain.rs new file mode 100644 index 00000000..92e420b7 --- /dev/null +++ b/xcm-simulator/src/relay_chain.rs @@ -0,0 +1,549 @@ +// Copyright 2021 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Relay chain runtime mock. + +use frame_support::{ + construct_runtime, parameter_types, + traits::{Everything, Nothing}, +}; +use polkadot_core_primitives::BlockNumber; +use sp_core::H256; +use sp_runtime::{generic, traits::IdentityLookup, AccountId32}; + +use polkadot_parachain::primitives::Id as ParaId; +use polkadot_runtime_parachains::{configuration, dmp, hrmp, origin, paras, shared, ump}; +use rococo_runtime::FirstMessageFactorPercent; +use sp_runtime::traits::BlakeTwo256; +use xcm::latest::prelude::*; +use xcm_builder::{ + AccountId32Aliases, AllowUnpaidExecutionFrom, ChildParachainAsNative, + ChildParachainConvertsVia, ChildSystemParachainAsSuperuser, + CurrencyAdapter as XcmCurrencyAdapter, FixedRateOfFungible, FixedWeightBounds, IsConcrete, + LocationInverter, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, +}; +use xcm_executor::{Config, XcmExecutor}; + +pub type AccountId = AccountId32; +pub type Balance = u128; + +parameter_types! { + pub const BlockHashCount: BlockNumber = 250; +} + +impl frame_system::Config for Runtime { + type BaseCallFilter = Everything; + type BlockWeights = (); + type BlockLength = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Index = u64; + type BlockNumber = BlockNumber; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type Header = generic::Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type DbWeight = (); + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = (); + type OnSetCode = (); + type MaxConsumers = frame_support::traits::ConstU32<16>; +} + +parameter_types! { + pub ExistentialDeposit: Balance = 1; + pub const MaxLocks: u32 = 50; + pub const MaxReserves: u32 = 50; +} + +impl pallet_balances::Config for Runtime { + type Balance = Balance; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ExistentialDeposit; + type AccountStore = System; + type WeightInfo = (); + type MaxLocks = MaxLocks; + type MaxReserves = MaxReserves; + type ReserveIdentifier = [u8; 8]; +} + +impl shared::Config for Runtime {} + +impl configuration::Config for Runtime { + type WeightInfo = configuration::TestWeightInfo; +} + +parameter_types! { + pub const KsmLocation: MultiLocation = Here.into(); + pub const KusamaNetwork: NetworkId = NetworkId::Kusama; + pub const AnyNetwork: NetworkId = NetworkId::Any; + pub Ancestry: MultiLocation = Here.into(); + pub UnitWeightCost: u64 = 1_000; +} + +pub type SovereignAccountOf = + (ChildParachainConvertsVia, AccountId32Aliases); + +pub type LocalAssetTransactor = + XcmCurrencyAdapter, SovereignAccountOf, AccountId, ()>; + +type LocalOriginConverter = ( + SovereignSignedViaLocation, + ChildParachainAsNative, + SignedAccountId32AsNative, + ChildSystemParachainAsSuperuser, +); + +parameter_types! { + pub const BaseXcmWeight: u64 = 1_000; + pub KsmPerSecond: (AssetId, u128) = (Concrete(KsmLocation::get()), 1); + pub const MaxInstructions: u32 = 100; +} + +pub type XcmRouter = super::RelayChainXcmRouter; +pub type Barrier = AllowUnpaidExecutionFrom; + +pub struct XcmConfig; +impl Config for XcmConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + type AssetTransactor = LocalAssetTransactor; + type OriginConverter = LocalOriginConverter; + type IsReserve = (); + type IsTeleporter = (); + type LocationInverter = LocationInverter; + type Barrier = Barrier; + type Weigher = FixedWeightBounds; + type Trader = FixedRateOfFungible; + type ResponseHandler = (); + type AssetTrap = (); + type AssetClaims = (); + type SubscriptionService = (); +} + +pub type LocalOriginToLocation = SignedToAccountId32; + +impl pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type SendXcmOrigin = xcm_builder::EnsureXcmOrigin; + type XcmRouter = XcmRouter; + // Anyone can execute XCM messages locally... + type ExecuteXcmOrigin = xcm_builder::EnsureXcmOrigin; + type XcmExecuteFilter = Nothing; + type XcmExecutor = XcmExecutor; + type XcmTeleportFilter = Everything; + type XcmReserveTransferFilter = Everything; + type Weigher = FixedWeightBounds; + type LocationInverter = LocationInverter; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; +} + +// impl paras::Config for Runtime { +// type RuntimeEvent = RuntimeEvent; +// type UnsignedPriority = ParasUnsignedPriority; +// type NextSessionRotation = Babe; +// type WeightInfo = weights::runtime_parachains_paras::WeightInfo; +// } + +impl ump::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type UmpSink = ump::XcmSink, Runtime>; + type FirstMessageFactorPercent = FirstMessageFactorPercent; + type ExecuteOverweightOrigin = frame_system::EnsureRoot; + type WeightInfo = ump::TestWeightInfo; +} + +impl dmp::Config for Runtime {} + +// impl hrmp::Config for Runtime { +// type RuntimeEvent = RuntimeEvent; +// type RuntimeOrigin = RuntimeOrigin; +// type Currency = Balances; +// type WeightInfo = weights::runtime_parachains_hrmp::WeightInfo; +// } + +impl origin::Config for Runtime {} + +impl pallet_sudo::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; +} + +#[frame_support::pallet] +pub mod mock_paras_sudo_wrapper { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; + + #[pallet::config] + pub trait Config: frame_system::Config { + type XcmRouter: SendXcm; + } + + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + #[pallet::without_storage_info] + pub struct Pallet(_); + + #[pallet::error] + pub enum Error {} + + #[pallet::call] + impl Pallet { + #[pallet::weight((1_000, DispatchClass::Operational))] + pub fn sudo_queue_downward_xcm( + origin: OriginFor, + id: ParaId, + xcm: Box, + ) -> DispatchResult { + ensure_root(origin)?; + let dest = MultiLocation::new(0, Junctions::X1(Parachain(id.into()))); + let message = Xcm::<()>::try_from(*xcm).unwrap(); + T::XcmRouter::send_xcm(dest, message) + .map_err(|_| sp_runtime::DispatchError::Other("Sudo routing failed")) + } + } +} + +impl mock_paras_sudo_wrapper::Config for Runtime { + type XcmRouter = XcmRouter; +} + +impl frame_system::offchain::SendTransactionTypes for Runtime +where + RuntimeCall: From, +{ + type Extrinsic = UncheckedExtrinsic; + type OverarchingCall = RuntimeCall; +} + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +construct_runtime!( + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Storage, Config, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + ParasOrigin: origin::{Pallet, Origin}, + ParasUmp: ump::{Pallet, Call, Storage, Event}, + XcmPallet: pallet_xcm::{Pallet, Call, Storage, Event, Origin, Config}, + + ParasSudoWrapper: mock_paras_sudo_wrapper::{Pallet, Call}, + Sudo: pallet_sudo::{Pallet, Call, Storage, Event, Config}, + } +); + +mod weights { + pub(crate) mod runtime_parachains_hrmp { + use frame_support::{traits::Get, weights::Weight}; + use sp_std::marker::PhantomData; + + /// Weight functions for `runtime_parachains::hrmp`. + pub struct WeightInfo(PhantomData); + impl super::super::hrmp::WeightInfo for WeightInfo { + // Storage: Paras ParaLifecycles (r:2 w:0) + // Storage: Configuration ActiveConfig (r:1 w:0) + // Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) + // Storage: Hrmp HrmpChannels (r:1 w:0) + // Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:0) + // Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1) + // Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) + // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) + // Storage: Dmp DownwardMessageQueues (r:1 w:1) + fn hrmp_init_open_channel() -> Weight { + Weight::from_ref_time(40_520_000 as u64) + .saturating_add(T::DbWeight::get().reads(10 as u64)) + .saturating_add(T::DbWeight::get().writes(5 as u64)) + } + // Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) + // Storage: Configuration ActiveConfig (r:1 w:0) + // Storage: Paras ParaLifecycles (r:1 w:0) + // Storage: Hrmp HrmpIngressChannelsIndex (r:1 w:0) + // Storage: Hrmp HrmpAcceptedChannelRequestCount (r:1 w:1) + // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) + // Storage: Dmp DownwardMessageQueues (r:1 w:1) + fn hrmp_accept_open_channel() -> Weight { + Weight::from_ref_time(39_646_000 as u64) + .saturating_add(T::DbWeight::get().reads(7 as u64)) + .saturating_add(T::DbWeight::get().writes(4 as u64)) + } + // Storage: Hrmp HrmpChannels (r:1 w:0) + // Storage: Hrmp HrmpCloseChannelRequests (r:1 w:1) + // Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:1) + // Storage: Configuration ActiveConfig (r:1 w:0) + // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) + // Storage: Dmp DownwardMessageQueues (r:1 w:1) + fn hrmp_close_channel() -> Weight { + Weight::from_ref_time(36_691_000 as u64) + .saturating_add(T::DbWeight::get().reads(6 as u64)) + .saturating_add(T::DbWeight::get().writes(4 as u64)) + } + // Storage: Hrmp HrmpIngressChannelsIndex (r:128 w:127) + // Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:1) + // Storage: Hrmp HrmpChannels (r:127 w:127) + // Storage: Hrmp HrmpAcceptedChannelRequestCount (r:0 w:1) + // Storage: Hrmp HrmpChannelContents (r:0 w:127) + // Storage: Hrmp HrmpOpenChannelRequestCount (r:0 w:1) + /// The range of component `i` is `[0, 127]`. + /// The range of component `e` is `[0, 127]`. + fn force_clean_hrmp(i: u32, e: u32) -> Weight { + Weight::from_ref_time(0 as u64) + // Standard Error: 16_000 + .saturating_add( + Weight::from_ref_time(7_248_000 as u64).saturating_mul(i as u64), + ) + // Standard Error: 16_000 + .saturating_add( + Weight::from_ref_time(7_311_000 as u64).saturating_mul(e as u64), + ) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(i as u64))) + .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(e as u64))) + .saturating_add(T::DbWeight::get().writes(4 as u64)) + .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(i as u64))) + .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(e as u64))) + } + // Storage: Configuration ActiveConfig (r:1 w:0) + // Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:0) + // Storage: Hrmp HrmpOpenChannelRequests (r:2 w:2) + // Storage: Paras ParaLifecycles (r:4 w:0) + // Storage: Hrmp HrmpIngressChannelsIndex (r:2 w:2) + // Storage: Hrmp HrmpEgressChannelsIndex (r:2 w:2) + // Storage: Hrmp HrmpOpenChannelRequestCount (r:2 w:2) + // Storage: Hrmp HrmpAcceptedChannelRequestCount (r:2 w:2) + // Storage: Hrmp HrmpChannels (r:0 w:2) + /// The range of component `c` is `[0, 128]`. + fn force_process_hrmp_open(c: u32) -> Weight { + Weight::from_ref_time(0 as u64) + // Standard Error: 19_000 + .saturating_add( + Weight::from_ref_time(15_783_000 as u64).saturating_mul(c as u64), + ) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().reads((7 as u64).saturating_mul(c as u64))) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + .saturating_add(T::DbWeight::get().writes((6 as u64).saturating_mul(c as u64))) + } + // Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:0) + // Storage: Hrmp HrmpChannels (r:2 w:2) + // Storage: Hrmp HrmpEgressChannelsIndex (r:2 w:2) + // Storage: Hrmp HrmpIngressChannelsIndex (r:2 w:2) + // Storage: Hrmp HrmpCloseChannelRequests (r:0 w:2) + // Storage: Hrmp HrmpChannelContents (r:0 w:2) + /// The range of component `c` is `[0, 128]`. + fn force_process_hrmp_close(c: u32) -> Weight { + Weight::from_ref_time(0 as u64) + // Standard Error: 12_000 + .saturating_add( + Weight::from_ref_time(9_624_000 as u64).saturating_mul(c as u64), + ) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(c as u64))) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + .saturating_add(T::DbWeight::get().writes((5 as u64).saturating_mul(c as u64))) + } + // Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) + // Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) + // Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1) + /// The range of component `c` is `[0, 128]`. + fn hrmp_cancel_open_request(c: u32) -> Weight { + Weight::from_ref_time(30_548_000 as u64) + // Standard Error: 1_000 + .saturating_add(Weight::from_ref_time(89_000 as u64).saturating_mul(c as u64)) + .saturating_add(T::DbWeight::get().reads(3 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) + } + // Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) + // Storage: Hrmp HrmpOpenChannelRequests (r:2 w:2) + /// The range of component `c` is `[0, 128]`. + fn clean_open_channel_requests(c: u32) -> Weight { + Weight::from_ref_time(1_732_000 as u64) + // Standard Error: 4_000 + .saturating_add( + Weight::from_ref_time(2_574_000 as u64).saturating_mul(c as u64), + ) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(c as u64))) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(c as u64))) + } + } + } + + pub(crate) mod runtime_parachains_paras { + use frame_support::{traits::Get, weights::Weight}; + use sp_std::marker::PhantomData; + + /// Weight functions for `runtime_parachains::paras`. + pub struct WeightInfo(PhantomData); + impl super::super::paras::WeightInfo for WeightInfo { + // Storage: Paras CurrentCodeHash (r:1 w:1) + // Storage: Paras CodeByHashRefs (r:1 w:1) + // Storage: Paras PastCodeMeta (r:1 w:1) + // Storage: Paras PastCodePruning (r:1 w:1) + // Storage: Paras PastCodeHash (r:0 w:1) + // Storage: Paras CodeByHash (r:0 w:1) + /// The range of component `c` is `[1, 3145728]`. + fn force_set_current_code(c: u32) -> Weight { + Weight::from_ref_time(0 as u64) + // Standard Error: 0 + .saturating_add(Weight::from_ref_time(2_000 as u64).saturating_mul(c as u64)) + .saturating_add(T::DbWeight::get().reads(4 as u64)) + .saturating_add(T::DbWeight::get().writes(6 as u64)) + } + // Storage: Paras Heads (r:0 w:1) + /// The range of component `s` is `[1, 1048576]`. + fn force_set_current_head(s: u32) -> Weight { + Weight::from_ref_time(0 as u64) + // Standard Error: 0 + .saturating_add(Weight::from_ref_time(1_000 as u64).saturating_mul(s as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: Configuration ActiveConfig (r:1 w:0) + // Storage: Paras FutureCodeHash (r:1 w:1) + // Storage: Paras CurrentCodeHash (r:1 w:0) + // Storage: Paras UpgradeCooldowns (r:1 w:1) + // Storage: Paras PvfActiveVoteMap (r:1 w:0) + // Storage: Paras CodeByHash (r:1 w:1) + // Storage: Paras UpcomingUpgrades (r:1 w:1) + // Storage: System Digest (r:1 w:1) + // Storage: Paras CodeByHashRefs (r:1 w:1) + // Storage: Paras FutureCodeUpgrades (r:0 w:1) + // Storage: Paras UpgradeRestrictionSignal (r:0 w:1) + /// The range of component `c` is `[1, 3145728]`. + fn force_schedule_code_upgrade(c: u32) -> Weight { + Weight::from_ref_time(0 as u64) + // Standard Error: 0 + .saturating_add(Weight::from_ref_time(2_000 as u64).saturating_mul(c as u64)) + .saturating_add(T::DbWeight::get().reads(9 as u64)) + .saturating_add(T::DbWeight::get().writes(8 as u64)) + } + // Storage: Paras FutureCodeUpgrades (r:1 w:0) + // Storage: Paras Heads (r:0 w:1) + // Storage: Paras UpgradeGoAheadSignal (r:0 w:1) + /// The range of component `s` is `[1, 1048576]`. + fn force_note_new_head(s: u32) -> Weight { + Weight::from_ref_time(0 as u64) + // Standard Error: 0 + .saturating_add(Weight::from_ref_time(1_000 as u64).saturating_mul(s as u64)) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: ParasShared CurrentSessionIndex (r:1 w:0) + // Storage: Paras ActionsQueue (r:1 w:1) + fn force_queue_action() -> Weight { + Weight::from_ref_time(24_187_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: Paras PvfActiveVoteMap (r:1 w:0) + // Storage: Paras CodeByHash (r:1 w:1) + /// The range of component `c` is `[1, 3145728]`. + fn add_trusted_validation_code(c: u32) -> Weight { + Weight::from_ref_time(0 as u64) + // Standard Error: 0 + .saturating_add(Weight::from_ref_time(2_000 as u64).saturating_mul(c as u64)) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: Paras CodeByHashRefs (r:1 w:0) + // Storage: Paras CodeByHash (r:0 w:1) + fn poke_unused_validation_code() -> Weight { + Weight::from_ref_time(7_273_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: Configuration ActiveConfig (r:1 w:0) + // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) + // Storage: ParasShared CurrentSessionIndex (r:1 w:0) + // Storage: Paras PvfActiveVoteMap (r:1 w:1) + fn include_pvf_check_statement() -> Weight { + Weight::from_ref_time(96_047_000 as u64) + .saturating_add(T::DbWeight::get().reads(4 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: Configuration ActiveConfig (r:1 w:0) + // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) + // Storage: ParasShared CurrentSessionIndex (r:1 w:0) + // Storage: Paras PvfActiveVoteMap (r:1 w:1) + // Storage: Paras PvfActiveVoteList (r:1 w:1) + // Storage: Paras UpcomingUpgrades (r:1 w:1) + // Storage: System Digest (r:1 w:1) + // Storage: Paras FutureCodeUpgrades (r:0 w:100) + fn include_pvf_check_statement_finalize_upgrade_accept() -> Weight { + Weight::from_ref_time(630_640_000 as u64) + .saturating_add(T::DbWeight::get().reads(7 as u64)) + .saturating_add(T::DbWeight::get().writes(104 as u64)) + } + // Storage: Configuration ActiveConfig (r:1 w:0) + // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) + // Storage: ParasShared CurrentSessionIndex (r:1 w:0) + // Storage: Paras PvfActiveVoteMap (r:1 w:1) + // Storage: Paras PvfActiveVoteList (r:1 w:1) + // Storage: Paras CodeByHashRefs (r:1 w:1) + // Storage: Paras CodeByHash (r:0 w:1) + // Storage: Paras UpgradeGoAheadSignal (r:0 w:100) + // Storage: Paras FutureCodeHash (r:0 w:100) + fn include_pvf_check_statement_finalize_upgrade_reject() -> Weight { + Weight::from_ref_time(599_325_000 as u64) + .saturating_add(T::DbWeight::get().reads(6 as u64)) + .saturating_add(T::DbWeight::get().writes(204 as u64)) + } + // Storage: Configuration ActiveConfig (r:1 w:0) + // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) + // Storage: ParasShared CurrentSessionIndex (r:1 w:0) + // Storage: Paras PvfActiveVoteMap (r:1 w:1) + // Storage: Paras PvfActiveVoteList (r:1 w:1) + // Storage: Paras ActionsQueue (r:1 w:1) + fn include_pvf_check_statement_finalize_onboarding_accept() -> Weight { + Weight::from_ref_time(505_499_000 as u64) + .saturating_add(T::DbWeight::get().reads(6 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) + } + // Storage: Configuration ActiveConfig (r:1 w:0) + // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) + // Storage: ParasShared CurrentSessionIndex (r:1 w:0) + // Storage: Paras PvfActiveVoteMap (r:1 w:1) + // Storage: Paras PvfActiveVoteList (r:1 w:1) + // Storage: Paras CodeByHashRefs (r:1 w:1) + // Storage: Paras ParaLifecycles (r:0 w:100) + // Storage: Paras CodeByHash (r:0 w:1) + // Storage: Paras CurrentCodeHash (r:0 w:100) + // Storage: Paras UpcomingParasGenesis (r:0 w:100) + fn include_pvf_check_statement_finalize_onboarding_reject() -> Weight { + Weight::from_ref_time(668_669_000 as u64) + .saturating_add(T::DbWeight::get().reads(6 as u64)) + .saturating_add(T::DbWeight::get().writes(304 as u64)) + } + } + } +} From 9340dda2fb4e6416d8c045d05051fec94e596ae1 Mon Sep 17 00:00:00 2001 From: Frank Bell Date: Fri, 6 Jan 2023 18:16:07 +0000 Subject: [PATCH 02/16] test: add (dmp) teleport test --- xcm-simulator/Cargo.toml | 1 + xcm-simulator/src/lib.rs | 99 ++-- xcm-simulator/src/relay_chain.rs | 786 +++++++++++++++++++------------ 3 files changed, 549 insertions(+), 337 deletions(-) diff --git a/xcm-simulator/Cargo.toml b/xcm-simulator/Cargo.toml index e9bdd57b..6ec1adb4 100644 --- a/xcm-simulator/Cargo.toml +++ b/xcm-simulator/Cargo.toml @@ -41,6 +41,7 @@ parachains-common = { git = "https://github.com/paritytech/cumulus", branch = "p # Runtimes rococo-runtime = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.30" } +rococo-runtime-constants = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.30" } statemine-runtime = { git = "https://github.com/paritytech/cumulus", branch = "polkadot-v0.9.30" } base-runtime = { path = "../runtime/base" } trappist-runtime = { path = "../runtime/trappist" } \ No newline at end of file diff --git a/xcm-simulator/src/lib.rs b/xcm-simulator/src/lib.rs index 2ddec9c3..40a16739 100644 --- a/xcm-simulator/src/lib.rs +++ b/xcm-simulator/src/lib.rs @@ -28,7 +28,7 @@ use sp_runtime::traits::AccountIdConversion; use xcm_simulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain}; pub const ALICE: sp_runtime::AccountId32 = sp_runtime::AccountId32::new([0u8; 32]); -pub const INITIAL_BALANCE: u128 = 1_000_000_000; +pub const INITIAL_BALANCE: u128 = 10_000_000_000; const ASSET_RESERVE_PARA_ID: u32 = 1000; decl_test_parachain! { @@ -178,13 +178,12 @@ mod tests { use crate::relay_chain::mock_paras_sudo_wrapper; use codec::Encode; use frame_support::assert_ok; - use sp_runtime::MultiAddress::Id; use std::sync::Once; - use xcm::{latest::prelude::*, opaque::VersionedXcm, VersionedMultiAssets::V1}; + use xcm::{latest::prelude::*, opaque::VersionedXcm}; use xcm_simulator::TestExt; static INIT: Once = Once::new(); - pub fn init() { + pub fn init_tracing() { INIT.call_once(|| { // Add test tracing // todo: filter to only show xcm logs @@ -195,19 +194,58 @@ mod tests { const ASSET_RESERVE_PALLET_INDEX: u8 = 50; #[test] - fn dmp_teleport_asset_from_relay_chain_asset_reserve_parachain() { - todo!() + fn teleport_asset_from_relay_chain_asset_reserve_parachain() { + init_tracing(); + + MockNet::reset(); + + const AMOUNT: u128 = 1_000_000_000; + let mut receiver_balance = 0; + let mut total_issuance = 0; + + AssetReserve::execute_with(|| { + // Check receiver balance increased by teleport amount + receiver_balance = asset_reserve::Balances::free_balance(&ALICE); + total_issuance = asset_reserve::Balances::total_issuance(); + }); + + Relay::execute_with(|| { + assert_ok!(relay_chain::XcmPallet::teleport_assets( + relay_chain::RuntimeOrigin::signed(ALICE), + Box::new(Parachain(ASSET_RESERVE_PARA_ID).into().into()), + Box::new(X1(AccountId32 { network: Any, id: ALICE.into() }).into().into()), + Box::new((Here, AMOUNT).into()), + 0 + )); + + // Check teleport amount checked out to check account + assert_eq!(relay_chain::Balances::free_balance(&relay_chain::check_account()), AMOUNT); + + // Check sender balance decreased by teleport amount + assert_eq!(relay_chain::Balances::free_balance(&ALICE), INITIAL_BALANCE - AMOUNT); + }); + + const EST_FEES: u128 = 4_000_000; + AssetReserve::execute_with(|| { + // Check receiver balance and total issuance increased by teleport amount + assert_balance( + asset_reserve::Balances::free_balance(&ALICE), + receiver_balance + AMOUNT, + EST_FEES, + ); + assert_eq!(asset_reserve::Balances::total_issuance(), total_issuance + AMOUNT) + }); } #[test] - fn ump_teleport_asset_from_asset_reserve_parachain_to_relay_chain() { + fn teleport_asset_from_asset_reserve_parachain_to_relay_chain() { todo!() } #[test] #[allow(non_upper_case_globals)] - fn hrmp_reserve_transfer_asset_from_asset_reserve_parachain_to_trappist_parachain() { - init(); + fn reserve_transfer_asset_from_asset_reserve_parachain_to_trappist_parachain() { + init_tracing(); MockNet::reset(); @@ -221,7 +259,7 @@ mod tests { assert_ok!(asset_reserve::Assets::create( asset_reserve::RuntimeOrigin::signed(ALICE), xUSD, - Id(ALICE), + ALICE.into(), MIN_BALANCE )); @@ -229,7 +267,7 @@ mod tests { assert_ok!(asset_reserve::Assets::mint( asset_reserve::RuntimeOrigin::signed(ALICE), xUSD, - Id(ALICE), + ALICE.into(), MINT_AMOUNT )); assert_eq!(asset_reserve::Assets::balance(xUSD, &ALICE), MINT_AMOUNT); @@ -240,10 +278,10 @@ mod tests { paras_sudo_wrapper_sudo_queue_downward_xcm(asset_reserve::RuntimeCall::Assets( pallet_assets::Call::::force_asset_status { id: xUSD, - owner: Id(ALICE), - issuer: Id(ALICE), - admin: Id(ALICE), - freezer: Id(ALICE), + owner: ALICE.into(), + issuer: ALICE.into(), + admin: ALICE.into(), + freezer: ALICE.into(), min_balance: MIN_BALANCE, is_sufficient: true, is_frozen: false, @@ -256,7 +294,7 @@ mod tests { assert_ok!(trappist::Assets::create( trappist::RuntimeOrigin::signed(ALICE), txUSD, - Id(ALICE), + ALICE.into(), MIN_BALANCE )); @@ -282,7 +320,7 @@ mod tests { assert!(trappist::AssetRegistry::asset_id_multilocation(txUSD).is_some()) }); - const SEND_AMOUNT: u128 = 10_000_000_000_000_000; + const AMOUNT: u128 = 10_000_000_000_000_000; AssetReserve::execute_with(|| { // Reserve parachain should be able to reserve-transfer an asset to Trappist Parachain @@ -290,37 +328,32 @@ mod tests { asset_reserve::RuntimeOrigin::signed(ALICE), Box::new((Parent, Parachain(TRAPPIST_PARA_ID)).into()), Box::new(X1(AccountId32 { network: Any, id: ALICE.into() }).into().into()), - Box::new(V1(MultiAssets::from_sorted_and_deduplicated_skip_checks(vec![ - MultiAsset { - id: Concrete( - X2( - PalletInstance(ASSET_RESERVE_PALLET_INDEX), - GeneralIndex(xUSD as u128) - ) - .into(), - ), - fun: Fungible(SEND_AMOUNT), - } - ]))), + Box::new( + ( + X2(PalletInstance(ASSET_RESERVE_PALLET_INDEX), GeneralIndex(xUSD as u128)), + AMOUNT + ) + .into() + ), 0, WeightLimit::Unlimited, )); // Check send amount moved to sovereign account let sovereign_account = asset_reserve::sovereign_account(TRAPPIST_PARA_ID); - assert_eq!(asset_reserve::Assets::balance(xUSD, &sovereign_account), SEND_AMOUNT); + assert_eq!(asset_reserve::Assets::balance(xUSD, &sovereign_account), AMOUNT); }); - const FEES: u128 = 1_600_000_000; + const EST_FEES: u128 = 1_600_000_000; Trappist::execute_with(|| { // Check beneficiary account balance - assert_balance(trappist::Assets::balance(txUSD, &ALICE), SEND_AMOUNT, FEES); + assert_balance(trappist::Assets::balance(txUSD, &ALICE), AMOUNT, EST_FEES); }); } #[test] #[allow(non_upper_case_globals)] - fn hrmp_two_hop_reserve_transfer_from_trappist_parachain_to_tertiary_parachain() { + fn two_hop_reserve_transfer_from_trappist_parachain_to_tertiary_parachain() { todo!() } diff --git a/xcm-simulator/src/relay_chain.rs b/xcm-simulator/src/relay_chain.rs index 92e420b7..25961e5e 100644 --- a/xcm-simulator/src/relay_chain.rs +++ b/xcm-simulator/src/relay_chain.rs @@ -16,34 +16,32 @@ //! Relay chain runtime mock. +use crate::{relay_chain, ASSET_RESERVE_PARA_ID}; use frame_support::{ - construct_runtime, parameter_types, + construct_runtime, match_types, parameter_types, traits::{Everything, Nothing}, }; -use polkadot_core_primitives::BlockNumber; -use sp_core::H256; -use sp_runtime::{generic, traits::IdentityLookup, AccountId32}; - +pub use polkadot_core_primitives::AccountId; +use polkadot_core_primitives::{Balance, BlockNumber, Hash}; use polkadot_parachain::primitives::Id as ParaId; -use polkadot_runtime_parachains::{configuration, dmp, hrmp, origin, paras, shared, ump}; -use rococo_runtime::FirstMessageFactorPercent; -use sp_runtime::traits::BlakeTwo256; +use polkadot_runtime_common::BlockHashCount; +use polkadot_runtime_parachains::{configuration, dmp, origin, shared, ump, Origin}; +use rococo_runtime::{ExistentialDeposit, FirstMessageFactorPercent, MaxLocks, MaxReserves}; +use sp_runtime::{ + generic, + traits::{BlakeTwo256, IdentityLookup}, +}; use xcm::latest::prelude::*; use xcm_builder::{ - AccountId32Aliases, AllowUnpaidExecutionFrom, ChildParachainAsNative, + AccountId32Aliases, AllowKnownQueryResponses, AllowSubscriptionsFrom, + AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, ChildParachainAsNative, ChildParachainConvertsVia, ChildSystemParachainAsSuperuser, - CurrencyAdapter as XcmCurrencyAdapter, FixedRateOfFungible, FixedWeightBounds, IsConcrete, + CurrencyAdapter as XcmCurrencyAdapter, FixedWeightBounds, IsChildSystemParachain, IsConcrete, LocationInverter, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, + TakeWeightCredit, UsingComponents, WeightInfoBounds, }; use xcm_executor::{Config, XcmExecutor}; -pub type AccountId = AccountId32; -pub type Balance = u128; - -parameter_types! { - pub const BlockHashCount: BlockNumber = 250; -} - impl frame_system::Config for Runtime { type BaseCallFilter = Everything; type BlockWeights = (); @@ -52,7 +50,7 @@ impl frame_system::Config for Runtime { type RuntimeCall = RuntimeCall; type Index = u64; type BlockNumber = BlockNumber; - type Hash = H256; + type Hash = Hash; type Hashing = BlakeTwo256; type AccountId = AccountId; type Lookup = IdentityLookup; @@ -71,19 +69,13 @@ impl frame_system::Config for Runtime { type MaxConsumers = frame_support::traits::ConstU32<16>; } -parameter_types! { - pub ExistentialDeposit: Balance = 1; - pub const MaxLocks: u32 = 50; - pub const MaxReserves: u32 = 50; -} - impl pallet_balances::Config for Runtime { type Balance = Balance; type DustRemoval = (); type RuntimeEvent = RuntimeEvent; type ExistentialDeposit = ExistentialDeposit; type AccountStore = System; - type WeightInfo = (); + type WeightInfo = weights::pallet_balances::WeightInfo; type MaxLocks = MaxLocks; type MaxReserves = MaxReserves; type ReserveIdentifier = [u8; 8]; @@ -96,34 +88,54 @@ impl configuration::Config for Runtime { } parameter_types! { - pub const KsmLocation: MultiLocation = Here.into(); - pub const KusamaNetwork: NetworkId = NetworkId::Kusama; - pub const AnyNetwork: NetworkId = NetworkId::Any; + pub const RocLocation: MultiLocation = Here.into(); + pub RococoNetwork: NetworkId = + NetworkId::Named(b"Rococo".to_vec().try_into().expect("shorter than length limit; qed")); pub Ancestry: MultiLocation = Here.into(); - pub UnitWeightCost: u64 = 1_000; + pub CheckAccount: AccountId = XcmPallet::check_account(); } pub type SovereignAccountOf = - (ChildParachainConvertsVia, AccountId32Aliases); + (ChildParachainConvertsVia, AccountId32Aliases); -pub type LocalAssetTransactor = - XcmCurrencyAdapter, SovereignAccountOf, AccountId, ()>; +pub type LocalAssetTransactor = XcmCurrencyAdapter< + Balances, + IsConcrete, + SovereignAccountOf, + AccountId, + CheckAccount, +>; type LocalOriginConverter = ( SovereignSignedViaLocation, - ChildParachainAsNative, - SignedAccountId32AsNative, + ChildParachainAsNative, + SignedAccountId32AsNative, ChildSystemParachainAsSuperuser, ); parameter_types! { - pub const BaseXcmWeight: u64 = 1_000; - pub KsmPerSecond: (AssetId, u128) = (Concrete(KsmLocation::get()), 1); + pub const BaseXcmWeight: u64 = 1_000_000_000; pub const MaxInstructions: u32 = 100; + pub const Rococo: MultiAssetFilter = Wild(AllOf { fun: WildFungible, id: Concrete(RocLocation::get()) }); + pub const Statemine: MultiLocation = Parachain(ASSET_RESERVE_PARA_ID).into(); + pub const RococoForStatemine: (MultiAssetFilter, MultiLocation) = (Rococo::get(), Statemine::get()); +} + +match_types! { + pub type OnlyParachains: impl Contains = { + MultiLocation { parents: 0, interior: X1(Parachain(_)) } + }; } +pub type Barrier = ( + TakeWeightCredit, + AllowTopLevelPaidExecutionFrom, + AllowUnpaidExecutionFrom>, + AllowKnownQueryResponses, + AllowSubscriptionsFrom, +); +pub type TrustedTeleporters = (xcm_builder::Case,); pub type XcmRouter = super::RelayChainXcmRouter; -pub type Barrier = AllowUnpaidExecutionFrom; pub struct XcmConfig; impl Config for XcmConfig { @@ -132,18 +144,25 @@ impl Config for XcmConfig { type AssetTransactor = LocalAssetTransactor; type OriginConverter = LocalOriginConverter; type IsReserve = (); - type IsTeleporter = (); + type IsTeleporter = TrustedTeleporters; type LocationInverter = LocationInverter; type Barrier = Barrier; - type Weigher = FixedWeightBounds; - type Trader = FixedRateOfFungible; - type ResponseHandler = (); - type AssetTrap = (); - type AssetClaims = (); - type SubscriptionService = (); + type Weigher = + WeightInfoBounds, RuntimeCall, MaxInstructions>; + type Trader = UsingComponents< + rococo_runtime_constants::fee::WeightToFee, + RocLocation, + AccountId, + Balances, + (), + >; + type ResponseHandler = XcmPallet; + type AssetTrap = XcmPallet; + type AssetClaims = XcmPallet; + type SubscriptionService = XcmPallet; } -pub type LocalOriginToLocation = SignedToAccountId32; +pub type LocalOriginToLocation = SignedToAccountId32; impl pallet_xcm::Config for Runtime { type RuntimeEvent = RuntimeEvent; @@ -262,287 +281,446 @@ construct_runtime!( } ); +#[allow(dead_code)] +pub(crate) fn check_account() -> AccountId { + relay_chain::XcmPallet::check_account() +} + mod weights { - pub(crate) mod runtime_parachains_hrmp { + + pub(crate) mod pallet_balances { use frame_support::{traits::Get, weights::Weight}; use sp_std::marker::PhantomData; - /// Weight functions for `runtime_parachains::hrmp`. + /// Weight functions for `pallet_balances`. pub struct WeightInfo(PhantomData); - impl super::super::hrmp::WeightInfo for WeightInfo { - // Storage: Paras ParaLifecycles (r:2 w:0) - // Storage: Configuration ActiveConfig (r:1 w:0) - // Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) - // Storage: Hrmp HrmpChannels (r:1 w:0) - // Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:0) - // Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1) - // Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) - // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) - // Storage: Dmp DownwardMessageQueues (r:1 w:1) - fn hrmp_init_open_channel() -> Weight { - Weight::from_ref_time(40_520_000 as u64) - .saturating_add(T::DbWeight::get().reads(10 as u64)) - .saturating_add(T::DbWeight::get().writes(5 as u64)) - } - // Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) - // Storage: Configuration ActiveConfig (r:1 w:0) - // Storage: Paras ParaLifecycles (r:1 w:0) - // Storage: Hrmp HrmpIngressChannelsIndex (r:1 w:0) - // Storage: Hrmp HrmpAcceptedChannelRequestCount (r:1 w:1) - // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) - // Storage: Dmp DownwardMessageQueues (r:1 w:1) - fn hrmp_accept_open_channel() -> Weight { - Weight::from_ref_time(39_646_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) - } - // Storage: Hrmp HrmpChannels (r:1 w:0) - // Storage: Hrmp HrmpCloseChannelRequests (r:1 w:1) - // Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:1) - // Storage: Configuration ActiveConfig (r:1 w:0) - // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) - // Storage: Dmp DownwardMessageQueues (r:1 w:1) - fn hrmp_close_channel() -> Weight { - Weight::from_ref_time(36_691_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(4 as u64)) - } - // Storage: Hrmp HrmpIngressChannelsIndex (r:128 w:127) - // Storage: Hrmp HrmpEgressChannelsIndex (r:1 w:1) - // Storage: Hrmp HrmpChannels (r:127 w:127) - // Storage: Hrmp HrmpAcceptedChannelRequestCount (r:0 w:1) - // Storage: Hrmp HrmpChannelContents (r:0 w:127) - // Storage: Hrmp HrmpOpenChannelRequestCount (r:0 w:1) - /// The range of component `i` is `[0, 127]`. - /// The range of component `e` is `[0, 127]`. - fn force_clean_hrmp(i: u32, e: u32) -> Weight { - Weight::from_ref_time(0 as u64) - // Standard Error: 16_000 - .saturating_add( - Weight::from_ref_time(7_248_000 as u64).saturating_mul(i as u64), - ) - // Standard Error: 16_000 - .saturating_add( - Weight::from_ref_time(7_311_000 as u64).saturating_mul(e as u64), - ) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(i as u64))) - .saturating_add(T::DbWeight::get().reads((2 as u64).saturating_mul(e as u64))) - .saturating_add(T::DbWeight::get().writes(4 as u64)) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(i as u64))) - .saturating_add(T::DbWeight::get().writes((3 as u64).saturating_mul(e as u64))) - } - // Storage: Configuration ActiveConfig (r:1 w:0) - // Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:0) - // Storage: Hrmp HrmpOpenChannelRequests (r:2 w:2) - // Storage: Paras ParaLifecycles (r:4 w:0) - // Storage: Hrmp HrmpIngressChannelsIndex (r:2 w:2) - // Storage: Hrmp HrmpEgressChannelsIndex (r:2 w:2) - // Storage: Hrmp HrmpOpenChannelRequestCount (r:2 w:2) - // Storage: Hrmp HrmpAcceptedChannelRequestCount (r:2 w:2) - // Storage: Hrmp HrmpChannels (r:0 w:2) - /// The range of component `c` is `[0, 128]`. - fn force_process_hrmp_open(c: u32) -> Weight { - Weight::from_ref_time(0 as u64) - // Standard Error: 19_000 - .saturating_add( - Weight::from_ref_time(15_783_000 as u64).saturating_mul(c as u64), - ) - .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().reads((7 as u64).saturating_mul(c as u64))) - .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((6 as u64).saturating_mul(c as u64))) - } - // Storage: Hrmp HrmpCloseChannelRequestsList (r:1 w:0) - // Storage: Hrmp HrmpChannels (r:2 w:2) - // Storage: Hrmp HrmpEgressChannelsIndex (r:2 w:2) - // Storage: Hrmp HrmpIngressChannelsIndex (r:2 w:2) - // Storage: Hrmp HrmpCloseChannelRequests (r:0 w:2) - // Storage: Hrmp HrmpChannelContents (r:0 w:2) - /// The range of component `c` is `[0, 128]`. - fn force_process_hrmp_close(c: u32) -> Weight { - Weight::from_ref_time(0 as u64) - // Standard Error: 12_000 - .saturating_add( - Weight::from_ref_time(9_624_000 as u64).saturating_mul(c as u64), - ) + impl pallet_balances::WeightInfo for WeightInfo { + // Storage: System Account (r:1 w:1) + fn transfer() -> Weight { + Weight::from_ref_time(40_460_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().reads((3 as u64).saturating_mul(c as u64))) .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((5 as u64).saturating_mul(c as u64))) - } - // Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) - // Storage: Hrmp HrmpOpenChannelRequests (r:1 w:1) - // Storage: Hrmp HrmpOpenChannelRequestCount (r:1 w:1) - /// The range of component `c` is `[0, 128]`. - fn hrmp_cancel_open_request(c: u32) -> Weight { - Weight::from_ref_time(30_548_000 as u64) - // Standard Error: 1_000 - .saturating_add(Weight::from_ref_time(89_000 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(3 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - } - // Storage: Hrmp HrmpOpenChannelRequestsList (r:1 w:1) - // Storage: Hrmp HrmpOpenChannelRequests (r:2 w:2) - /// The range of component `c` is `[0, 128]`. - fn clean_open_channel_requests(c: u32) -> Weight { - Weight::from_ref_time(1_732_000 as u64) - // Standard Error: 4_000 - .saturating_add( - Weight::from_ref_time(2_574_000 as u64).saturating_mul(c as u64), - ) + } + // Storage: System Account (r:1 w:1) + fn transfer_keep_alive() -> Weight { + Weight::from_ref_time(29_508_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().reads((1 as u64).saturating_mul(c as u64))) .saturating_add(T::DbWeight::get().writes(1 as u64)) - .saturating_add(T::DbWeight::get().writes((1 as u64).saturating_mul(c as u64))) } - } - } - - pub(crate) mod runtime_parachains_paras { - use frame_support::{traits::Get, weights::Weight}; - use sp_std::marker::PhantomData; - - /// Weight functions for `runtime_parachains::paras`. - pub struct WeightInfo(PhantomData); - impl super::super::paras::WeightInfo for WeightInfo { - // Storage: Paras CurrentCodeHash (r:1 w:1) - // Storage: Paras CodeByHashRefs (r:1 w:1) - // Storage: Paras PastCodeMeta (r:1 w:1) - // Storage: Paras PastCodePruning (r:1 w:1) - // Storage: Paras PastCodeHash (r:0 w:1) - // Storage: Paras CodeByHash (r:0 w:1) - /// The range of component `c` is `[1, 3145728]`. - fn force_set_current_code(c: u32) -> Weight { - Weight::from_ref_time(0 as u64) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(2_000 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(4 as u64)) - .saturating_add(T::DbWeight::get().writes(6 as u64)) - } - // Storage: Paras Heads (r:0 w:1) - /// The range of component `s` is `[1, 1048576]`. - fn force_set_current_head(s: u32) -> Weight { - Weight::from_ref_time(0 as u64) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(1_000 as u64).saturating_mul(s as u64)) + // Storage: System Account (r:1 w:1) + fn set_balance_creating() -> Weight { + Weight::from_ref_time(22_142_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } - // Storage: Configuration ActiveConfig (r:1 w:0) - // Storage: Paras FutureCodeHash (r:1 w:1) - // Storage: Paras CurrentCodeHash (r:1 w:0) - // Storage: Paras UpgradeCooldowns (r:1 w:1) - // Storage: Paras PvfActiveVoteMap (r:1 w:0) - // Storage: Paras CodeByHash (r:1 w:1) - // Storage: Paras UpcomingUpgrades (r:1 w:1) - // Storage: System Digest (r:1 w:1) - // Storage: Paras CodeByHashRefs (r:1 w:1) - // Storage: Paras FutureCodeUpgrades (r:0 w:1) - // Storage: Paras UpgradeRestrictionSignal (r:0 w:1) - /// The range of component `c` is `[1, 3145728]`. - fn force_schedule_code_upgrade(c: u32) -> Weight { - Weight::from_ref_time(0 as u64) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(2_000 as u64).saturating_mul(c as u64)) - .saturating_add(T::DbWeight::get().reads(9 as u64)) - .saturating_add(T::DbWeight::get().writes(8 as u64)) - } - // Storage: Paras FutureCodeUpgrades (r:1 w:0) - // Storage: Paras Heads (r:0 w:1) - // Storage: Paras UpgradeGoAheadSignal (r:0 w:1) - /// The range of component `s` is `[1, 1048576]`. - fn force_note_new_head(s: u32) -> Weight { - Weight::from_ref_time(0 as u64) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(1_000 as u64).saturating_mul(s as u64)) + // Storage: System Account (r:1 w:1) + fn set_balance_killing() -> Weight { + Weight::from_ref_time(25_653_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) - .saturating_add(T::DbWeight::get().writes(2 as u64)) - } - // Storage: ParasShared CurrentSessionIndex (r:1 w:0) - // Storage: Paras ActionsQueue (r:1 w:1) - fn force_queue_action() -> Weight { - Weight::from_ref_time(24_187_000 as u64) - .saturating_add(T::DbWeight::get().reads(2 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } - // Storage: Paras PvfActiveVoteMap (r:1 w:0) - // Storage: Paras CodeByHash (r:1 w:1) - /// The range of component `c` is `[1, 3145728]`. - fn add_trusted_validation_code(c: u32) -> Weight { - Weight::from_ref_time(0 as u64) - // Standard Error: 0 - .saturating_add(Weight::from_ref_time(2_000 as u64).saturating_mul(c as u64)) + // Storage: System Account (r:2 w:2) + fn force_transfer() -> Weight { + Weight::from_ref_time(39_913_000 as u64) .saturating_add(T::DbWeight::get().reads(2 as u64)) - .saturating_add(T::DbWeight::get().writes(1 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) } - // Storage: Paras CodeByHashRefs (r:1 w:0) - // Storage: Paras CodeByHash (r:0 w:1) - fn poke_unused_validation_code() -> Weight { - Weight::from_ref_time(7_273_000 as u64) + // Storage: System Account (r:1 w:1) + fn transfer_all() -> Weight { + Weight::from_ref_time(34_497_000 as u64) .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } - // Storage: Configuration ActiveConfig (r:1 w:0) - // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - // Storage: ParasShared CurrentSessionIndex (r:1 w:0) - // Storage: Paras PvfActiveVoteMap (r:1 w:1) - fn include_pvf_check_statement() -> Weight { - Weight::from_ref_time(96_047_000 as u64) - .saturating_add(T::DbWeight::get().reads(4 as u64)) + // Storage: System Account (r:1 w:1) + fn force_unreserve() -> Weight { + Weight::from_ref_time(19_749_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) .saturating_add(T::DbWeight::get().writes(1 as u64)) } - // Storage: Configuration ActiveConfig (r:1 w:0) - // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - // Storage: ParasShared CurrentSessionIndex (r:1 w:0) - // Storage: Paras PvfActiveVoteMap (r:1 w:1) - // Storage: Paras PvfActiveVoteList (r:1 w:1) - // Storage: Paras UpcomingUpgrades (r:1 w:1) - // Storage: System Digest (r:1 w:1) - // Storage: Paras FutureCodeUpgrades (r:0 w:100) - fn include_pvf_check_statement_finalize_upgrade_accept() -> Weight { - Weight::from_ref_time(630_640_000 as u64) - .saturating_add(T::DbWeight::get().reads(7 as u64)) - .saturating_add(T::DbWeight::get().writes(104 as u64)) - } - // Storage: Configuration ActiveConfig (r:1 w:0) - // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - // Storage: ParasShared CurrentSessionIndex (r:1 w:0) - // Storage: Paras PvfActiveVoteMap (r:1 w:1) - // Storage: Paras PvfActiveVoteList (r:1 w:1) - // Storage: Paras CodeByHashRefs (r:1 w:1) - // Storage: Paras CodeByHash (r:0 w:1) - // Storage: Paras UpgradeGoAheadSignal (r:0 w:100) - // Storage: Paras FutureCodeHash (r:0 w:100) - fn include_pvf_check_statement_finalize_upgrade_reject() -> Weight { - Weight::from_ref_time(599_325_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(204 as u64)) - } - // Storage: Configuration ActiveConfig (r:1 w:0) - // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - // Storage: ParasShared CurrentSessionIndex (r:1 w:0) - // Storage: Paras PvfActiveVoteMap (r:1 w:1) - // Storage: Paras PvfActiveVoteList (r:1 w:1) - // Storage: Paras ActionsQueue (r:1 w:1) - fn include_pvf_check_statement_finalize_onboarding_accept() -> Weight { - Weight::from_ref_time(505_499_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(3 as u64)) - } - // Storage: Configuration ActiveConfig (r:1 w:0) - // Storage: ParasShared ActiveValidatorKeys (r:1 w:0) - // Storage: ParasShared CurrentSessionIndex (r:1 w:0) - // Storage: Paras PvfActiveVoteMap (r:1 w:1) - // Storage: Paras PvfActiveVoteList (r:1 w:1) - // Storage: Paras CodeByHashRefs (r:1 w:1) - // Storage: Paras ParaLifecycles (r:0 w:100) - // Storage: Paras CodeByHash (r:0 w:1) - // Storage: Paras CurrentCodeHash (r:0 w:100) - // Storage: Paras UpcomingParasGenesis (r:0 w:100) - fn include_pvf_check_statement_finalize_onboarding_reject() -> Weight { - Weight::from_ref_time(668_669_000 as u64) - .saturating_add(T::DbWeight::get().reads(6 as u64)) - .saturating_add(T::DbWeight::get().writes(304 as u64)) + } + } + + pub(crate) mod xcm { + use super::super::Runtime; + use frame_support::weights::Weight; + use sp_std::prelude::*; + use xcm::{ + latest::{prelude::*, Weight as XCMWeight}, + DoubleEncoded, + }; + + use pallet_xcm_benchmarks_fungible::WeightInfo as XcmBalancesWeight; + use pallet_xcm_benchmarks_generic::WeightInfo as XcmGeneric; + + /// Types of asset supported by the Rococo runtime. + pub enum AssetTypes { + /// An asset backed by `pallet-balances`. + Balances, + /// Unknown asset. + Unknown, + } + + impl From<&MultiAsset> for AssetTypes { + fn from(asset: &MultiAsset) -> Self { + match asset { + MultiAsset { + id: Concrete(MultiLocation { parents: 0, interior: Here }), + .. + } => AssetTypes::Balances, + _ => AssetTypes::Unknown, + } + } + } + + trait WeighMultiAssets { + fn weigh_multi_assets(&self, balances_weight: Weight) -> XCMWeight; + } + + // Rococo only knows about one asset, the balances pallet. + const MAX_ASSETS: u32 = 1; + + impl WeighMultiAssets for MultiAssetFilter { + fn weigh_multi_assets(&self, balances_weight: Weight) -> XCMWeight { + let weight = match self { + Self::Definite(assets) => assets + .inner() + .into_iter() + .map(From::from) + .map(|t| match t { + AssetTypes::Balances => balances_weight, + AssetTypes::Unknown => Weight::MAX, + }) + .fold(Weight::zero(), |acc, x| acc.saturating_add(x)), + Self::Wild(_) => balances_weight.saturating_mul(MAX_ASSETS as u64), + }; + + weight.ref_time() + } + } + + impl WeighMultiAssets for MultiAssets { + fn weigh_multi_assets(&self, balances_weight: Weight) -> XCMWeight { + let weight = self + .inner() + .into_iter() + .map(|m| >::from(m)) + .map(|t| match t { + AssetTypes::Balances => balances_weight, + AssetTypes::Unknown => Weight::MAX, + }) + .fold(Weight::zero(), |acc, x| acc.saturating_add(x)); + + weight.ref_time() + } + } + + pub struct RococoXcmWeight(core::marker::PhantomData); + impl XcmWeightInfo for RococoXcmWeight { + fn withdraw_asset(assets: &MultiAssets) -> XCMWeight { + assets.weigh_multi_assets(XcmBalancesWeight::::withdraw_asset()) + } + fn reserve_asset_deposited(assets: &MultiAssets) -> XCMWeight { + assets.weigh_multi_assets(XcmBalancesWeight::::reserve_asset_deposited()) + } + fn receive_teleported_asset(assets: &MultiAssets) -> XCMWeight { + assets.weigh_multi_assets(XcmBalancesWeight::::receive_teleported_asset()) + } + fn query_response( + _query_id: &u64, + _response: &Response, + _max_weight: &u64, + ) -> XCMWeight { + XcmGeneric::::query_response().ref_time() + } + fn transfer_asset(assets: &MultiAssets, _dest: &MultiLocation) -> XCMWeight { + assets.weigh_multi_assets(XcmBalancesWeight::::transfer_asset()) + } + fn transfer_reserve_asset( + assets: &MultiAssets, + _dest: &MultiLocation, + _xcm: &Xcm<()>, + ) -> XCMWeight { + assets.weigh_multi_assets(XcmBalancesWeight::::transfer_reserve_asset()) + } + fn transact( + _origin_type: &OriginKind, + _require_weight_at_most: &u64, + _call: &DoubleEncoded, + ) -> XCMWeight { + XcmGeneric::::transact().ref_time() + } + fn hrmp_new_channel_open_request( + _sender: &u32, + _max_message_size: &u32, + _max_capacity: &u32, + ) -> XCMWeight { + // XCM Executor does not currently support HRMP channel operations + Weight::MAX.ref_time() + } + fn hrmp_channel_accepted(_recipient: &u32) -> XCMWeight { + // XCM Executor does not currently support HRMP channel operations + Weight::MAX.ref_time() + } + fn hrmp_channel_closing( + _initiator: &u32, + _sender: &u32, + _recipient: &u32, + ) -> XCMWeight { + // XCM Executor does not currently support HRMP channel operations + Weight::MAX.ref_time() + } + fn clear_origin() -> XCMWeight { + XcmGeneric::::clear_origin().ref_time() + } + fn descend_origin(_who: &InteriorMultiLocation) -> XCMWeight { + XcmGeneric::::descend_origin().ref_time() + } + fn report_error( + _query_id: &QueryId, + _dest: &MultiLocation, + _max_response_weight: &u64, + ) -> XCMWeight { + XcmGeneric::::report_error().ref_time() + } + + fn deposit_asset( + assets: &MultiAssetFilter, + _max_assets: &u32, // TODO use max assets? + _dest: &MultiLocation, + ) -> XCMWeight { + assets.weigh_multi_assets(XcmBalancesWeight::::deposit_asset()) + } + fn deposit_reserve_asset( + assets: &MultiAssetFilter, + _max_assets: &u32, // TODO use max assets? + _dest: &MultiLocation, + _xcm: &Xcm<()>, + ) -> XCMWeight { + assets.weigh_multi_assets(XcmBalancesWeight::::deposit_reserve_asset()) + } + fn exchange_asset(_give: &MultiAssetFilter, _receive: &MultiAssets) -> XCMWeight { + Weight::MAX.ref_time() // todo fix + } + fn initiate_reserve_withdraw( + assets: &MultiAssetFilter, + _reserve: &MultiLocation, + _xcm: &Xcm<()>, + ) -> XCMWeight { + assets.weigh_multi_assets(XcmGeneric::::initiate_reserve_withdraw()) + } + fn initiate_teleport( + assets: &MultiAssetFilter, + _dest: &MultiLocation, + _xcm: &Xcm<()>, + ) -> XCMWeight { + assets.weigh_multi_assets(XcmBalancesWeight::::initiate_teleport()) + } + fn query_holding( + _query_id: &u64, + _dest: &MultiLocation, + _assets: &MultiAssetFilter, + _max_response_weight: &u64, + ) -> XCMWeight { + XcmGeneric::::query_holding().ref_time() + } + fn buy_execution(_fees: &MultiAsset, _weight_limit: &WeightLimit) -> XCMWeight { + XcmGeneric::::buy_execution().ref_time() + } + fn refund_surplus() -> XCMWeight { + XcmGeneric::::refund_surplus().ref_time() + } + fn set_error_handler(_xcm: &Xcm) -> XCMWeight { + XcmGeneric::::set_error_handler().ref_time() + } + fn set_appendix(_xcm: &Xcm) -> XCMWeight { + XcmGeneric::::set_appendix().ref_time() + } + fn clear_error() -> XCMWeight { + XcmGeneric::::clear_error().ref_time() + } + fn claim_asset(_assets: &MultiAssets, _ticket: &MultiLocation) -> XCMWeight { + XcmGeneric::::claim_asset().ref_time() + } + fn trap(_code: &u64) -> XCMWeight { + XcmGeneric::::trap().ref_time() + } + fn subscribe_version(_query_id: &QueryId, _max_response_weight: &u64) -> XCMWeight { + XcmGeneric::::subscribe_version().ref_time() + } + fn unsubscribe_version() -> XCMWeight { + XcmGeneric::::unsubscribe_version().ref_time() + } + } + + mod pallet_xcm_benchmarks_fungible { + use frame_support::{traits::Get, weights::Weight}; + use sp_std::marker::PhantomData; + + /// Weights for `pallet_xcm_benchmarks::fungible`. + pub struct WeightInfo(PhantomData); + impl WeightInfo { + // Storage: System Account (r:1 w:1) + pub(crate) fn withdraw_asset() -> Weight { + Weight::from_ref_time(20_385_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: System Account (r:2 w:2) + pub(crate) fn transfer_asset() -> Weight { + Weight::from_ref_time(32_756_000 as u64) + .saturating_add(T::DbWeight::get().reads(2 as u64)) + .saturating_add(T::DbWeight::get().writes(2 as u64)) + } + // Storage: System Account (r:2 w:2) + // Storage: XcmPallet SupportedVersion (r:1 w:0) + // Storage: XcmPallet VersionDiscoveryQueue (r:1 w:1) + // Storage: XcmPallet SafeXcmVersion (r:1 w:0) + // Storage: Configuration ActiveConfig (r:1 w:0) + // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) + // Storage: Dmp DownwardMessageQueues (r:1 w:1) + pub(crate) fn transfer_reserve_asset() -> Weight { + Weight::from_ref_time(50_645_000 as u64) + .saturating_add(T::DbWeight::get().reads(8 as u64)) + .saturating_add(T::DbWeight::get().writes(5 as u64)) + } + // Storage: Benchmark Override (r:0 w:0) + pub(crate) fn reserve_asset_deposited() -> Weight { + Weight::from_ref_time(2_000_000_000_000 as u64) + } + // Storage: System Account (r:1 w:1) + pub(crate) fn receive_teleported_asset() -> Weight { + Weight::from_ref_time(19_595_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: System Account (r:1 w:1) + pub(crate) fn deposit_asset() -> Weight { + Weight::from_ref_time(21_763_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: System Account (r:1 w:1) + // Storage: XcmPallet SupportedVersion (r:1 w:0) + // Storage: XcmPallet VersionDiscoveryQueue (r:1 w:1) + // Storage: XcmPallet SafeXcmVersion (r:1 w:0) + // Storage: Configuration ActiveConfig (r:1 w:0) + // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) + // Storage: Dmp DownwardMessageQueues (r:1 w:1) + pub(crate) fn deposit_reserve_asset() -> Weight { + Weight::from_ref_time(40_930_000 as u64) + .saturating_add(T::DbWeight::get().reads(7 as u64)) + .saturating_add(T::DbWeight::get().writes(4 as u64)) + } + // Storage: System Account (r:1 w:1) + // Storage: XcmPallet SupportedVersion (r:1 w:0) + // Storage: XcmPallet VersionDiscoveryQueue (r:1 w:1) + // Storage: XcmPallet SafeXcmVersion (r:1 w:0) + // Storage: Configuration ActiveConfig (r:1 w:0) + // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) + // Storage: Dmp DownwardMessageQueues (r:1 w:1) + pub(crate) fn initiate_teleport() -> Weight { + Weight::from_ref_time(40_788_000 as u64) + .saturating_add(T::DbWeight::get().reads(7 as u64)) + .saturating_add(T::DbWeight::get().writes(4 as u64)) + } + } + } + + mod pallet_xcm_benchmarks_generic { + use frame_support::{traits::Get, weights::Weight}; + use sp_std::marker::PhantomData; + + /// Weights for `pallet_xcm_benchmarks::generic`. + pub struct WeightInfo(PhantomData); + impl WeightInfo { + // Storage: XcmPallet SupportedVersion (r:1 w:0) + // Storage: XcmPallet VersionDiscoveryQueue (r:1 w:1) + // Storage: XcmPallet SafeXcmVersion (r:1 w:0) + // Storage: Configuration ActiveConfig (r:1 w:0) + // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) + // Storage: Dmp DownwardMessageQueues (r:1 w:1) + pub(crate) fn query_holding() -> Weight { + Weight::from_ref_time(21_822_000 as u64) + .saturating_add(T::DbWeight::get().reads(6 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) + } + pub(crate) fn buy_execution() -> Weight { + Weight::from_ref_time(3_109_000 as u64) + } + // Storage: XcmPallet Queries (r:1 w:0) + pub(crate) fn query_response() -> Weight { + Weight::from_ref_time(12_087_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + } + pub(crate) fn transact() -> Weight { + Weight::from_ref_time(12_398_000 as u64) + } + pub(crate) fn refund_surplus() -> Weight { + Weight::from_ref_time(3_247_000 as u64) + } + pub(crate) fn set_error_handler() -> Weight { + Weight::from_ref_time(3_086_000 as u64) + } + pub(crate) fn set_appendix() -> Weight { + Weight::from_ref_time(3_112_000 as u64) + } + pub(crate) fn clear_error() -> Weight { + Weight::from_ref_time(3_118_000 as u64) + } + pub(crate) fn descend_origin() -> Weight { + Weight::from_ref_time(4_054_000 as u64) + } + pub(crate) fn clear_origin() -> Weight { + Weight::from_ref_time(3_111_000 as u64) + } + // Storage: XcmPallet SupportedVersion (r:1 w:0) + // Storage: XcmPallet VersionDiscoveryQueue (r:1 w:1) + // Storage: XcmPallet SafeXcmVersion (r:1 w:0) + // Storage: Configuration ActiveConfig (r:1 w:0) + // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) + // Storage: Dmp DownwardMessageQueues (r:1 w:1) + pub(crate) fn report_error() -> Weight { + Weight::from_ref_time(18_425_000 as u64) + .saturating_add(T::DbWeight::get().reads(6 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) + } + // Storage: XcmPallet AssetTraps (r:1 w:1) + pub(crate) fn claim_asset() -> Weight { + Weight::from_ref_time(7_144_000 as u64) + .saturating_add(T::DbWeight::get().reads(1 as u64)) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + pub(crate) fn trap() -> Weight { + Weight::from_ref_time(3_060_000 as u64) + } + // Storage: XcmPallet VersionNotifyTargets (r:1 w:1) + // Storage: XcmPallet SupportedVersion (r:1 w:0) + // Storage: XcmPallet VersionDiscoveryQueue (r:1 w:1) + // Storage: XcmPallet SafeXcmVersion (r:1 w:0) + // Storage: Configuration ActiveConfig (r:1 w:0) + // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) + // Storage: Dmp DownwardMessageQueues (r:1 w:1) + pub(crate) fn subscribe_version() -> Weight { + Weight::from_ref_time(21_642_000 as u64) + .saturating_add(T::DbWeight::get().reads(7 as u64)) + .saturating_add(T::DbWeight::get().writes(4 as u64)) + } + // Storage: XcmPallet VersionNotifyTargets (r:0 w:1) + pub(crate) fn unsubscribe_version() -> Weight { + Weight::from_ref_time(4_873_000 as u64) + .saturating_add(T::DbWeight::get().writes(1 as u64)) + } + // Storage: XcmPallet SupportedVersion (r:1 w:0) + // Storage: XcmPallet VersionDiscoveryQueue (r:1 w:1) + // Storage: XcmPallet SafeXcmVersion (r:1 w:0) + // Storage: Configuration ActiveConfig (r:1 w:0) + // Storage: Dmp DownwardMessageQueueHeads (r:1 w:1) + // Storage: Dmp DownwardMessageQueues (r:1 w:1) + pub(crate) fn initiate_reserve_withdraw() -> Weight { + Weight::from_ref_time(22_809_000 as u64) + .saturating_add(T::DbWeight::get().reads(6 as u64)) + .saturating_add(T::DbWeight::get().writes(3 as u64)) + } } } } From 9d53ad1a5dc7fc5c5c1689611788e723bee8a529 Mon Sep 17 00:00:00 2001 From: Frank Bell Date: Fri, 6 Jan 2023 18:56:06 +0000 Subject: [PATCH 03/16] test: add (ump) teleport test --- xcm-simulator/src/lib.rs | 52 ++++++++++++++++++- xcm-simulator/src/parachains/asset_reserve.rs | 5 ++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/xcm-simulator/src/lib.rs b/xcm-simulator/src/lib.rs index 40a16739..3a9f7f19 100644 --- a/xcm-simulator/src/lib.rs +++ b/xcm-simulator/src/lib.rs @@ -194,7 +194,7 @@ mod tests { const ASSET_RESERVE_PALLET_INDEX: u8 = 50; #[test] - fn teleport_asset_from_relay_chain_asset_reserve_parachain() { + fn teleport_asset_from_relay_chain_to_asset_reserve_parachain() { init_tracing(); MockNet::reset(); @@ -239,7 +239,55 @@ mod tests { #[test] fn teleport_asset_from_asset_reserve_parachain_to_relay_chain() { - todo!() + init_tracing(); + + MockNet::reset(); + + const AMOUNT: u128 = 1_000_000_000; + let mut receiver_balance = 0; + let mut total_issuance = 0; + + Relay::execute_with(|| { + // Teleport some amount to asset reserve so there are tokens to teleport back + assert_ok!(relay_chain::XcmPallet::teleport_assets( + relay_chain::RuntimeOrigin::signed(ALICE), + Box::new(Parachain(ASSET_RESERVE_PARA_ID).into().into()), + Box::new(X1(AccountId32 { network: Any, id: ALICE.into() }).into().into()), + Box::new((Here, AMOUNT).into()), + 0 + )); + + // Check receiver balance and total issuance + receiver_balance = relay_chain::Balances::free_balance(&ALICE); + total_issuance = relay_chain::Balances::total_issuance(); + }); + + AssetReserve::execute_with(|| { + let sender_balance = asset_reserve::Balances::free_balance(&ALICE); + let total_issuance = asset_reserve::Balances::total_issuance(); + + assert_ok!(asset_reserve::PolkadotXcm::teleport_assets( + asset_reserve::RuntimeOrigin::signed(ALICE), + Box::new(Parent.into()), + Box::new(X1(AccountId32 { network: Any, id: ALICE.into() }).into().into()), + Box::new((Parent, AMOUNT).into()), + 0 + )); + + // Check sender balance and total issuance decreased by teleport amount + assert_eq!(asset_reserve::Balances::free_balance(&ALICE), sender_balance - AMOUNT); + assert_eq!(asset_reserve::Balances::total_issuance(), total_issuance - AMOUNT) + }); + + const EST_FEES: u128 = 4_000_000; + Relay::execute_with(|| { + // Check receiver balance increased by teleport amount + assert_balance( + relay_chain::Balances::free_balance(&ALICE), + receiver_balance + AMOUNT, + EST_FEES, + ); + }); } #[test] diff --git a/xcm-simulator/src/parachains/asset_reserve.rs b/xcm-simulator/src/parachains/asset_reserve.rs index a45175f7..fb6454cb 100644 --- a/xcm-simulator/src/parachains/asset_reserve.rs +++ b/xcm-simulator/src/parachains/asset_reserve.rs @@ -243,6 +243,11 @@ construct_runtime!( } ); +#[allow(dead_code)] +pub(crate) fn check_account() -> AccountId { + PolkadotXcm::check_account() +} + #[allow(dead_code)] pub(crate) fn sovereign_account(para_id: u32) -> AccountId { LocationToAccountId::convert_ref(MultiLocation::new(1, X1(Parachain(para_id)))).unwrap() From 24aeac1e3c970e37d22de1ff7038af5199183cc1 Mon Sep 17 00:00:00 2001 From: Frank Bell Date: Sat, 7 Jan 2023 13:15:00 +0000 Subject: [PATCH 04/16] test: add two-hop reserve transfer test --- runtime/base/src/lib.rs | 2 +- xcm-simulator/Cargo.toml | 4 +- xcm-simulator/src/lib.rs | 440 ++++++++++++++++++----- xcm-simulator/src/parachains/base.rs | 214 +++++++++++ xcm-simulator/src/parachains/mod.rs | 1 + xcm-simulator/src/parachains/trappist.rs | 5 +- 6 files changed, 570 insertions(+), 96 deletions(-) create mode 100644 xcm-simulator/src/parachains/base.rs diff --git a/runtime/base/src/lib.rs b/runtime/base/src/lib.rs index 42854f5f..9d15e941 100644 --- a/runtime/base/src/lib.rs +++ b/runtime/base/src/lib.rs @@ -23,7 +23,7 @@ include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); pub mod constants; mod contracts; -mod xcm_config; +pub mod xcm_config; use cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases; use sp_api::impl_runtime_apis; diff --git a/xcm-simulator/Cargo.toml b/xcm-simulator/Cargo.toml index 6ec1adb4..a03e9ba4 100644 --- a/xcm-simulator/Cargo.toml +++ b/xcm-simulator/Cargo.toml @@ -8,6 +8,9 @@ edition = "2021" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0" } scale-info = { version = "2.1.2", features = ["derive"] } +thousands = "0.2.0" +tracing = { version = "0.1.37" } +tracing-subscriber = { version = "0.3.16", features = ["env-filter", "tracing-log"] } frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } @@ -19,7 +22,6 @@ sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } -sp-tracing = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.30" } xcm = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.30" } xcm-simulator = { git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.30" } diff --git a/xcm-simulator/src/lib.rs b/xcm-simulator/src/lib.rs index 3a9f7f19..303aec8b 100644 --- a/xcm-simulator/src/lib.rs +++ b/xcm-simulator/src/lib.rs @@ -20,7 +20,7 @@ mod parachains; mod relay_chain; use frame_support::{sp_tracing, traits::GenesisBuild}; -use parachains::{asset_reserve, parachain, trappist}; +use parachains::{asset_reserve, base, parachain, trappist}; use polkadot_parachain::primitives::Id as ParaId; use sp_core::Get; use sp_runtime::traits::AccountIdConversion; @@ -28,22 +28,27 @@ use sp_runtime::traits::AccountIdConversion; use xcm_simulator::{decl_test_network, decl_test_parachain, decl_test_relay_chain}; pub const ALICE: sp_runtime::AccountId32 = sp_runtime::AccountId32::new([0u8; 32]); -pub const INITIAL_BALANCE: u128 = 10_000_000_000; +pub const INITIAL_BALANCE: u128 = 2_000_000_000; const ASSET_RESERVE_PARA_ID: u32 = 1000; decl_test_parachain! { + // An asset reserve parachain (Statemine) pub struct AssetReserve { Runtime = asset_reserve::Runtime, XcmpMessageHandler = asset_reserve::MsgQueue, DmpMessageHandler = asset_reserve::MsgQueue, new_ext = { + // Initialise parachain-specific genesis state use asset_reserve::{MsgQueue, Runtime, System}; const INITIAL_BALANCE: u128 = ::AssetDeposit::get() * 2; let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - pallet_balances::GenesisConfig:: { balances: vec![(ALICE, INITIAL_BALANCE)] } + pallet_balances::GenesisConfig:: { balances: vec![ + (ALICE, INITIAL_BALANCE), + (asset_reserve::sovereign_account(TRAPPIST_PARA_ID), INITIAL_BALANCE) + ]} .assimilate_storage(&mut t) .unwrap(); @@ -60,11 +65,13 @@ decl_test_parachain! { const TRAPPIST_PARA_ID: u32 = 2000; decl_test_parachain! { + // The trappist parachain pub struct Trappist { Runtime = trappist::Runtime, XcmpMessageHandler = trappist::MsgQueue, DmpMessageHandler = trappist::MsgQueue, new_ext = { + // Initialise parachain-specific genesis state use trappist::{MsgQueue, Runtime, System}; let asset_deposit: u128 = ::AssetDeposit::get(); @@ -93,16 +100,42 @@ decl_test_parachain! { const BASE_PARA_ID: u32 = 3000; decl_test_parachain! { + // A parachain using the trappist 'base' runtime pub struct Base { - Runtime = parachains::parachain::Runtime, - XcmpMessageHandler = parachains::parachain::MsgQueue, - DmpMessageHandler = parachains::parachain::MsgQueue, - new_ext = para_ext(BASE_PARA_ID), + Runtime = base::Runtime, + XcmpMessageHandler = base::MsgQueue, + DmpMessageHandler = base::MsgQueue, + new_ext = { + // Initialise parachain-specific genesis state + use trappist::{MsgQueue, Runtime, System}; + + let asset_deposit: u128 = ::AssetDeposit::get(); + let initial_balance: u128 = asset_deposit * 2; + + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + + pallet_balances::GenesisConfig:: { balances: vec![(ALICE, initial_balance)] } + .assimilate_storage(&mut t) + .unwrap(); + + pallet_sudo::GenesisConfig:: { key: Some(ALICE) } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + sp_tracing::try_init_simple(); + System::set_block_number(1); + MsgQueue::set_para_id(BASE_PARA_ID.into()); + }); + ext + }, } } const A_PARA_ID: u32 = 1; decl_test_parachain! { + // Some generic parachain pub struct ParaA { Runtime = parachains::parachain::Runtime, XcmpMessageHandler = parachains::parachain::MsgQueue, @@ -112,10 +145,12 @@ decl_test_parachain! { } decl_test_relay_chain! { + // The relay chain (Rococo) pub struct Relay { Runtime = relay_chain::Runtime, XcmConfig = relay_chain::XcmConfig, new_ext = { + // Initialise relay chain genesis state use relay_chain::{Runtime, System}; let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); @@ -166,7 +201,7 @@ fn para_ext(para_id: u32) -> sp_io::TestExternalities { ext.execute_with(|| { sp_tracing::try_init_simple(); System::set_block_number(1); - MsgQueue::set_para_id(para_id.into()); + MsgQueue::set_para_id(ParaId::new(para_id)); }); ext } @@ -174,42 +209,59 @@ fn para_ext(para_id: u32) -> sp_io::TestExternalities { #[cfg(test)] mod tests { use super::*; - use crate::relay_chain::mock_paras_sudo_wrapper; use codec::Encode; - use frame_support::assert_ok; + use frame_support::{ + assert_ok, + pallet_prelude::{DispatchResult, DispatchResultWithPostInfo}, + traits::PalletInfoAccess, + }; use std::sync::Once; - use xcm::{latest::prelude::*, opaque::VersionedXcm}; - use xcm_simulator::TestExt; + use thousands::Separable; + use xcm::prelude::*; + use xcm_simulator::{TestExt, Weight}; static INIT: Once = Once::new(); pub fn init_tracing() { INIT.call_once(|| { - // Add test tracing - // todo: filter to only show xcm logs - sp_tracing::init_for_tests(); + // Add test tracing (from sp_tracing::init_for_tests()) but filtering for xcm logs only + let _ = tracing_subscriber::fmt() + .with_max_level(tracing::Level::TRACE) + .with_env_filter("xcm=trace") // Comment out this line to see all traces + .with_test_writer() + .init(); }); } - const ASSET_RESERVE_PALLET_INDEX: u8 = 50; + #[allow(non_upper_case_globals)] + const xUSD: u32 = 1; + #[allow(non_upper_case_globals)] + const txUSD: u32 = 10; + #[allow(non_upper_case_globals)] + const pxUSD: u32 = xUSD; // Must match asset reserve identifier as no asset registry available in base runtime + // Teleports some amount of the native asset of the relay chain to the asset reserve parachain + // (DMP) #[test] - fn teleport_asset_from_relay_chain_to_asset_reserve_parachain() { + fn teleport_native_asset_from_relay_chain_to_asset_reserve_parachain() { init_tracing(); MockNet::reset(); - const AMOUNT: u128 = 1_000_000_000; - let mut receiver_balance = 0; + let mut beneficiary_balance = 0; let mut total_issuance = 0; AssetReserve::execute_with(|| { - // Check receiver balance increased by teleport amount - receiver_balance = asset_reserve::Balances::free_balance(&ALICE); + // Check beneficiary balance and total issuance on asset reserve before teleport + beneficiary_balance = asset_reserve::Balances::free_balance(&ALICE); total_issuance = asset_reserve::Balances::total_issuance(); }); + const AMOUNT: u128 = 1_000_000_000; + Relay::execute_with(|| { + // Teleport, ensuring relay chain total issuance remains constant + let total_issuance = relay_chain::Balances::total_issuance(); assert_ok!(relay_chain::XcmPallet::teleport_assets( relay_chain::RuntimeOrigin::signed(ALICE), Box::new(Parachain(ASSET_RESERVE_PARA_ID).into().into()), @@ -217,35 +269,42 @@ mod tests { Box::new((Here, AMOUNT).into()), 0 )); + assert_eq!(relay_chain::Balances::total_issuance(), total_issuance); - // Check teleport amount checked out to check account + // Ensure teleport amount 'checked out' to check account assert_eq!(relay_chain::Balances::free_balance(&relay_chain::check_account()), AMOUNT); - - // Check sender balance decreased by teleport amount + // Ensure sender balance decreased by teleport amount assert_eq!(relay_chain::Balances::free_balance(&ALICE), INITIAL_BALANCE - AMOUNT); }); const EST_FEES: u128 = 4_000_000; AssetReserve::execute_with(|| { - // Check receiver balance and total issuance increased by teleport amount - assert_balance( - asset_reserve::Balances::free_balance(&ALICE), - receiver_balance + AMOUNT, - EST_FEES, + // Ensure receiver balance and total issuance increased by teleport amount + let current_balance = asset_reserve::Balances::free_balance(&ALICE); + assert_balance(current_balance, beneficiary_balance + AMOUNT, EST_FEES); + assert_eq!(asset_reserve::Balances::total_issuance(), total_issuance + AMOUNT); + + println!( + "Teleport: initial balance {} teleport amount {} current balance {} estimated fees {} actual fees {}", + beneficiary_balance.separate_with_commas(), + AMOUNT.separate_with_commas(), + current_balance.separate_with_commas(), + EST_FEES.separate_with_commas(), + (beneficiary_balance + AMOUNT - current_balance).separate_with_commas() ); - assert_eq!(asset_reserve::Balances::total_issuance(), total_issuance + AMOUNT) }); } + // Teleports some amount of the (shared) native asset of the asset reserve parachain back to the + // relay chain (UMP) #[test] - fn teleport_asset_from_asset_reserve_parachain_to_relay_chain() { + fn teleport_native_asset_from_asset_reserve_parachain_to_relay_chain() { init_tracing(); MockNet::reset(); const AMOUNT: u128 = 1_000_000_000; - let mut receiver_balance = 0; - let mut total_issuance = 0; + let mut beneficiary_balance = 0; Relay::execute_with(|| { // Teleport some amount to asset reserve so there are tokens to teleport back @@ -257,15 +316,15 @@ mod tests { 0 )); - // Check receiver balance and total issuance - receiver_balance = relay_chain::Balances::free_balance(&ALICE); - total_issuance = relay_chain::Balances::total_issuance(); + // Check beneficiary balance + beneficiary_balance = relay_chain::Balances::free_balance(&ALICE); }); AssetReserve::execute_with(|| { + // Check sender balance & total issuance of native asset on asset reserve before + // teleporting let sender_balance = asset_reserve::Balances::free_balance(&ALICE); let total_issuance = asset_reserve::Balances::total_issuance(); - assert_ok!(asset_reserve::PolkadotXcm::teleport_assets( asset_reserve::RuntimeOrigin::signed(ALICE), Box::new(Parent.into()), @@ -274,50 +333,45 @@ mod tests { 0 )); - // Check sender balance and total issuance decreased by teleport amount + // Ensure sender balance and total issuance (of native asset on asset reserve) decreased + // by teleport amount assert_eq!(asset_reserve::Balances::free_balance(&ALICE), sender_balance - AMOUNT); assert_eq!(asset_reserve::Balances::total_issuance(), total_issuance - AMOUNT) }); - const EST_FEES: u128 = 4_000_000; + const EST_FEES: u128 = 2_500_000; Relay::execute_with(|| { - // Check receiver balance increased by teleport amount - assert_balance( - relay_chain::Balances::free_balance(&ALICE), - receiver_balance + AMOUNT, - EST_FEES, + // Ensure receiver balance increased by teleport amount + let current_balance = relay_chain::Balances::free_balance(&ALICE); + assert_balance(current_balance, beneficiary_balance + AMOUNT, EST_FEES); + println!( + "Teleport: initial balance {} teleport amount {} current balance {} estimated fees {} actual fees {}", + beneficiary_balance.separate_with_commas(), + AMOUNT.separate_with_commas(), + current_balance.separate_with_commas(), + EST_FEES.separate_with_commas(), + (beneficiary_balance + AMOUNT - current_balance).separate_with_commas() ); }); } + // Initiates a reserve-transfer of some asset on the asset reserve parachain to the trappist + // parachain (HRMP) #[test] - #[allow(non_upper_case_globals)] fn reserve_transfer_asset_from_asset_reserve_parachain_to_trappist_parachain() { init_tracing(); MockNet::reset(); - const xUSD: u32 = 1; - const txUSD: u32 = 10; - const MIN_BALANCE: asset_reserve::Balance = 1_000_000_000; + const ASSET_MIN_BALANCE: asset_reserve::Balance = 1_000_000_000; const MINT_AMOUNT: u128 = 1_000_000_000_000_000_000; AssetReserve::execute_with(|| { // Create fungible asset on Reserve Parachain - assert_ok!(asset_reserve::Assets::create( - asset_reserve::RuntimeOrigin::signed(ALICE), - xUSD, - ALICE.into(), - MIN_BALANCE - )); + assert_ok!(create_asset_on_asset_reserve(xUSD, ALICE, ASSET_MIN_BALANCE)); // Mint fungible asset - assert_ok!(asset_reserve::Assets::mint( - asset_reserve::RuntimeOrigin::signed(ALICE), - xUSD, - ALICE.into(), - MINT_AMOUNT - )); + assert_ok!(mint_asset_on_asset_reserve(xUSD, ALICE, MINT_AMOUNT)); assert_eq!(asset_reserve::Assets::balance(xUSD, &ALICE), MINT_AMOUNT); }); @@ -330,45 +384,28 @@ mod tests { issuer: ALICE.into(), admin: ALICE.into(), freezer: ALICE.into(), - min_balance: MIN_BALANCE, + min_balance: ASSET_MIN_BALANCE, is_sufficient: true, is_frozen: false, }, )); }); + let mut beneficiary_balance = 0; Trappist::execute_with(|| { // Create derivative asset on Trappist Parachain - assert_ok!(trappist::Assets::create( - trappist::RuntimeOrigin::signed(ALICE), - txUSD, - ALICE.into(), - MIN_BALANCE - )); + assert_ok!(create_derivative_asset_on_trappist(txUSD, ALICE.into(), ASSET_MIN_BALANCE)); // Map derivative asset (txUSD) to multi-location (xUSD within Assets pallet on Reserve // Parachain) via Asset Registry - assert_ok!(trappist::Sudo::sudo( - trappist::RuntimeOrigin::signed(ALICE), - Box::new(trappist::RuntimeCall::AssetRegistry(pallet_asset_registry::Call::< - trappist::Runtime, - >::register_reserve_asset { - asset_id: txUSD, - asset_multi_location: ( - Parent, - X3( - Parachain(ASSET_RESERVE_PARA_ID), - PalletInstance(ASSET_RESERVE_PALLET_INDEX), - GeneralIndex(xUSD as u128), - ), - ) - .into(), - })), - )); - assert!(trappist::AssetRegistry::asset_id_multilocation(txUSD).is_some()) + assert_ok!(register_reserve_asset_on_trappist(ALICE, txUSD)); + assert!(trappist::AssetRegistry::asset_id_multilocation(txUSD).is_some()); + + // Check beneficiary balance + beneficiary_balance = trappist::Assets::balance(txUSD, &ALICE); }); - const AMOUNT: u128 = 10_000_000_000_000_000; + const AMOUNT: u128 = 10_000_000_000; AssetReserve::execute_with(|| { // Reserve parachain should be able to reserve-transfer an asset to Trappist Parachain @@ -378,7 +415,10 @@ mod tests { Box::new(X1(AccountId32 { network: Any, id: ALICE.into() }).into().into()), Box::new( ( - X2(PalletInstance(ASSET_RESERVE_PALLET_INDEX), GeneralIndex(xUSD as u128)), + X2( + PalletInstance(asset_reserve::Assets::index() as u8), + GeneralIndex(xUSD as u128) + ), AMOUNT ) .into() @@ -387,22 +427,168 @@ mod tests { WeightLimit::Unlimited, )); - // Check send amount moved to sovereign account + // Ensure send amount moved to sovereign account let sovereign_account = asset_reserve::sovereign_account(TRAPPIST_PARA_ID); assert_eq!(asset_reserve::Assets::balance(xUSD, &sovereign_account), AMOUNT); }); const EST_FEES: u128 = 1_600_000_000; Trappist::execute_with(|| { - // Check beneficiary account balance - assert_balance(trappist::Assets::balance(txUSD, &ALICE), AMOUNT, EST_FEES); + // Ensure beneficiary account balance increased + let current_balance = trappist::Assets::balance(txUSD, &ALICE); + assert_balance(current_balance, beneficiary_balance + AMOUNT, EST_FEES); + println!( + "Reserve-transfer: initial balance {} transfer amount {} current balance {} estimated fees {} actual fees {}", + beneficiary_balance.separate_with_commas(), + AMOUNT.separate_with_commas(), + current_balance.separate_with_commas(), + EST_FEES.separate_with_commas(), + (beneficiary_balance + AMOUNT - current_balance).separate_with_commas() + ); }); } + // Initiates a send of a XCM message from trappist to the asset reserve parachain, instructing + // it to transfer some amount of a fungible asset to some tertiary (base) parachain (HRMP) #[test] - #[allow(non_upper_case_globals)] fn two_hop_reserve_transfer_from_trappist_parachain_to_tertiary_parachain() { - todo!() + init_tracing(); + + MockNet::reset(); + + const ASSET_MIN_BALANCE: asset_reserve::Balance = 1_000_000_000; + const AMOUNT: u128 = 100_000_000_000; + + AssetReserve::execute_with(|| { + // Create and mint fungible asset on Reserve Parachain + assert_ok!(create_asset_on_asset_reserve(xUSD, ALICE, ASSET_MIN_BALANCE)); + assert_ok!(mint_asset_on_asset_reserve(xUSD, ALICE, AMOUNT * 2)); + + // Touch parachain account + assert_ok!(asset_reserve::Assets::transfer( + asset_reserve::RuntimeOrigin::signed(ALICE), + xUSD, + asset_reserve::sovereign_account(TRAPPIST_PARA_ID).into(), + AMOUNT + )); + }); + + Relay::execute_with(|| { + // Declare xUSD (on Reserve Parachain) as self-sufficient via Relay Chain + paras_sudo_wrapper_sudo_queue_downward_xcm(asset_reserve::RuntimeCall::Assets( + pallet_assets::Call::::force_asset_status { + id: xUSD, + owner: ALICE.into(), + issuer: ALICE.into(), + admin: ALICE.into(), + freezer: ALICE.into(), + min_balance: ASSET_MIN_BALANCE, + is_sufficient: true, + is_frozen: false, + }, + )); + }); + + let mut beneficiary_balance = 0; + Base::execute_with(|| { + // Create fungible asset on tertiary parachain + assert_ok!(create_derivative_asset_on_tertiary_parachain( + pxUSD, + ALICE, + ASSET_MIN_BALANCE + )); + beneficiary_balance = base::Assets::balance(pxUSD, &ALICE); + }); + + const MAX_WEIGHT: u128 = 1_000_000_000 * 2; // 1,000,000,000 per instruction + const EXECUTION_COST: u128 = 65_000_000_000; + + Trappist::execute_with(|| { + // Create derivative asset on Trappist Parachain + assert_ok!(create_derivative_asset_on_trappist(txUSD, ALICE.into(), ASSET_MIN_BALANCE)); + + // Mint derivative asset on Trappist Parachain + assert_ok!(trappist::Assets::mint( + trappist::RuntimeOrigin::signed(ALICE), + txUSD, + ALICE.into(), + AMOUNT * 2 + )); + assert_eq!(trappist::Assets::balance(txUSD, &ALICE), AMOUNT * 2); + + // Map derivative asset (txUSD) to multi-location (xUSD within Assets pallet on Reserve + // Parachain) via Asset Registry + assert_ok!(register_reserve_asset_on_trappist(ALICE, txUSD)); + assert!(trappist::AssetRegistry::asset_id_multilocation(txUSD).is_some()); + + // Trappist parachain should be able to reserve-transfer an asset to Tertiary Parachain + assert_ok!(trappist::PolkadotXcm::execute( + trappist::RuntimeOrigin::signed(ALICE), + Box::new(VersionedXcm::from(Xcm(vec![ + WithdrawAsset( + ( + ( + Parent, + X3( + Parachain(ASSET_RESERVE_PARA_ID), + PalletInstance(asset_reserve::Assets::index() as u8), + GeneralIndex(xUSD as u128) + ) + ), + AMOUNT + ) + .into() + ), + InitiateReserveWithdraw { + assets: Wild(All), + reserve: (Parent, Parachain(ASSET_RESERVE_PARA_ID)).into(), + xcm: Xcm(vec![ + BuyExecution { + fees: ( + X2( + PalletInstance(asset_reserve::Assets::index() as u8), + GeneralIndex(xUSD as u128) + ), + EXECUTION_COST + ) + .into(), + weight_limit: Unlimited + }, + DepositReserveAsset { + assets: Wild(All), + max_assets: 1, + dest: (Parent, Parachain(BASE_PARA_ID)).into(), + xcm: Xcm(vec![DepositAsset { + assets: Wild(All), + max_assets: 1, + beneficiary: X1(AccountId32 { network: Any, id: ALICE.into() }) + .into() + }]) + } + ]) + }, + ]))), + Weight::from_ref_time(MAX_WEIGHT as u64) + )); + + // // Check send amount moved to sovereign account + // let sovereign_account = asset_reserve::sovereign_account(TRAPPIST_PARA_ID); + // assert_eq!(asset_reserve::Assets::balance(xUSD, &sovereign_account), AMOUNT); + }); + + Base::execute_with(|| { + // Ensure beneficiary received amount, less fees + let current_balance = base::Assets::balance(pxUSD, &ALICE); + assert_balance(current_balance, beneficiary_balance + AMOUNT, EXECUTION_COST); + println!( + "Two-hop Reserve-transfer: initial balance {} transfer amount {} current balance {} estimated fees {} actual fees {}", + beneficiary_balance.separate_with_commas(), + AMOUNT.separate_with_commas(), + current_balance.separate_with_commas(), + EXECUTION_COST.separate_with_commas(), + (beneficiary_balance + AMOUNT - current_balance).separate_with_commas() + ); + }); } fn assert_balance(actual: u128, expected: u128, fees: u128) { @@ -412,6 +598,53 @@ mod tests { ) } + fn create_asset_on_asset_reserve( + id: asset_reserve::AssetId, + admin: asset_reserve::AccountId, + min_balance: asset_reserve::Balance, + ) -> DispatchResult { + asset_reserve::Assets::create( + asset_reserve::RuntimeOrigin::signed(ALICE), + id, + admin.into(), + min_balance, + ) + } + + fn create_derivative_asset_on_trappist( + id: trappist::AssetId, + admin: trappist::AccountId, + min_balance: trappist::Balance, + ) -> DispatchResult { + trappist::Assets::create( + trappist::RuntimeOrigin::signed(ALICE), + id, + admin.into(), + min_balance, + ) + } + + fn create_derivative_asset_on_tertiary_parachain( + id: base::AssetId, + admin: base::AccountId, + min_balance: base::Balance, + ) -> DispatchResult { + base::Assets::create(base::RuntimeOrigin::signed(ALICE), id, admin.into(), min_balance) + } + + fn mint_asset_on_asset_reserve( + asset_id: asset_reserve::AssetId, + origin: asset_reserve::AccountId, + mint_amount: asset_reserve::Balance, + ) -> DispatchResult { + asset_reserve::Assets::mint( + asset_reserve::RuntimeOrigin::signed(origin), + asset_id, + ALICE.into(), + mint_amount, + ) + } + fn paras_sudo_wrapper_sudo_queue_downward_xcm(call: RuntimeCall) { let sudo_queue_downward_xcm = relay_chain::RuntimeCall::ParasSudoWrapper(mock_paras_sudo_wrapper::Call::< @@ -430,4 +663,27 @@ mod tests { Box::new(sudo_queue_downward_xcm), )); } + + fn register_reserve_asset_on_trappist( + origin: trappist::AccountId, + asset_id: trappist::AssetId, + ) -> DispatchResultWithPostInfo { + trappist::Sudo::sudo( + trappist::RuntimeOrigin::signed(origin), + Box::new(trappist::RuntimeCall::AssetRegistry(pallet_asset_registry::Call::< + trappist::Runtime, + >::register_reserve_asset { + asset_id, + asset_multi_location: ( + Parent, + X3( + Parachain(ASSET_RESERVE_PARA_ID), + PalletInstance(asset_reserve::Assets::index() as u8), + GeneralIndex(xUSD as u128), + ), + ) + .into(), + })), + ) + } } diff --git a/xcm-simulator/src/parachains/base.rs b/xcm-simulator/src/parachains/base.rs new file mode 100644 index 00000000..1f8710e6 --- /dev/null +++ b/xcm-simulator/src/parachains/base.rs @@ -0,0 +1,214 @@ +// Copyright 2021 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Polkadot is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Polkadot. If not, see . + +//! Base Parachain runtime mock. + +use base_runtime::{ + constants::{ + currency::{CENTS, EXISTENTIAL_DEPOSIT, UNITS}, + fee::WeightToFee, + }, + xcm_config::{ + AssetTransactors, Barrier, CollatorSelectionUpdateOrigin, LocationToAccountId, + MaxInstructions, RelayLocation, RelayNetwork, Reserves, SelfReserve, UnitWeightCost, + XUsdPerSecond, + }, + BlockNumber, DealWithFees, Hash, Header, Index, Period, PotId, RuntimeBlockLength, + RuntimeBlockWeights, Session, UnitBody, Version, +}; +use frame_support::{ + construct_runtime, parameter_types, + traits::{EitherOfDiverse, Everything, Nothing}, + weights::constants::RocksDbWeight, +}; +use frame_system::EnsureRoot; +use pallet_xcm::{EnsureXcm, IsMajorityOfBody, XcmPassthrough}; +use polkadot_runtime_common::BlockHashCount; +use sp_core::{ConstU128, ConstU16, ConstU32}; +use sp_runtime::traits::{AccountIdLookup, BlakeTwo256}; +use sp_std::prelude::*; +pub use trappist_runtime::{AccountId, AssetId, Balance}; +use xcm::latest::prelude::*; +use xcm_builder::{ + EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, LocationInverter, ParentAsSuperuser, + RelayChainAsNative, SiblingParachainAsNative, SignedAccountId32AsNative, SignedToAccountId32, + SovereignSignedViaLocation, UsingComponents, +}; +use xcm_executor::{Config, XcmExecutor}; + +impl frame_system::Config for Runtime { + type BaseCallFilter = Everything; + type BlockWeights = RuntimeBlockWeights; + type BlockLength = RuntimeBlockLength; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Index = Index; + type BlockNumber = BlockNumber; + type Hash = Hash; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = AccountIdLookup; + type Header = Header; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = BlockHashCount; + type DbWeight = RocksDbWeight; + type Version = Version; + type PalletInfo = PalletInfo; + type AccountData = pallet_balances::AccountData; + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = frame_system::weights::SubstrateWeight; + type SS58Prefix = ConstU16<42>; + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; +} + +impl super::mock_msg_queue::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +pub type AssetsForceOrigin = + EitherOfDiverse, EnsureXcm>>; + +impl pallet_assets::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Balance = Balance; + type AssetId = AssetId; + type Currency = Balances; + type ForceOrigin = AssetsForceOrigin; + type AssetDeposit = ConstU128; + type AssetAccountDeposit = ConstU128<{ UNITS }>; + type MetadataDepositBase = ConstU128<{ UNITS }>; + type MetadataDepositPerByte = ConstU128<{ 10 * CENTS }>; + type ApprovalDeposit = ConstU128<{ 10 * CENTS }>; + type StringLimit = ConstU32<50>; + type Freezer = (); + type Extra = (); + type WeightInfo = pallet_assets::weights::SubstrateWeight; +} + +impl pallet_balances::Config for Runtime { + type Balance = Balance; + type DustRemoval = (); + type RuntimeEvent = RuntimeEvent; + type ExistentialDeposit = ConstU128; + type AccountStore = System; + type WeightInfo = pallet_balances::weights::SubstrateWeight; + type MaxLocks = ConstU32<50>; + type MaxReserves = ConstU32<50>; + type ReserveIdentifier = [u8; 8]; +} + +impl pallet_collator_selection::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Currency = Balances; + type UpdateOrigin = CollatorSelectionUpdateOrigin; + type PotId = PotId; + type MaxCandidates = ConstU32<1000>; + type MinCandidates = ConstU32<5>; + type MaxInvulnerables = ConstU32<100>; + type KickThreshold = Period; + type ValidatorId = ::AccountId; + type ValidatorIdOf = pallet_collator_selection::IdentityCollator; + type ValidatorRegistration = Session; + type WeightInfo = pallet_collator_selection::weights::SubstrateWeight; +} + +impl pallet_sudo::Config for Runtime { + type RuntimeCall = RuntimeCall; + type RuntimeEvent = RuntimeEvent; +} + +pub type LocalOriginToLocation = SignedToAccountId32; + +impl pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type SendXcmOrigin = EnsureXcmOrigin; + type XcmRouter = XcmRouter; + type ExecuteXcmOrigin = EnsureXcmOrigin; + type XcmExecuteFilter = Everything; + type XcmExecutor = XcmExecutor; + type XcmTeleportFilter = Nothing; + type XcmReserveTransferFilter = Everything; + type Weigher = FixedWeightBounds; + type LocationInverter = LocationInverter; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + const VERSION_DISCOVERY_QUEUE_SIZE: u32 = 100; + type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; +} + +impl cumulus_pallet_xcm::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type XcmExecutor = XcmExecutor; +} + +parameter_types! { + pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); + pub Ancestry: MultiLocation = Parachain(MsgQueue::parachain_id().into()).into(); +} + +pub type XcmOriginToTransactDispatchOrigin = ( + SovereignSignedViaLocation, + RelayChainAsNative, + SiblingParachainAsNative, + ParentAsSuperuser, + SignedAccountId32AsNative, + XcmPassthrough, +); +pub type XcmRouter = crate::ParachainXcmRouter; + +pub struct XcmConfig; +impl Config for XcmConfig { + type RuntimeCall = RuntimeCall; + type XcmSender = XcmRouter; + type AssetTransactor = AssetTransactors; + type OriginConverter = XcmOriginToTransactDispatchOrigin; + type IsReserve = Reserves; + type IsTeleporter = (); + type LocationInverter = LocationInverter; + type Barrier = Barrier; + type Weigher = FixedWeightBounds; + type Trader = ( + FixedRateOfFungible, + UsingComponents>, + ); + type ResponseHandler = PolkadotXcm; + type AssetTrap = PolkadotXcm; + type AssetClaims = PolkadotXcm; + type SubscriptionService = PolkadotXcm; +} + +type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; +type Block = frame_system::mocking::MockBlock; + +construct_runtime!( + pub enum Runtime where + Block = Block, + NodeBlock = Block, + UncheckedExtrinsic = UncheckedExtrinsic, + { + System: frame_system::{Pallet, Call, Storage, Config, Event}, + Balances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + MsgQueue: super::mock_msg_queue::{Pallet, Storage, Event}, + CollatorSelection: pallet_collator_selection::{Pallet, Call, Storage, Event, Config} = 21, + PolkadotXcm: pallet_xcm::{Pallet, Call, Event, Origin} = 31, + CumulusXcm: cumulus_pallet_xcm::{Pallet, Event, Origin} = 32, + Sudo: pallet_sudo = 40, + Assets: pallet_assets = 43, + } +); diff --git a/xcm-simulator/src/parachains/mod.rs b/xcm-simulator/src/parachains/mod.rs index 0982a3b1..8d06548a 100644 --- a/xcm-simulator/src/parachains/mod.rs +++ b/xcm-simulator/src/parachains/mod.rs @@ -22,6 +22,7 @@ use sp_runtime::traits::Hash; use xcm::{latest::prelude::*, VersionedXcm}; pub(crate) mod asset_reserve; +pub(crate) mod base; pub(crate) mod parachain; pub(crate) mod trappist; diff --git a/xcm-simulator/src/parachains/trappist.rs b/xcm-simulator/src/parachains/trappist.rs index 0f0cad3a..46c05080 100644 --- a/xcm-simulator/src/parachains/trappist.rs +++ b/xcm-simulator/src/parachains/trappist.rs @@ -37,9 +37,10 @@ use trappist_runtime::{ MaxInstructions, RelayLocation, RelayNetwork, Reserves, SelfReserve, UnitWeightCost, XUsdPerSecond, }, - AccountId, AssetId, Balance, BlockNumber, DealWithFees, Hash, Header, Index, Period, PotId, - RuntimeBlockLength, RuntimeBlockWeights, Session, UnitBody, Version, + BlockNumber, DealWithFees, Hash, Header, Index, Period, PotId, RuntimeBlockLength, + RuntimeBlockWeights, Session, UnitBody, Version, }; +pub use trappist_runtime::{AccountId, AssetId, Balance}; use xcm::latest::prelude::*; use xcm_builder::{ EnsureXcmOrigin, FixedRateOfFungible, FixedWeightBounds, LocationInverter, ParentAsSuperuser, From 55504e2dadb9430a8190358ed86c346de6344bfe Mon Sep 17 00:00:00 2001 From: Frank Bell Date: Tue, 10 Jan 2023 10:20:34 +0000 Subject: [PATCH 05/16] refactor: rename crate and remove unused code --- xcm-simulator/Cargo.toml | 2 +- xcm-simulator/src/relay_chain.rs | 15 +-------------- 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/xcm-simulator/Cargo.toml b/xcm-simulator/Cargo.toml index a03e9ba4..659f181d 100644 --- a/xcm-simulator/Cargo.toml +++ b/xcm-simulator/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "trappist-xcm-simulator" +name = "xcm-simulator-trappist" version = "0.1.0" authors = ["Parity Technologies "] description = "Examples of xcm-simulator usage." diff --git a/xcm-simulator/src/relay_chain.rs b/xcm-simulator/src/relay_chain.rs index 25961e5e..3458ea1a 100644 --- a/xcm-simulator/src/relay_chain.rs +++ b/xcm-simulator/src/relay_chain.rs @@ -182,13 +182,6 @@ impl pallet_xcm::Config for Runtime { type AdvertisedXcmVersion = pallet_xcm::CurrentXcmVersion; } -// impl paras::Config for Runtime { -// type RuntimeEvent = RuntimeEvent; -// type UnsignedPriority = ParasUnsignedPriority; -// type NextSessionRotation = Babe; -// type WeightInfo = weights::runtime_parachains_paras::WeightInfo; -// } - impl ump::Config for Runtime { type RuntimeEvent = RuntimeEvent; type UmpSink = ump::XcmSink, Runtime>; @@ -199,13 +192,6 @@ impl ump::Config for Runtime { impl dmp::Config for Runtime {} -// impl hrmp::Config for Runtime { -// type RuntimeEvent = RuntimeEvent; -// type RuntimeOrigin = RuntimeOrigin; -// type Currency = Balances; -// type WeightInfo = weights::runtime_parachains_hrmp::WeightInfo; -// } - impl origin::Config for Runtime {} impl pallet_sudo::Config for Runtime { @@ -213,6 +199,7 @@ impl pallet_sudo::Config for Runtime { type RuntimeCall = RuntimeCall; } +// Mock of paras_sudo_wrapper::sudo_queue_downward_xcm, using local message queue #[frame_support::pallet] pub mod mock_paras_sudo_wrapper { use super::*; From d4ba7cf290ebc89dd1193c9330c28d60f0e414f0 Mon Sep 17 00:00:00 2001 From: Frank Bell Date: Tue, 10 Jan 2023 10:21:05 +0000 Subject: [PATCH 06/16] docs: add xcm-simulator overview --- README.md | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1779cb3a..6844a145 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,7 @@ First, complete the [basic Rust setup instructions](./docs/rust-setup.md). #### Build -Use the following command to build the Trappist collector binary: +Use the following command to build the Trappist collator binary: When the base collator is built, rename the binary into `base-collator` and place it into the `./bin` folder. ``` @@ -83,6 +83,17 @@ Then, start the **Trappist** playground with: ./zombienet-linux -p native spawn xcm-playground.toml ``` +### XCM Simulator +The [XCM simulator](./xcm-simulator) can be used to further explore XCM message execution across the various runtimes used by Trappist. +Each Trappist use case is written as a test, allowing interactive debugging/exploration of message flows and instruction execution. +Each `execute_with` closure scope within a test can be considered as a block on the corresponding chain, with messages being dispatched to the destination chains via a mock message queue as the closure goes out of scope. +All XCM-specific traces from the interactions are also collected in a single place for easier inspection. + +You can run all tests, including the tracing output, with: +``` +cd xcm-simulator && cargo nextest run tests:: --no-capture --release +``` + ## License Trappist is licensed under [Apache 2](LICENSE). From 5ab0cbe8c6ab5322a3e222456fd214b2a51ed737 Mon Sep 17 00:00:00 2001 From: Frank Bell Date: Tue, 10 Jan 2023 11:45:59 +0000 Subject: [PATCH 07/16] ci: add simulator workflow --- .github/workflows/simulate.yml | 82 ++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 .github/workflows/simulate.yml diff --git a/.github/workflows/simulate.yml b/.github/workflows/simulate.yml new file mode 100644 index 00000000..e5e4842c --- /dev/null +++ b/.github/workflows/simulate.yml @@ -0,0 +1,82 @@ +name: XCM Simulator + +# Controls when the action will run. +on: + # Triggers the workflow on push or pull request events but only for the master branch + push: + branches: [ master, xcm-simulator ] + pull_request: + branches: [ master ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# A workflow run is made up of one or more jobs that can run sequentially or in parallel +jobs: + simulate: + # The type of runner that the job will run on + runs-on: ubuntu-20.04 + defaults: + run: + working-directory: xcm-simulator + env: + NIGHTLY: nightly-2022-11-02 # Fix version to prevent cache misses with nightly changes + SKIP_WASM_BUILD: '1' # Skip for all steps, so no wasm32-unknown-unknown target required + + # Steps represent a sequence of tasks that will be executed as part of the job + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v3 + + - name: Set-Up + run: sudo apt update && sudo apt install -y git clang curl libssl-dev llvm libudev-dev cmake protobuf-compiler + + - name: Install Rust + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: stable + + - name: Install Nightly + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: ${{ env.NIGHTLY }} + override: true + + - name: Cache Build artefacts + uses: actions/cache@v3 + with: + path: | + ~/.cargo/bin/ + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: ${{ runner.os }}-cargo-test-${{ hashFiles('**/Cargo.lock') }} + restore-keys: ${{ runner.os }}-cargo-test + + # Install cargo-nextest, 60% faster than cargo test and support for junit output format + - name: Install cargo-nextest + uses: actions-rs/install@v0.1 + with: + crate: cargo-nextest + version: latest + + # Create profile with JUnit output enabled + - name: Configure CI + run: mkdir .config && echo -e "[profile.ci.junit]\npath = \"junit.xml\"" > .config/nextest.toml + + # Run all tests in solution using CI profile created above + - name: Run tests + run: cargo nextest run "tests::" --no-capture --release --profile ci + + # Report test results + - name: Report test results + uses: dorny/test-reporter@v1 + if: success() || failure() # run this step even if previous step failed + with: + name: tests + path: target/nextest/ci/junit.xml + reporter: jest-junit + working-directory: 'xcm-simulator' From fb40c50cd6db6b3dd94e78c4bc0310d01ab6dc13 Mon Sep 17 00:00:00 2001 From: Frank Bell Date: Tue, 10 Jan 2023 15:44:29 +0000 Subject: [PATCH 08/16] docs: fix xcm simulator test command --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 6844a145..2b43cbce 100644 --- a/README.md +++ b/README.md @@ -91,7 +91,7 @@ All XCM-specific traces from the interactions are also collected in a single pla You can run all tests, including the tracing output, with: ``` -cd xcm-simulator && cargo nextest run tests:: --no-capture --release +cd xcm-simulator && cargo test run tests:: --no-capture --release ``` ## License From 6a619a457a99baad10ce478be6023b61aa7479bd Mon Sep 17 00:00:00 2001 From: Frank Bell <60948618+evilrobot-01@users.noreply.github.com> Date: Tue, 10 Jan 2023 15:49:26 +0000 Subject: [PATCH 09/16] docs: update readme with suggested improvement Co-authored-by: bernardo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2b43cbce..7e3fe7e8 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,7 @@ Then, start the **Trappist** playground with: ### XCM Simulator The [XCM simulator](./xcm-simulator) can be used to further explore XCM message execution across the various runtimes used by Trappist. -Each Trappist use case is written as a test, allowing interactive debugging/exploration of message flows and instruction execution. +Each Trappist use case is written as a Rust unit test, allowing interactive debugging/exploration of message flows and instruction execution. Each `execute_with` closure scope within a test can be considered as a block on the corresponding chain, with messages being dispatched to the destination chains via a mock message queue as the closure goes out of scope. All XCM-specific traces from the interactions are also collected in a single place for easier inspection. From fac4ad826800d1684a79ca5cb9bc3062a0a5b0c0 Mon Sep 17 00:00:00 2001 From: Frank Bell <60948618+evilrobot-01@users.noreply.github.com> Date: Tue, 10 Jan 2023 15:52:20 +0000 Subject: [PATCH 10/16] docs: update readme with suggested improvement Co-authored-by: bernardo --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 7e3fe7e8..7cca2cd8 100644 --- a/README.md +++ b/README.md @@ -83,6 +83,11 @@ Then, start the **Trappist** playground with: ./zombienet-linux -p native spawn xcm-playground.toml ``` +### Integration Tests +[parachains-integration-tests](https://github.com/paritytech/parachains-integration-tests) is a tool meant for XCM message execution in a locally spawned network. Tests are written as YAML files and converted into [Mocha](https://mochajs.org/) tests with [Chai](https://www.chaijs.com/) assertions. + +The [`integration-tests`] directory has tests on Trappist use cases and instructions on how to run them. + ### XCM Simulator The [XCM simulator](./xcm-simulator) can be used to further explore XCM message execution across the various runtimes used by Trappist. Each Trappist use case is written as a Rust unit test, allowing interactive debugging/exploration of message flows and instruction execution. From 728929e2c8efb83c6cc9af00d21918bd29d8b878 Mon Sep 17 00:00:00 2001 From: Frank Bell Date: Tue, 10 Jan 2023 15:54:45 +0000 Subject: [PATCH 11/16] docs: add link to integration-tests --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 7cca2cd8..4f0f1272 100644 --- a/README.md +++ b/README.md @@ -86,7 +86,7 @@ Then, start the **Trappist** playground with: ### Integration Tests [parachains-integration-tests](https://github.com/paritytech/parachains-integration-tests) is a tool meant for XCM message execution in a locally spawned network. Tests are written as YAML files and converted into [Mocha](https://mochajs.org/) tests with [Chai](https://www.chaijs.com/) assertions. -The [`integration-tests`] directory has tests on Trappist use cases and instructions on how to run them. +The [integration-tests](./integration-tests) directory has tests on Trappist use cases and instructions on how to run them. ### XCM Simulator The [XCM simulator](./xcm-simulator) can be used to further explore XCM message execution across the various runtimes used by Trappist. From 6c8dc9b0d710c3811a29ccebfebe9389d66c3e1e Mon Sep 17 00:00:00 2001 From: Frank Bell Date: Tue, 10 Jan 2023 16:15:32 +0000 Subject: [PATCH 12/16] docs: fix simulator test command Tests are run in parallel by default, resulting in mixing of logging output in console --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 4f0f1272..88b7959c 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ All XCM-specific traces from the interactions are also collected in a single pla You can run all tests, including the tracing output, with: ``` -cd xcm-simulator && cargo test run tests:: --no-capture --release +cd xcm-simulator && cargo test --release tests::; cd .. ``` ## License From e9874c288b335eb7d9537f03e65e717e35dc4923 Mon Sep 17 00:00:00 2001 From: Frank Bell Date: Tue, 10 Jan 2023 17:58:27 +0000 Subject: [PATCH 13/16] ci: adjust simulate workflow --- .github/workflows/simulate.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/simulate.yml b/.github/workflows/simulate.yml index e5e4842c..65357328 100644 --- a/.github/workflows/simulate.yml +++ b/.github/workflows/simulate.yml @@ -69,14 +69,14 @@ jobs: # Run all tests in solution using CI profile created above - name: Run tests - run: cargo nextest run "tests::" --no-capture --release --profile ci + run: cargo nextest run "tests::" --release --profile ci # Report test results - name: Report test results uses: dorny/test-reporter@v1 if: success() || failure() # run this step even if previous step failed with: - name: tests + name: simulate path: target/nextest/ci/junit.xml reporter: jest-junit working-directory: 'xcm-simulator' From 341192c334f1ec3d6c5dfe6cc81fa4b9ce50e58d Mon Sep 17 00:00:00 2001 From: Frank Bell Date: Tue, 10 Jan 2023 18:08:07 +0000 Subject: [PATCH 14/16] ci: add cache handling for nextest install --- .github/workflows/simulate.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/simulate.yml b/.github/workflows/simulate.yml index 65357328..260bd342 100644 --- a/.github/workflows/simulate.yml +++ b/.github/workflows/simulate.yml @@ -62,6 +62,7 @@ jobs: with: crate: cargo-nextest version: latest + use-tool-cache: true # Create profile with JUnit output enabled - name: Configure CI From b8edc5ee8d48556d90baae4f9a3f236b5e676fb5 Mon Sep 17 00:00:00 2001 From: Frank Bell Date: Tue, 10 Jan 2023 18:17:10 +0000 Subject: [PATCH 15/16] ci: improve nextest install --- .github/workflows/simulate.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/simulate.yml b/.github/workflows/simulate.yml index 260bd342..38154dd5 100644 --- a/.github/workflows/simulate.yml +++ b/.github/workflows/simulate.yml @@ -58,11 +58,7 @@ jobs: # Install cargo-nextest, 60% faster than cargo test and support for junit output format - name: Install cargo-nextest - uses: actions-rs/install@v0.1 - with: - crate: cargo-nextest - version: latest - use-tool-cache: true + run: if ! which cargo-nextest &> /dev/null; then cargo install cargo-nextest; fi # Create profile with JUnit output enabled - name: Configure CI From 84c7378ed3c974dbedcb3fac8c16a8361517bf46 Mon Sep 17 00:00:00 2001 From: Frank Bell Date: Tue, 10 Jan 2023 18:51:16 +0000 Subject: [PATCH 16/16] refactor: rename parachain to template to better describe intention --- xcm-simulator/src/lib.rs | 52 +++++++++---------- xcm-simulator/src/parachains/mod.rs | 2 +- .../parachains/{parachain.rs => template.rs} | 0 3 files changed, 26 insertions(+), 28 deletions(-) rename xcm-simulator/src/parachains/{parachain.rs => template.rs} (100%) diff --git a/xcm-simulator/src/lib.rs b/xcm-simulator/src/lib.rs index 303aec8b..c58ef0ad 100644 --- a/xcm-simulator/src/lib.rs +++ b/xcm-simulator/src/lib.rs @@ -20,7 +20,7 @@ mod parachains; mod relay_chain; use frame_support::{sp_tracing, traits::GenesisBuild}; -use parachains::{asset_reserve, base, parachain, trappist}; +use parachains::{asset_reserve, base, template, trappist}; use polkadot_parachain::primitives::Id as ParaId; use sp_core::Get; use sp_runtime::traits::AccountIdConversion; @@ -133,14 +133,31 @@ decl_test_parachain! { } } -const A_PARA_ID: u32 = 1; +const TEMPLATE_PARA_ID: u32 = 4000; decl_test_parachain! { - // Some generic parachain - pub struct ParaA { - Runtime = parachains::parachain::Runtime, - XcmpMessageHandler = parachains::parachain::MsgQueue, - DmpMessageHandler = parachains::parachain::MsgQueue, - new_ext = para_ext(A_PARA_ID), + // A simple parachain configuration template, which can be copied and customised to add another mock + // parachain to the network + pub struct Template { + Runtime = template::Runtime, + XcmpMessageHandler = template::MsgQueue, + DmpMessageHandler = template::MsgQueue, + new_ext = { + use template::{MsgQueue, Runtime, System}; + + let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); + + pallet_balances::GenesisConfig:: { balances: vec![(ALICE, INITIAL_BALANCE)] } + .assimilate_storage(&mut t) + .unwrap(); + + let mut ext = sp_io::TestExternalities::new(t); + ext.execute_with(|| { + sp_tracing::try_init_simple(); + System::set_block_number(1); + MsgQueue::set_para_id(ParaId::new(TEMPLATE_PARA_ID)); + }); + ext + }, } } @@ -176,7 +193,6 @@ decl_test_network! { pub struct MockNet { relay_chain = Relay, parachains = vec![ - (A_PARA_ID, ParaA), (ASSET_RESERVE_PARA_ID, AssetReserve), (TRAPPIST_PARA_ID, Trappist), (BASE_PARA_ID, Base), @@ -188,24 +204,6 @@ pub fn para_account_id(id: u32) -> relay_chain::AccountId { ParaId::from(id).into_account_truncating() } -fn para_ext(para_id: u32) -> sp_io::TestExternalities { - use parachain::{MsgQueue, Runtime, System}; - - let mut t = frame_system::GenesisConfig::default().build_storage::().unwrap(); - - pallet_balances::GenesisConfig:: { balances: vec![(ALICE, INITIAL_BALANCE)] } - .assimilate_storage(&mut t) - .unwrap(); - - let mut ext = sp_io::TestExternalities::new(t); - ext.execute_with(|| { - sp_tracing::try_init_simple(); - System::set_block_number(1); - MsgQueue::set_para_id(ParaId::new(para_id)); - }); - ext -} - #[cfg(test)] mod tests { use super::*; diff --git a/xcm-simulator/src/parachains/mod.rs b/xcm-simulator/src/parachains/mod.rs index 8d06548a..5466f590 100644 --- a/xcm-simulator/src/parachains/mod.rs +++ b/xcm-simulator/src/parachains/mod.rs @@ -23,7 +23,7 @@ use xcm::{latest::prelude::*, VersionedXcm}; pub(crate) mod asset_reserve; pub(crate) mod base; -pub(crate) mod parachain; +pub(crate) mod template; pub(crate) mod trappist; #[frame_support::pallet] diff --git a/xcm-simulator/src/parachains/parachain.rs b/xcm-simulator/src/parachains/template.rs similarity index 100% rename from xcm-simulator/src/parachains/parachain.rs rename to xcm-simulator/src/parachains/template.rs