diff --git a/cumulus/Cargo.lock b/cumulus/Cargo.lock index d63da6462a..60792541ae 100644 --- a/cumulus/Cargo.lock +++ b/cumulus/Cargo.lock @@ -1357,6 +1357,34 @@ dependencies = [ "xcm-executor", ] +[[package]] +name = "bridge-hub-rococo-integration-tests" +version = "1.0.0" +dependencies = [ + "bp-messages", + "bridge-hub-rococo-runtime", + "cumulus-pallet-xcmp-queue", + "frame-support", + "frame-system", + "integration-tests-common", + "pallet-assets", + "pallet-balances", + "pallet-bridge-messages", + "pallet-xcm", + "parachains-common", + "parity-scale-codec", + "polkadot-core-primitives", + "polkadot-parachain", + "polkadot-runtime", + "polkadot-runtime-parachains", + "sp-core", + "sp-runtime", + "sp-weights", + "xcm", + "xcm-emulator", + "xcm-executor", +] + [[package]] name = "bridge-hub-rococo-runtime" version = "0.1.0" @@ -1883,7 +1911,7 @@ dependencies = [ ] [[package]] -name = "collectives-polkadot-it" +name = "collectives-polkadot-integration-tests" version = "0.1.0" dependencies = [ "asset-hub-polkadot-runtime", @@ -5261,8 +5289,12 @@ dependencies = [ "asset-hub-kusama-runtime", "asset-hub-polkadot-runtime", "asset-hub-westend-runtime", + "bp-messages", + "bp-runtime", "bridge-hub-kusama-runtime", "bridge-hub-polkadot-runtime", + "bridge-hub-rococo-runtime", + "bridge-runtime-common", "collectives-polkadot-runtime", "cumulus-primitives-core", "frame-support", @@ -5271,6 +5303,7 @@ dependencies = [ "kusama-runtime-constants", "pallet-assets", "pallet-balances", + "pallet-bridge-messages", "pallet-im-online", "pallet-staking", "pallet-xcm", @@ -5285,9 +5318,12 @@ dependencies = [ "polkadot-runtime-constants", "polkadot-runtime-parachains", "polkadot-service", + "rococo-runtime", + "rococo-runtime-constants", "sc-consensus-grandpa", "sp-authority-discovery", "sp-consensus-babe", + "sp-consensus-beefy", "sp-core", "sp-runtime", "sp-weights", @@ -16378,7 +16414,6 @@ dependencies = [ "sp-std", "sp-trie", "xcm", - "xcm-executor", ] [[package]] diff --git a/cumulus/Cargo.toml b/cumulus/Cargo.toml index 77b3201968..a376d06f80 100644 --- a/cumulus/Cargo.toml +++ b/cumulus/Cargo.toml @@ -57,6 +57,7 @@ members = [ "parachains/integration-tests/emulated/assets/asset-hub-polkadot", "parachains/integration-tests/emulated/assets/asset-hub-westend", "parachains/integration-tests/emulated/collectives/collectives-polkadot", + "parachains/integration-tests/emulated/bridges/bridge-hub-rococo", "test/client", "test/relay-sproof-builder", "test/relay-validation-worker-provider", diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/lib.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/lib.rs index 596d589380..b090432fa7 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-kusama/src/lib.rs @@ -25,12 +25,12 @@ pub use integration_tests_common::{ PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3, }, AccountId, AssetHubKusama, AssetHubKusamaPallet, AssetHubKusamaReceiver, AssetHubKusamaSender, - BHKusama, BHKusamaPallet, BHKusamaReceiver, BHKusamaSender, BHPolkadot, BHPolkadotPallet, - BHPolkadotReceiver, BHPolkadotSender, Collectives, CollectivesPallet, CollectivesReceiver, - CollectivesSender, Kusama, KusamaMockNet, KusamaPallet, KusamaReceiver, KusamaSender, - PenpalKusama, PenpalKusamaReceiver, PenpalKusamaSender, PenpalPolkadot, PenpalPolkadotReceiver, - PenpalPolkadotSender, Polkadot, PolkadotMockNet, PolkadotPallet, PolkadotReceiver, - PolkadotSender, + BridgeHubKusama, BridgeHubKusamaPallet, BridgeHubKusamaReceiver, BridgeHubKusamaSender, + BridgeHubPolkadot, BridgeHubPolkadotPallet, BridgeHubPolkadotReceiver, BridgeHubPolkadotSender, + Collectives, CollectivesPallet, CollectivesReceiver, CollectivesSender, Kusama, KusamaMockNet, + KusamaPallet, KusamaReceiver, KusamaSender, PenpalKusama, PenpalKusamaReceiver, + PenpalKusamaSender, PenpalPolkadot, PenpalPolkadotReceiver, PenpalPolkadotSender, Polkadot, + PolkadotMockNet, PolkadotPallet, PolkadotReceiver, PolkadotSender, }; pub use polkadot_core_primitives::InboundDownwardMessage; pub use xcm::{ diff --git a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/lib.rs b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/lib.rs index 02296fa996..70506d98cb 100644 --- a/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/assets/asset-hub-polkadot/src/lib.rs @@ -26,12 +26,12 @@ pub use integration_tests_common::{ }, AccountId, AssetHubKusama, AssetHubKusamaPallet, AssetHubKusamaReceiver, AssetHubKusamaSender, AssetHubPolkadot, AssetHubPolkadotPallet, AssetHubPolkadotReceiver, AssetHubPolkadotSender, - BHKusama, BHKusamaPallet, BHKusamaReceiver, BHKusamaSender, BHPolkadot, BHPolkadotPallet, - BHPolkadotReceiver, BHPolkadotSender, Collectives, CollectivesPallet, CollectivesReceiver, - CollectivesSender, Kusama, KusamaMockNet, KusamaPallet, KusamaReceiver, KusamaSender, - PenpalKusama, PenpalKusamaReceiver, PenpalKusamaSender, PenpalPolkadot, PenpalPolkadotReceiver, - PenpalPolkadotSender, Polkadot, PolkadotMockNet, PolkadotPallet, PolkadotReceiver, - PolkadotSender, + BridgeHubKusama, BridgeHubKusamaPallet, BridgeHubKusamaReceiver, BridgeHubKusamaSender, + BridgeHubPolkadot, BridgeHubPolkadotPallet, BridgeHubPolkadotReceiver, BridgeHubPolkadotSender, + Collectives, CollectivesPallet, CollectivesReceiver, CollectivesSender, Kusama, KusamaMockNet, + KusamaPallet, KusamaReceiver, KusamaSender, PenpalKusama, PenpalKusamaReceiver, + PenpalKusamaSender, PenpalPolkadot, PenpalPolkadotReceiver, PenpalPolkadotSender, Polkadot, + PolkadotMockNet, PolkadotPallet, PolkadotReceiver, PolkadotSender, }; pub use polkadot_core_primitives::InboundDownwardMessage; pub use xcm::{ diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml new file mode 100644 index 0000000000..d61de30915 --- /dev/null +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/Cargo.toml @@ -0,0 +1,38 @@ +[package] +name = "bridge-hub-rococo-integration-tests" +version = "1.0.0" +authors = ["Parity Technologies "] +edition = "2021" +description = "Bridge Hub Rococo runtime integration tests with xcm-emulator" + +[dependencies] +codec = { package = "parity-scale-codec", version = "3.4.0", default-features = false } + +# Substrate +sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" } +frame-support = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" } +frame-system = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" } +sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" } +sp-weights = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" } +pallet-assets = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" } + +# Polkadot +polkadot-core-primitives = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-parachain = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" } +polkadot-runtime = { git = "https://github.com/paritytech/polkadot", branch = "master" } +xcm = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" } +xcm-executor = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" } +pallet-xcm = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" } + +# Cumulus +parachains-common = { path = "../../../../common" } +cumulus-pallet-xcmp-queue = { default-features = false, path = "../../../../../pallets/xcmp-queue" } +bridge-hub-rococo-runtime = { path = "../../../../runtimes/bridge-hubs/bridge-hub-rococo" } +pallet-bridge-messages = { default-features = false, path = "../../../../../bridges/modules/messages" } +bp-messages = { default-features = false, path = "../../../../../bridges/primitives/messages" } + +# Local +xcm-emulator = { default-features = false, path = "../../../../../xcm/xcm-emulator" } +integration-tests-common = { default-features = false, path = "../../common" } diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/lib.rs new file mode 100644 index 0000000000..105212b190 --- /dev/null +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/lib.rs @@ -0,0 +1,48 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus 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. + +// Cumulus 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 Cumulus. If not, see . + +pub use bp_messages::LaneId; +pub use codec::Encode; +pub use frame_support::{assert_ok, pallet_prelude::Weight}; +pub use integration_tests_common::{ + constants::{ + accounts::{ALICE, BOB}, + rococo::{ED as ROCOCO_ED, ED as WOCOCO_ED}, + PROOF_SIZE_THRESHOLD, REF_TIME_THRESHOLD, XCM_V3, + }, + AccountId, AssetHubWococo, BridgeHubPolkadot, BridgeHubPolkadotPallet, + BridgeHubPolkadotReceiver, BridgeHubPolkadotSender, BridgeHubRococo, BridgeHubRococoPallet, + BridgeHubRococoReceiver, BridgeHubRococoSender, BridgeHubWococo, Collectives, + CollectivesPallet, CollectivesReceiver, CollectivesSender, Kusama, KusamaPallet, + PenpalPolkadot, PenpalPolkadotReceiver, PenpalPolkadotSender, Polkadot, PolkadotMockNet, + PolkadotPallet, PolkadotReceiver, PolkadotSender, Rococo, RococoMockNet, RococoPallet, + RococoReceiver, RococoSender, +}; +// pub use polkadot_core_primitives::InboundDownwardMessage; +pub use xcm::{ + prelude::*, + v3::{ + Error, + NetworkId::{Rococo as RococoId, Wococo as WococoId}, + }, +}; +pub use xcm_emulator::{ + assert_expected_events, bx, cumulus_pallet_dmp_queue, helpers::weight_within_threshold, + Parachain as Para, RelayChain as Relay, TestExt, +}; + +#[cfg(test)] +mod tests; diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/example.rs b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/example.rs new file mode 100644 index 0000000000..1d06d7f9fc --- /dev/null +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/example.rs @@ -0,0 +1,99 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus 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. + +// Cumulus 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 Cumulus. If not, see . + +use crate::*; + +#[test] +fn example() { + // Init tests variables + // XcmPallet send arguments + let sudo_origin = ::RuntimeOrigin::root(); + let destination = Rococo::child_location_of(BridgeHubRococo::para_id()).into(); + let weight_limit = WeightLimit::Unlimited; + let check_origin = None; + + let remote_xcm = Xcm(vec![ClearOrigin]); + + let xcm = VersionedXcm::from(Xcm(vec![ + UnpaidExecution { weight_limit, check_origin }, + ExportMessage { + network: WococoId, + destination: X1(Parachain(AssetHubWococo::para_id().into())), + xcm: remote_xcm, + }, + ])); + + //Rococo Global Consensus + // Send XCM message from Relay Chain to Bridge Hub source Parachain + Rococo::execute_with(|| { + assert_ok!(::XcmPallet::send( + sudo_origin, + bx!(destination), + bx!(xcm), + )); + + type RuntimeEvent = ::RuntimeEvent; + + assert_expected_events!( + Rococo, + vec![ + RuntimeEvent::XcmPallet(pallet_xcm::Event::Sent { .. }) => {}, + ] + ); + }); + // Receive XCM message in Bridge Hub source Parachain + BridgeHubRococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + + assert_expected_events!( + BridgeHubRococo, + vec![ + RuntimeEvent::DmpQueue(cumulus_pallet_dmp_queue::Event::ExecutedDownward { + outcome: Outcome::Complete(_), + .. + }) => {}, + RuntimeEvent::BridgeWococoMessages(pallet_bridge_messages::Event::MessageAccepted { + lane_id: LaneId([0, 0, 0, 1]), + nonce: 1, + }) => {}, + ] + ); + }); + + // Wococo GLobal Consensus + // Receive XCM message in Bridge Hub target Parachain + BridgeHubWococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + + assert_expected_events!( + BridgeHubWococo, + vec![ + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { .. }) => {}, + ] + ); + }); + // Receive embeded XCM message within `ExportMessage` in Parachain destination + AssetHubWococo::execute_with(|| { + type RuntimeEvent = ::RuntimeEvent; + + assert_expected_events!( + AssetHubWococo, + vec![ + RuntimeEvent::XcmpQueue(cumulus_pallet_xcmp_queue::Event::Fail { .. }) => {}, + ] + ); + }); +} diff --git a/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/mod.rs new file mode 100644 index 0000000000..532e31aa1a --- /dev/null +++ b/cumulus/parachains/integration-tests/emulated/bridges/bridge-hub-rococo/src/tests/mod.rs @@ -0,0 +1,17 @@ +// Copyright Parity Technologies (UK) Ltd. +// This file is part of Cumulus. + +// Cumulus 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. + +// Cumulus 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 Cumulus. If not, see . + +mod example; diff --git a/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/Cargo.toml b/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/Cargo.toml index b836994e5f..2f81d34b51 100644 --- a/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/collectives/collectives-polkadot/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "collectives-polkadot-it" +name = "collectives-polkadot-integration-tests" version = "0.1.0" authors = ["Parity Technologies "] edition = "2021" diff --git a/cumulus/parachains/integration-tests/emulated/common/Cargo.toml b/cumulus/parachains/integration-tests/emulated/common/Cargo.toml index 340ca87499..ec9f0c24e1 100644 --- a/cumulus/parachains/integration-tests/emulated/common/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/common/Cargo.toml @@ -21,6 +21,7 @@ pallet-balances = { default-features = false, git = "https://github.com/parityte pallet-assets = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" } pallet-staking = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" } pallet-im-online = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "master" } +beefy-primitives = { package = "sp-consensus-beefy", git = "https://github.com/paritytech/substrate", branch = "master" } # Polkadot polkadot-core-primitives = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" } @@ -32,7 +33,9 @@ polkadot-runtime = { git = "https://github.com/paritytech/polkadot", branch = "m polkadot-runtime-constants = { git = "https://github.com/paritytech/polkadot", branch = "master" } kusama-runtime = { git = "https://github.com/paritytech/polkadot", branch = "master" } kusama-runtime-constants = { git = "https://github.com/paritytech/polkadot", branch = "master" } -westend-runtime = { git = "https://github.com/paritytech/polkadot", branch = "master" } +rococo-runtime = { git = "https://github.com/paritytech/polkadot", branch = "master" } +rococo-runtime-constants = { git = "https://github.com/paritytech/polkadot", branch = "master" } +westend-runtime = { git = "https://github.com/paritytech/polkadot", branch = "master" } westend-runtime-constants = { git = "https://github.com/paritytech/polkadot", branch = "master" } xcm = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" } xcm-executor = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "master" } @@ -49,7 +52,12 @@ asset-hub-westend-runtime = { path = "../../../runtimes/assets/asset-hub-westend collectives-polkadot-runtime = { path = "../../../runtimes/collectives/collectives-polkadot" } bridge-hub-kusama-runtime = { path = "../../../runtimes/bridge-hubs/bridge-hub-kusama" } bridge-hub-polkadot-runtime = { path = "../../../runtimes/bridge-hubs/bridge-hub-polkadot" } +bridge-hub-rococo-runtime = { path = "../../../runtimes/bridge-hubs/bridge-hub-rococo" } xcm-emulator = { default-features = false, path = "../../../../xcm/xcm-emulator" } +bp-messages = { path = "../../../../bridges/primitives/messages"} +bp-runtime = { path = "../../../../bridges/primitives/runtime"} +pallet-bridge-messages = { path = "../../../../bridges/modules/messages" } +bridge-runtime-common = { path = "../../../../bridges/bin/runtime-common"} [features] runtime-benchmarks = [ diff --git a/cumulus/parachains/integration-tests/emulated/common/src/constants.rs b/cumulus/parachains/integration-tests/emulated/common/src/constants.rs index 4155a4a5b9..197db0b939 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/constants.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/constants.rs @@ -1,8 +1,9 @@ +use beefy_primitives::crypto::AuthorityId as BeefyId; use grandpa::AuthorityId as GrandpaId; use pallet_im_online::sr25519::AuthorityId as ImOnlineId; -pub use parachains_common::{AccountId, AssetHubPolkadotAuraId, AuraId, Balance, BlockNumber}; +use parachains_common::{AccountId, AssetHubPolkadotAuraId, AuraId, Balance, BlockNumber}; use polkadot_primitives::{AssignmentId, ValidatorId}; -pub use polkadot_runtime_parachains::configuration::HostConfiguration; +use polkadot_runtime_parachains::configuration::HostConfiguration; use polkadot_service::chain_spec::get_authority_keys_from_seed_no_beefy; use sp_authority_discovery::AuthorityId as AuthorityDiscoveryId; use sp_consensus_babe::AuthorityId as BabeId; @@ -11,7 +12,7 @@ use sp_runtime::{ traits::{IdentifyAccount, Verify}, BuildStorage, MultiSignature, Perbill, }; -pub use xcm; +use xcm; pub const XCM_V2: u32 = 3; pub const XCM_V3: u32 = 2; @@ -49,6 +50,7 @@ pub mod accounts { pub const DAVE_STASH: &str = "Dave//stash"; pub const EVE_STASH: &str = "Eve//stash"; pub const FERDIE_STASH: &str = "Ferdie//stash"; + pub const FERDIE_BEEFY: &str = "Ferdie//stash"; pub fn init_balances() -> Vec { vec![ @@ -209,6 +211,7 @@ pub mod polkadot { } } +// Westend pub mod westend { use super::*; use westend_runtime_constants::currency::UNITS as WND; @@ -401,6 +404,93 @@ pub mod kusama { } } +// Rococo +pub mod rococo { + use super::*; + pub const ED: Balance = rococo_runtime_constants::currency::EXISTENTIAL_DEPOSIT; + use rococo_runtime_constants::currency::UNITS as ROC; + const ENDOWMENT: u128 = 1_000_000 * ROC; + + pub fn get_host_config() -> HostConfiguration { + HostConfiguration { + max_upward_queue_size: 51200, + max_upward_message_size: 51200, + max_upward_message_num_per_candidate: 10, + max_downward_message_size: 51200, + ..Default::default() + } + } + + fn session_keys( + babe: BabeId, + grandpa: GrandpaId, + im_online: ImOnlineId, + para_validator: ValidatorId, + para_assignment: AssignmentId, + authority_discovery: AuthorityDiscoveryId, + beefy: BeefyId, + ) -> rococo_runtime::SessionKeys { + rococo_runtime::SessionKeys { + babe, + grandpa, + im_online, + para_validator, + para_assignment, + authority_discovery, + beefy, + } + } + + pub fn genesis() -> Storage { + let genesis_config = rococo_runtime::RuntimeGenesisConfig { + system: rococo_runtime::SystemConfig { + code: rococo_runtime::WASM_BINARY.unwrap().to_vec(), + }, + balances: rococo_runtime::BalancesConfig { + balances: accounts::init_balances() + .iter() + .map(|k| (k.clone(), ENDOWMENT)) + .collect(), + }, + // indices: rococo_runtime::IndicesConfig { indices: vec![] }, + session: rococo_runtime::SessionConfig { + keys: validators::initial_authorities() + .iter() + .map(|x| { + ( + x.0.clone(), + x.0.clone(), + session_keys( + x.2.clone(), + x.3.clone(), + x.4.clone(), + x.5.clone(), + x.6.clone(), + x.7.clone(), + get_from_seed::("Alice"), + ), + ) + }) + .collect::>(), + }, + babe: rococo_runtime::BabeConfig { + authorities: Default::default(), + epoch_config: Some(rococo_runtime::BABE_GENESIS_EPOCH_CONFIG), + }, + sudo: rococo_runtime::SudoConfig { + key: Some(get_account_id_from_seed::("Alice")), + }, + configuration: rococo_runtime::ConfigurationConfig { config: get_host_config() }, + registrar: rococo_runtime::RegistrarConfig { + next_free_para_id: polkadot_primitives::LOWEST_PUBLIC_ID, + }, + ..Default::default() + }; + + genesis_config.build_storage().unwrap() + } +} + // Asset Hub Polkadot pub mod asset_hub_polkadot { use super::*; @@ -445,12 +535,10 @@ pub mod asset_hub_polkadot { }) .collect(), }, - aura: Default::default(), - aura_ext: Default::default(), - parachain_system: Default::default(), polkadot_xcm: asset_hub_polkadot_runtime::PolkadotXcmConfig { safe_xcm_version: Some(SAFE_XCM_VERSION), }, + ..Default::default() }; genesis_config.build_storage().unwrap() @@ -501,12 +589,10 @@ pub mod asset_hub_westend { }) .collect(), }, - aura: Default::default(), - aura_ext: Default::default(), - parachain_system: Default::default(), polkadot_xcm: asset_hub_westend_runtime::PolkadotXcmConfig { safe_xcm_version: Some(SAFE_XCM_VERSION), }, + ..Default::default() }; genesis_config.build_storage().unwrap() @@ -557,12 +643,10 @@ pub mod asset_hub_kusama { }) .collect(), }, - aura: Default::default(), - aura_ext: Default::default(), - parachain_system: Default::default(), polkadot_xcm: asset_hub_kusama_runtime::PolkadotXcmConfig { safe_xcm_version: Some(SAFE_XCM_VERSION), }, + ..Default::default() }; genesis_config.build_storage().unwrap() @@ -611,15 +695,13 @@ pub mod penpal { }) .collect(), }, - aura: Default::default(), - aura_ext: Default::default(), - parachain_system: Default::default(), polkadot_xcm: penpal_runtime::PolkadotXcmConfig { safe_xcm_version: Some(SAFE_XCM_VERSION), }, sudo: penpal_runtime::SudoConfig { key: Some(get_account_id_from_seed::("Alice")), }, + ..Default::default() }; genesis_config.build_storage().unwrap() @@ -670,22 +752,17 @@ pub mod collectives { }) .collect(), }, - // no need to pass anything to aura, in fact it will panic if we do. Session will take care - // of this. - aura: Default::default(), - aura_ext: Default::default(), - parachain_system: Default::default(), polkadot_xcm: collectives_polkadot_runtime::PolkadotXcmConfig { safe_xcm_version: Some(SAFE_XCM_VERSION), }, - alliance: Default::default(), - alliance_motion: Default::default(), + ..Default::default() }; genesis_config.build_storage().unwrap() } } +// Bridge Hub Kusama pub mod bridge_hub_kusama { use super::*; pub const PARA_ID: u32 = 1002; @@ -729,18 +806,17 @@ pub mod bridge_hub_kusama { }) .collect(), }, - aura: Default::default(), - aura_ext: Default::default(), - parachain_system: Default::default(), polkadot_xcm: bridge_hub_kusama_runtime::PolkadotXcmConfig { safe_xcm_version: Some(SAFE_XCM_VERSION), }, + ..Default::default() }; genesis_config.build_storage().unwrap() } } +// Bridge Hub Polkadot pub mod bridge_hub_polkadot { use super::*; pub const PARA_ID: u32 = 1002; @@ -784,12 +860,80 @@ pub mod bridge_hub_polkadot { }) .collect(), }, - aura: Default::default(), - aura_ext: Default::default(), - parachain_system: Default::default(), polkadot_xcm: bridge_hub_polkadot_runtime::PolkadotXcmConfig { safe_xcm_version: Some(SAFE_XCM_VERSION), }, + ..Default::default() + }; + + genesis_config.build_storage().unwrap() + } +} + +// Bridge Hub Rococo & Bridge Hub Wococo +pub mod bridge_hub_rococo { + use super::*; + pub const PARA_ID: u32 = 1013; + pub const ED: Balance = bridge_hub_rococo_runtime::constants::currency::EXISTENTIAL_DEPOSIT; + + pub fn genesis() -> Storage { + let genesis_config = bridge_hub_rococo_runtime::RuntimeGenesisConfig { + system: bridge_hub_rococo_runtime::SystemConfig { + code: bridge_hub_rococo_runtime::WASM_BINARY + .expect("WASM binary was not build, please build it!") + .to_vec(), + }, + balances: bridge_hub_rococo_runtime::BalancesConfig { + balances: accounts::init_balances() + .iter() + .cloned() + .map(|k| (k, ED * 4096)) + .collect(), + }, + parachain_info: bridge_hub_rococo_runtime::ParachainInfoConfig { + parachain_id: PARA_ID.into(), + }, + collator_selection: bridge_hub_rococo_runtime::CollatorSelectionConfig { + invulnerables: collators::invulnerables() + .iter() + .cloned() + .map(|(acc, _)| acc) + .collect(), + candidacy_bond: ED * 16, + ..Default::default() + }, + session: bridge_hub_rococo_runtime::SessionConfig { + keys: collators::invulnerables() + .into_iter() + .map(|(acc, aura)| { + ( + acc.clone(), // account id + acc, // validator id + bridge_hub_rococo_runtime::SessionKeys { aura }, // session keys + ) + }) + .collect(), + }, + polkadot_xcm: bridge_hub_rococo_runtime::PolkadotXcmConfig { + safe_xcm_version: Some(SAFE_XCM_VERSION), + }, + bridge_wococo_grandpa: bridge_hub_rococo_runtime::BridgeWococoGrandpaConfig { + owner: Some(get_account_id_from_seed::("Alice")), + ..Default::default() + }, + bridge_rococo_grandpa: bridge_hub_rococo_runtime::BridgeRococoGrandpaConfig { + owner: Some(get_account_id_from_seed::("Alice")), + ..Default::default() + }, + bridge_rococo_messages: bridge_hub_rococo_runtime::BridgeRococoMessagesConfig { + owner: Some(get_account_id_from_seed::("Alice")), + ..Default::default() + }, + bridge_wococo_messages: bridge_hub_rococo_runtime::BridgeWococoMessagesConfig { + owner: Some(get_account_id_from_seed::("Alice")), + ..Default::default() + }, + ..Default::default() }; genesis_config.build_storage().unwrap() diff --git a/cumulus/parachains/integration-tests/emulated/common/src/impls.rs b/cumulus/parachains/integration-tests/emulated/common/src/impls.rs new file mode 100644 index 0000000000..9c4acf4637 --- /dev/null +++ b/cumulus/parachains/integration-tests/emulated/common/src/impls.rs @@ -0,0 +1,126 @@ +use super::{BridgeHubRococo, BridgeHubWococo}; +use bp_messages::{ + target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, + LaneId, MessageKey, OutboundLaneData, +}; +use bridge_runtime_common::messages_xcm_extension::XcmBlobMessageDispatchResult; +use codec::Decode; +pub use cumulus_primitives_core::{DmpMessageHandler, XcmpMessageHandler}; +use pallet_bridge_messages::{Config, Instance1, Instance2, OutboundLanes, Pallet}; +use sp_core::Get; +use xcm_emulator::{BridgeMessage, BridgeMessageDispatchError, BridgeMessageHandler, Parachain}; + +pub struct BridgeHubMessageHandler { + _marker: std::marker::PhantomData<(S, T, I)>, +} + +struct LaneIdWrapper(LaneId); + +impl From for u32 { + fn from(lane_id: LaneIdWrapper) -> u32 { + u32::from_be_bytes(lane_id.0 .0) + } +} + +impl From for LaneIdWrapper { + fn from(id: u32) -> LaneIdWrapper { + LaneIdWrapper(LaneId(id.to_be_bytes())) + } +} + +type BridgeHubRococoRuntime = ::Runtime; +type BridgeHubWococoRuntime = ::Runtime; + +// TODO: uncomment when https://github.com/paritytech/cumulus/pull/2528 is merged +// type BridgeHubPolkadotRuntime = ::Runtime; +// type BridgeHubKusamaRuntime = ::Runtime; + +pub type RococoWococoMessageHandler = + BridgeHubMessageHandler; +pub type WococoRococoMessageHandler = + BridgeHubMessageHandler; + +// TODO: uncomment when https://github.com/paritytech/cumulus/pull/2528 is merged +// pub type PolkadotKusamaMessageHandler +// = BridgeHubMessageHandler; +// pub type KusamaPolkadotMessageHandler +// = BridgeHubMessageHandler; + +impl BridgeMessageHandler for BridgeHubMessageHandler +where + S: Config, + T: Config, + I: 'static, + >::InboundPayload: From>, + >::MessageDispatch: + MessageDispatch, +{ + fn get_source_outbound_messages() -> Vec { + // get the source active outbound lanes + let active_lanes = S::ActiveOutboundLanes::get(); + + let mut messages: Vec = Default::default(); + + // collect messages from `OutboundMessages` for each active outbound lane in the source + for lane in active_lanes { + let latest_generated_nonce = + OutboundLanes::::get(lane).latest_generated_nonce; + let latest_received_nonce = + OutboundLanes::::get(lane).latest_received_nonce; + + (latest_received_nonce + 1..=latest_generated_nonce).for_each(|nonce| { + let encoded_payload: Vec = + Pallet::::outbound_message_data(*lane, nonce) + .expect("Bridge message does not exist") + .into(); + let payload = Vec::::decode(&mut &encoded_payload[..]) + .expect("Decodign XCM message failed"); + let id: u32 = LaneIdWrapper(*lane).into(); + let message = BridgeMessage { id, nonce, payload }; + + messages.push(message); + }); + } + messages + } + + fn dispatch_target_inbound_message( + message: BridgeMessage, + ) -> Result<(), BridgeMessageDispatchError> { + type TargetMessageDispatch = >::MessageDispatch; + type InboundPayload = >::InboundPayload; + + let lane_id = LaneIdWrapper::from(message.id).0; + let nonce = message.nonce; + let payload = Ok(From::from(message.payload)); + + // Directly dispatch outbound messages assuming everything is correct + // and bypassing the `Relayers` and `InboundLane` logic + let dispatch_result = TargetMessageDispatch::::dispatch(DispatchMessage { + key: MessageKey { lane_id, nonce }, + data: DispatchMessageData::> { payload }, + }); + + let result = match dispatch_result.dispatch_level_result { + XcmBlobMessageDispatchResult::Dispatched => Ok(()), + XcmBlobMessageDispatchResult::InvalidPayload => Err(BridgeMessageDispatchError( + Box::new(XcmBlobMessageDispatchResult::InvalidPayload), + )), + XcmBlobMessageDispatchResult::NotDispatched(e) => Err(BridgeMessageDispatchError( + Box::new(XcmBlobMessageDispatchResult::NotDispatched(e)), + )), + }; + result + } + + fn notify_source_message_delivery(lane_id: u32) { + let data = OutboundLanes::::get(LaneIdWrapper::from(lane_id).0); + let new_data = OutboundLaneData { + oldest_unpruned_nonce: data.oldest_unpruned_nonce + 1, + latest_received_nonce: data.latest_received_nonce + 1, + ..data + }; + + OutboundLanes::::insert(LaneIdWrapper::from(lane_id).0, new_data); + } +} diff --git a/cumulus/parachains/integration-tests/emulated/common/src/lib.rs b/cumulus/parachains/integration-tests/emulated/common/src/lib.rs index dba3ef7dca..d88f1ddd3e 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/lib.rs @@ -1,41 +1,25 @@ pub mod constants; +pub mod impls; pub use constants::{ accounts::{ALICE, BOB}, asset_hub_kusama, asset_hub_polkadot, asset_hub_westend, bridge_hub_kusama, - bridge_hub_polkadot, collectives, kusama, penpal, polkadot, westend, + bridge_hub_polkadot, bridge_hub_rococo, collectives, kusama, penpal, polkadot, rococo, westend, }; +pub use impls::{RococoWococoMessageHandler, WococoRococoMessageHandler}; + use frame_support::{parameter_types, sp_io, sp_tracing}; pub use parachains_common::{AccountId, AssetHubPolkadotAuraId, AuraId, Balance, BlockNumber}; pub use sp_core::{sr25519, storage::Storage, Get}; use xcm::prelude::*; use xcm_emulator::{ - decl_test_networks, decl_test_parachains, decl_test_relay_chains, Parachain, RelayChain, - TestExt, + decl_test_bridges, decl_test_networks, decl_test_parachains, decl_test_relay_chains, + decl_test_sender_receiver_accounts_parameter_types, BridgeMessageHandler, Parachain, + RelayChain, TestExt, }; use xcm_executor::traits::ConvertLocation; decl_test_relay_chains! { - #[api_version(5)] - pub struct Westend { - genesis = westend::genesis(), - on_init = (), - runtime = { - Runtime: westend_runtime::Runtime, - RuntimeOrigin: westend_runtime::RuntimeOrigin, - RuntimeCall: westend_runtime::RuntimeCall, - RuntimeEvent: westend_runtime::RuntimeEvent, - MessageQueue: westend_runtime::MessageQueue, - XcmConfig: westend_runtime::xcm_config::XcmConfig, - SovereignAccountOf: westend_runtime::xcm_config::LocationConverter, //TODO: rename to SovereignAccountOf, - System: westend_runtime::System, - Balances: westend_runtime::Balances, - }, - pallets_extra = { - XcmPallet: westend_runtime::XcmPallet, - Sudo: westend_runtime::Sudo, - } - }, #[api_version(5)] pub struct Polkadot { genesis = polkadot::genesis(), @@ -73,35 +57,71 @@ decl_test_relay_chains! { pallets_extra = { XcmPallet: kusama_runtime::XcmPallet, } + }, + #[api_version(5)] + pub struct Westend { + genesis = westend::genesis(), + on_init = (), + runtime = { + Runtime: westend_runtime::Runtime, + RuntimeOrigin: westend_runtime::RuntimeOrigin, + RuntimeCall: westend_runtime::RuntimeCall, + RuntimeEvent: westend_runtime::RuntimeEvent, + MessageQueue: westend_runtime::MessageQueue, + XcmConfig: westend_runtime::xcm_config::XcmConfig, + SovereignAccountOf: westend_runtime::xcm_config::LocationConverter, //TODO: rename to SovereignAccountOf, + System: westend_runtime::System, + Balances: westend_runtime::Balances, + }, + pallets_extra = { + XcmPallet: westend_runtime::XcmPallet, + Sudo: westend_runtime::Sudo, + } + }, + #[api_version(5)] + pub struct Rococo { + genesis = rococo::genesis(), + on_init = (), + runtime = { + Runtime: rococo_runtime::Runtime, + RuntimeOrigin: rococo_runtime::RuntimeOrigin, + RuntimeCall: rococo_runtime::RuntimeCall, + RuntimeEvent: rococo_runtime::RuntimeEvent, + MessageQueue: rococo_runtime::MessageQueue, + XcmConfig: rococo_runtime::xcm_config::XcmConfig, + SovereignAccountOf: rococo_runtime::xcm_config::LocationConverter, //TODO: rename to SovereignAccountOf, + System: rococo_runtime::System, + Balances: rococo_runtime::Balances, + }, + pallets_extra = { + XcmPallet: rococo_runtime::XcmPallet, + Sudo: rococo_runtime::Sudo, + } + }, + #[api_version(5)] + pub struct Wococo { + genesis = rococo::genesis(), + on_init = (), + runtime = { + Runtime: rococo_runtime::Runtime, + RuntimeOrigin: rococo_runtime::RuntimeOrigin, + RuntimeCall: rococo_runtime::RuntimeCall, + RuntimeEvent: rococo_runtime::RuntimeEvent, + MessageQueue: rococo_runtime::MessageQueue, + XcmConfig: rococo_runtime::xcm_config::XcmConfig, + SovereignAccountOf: rococo_runtime::xcm_config::LocationConverter, //TODO: rename to SovereignAccountOf, + System: rococo_runtime::System, + Balances: rococo_runtime::Balances, + }, + pallets_extra = { + XcmPallet: rococo_runtime::XcmPallet, + Sudo: rococo_runtime::Sudo, + } } } decl_test_parachains! { - // Westend - pub struct AssetHubWestend { - genesis = asset_hub_westend::genesis(), - on_init = (), - runtime = { - Runtime: asset_hub_westend_runtime::Runtime, - RuntimeOrigin: asset_hub_westend_runtime::RuntimeOrigin, - RuntimeCall: asset_hub_westend_runtime::RuntimeCall, - RuntimeEvent: asset_hub_westend_runtime::RuntimeEvent, - XcmpMessageHandler: asset_hub_westend_runtime::XcmpQueue, - DmpMessageHandler: asset_hub_westend_runtime::DmpQueue, - LocationToAccountId: asset_hub_westend_runtime::xcm_config::LocationToAccountId, - System: asset_hub_westend_runtime::System, - Balances: asset_hub_westend_runtime::Balances, - ParachainSystem: asset_hub_westend_runtime::ParachainSystem, - ParachainInfo: asset_hub_westend_runtime::ParachainInfo, - }, - pallets_extra = { - PolkadotXcm: asset_hub_westend_runtime::PolkadotXcm, - Assets: asset_hub_westend_runtime::Assets, - ForeignAssets: asset_hub_westend_runtime::ForeignAssets, - AssetConversion: asset_hub_westend_runtime::AssetConversion, - } - }, - // Polkadot + // Polkadot Parachains pub struct AssetHubPolkadot { genesis = asset_hub_polkadot::genesis(), on_init = (), @@ -123,6 +143,46 @@ decl_test_parachains! { Assets: asset_hub_polkadot_runtime::Assets, } }, + pub struct Collectives { + genesis = collectives::genesis(), + on_init = (), + runtime = { + Runtime: collectives_polkadot_runtime::Runtime, + RuntimeOrigin: collectives_polkadot_runtime::RuntimeOrigin, + RuntimeCall: collectives_polkadot_runtime::RuntimeCall, + RuntimeEvent: collectives_polkadot_runtime::RuntimeEvent, + XcmpMessageHandler: collectives_polkadot_runtime::XcmpQueue, + DmpMessageHandler: collectives_polkadot_runtime::DmpQueue, + LocationToAccountId: collectives_polkadot_runtime::xcm_config::LocationToAccountId, + System: collectives_polkadot_runtime::System, + Balances: collectives_polkadot_runtime::Balances, + ParachainSystem: collectives_polkadot_runtime::ParachainSystem, + ParachainInfo: collectives_polkadot_runtime::ParachainInfo, + }, + pallets_extra = { + PolkadotXcm: collectives_polkadot_runtime::PolkadotXcm, + } + }, + pub struct BridgeHubPolkadot { + genesis = bridge_hub_polkadot::genesis(), + on_init = (), + runtime = { + Runtime: bridge_hub_polkadot_runtime::Runtime, + RuntimeOrigin: bridge_hub_polkadot_runtime::RuntimeOrigin, + RuntimeCall: bridge_hub_polkadot_runtime::RuntimeCall, + RuntimeEvent: bridge_hub_polkadot_runtime::RuntimeEvent, + XcmpMessageHandler: bridge_hub_polkadot_runtime::XcmpQueue, + DmpMessageHandler: bridge_hub_polkadot_runtime::DmpQueue, + LocationToAccountId: bridge_hub_polkadot_runtime::xcm_config::LocationToAccountId, + System: bridge_hub_polkadot_runtime::System, + Balances: bridge_hub_polkadot_runtime::Balances, + ParachainSystem: bridge_hub_polkadot_runtime::ParachainSystem, + ParachainInfo: bridge_hub_polkadot_runtime::ParachainInfo, + }, + pallets_extra = { + PolkadotXcm: bridge_hub_polkadot_runtime::PolkadotXcm, + } + }, pub struct PenpalPolkadot { genesis = penpal::genesis(penpal::PARA_ID), on_init = (), @@ -144,29 +204,7 @@ decl_test_parachains! { Assets: penpal_runtime::Assets, } }, - pub struct PenpalWestend { - genesis = penpal::genesis(penpal::PARA_ID), - on_init = (), - runtime = { - Runtime: penpal_runtime::Runtime, - RuntimeOrigin: penpal_runtime::RuntimeOrigin, - RuntimeCall: penpal_runtime::RuntimeCall, - RuntimeEvent: penpal_runtime::RuntimeEvent, - XcmpMessageHandler: penpal_runtime::XcmpQueue, - DmpMessageHandler: penpal_runtime::DmpQueue, - LocationToAccountId: penpal_runtime::xcm_config::LocationToAccountId, - System: penpal_runtime::System, - Balances: penpal_runtime::Balances, - ParachainSystem: penpal_runtime::ParachainSystem, - ParachainInfo: penpal_runtime::ParachainInfo, - }, - pallets_extra = { - PolkadotXcm: penpal_runtime::PolkadotXcm, - Assets: penpal_runtime::Assets, - } - }, - - // Kusama + // Kusama Parachains pub struct AssetHubKusama { genesis = asset_hub_kusama::genesis(), on_init = (), @@ -189,6 +227,26 @@ decl_test_parachains! { ForeignAssets: asset_hub_kusama_runtime::Assets, } }, + pub struct BridgeHubKusama { + genesis = bridge_hub_kusama::genesis(), + on_init = (), + runtime = { + Runtime: bridge_hub_kusama_runtime::Runtime, + RuntimeOrigin: bridge_hub_kusama_runtime::RuntimeOrigin, + RuntimeCall: bridge_hub_kusama_runtime::RuntimeCall, + RuntimeEvent: bridge_hub_kusama_runtime::RuntimeEvent, + XcmpMessageHandler: bridge_hub_kusama_runtime::XcmpQueue, + DmpMessageHandler: bridge_hub_kusama_runtime::DmpQueue, + LocationToAccountId: bridge_hub_kusama_runtime::xcm_config::LocationToAccountId, + System: bridge_hub_kusama_runtime::System, + Balances: bridge_hub_kusama_runtime::Balances, + ParachainSystem: bridge_hub_kusama_runtime::ParachainSystem, + ParachainInfo: bridge_hub_kusama_runtime::ParachainInfo, + }, + pallets_extra = { + PolkadotXcm: bridge_hub_kusama_runtime::PolkadotXcm, + } + }, pub struct PenpalKusama { genesis = penpal::genesis(penpal::PARA_ID), on_init = (), @@ -210,64 +268,133 @@ decl_test_parachains! { Assets: penpal_runtime::Assets, } }, - pub struct Collectives { - genesis = collectives::genesis(), + // Westend Parachains + pub struct AssetHubWestend { + genesis = asset_hub_westend::genesis(), on_init = (), runtime = { - Runtime: collectives_polkadot_runtime::Runtime, - RuntimeOrigin: collectives_polkadot_runtime::RuntimeOrigin, - RuntimeCall: collectives_polkadot_runtime::RuntimeCall, - RuntimeEvent: collectives_polkadot_runtime::RuntimeEvent, - XcmpMessageHandler: collectives_polkadot_runtime::XcmpQueue, - DmpMessageHandler: collectives_polkadot_runtime::DmpQueue, - LocationToAccountId: collectives_polkadot_runtime::xcm_config::LocationToAccountId, - System: collectives_polkadot_runtime::System, - Balances: collectives_polkadot_runtime::Balances, - ParachainSystem: collectives_polkadot_runtime::ParachainSystem, - ParachainInfo: collectives_polkadot_runtime::ParachainInfo, + Runtime: asset_hub_westend_runtime::Runtime, + RuntimeOrigin: asset_hub_westend_runtime::RuntimeOrigin, + RuntimeCall: asset_hub_westend_runtime::RuntimeCall, + RuntimeEvent: asset_hub_westend_runtime::RuntimeEvent, + XcmpMessageHandler: asset_hub_westend_runtime::XcmpQueue, + DmpMessageHandler: asset_hub_westend_runtime::DmpQueue, + LocationToAccountId: asset_hub_westend_runtime::xcm_config::LocationToAccountId, + System: asset_hub_westend_runtime::System, + Balances: asset_hub_westend_runtime::Balances, + ParachainSystem: asset_hub_westend_runtime::ParachainSystem, + ParachainInfo: asset_hub_westend_runtime::ParachainInfo, }, pallets_extra = { - PolkadotXcm: collectives_polkadot_runtime::PolkadotXcm, + PolkadotXcm: asset_hub_westend_runtime::PolkadotXcm, + Assets: asset_hub_westend_runtime::Assets, + ForeignAssets: asset_hub_westend_runtime::ForeignAssets, + AssetConversion: asset_hub_westend_runtime::AssetConversion, } }, - pub struct BHKusama { - genesis = bridge_hub_kusama::genesis(), + pub struct PenpalWestend { + genesis = penpal::genesis(penpal::PARA_ID), on_init = (), runtime = { - Runtime: bridge_hub_kusama_runtime::Runtime, - RuntimeOrigin: bridge_hub_kusama_runtime::RuntimeOrigin, - RuntimeCall: bridge_hub_kusama_runtime::RuntimeCall, - RuntimeEvent: bridge_hub_kusama_runtime::RuntimeEvent, - XcmpMessageHandler: bridge_hub_kusama_runtime::XcmpQueue, - DmpMessageHandler: bridge_hub_kusama_runtime::DmpQueue, - LocationToAccountId: bridge_hub_kusama_runtime::xcm_config::LocationToAccountId, - System: bridge_hub_kusama_runtime::System, - Balances: bridge_hub_kusama_runtime::Balances, - ParachainSystem: bridge_hub_kusama_runtime::ParachainSystem, - ParachainInfo:bridge_hub_kusama_runtime::ParachainInfo, + Runtime: penpal_runtime::Runtime, + RuntimeOrigin: penpal_runtime::RuntimeOrigin, + RuntimeCall: penpal_runtime::RuntimeCall, + RuntimeEvent: penpal_runtime::RuntimeEvent, + XcmpMessageHandler: penpal_runtime::XcmpQueue, + DmpMessageHandler: penpal_runtime::DmpQueue, + LocationToAccountId: penpal_runtime::xcm_config::LocationToAccountId, + System: penpal_runtime::System, + Balances: penpal_runtime::Balances, + ParachainSystem: penpal_runtime::ParachainSystem, + ParachainInfo: penpal_runtime::ParachainInfo, }, pallets_extra = { - PolkadotXcm: bridge_hub_kusama_runtime::PolkadotXcm, + PolkadotXcm: penpal_runtime::PolkadotXcm, + Assets: penpal_runtime::Assets, } }, - pub struct BHPolkadot { - genesis = bridge_hub_polkadot::genesis(), + // Rococo Parachains + pub struct BridgeHubRococo { + genesis = bridge_hub_rococo::genesis(), on_init = (), runtime = { - Runtime: bridge_hub_polkadot_runtime::Runtime, - RuntimeOrigin: bridge_hub_polkadot_runtime::RuntimeOrigin, - RuntimeCall: bridge_hub_polkadot_runtime::RuntimeCall, - RuntimeEvent: bridge_hub_polkadot_runtime::RuntimeEvent, - XcmpMessageHandler: bridge_hub_polkadot_runtime::XcmpQueue, - DmpMessageHandler: bridge_hub_polkadot_runtime::DmpQueue, - LocationToAccountId: bridge_hub_polkadot_runtime::xcm_config::LocationToAccountId, - System: bridge_hub_polkadot_runtime::System, - Balances: bridge_hub_polkadot_runtime::Balances, - ParachainSystem: bridge_hub_polkadot_runtime::ParachainSystem, - ParachainInfo:bridge_hub_polkadot_runtime::ParachainInfo, + Runtime: bridge_hub_rococo_runtime::Runtime, + RuntimeOrigin: bridge_hub_rococo_runtime::RuntimeOrigin, + RuntimeCall: bridge_hub_rococo_runtime::RuntimeCall, + RuntimeEvent: bridge_hub_rococo_runtime::RuntimeEvent, + XcmpMessageHandler: bridge_hub_rococo_runtime::XcmpQueue, + DmpMessageHandler: bridge_hub_rococo_runtime::DmpQueue, + LocationToAccountId: bridge_hub_rococo_runtime::xcm_config::LocationToAccountId, + System: bridge_hub_rococo_runtime::System, + Balances: bridge_hub_rococo_runtime::Balances, + ParachainSystem: bridge_hub_rococo_runtime::ParachainSystem, + ParachainInfo: bridge_hub_rococo_runtime::ParachainInfo, }, pallets_extra = { - PolkadotXcm: bridge_hub_polkadot_runtime::PolkadotXcm, + PolkadotXcm: bridge_hub_rococo_runtime::PolkadotXcm, + } + }, + pub struct AssetHubRococo { + genesis = asset_hub_polkadot::genesis(), + on_init = (), + runtime = { + Runtime: asset_hub_polkadot_runtime::Runtime, + RuntimeOrigin: asset_hub_polkadot_runtime::RuntimeOrigin, + RuntimeCall: asset_hub_polkadot_runtime::RuntimeCall, + RuntimeEvent: asset_hub_polkadot_runtime::RuntimeEvent, + XcmpMessageHandler: asset_hub_polkadot_runtime::XcmpQueue, + DmpMessageHandler: asset_hub_polkadot_runtime::DmpQueue, + LocationToAccountId: asset_hub_polkadot_runtime::xcm_config::LocationToAccountId, + System: asset_hub_polkadot_runtime::System, + Balances: asset_hub_polkadot_runtime::Balances, + ParachainSystem: asset_hub_polkadot_runtime::ParachainSystem, + ParachainInfo: asset_hub_polkadot_runtime::ParachainInfo, + }, + pallets_extra = { + PolkadotXcm: asset_hub_polkadot_runtime::PolkadotXcm, + Assets: asset_hub_polkadot_runtime::Assets, + } + }, + // Wococo Parachains + pub struct BridgeHubWococo { + genesis = bridge_hub_rococo::genesis(), + on_init = (), + runtime = { + Runtime: bridge_hub_rococo_runtime::Runtime, + RuntimeOrigin: bridge_hub_rococo_runtime::RuntimeOrigin, + RuntimeCall: bridge_hub_rococo_runtime::RuntimeCall, + RuntimeEvent: bridge_hub_rococo_runtime::RuntimeEvent, + XcmpMessageHandler: bridge_hub_rococo_runtime::XcmpQueue, + DmpMessageHandler: bridge_hub_rococo_runtime::DmpQueue, + LocationToAccountId: bridge_hub_rococo_runtime::xcm_config::LocationToAccountId, + System: bridge_hub_rococo_runtime::System, + Balances: bridge_hub_rococo_runtime::Balances, + ParachainSystem: bridge_hub_rococo_runtime::ParachainSystem, + ParachainInfo: bridge_hub_rococo_runtime::ParachainInfo, + }, + pallets_extra = { + PolkadotXcm: bridge_hub_rococo_runtime::PolkadotXcm, + } + }, + pub struct AssetHubWococo { + genesis = asset_hub_polkadot::genesis(), + on_init = (), + runtime = { + Runtime: asset_hub_polkadot_runtime::Runtime, + RuntimeOrigin: asset_hub_polkadot_runtime::RuntimeOrigin, + RuntimeCall: asset_hub_polkadot_runtime::RuntimeCall, + RuntimeEvent: asset_hub_polkadot_runtime::RuntimeEvent, + XcmpMessageHandler: asset_hub_polkadot_runtime::XcmpQueue, + DmpMessageHandler: asset_hub_polkadot_runtime::DmpQueue, + LocationToAccountId: asset_hub_polkadot_runtime::xcm_config::LocationToAccountId, + System: asset_hub_polkadot_runtime::System, + Balances: asset_hub_polkadot_runtime::Balances, + ParachainSystem: asset_hub_polkadot_runtime::ParachainSystem, + ParachainInfo: asset_hub_polkadot_runtime::ParachainInfo, + }, + pallets_extra = { + PolkadotXcm: asset_hub_polkadot_runtime::PolkadotXcm, + Assets: asset_hub_polkadot_runtime::Assets, } } } @@ -279,16 +406,22 @@ decl_test_networks! { AssetHubPolkadot, PenpalPolkadot, Collectives, - BHPolkadot, + BridgeHubPolkadot, ], + // TODO: uncomment when https://github.com/paritytech/cumulus/pull/2528 is merged + // bridge = PolkadotKusamaMockBridge + bridge = () }, pub struct KusamaMockNet { relay_chain = Kusama, parachains = vec![ AssetHubKusama, PenpalKusama, - BHKusama, + BridgeHubKusama, ], + // TODO: uncomment when https://github.com/paritytech/cumulus/pull/2528 is merged + // bridge = KusamaPolkadotMockBridge + bridge = () }, pub struct WestendMockNet { relay_chain = Westend, @@ -296,44 +429,72 @@ decl_test_networks! { AssetHubWestend, PenpalWestend, ], + bridge = () + }, + pub struct RococoMockNet { + relay_chain = Rococo, + parachains = vec![ + AssetHubRococo, + BridgeHubRococo, + ], + bridge = RococoWococoMockBridge + }, + pub struct WococoMockNet { + relay_chain = Wococo, + parachains = vec![ + AssetHubWococo, + BridgeHubWococo, + ], + bridge = WococoRococoMockBridge } } -parameter_types! { - // Polkadot - pub PolkadotSender: AccountId = Polkadot::account_id_of(ALICE); - pub PolkadotReceiver: AccountId = Polkadot::account_id_of(BOB); - // Kusama - pub KusamaSender: AccountId = Kusama::account_id_of(ALICE); - pub KusamaReceiver: AccountId = Kusama::account_id_of(BOB); - // Westend - pub WestendSender: AccountId = Westend::account_id_of(ALICE); - pub WestendReceiver: AccountId = Westend::account_id_of(BOB); - // Asset Hub Westend - pub AssetHubWestendSender: AccountId = AssetHubWestend::account_id_of(ALICE); - pub AssetHubWestendReceiver: AccountId = AssetHubWestend::account_id_of(BOB); - // Asset Hub Polkadot - pub AssetHubPolkadotSender: AccountId = AssetHubPolkadot::account_id_of(ALICE); - pub AssetHubPolkadotReceiver: AccountId = AssetHubPolkadot::account_id_of(BOB); - // Asset Hub Kusama - pub AssetHubKusamaSender: AccountId = AssetHubKusama::account_id_of(ALICE); - pub AssetHubKusamaReceiver: AccountId = AssetHubKusama::account_id_of(BOB); - // Penpal Polkadot - pub PenpalPolkadotSender: AccountId = PenpalPolkadot::account_id_of(ALICE); - pub PenpalPolkadotReceiver: AccountId = PenpalPolkadot::account_id_of(BOB); - // Penpal Kusama - pub PenpalKusamaSender: AccountId = PenpalKusama::account_id_of(ALICE); - pub PenpalKusamaReceiver: AccountId = PenpalKusama::account_id_of(BOB); - // Penpal Westend - pub PenpalWestendSender: AccountId = PenpalWestend::account_id_of(ALICE); - pub PenpalWestendReceiver: AccountId = PenpalWestend::account_id_of(BOB); - // Collectives - pub CollectivesSender: AccountId = Collectives::account_id_of(ALICE); - pub CollectivesReceiver: AccountId = Collectives::account_id_of(BOB); - // Bridge Hub Polkadot - pub BHPolkadotSender: AccountId = BHPolkadot::account_id_of(ALICE); - pub BHPolkadotReceiver: AccountId = BHPolkadot::account_id_of(BOB); - // Bridge Hub Kusama - pub BHKusamaSender: AccountId = BHKusama::account_id_of(ALICE); - pub BHKusamaReceiver: AccountId = BHKusama::account_id_of(BOB); +decl_test_bridges! { + pub struct RococoWococoMockBridge { + source = BridgeHubRococo, + target = BridgeHubWococo, + handler = RococoWococoMessageHandler + }, + pub struct WococoRococoMockBridge { + source = BridgeHubWococo, + target = BridgeHubRococo, + handler = WococoRococoMessageHandler + } + // TODO: uncomment when https://github.com/paritytech/cumulus/pull/2528 is merged + // pub struct PolkadotKusamaMockBridge { + // source = BridgeHubPolkadot, + // target = BridgeHubKusama, + // handler = PolkadotKusamaMessageHandler + // }, + // pub struct KusamaPolkadotMockBridge { + // source = BridgeHubKusama, + // target = BridgeHubPolkadot, + // handler = KusamaPolkadotMessageHandler + // } +} + +decl_test_sender_receiver_accounts_parameter_types! { + // Relays + Polkadot { sender: ALICE, receiver: BOB }, + Kusama { sender: ALICE, receiver: BOB }, + Westend { sender: ALICE, receiver: BOB }, + Rococo { sender: ALICE, receiver: BOB }, + Wococo { sender: ALICE, receiver: BOB }, + // Asset Hubs + AssetHubPolkadot { sender: ALICE, receiver: BOB }, + AssetHubKusama { sender: ALICE, receiver: BOB }, + AssetHubWestend { sender: ALICE, receiver: BOB }, + AssetHubRococo { sender: ALICE, receiver: BOB }, + AssetHubWococo { sender: ALICE, receiver: BOB }, + // Collectives + Collectives { sender: ALICE, receiver: BOB }, + // Bridged Hubs + BridgeHubPolkadot { sender: ALICE, receiver: BOB }, + BridgeHubKusama { sender: ALICE, receiver: BOB }, + BridgeHubRococo { sender: ALICE, receiver: BOB }, + BridgeHubWococo { sender: ALICE, receiver: BOB }, + // Penpals + PenpalPolkadot { sender: ALICE, receiver: BOB }, + PenpalKusama { sender: ALICE, receiver: BOB }, + PenpalWestend { sender: ALICE, receiver: BOB } } diff --git a/cumulus/xcm/xcm-emulator/Cargo.toml b/cumulus/xcm/xcm-emulator/Cargo.toml index 207f2c489b..449de22efc 100644 --- a/cumulus/xcm/xcm-emulator/Cargo.toml +++ b/cumulus/xcm/xcm-emulator/Cargo.toml @@ -12,6 +12,7 @@ quote = "1.0.29" casey = "0.4.0" log = { version = "0.4.19", default-features = false } +# Substrate frame-support = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-io = { git = "https://github.com/paritytech/substrate", branch = "master" } @@ -22,6 +23,7 @@ sp-trie = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-message-queue = { git = "https://github.com/paritytech/substrate", branch = "master" } +# Cumulus cumulus-primitives-core = { path = "../../primitives/core"} cumulus-pallet-xcmp-queue = { path = "../../pallets/xcmp-queue" } cumulus-pallet-dmp-queue = { path = "../../pallets/dmp-queue" } @@ -32,7 +34,7 @@ cumulus-primitives-parachain-inherent = { path = "../../primitives/parachain-inh cumulus-test-relay-sproof-builder = { path = "../../test/relay-sproof-builder" } parachains-common = { path = "../../parachains/common" } +# Polkadot xcm = { git = "https://github.com/paritytech/polkadot", branch = "master" } -xcm-executor = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-primitives = { git = "https://github.com/paritytech/polkadot", branch = "master" } polkadot-runtime-parachains = { git = "https://github.com/paritytech/polkadot", branch = "master" } diff --git a/cumulus/xcm/xcm-emulator/src/lib.rs b/cumulus/xcm/xcm-emulator/src/lib.rs index d66a94bed0..170ec1e6fb 100644 --- a/cumulus/xcm/xcm-emulator/src/lib.rs +++ b/cumulus/xcm/xcm-emulator/src/lib.rs @@ -14,23 +14,26 @@ // You should have received a copy of the GNU General Public License // along with Polkadot. If not, see . -pub use casey::pascal; -pub use codec::Encode; +pub use codec::{Decode, Encode}; +pub use log; +pub use paste; +pub use std::{collections::HashMap, error::Error, fmt, thread::LocalKey}; + +// Substrate pub use frame_support::{ - sp_runtime::BuildStorage, + assert_ok, traits::{EnqueueMessage, Get, Hooks, ProcessMessage, ProcessMessageError, ServiceQueues}, weights::{Weight, WeightMeter}, }; pub use frame_system::AccountInfo; -pub use log; pub use pallet_balances::AccountData; -pub use paste; pub use sp_arithmetic::traits::Bounded; -pub use sp_core::storage::Storage; +pub use sp_core::{storage::Storage, H256}; pub use sp_io; -pub use sp_std::{cell::RefCell, collections::vec_deque::VecDeque, marker::PhantomData}; +pub use sp_std::{cell::RefCell, collections::vec_deque::VecDeque, fmt::Debug}; pub use sp_trie::StorageProof; +//Cumulus pub use cumulus_pallet_dmp_queue; pub use cumulus_pallet_parachain_system; pub use cumulus_pallet_xcmp_queue; @@ -44,15 +47,14 @@ pub use cumulus_test_service::get_account_id_from_seed; pub use pallet_message_queue; pub use parachain_info; pub use parachains_common::{AccountId, BlockNumber}; - pub use polkadot_primitives; pub use polkadot_runtime_parachains::{ dmp, inclusion::{AggregateMessageOrigin, UmpQueueId}, }; -pub use std::{collections::HashMap, thread::LocalKey}; -pub use xcm::{v3::prelude::*, VersionedXcm}; -pub use xcm_executor::XcmExecutor; + +// Polkadot +pub use xcm::v3::prelude::*; thread_local! { /// Downward messages, each message is: `(to_para_id, [(relay_block_number, msg)])` @@ -67,8 +69,10 @@ thread_local! { #[allow(clippy::type_complexity)] pub static HORIZONTAL_MESSAGES: RefCell)>)>>> = RefCell::new(HashMap::new()); - /// Upward messages, each message is: `(from_para_id, msg) + /// Upward messages, each message is: `(from_para_id, msg)` pub static UPWARD_MESSAGES: RefCell)>>> = RefCell::new(HashMap::new()); + /// Bridged messages, each message is: `BridgeMessage` + pub static BRIDGED_MESSAGES: RefCell>> = RefCell::new(HashMap::new()); /// Global incremental relay chain block number pub static RELAY_BLOCK_NUMBER: RefCell> = RefCell::new(HashMap::new()); /// Parachains Ids a the Network @@ -85,41 +89,46 @@ pub trait TestExt { fn ext_wrapper(func: impl FnOnce() -> R) -> R; } +impl TestExt for () { + fn build_new_ext(_storage: Storage) -> sp_io::TestExternalities { + sp_io::TestExternalities::default() + } + fn new_ext() -> sp_io::TestExternalities { + sp_io::TestExternalities::default() + } + fn reset_ext() {} + fn execute_with(execute: impl FnOnce() -> R) -> R { + execute() + } + fn ext_wrapper(func: impl FnOnce() -> R) -> R { + func() + } +} + pub trait Network { - fn _init(); - fn _para_ids() -> Vec; - fn _relay_block_number() -> u32; - fn _set_relay_block_number(block_number: u32); - fn _process_messages(); - fn _has_unprocessed_messages() -> bool; - fn _process_downward_messages(); - fn _process_horizontal_messages(); - fn _process_upward_messages(); - fn _hrmp_channel_parachain_inherent_data( + type Bridge: Bridge; + + fn init(); + fn para_ids() -> Vec; + fn relay_block_number() -> u32; + fn set_relay_block_number(block_number: u32); + fn process_messages(); + fn has_unprocessed_messages() -> bool; + fn process_downward_messages(); + fn process_horizontal_messages(); + fn process_upward_messages(); + fn process_bridged_messages(); + fn hrmp_channel_parachain_inherent_data( para_id: u32, relay_parent_number: u32, ) -> ParachainInherentData; } -pub trait NetworkComponent { +pub trait NetworkComponent { + type Network: Network; + fn network_name() -> &'static str; - fn init() { - N::_init(); - } - - fn relay_block_number() -> u32 { - N::_relay_block_number() - } - - fn set_relay_block_number(block_number: u32) { - N::_set_relay_block_number(block_number); - } - - fn para_ids() -> Vec { - N::_para_ids() - } - fn send_horizontal_messages)>>( to_para_id: u32, iter: I, @@ -153,15 +162,9 @@ pub trait NetworkComponent { }); } - fn hrmp_channel_parachain_inherent_data( - para_id: u32, - relay_parent_number: u32, - ) -> ParachainInherentData { - N::_hrmp_channel_parachain_inherent_data(para_id, relay_parent_number) - } - - fn process_messages() { - N::_process_messages(); + fn send_bridged_messages(msg: BridgeMessage) { + BRIDGED_MESSAGES + .with(|b| b.borrow_mut().get_mut(Self::network_name()).unwrap().push_back(msg)); } } @@ -190,6 +193,64 @@ pub trait Parachain: XcmpMessageHandler + DmpMessageHandler { type ParachainInfo; } +pub trait Bridge { + type Source: TestExt; + type Target: TestExt; + type Handler: BridgeMessageHandler; + + fn init(); +} + +impl Bridge for () { + type Source = (); + type Target = (); + type Handler = (); + + fn init() {} +} + +#[derive(Clone, Default, Debug)] +pub struct BridgeMessage { + pub id: u32, + pub nonce: u64, + pub payload: Vec, +} + +pub trait BridgeMessageHandler { + fn get_source_outbound_messages() -> Vec; + + fn dispatch_target_inbound_message( + message: BridgeMessage, + ) -> Result<(), BridgeMessageDispatchError>; + + fn notify_source_message_delivery(lane_id: u32); +} + +impl BridgeMessageHandler for () { + fn get_source_outbound_messages() -> Vec { + Default::default() + } + + fn dispatch_target_inbound_message( + _message: BridgeMessage, + ) -> Result<(), BridgeMessageDispatchError> { + Err(BridgeMessageDispatchError(Box::new("Not a bridge"))) + } + + fn notify_source_message_delivery(_lane_id: u32) {} +} + +#[derive(Debug)] +pub struct BridgeMessageDispatchError(pub Box); + +impl Error for BridgeMessageDispatchError {} + +impl fmt::Display for BridgeMessageDispatchError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{:?}", self.0) + } +} + // Relay Chain Implementation #[macro_export] macro_rules! decl_test_relay_chains { @@ -322,9 +383,9 @@ macro_rules! __impl_test_ext_for_relay_chain { } fn execute_with(execute: impl FnOnce() -> R) -> R { - use $crate::{NetworkComponent}; + use $crate::{NetworkComponent, Network}; // Make sure the Network is initialized - <$name>::init(); + <$name as NetworkComponent>::Network::init(); let r = $ext_name.with(|v| v.borrow_mut().execute_with(execute)); @@ -334,7 +395,7 @@ macro_rules! __impl_test_ext_for_relay_chain { use $crate::polkadot_primitives::runtime_api::runtime_decl_for_parachain_host::$api_version; //TODO: mark sent count & filter out sent msg - for para_id in <$name>::para_ids() { + for para_id in<$name as NetworkComponent>::Network::para_ids() { // downward messages let downward_messages = ::Runtime::dmq_contents(para_id.into()) .into_iter() @@ -350,7 +411,7 @@ macro_rules! __impl_test_ext_for_relay_chain { }) }); - <$name>::process_messages(); + <$name as NetworkComponent>::Network::process_messages(); r } @@ -368,10 +429,12 @@ macro_rules! __impl_test_ext_for_relay_chain { #[macro_export] macro_rules! __impl_relay { - ($network_name:ident, $relay_chain:ty) => { - impl $crate::NetworkComponent<$network_name> for $relay_chain { + ($network:ident, $relay_chain:ty) => { + impl $crate::NetworkComponent for $relay_chain { + type Network = $network; + fn network_name() -> &'static str { - stringify!($network_name) + stringify!($network) } } @@ -549,24 +612,24 @@ macro_rules! __impl_test_ext_for_parachain { } fn execute_with(execute: impl FnOnce() -> R) -> R { - use $crate::{Get, Hooks, NetworkComponent}; + use $crate::{Get, Hooks, NetworkComponent, Network, Bridge}; // Make sure the Network is initialized - <$name>::init(); + <$name as NetworkComponent>::Network::init(); - let mut relay_block_number = <$name>::relay_block_number(); + let mut relay_block_number = <$name as NetworkComponent>::Network::relay_block_number(); relay_block_number += 1; - <$name>::set_relay_block_number(relay_block_number); + <$name as NetworkComponent>::Network::set_relay_block_number(relay_block_number); let para_id = <$name>::para_id().into(); $ext_name.with(|v| { v.borrow_mut().execute_with(|| { // Make sure it has been recorded properly - let relay_block_number = <$name>::relay_block_number(); + let relay_block_number = <$name as NetworkComponent>::Network::relay_block_number(); let _ = ::ParachainSystem::set_validation_data( ::RuntimeOrigin::none(), - <$name>::hrmp_channel_parachain_inherent_data(para_id, relay_block_number), + <$name as NetworkComponent>::Network::hrmp_channel_parachain_inherent_data(para_id, relay_block_number), ); }) }); @@ -588,12 +651,12 @@ macro_rules! __impl_test_ext_for_parachain { Default::default(), ); - // get messages + // get xcmp messages ::ParachainSystem::on_finalize(block_number); let collation_info = ::ParachainSystem::collect_collation_info(&mock_header); // send upward messages - let relay_block_number = <$name>::relay_block_number(); + let relay_block_number = <$name as NetworkComponent>::Network::relay_block_number(); for msg in collation_info.upward_messages.clone() { <$name>::send_upward_message(para_id, msg); } @@ -606,12 +669,22 @@ macro_rules! __impl_test_ext_for_parachain { ); } + // get bridge messages + type NetworkBridge = <<$name as NetworkComponent>::Network as Network>::Bridge; + + let bridge_messages = ::Handler::get_source_outbound_messages(); + + // send bridged messages + for msg in bridge_messages { + <$name>::send_bridged_messages(msg); + } + // clean messages ::ParachainSystem::on_initialize(block_number); }) }); - <$name>::process_messages(); + <$name as NetworkComponent>::Network::process_messages(); r } @@ -629,10 +702,12 @@ macro_rules! __impl_test_ext_for_parachain { #[macro_export] macro_rules! __impl_parachain { - ($network_name:ident, $parachain:ty) => { - impl $crate::NetworkComponent<$network_name> for $parachain { + ($network:ident, $parachain:ty) => { + impl $crate::NetworkComponent for $parachain { + type Network = $network; + fn network_name() -> &'static str { - stringify!($network_name) + stringify!($network) } } @@ -645,6 +720,10 @@ macro_rules! __impl_parachain { (Parent).into() } + pub fn sibling_location_of(para_id: $crate::ParaId) -> $crate::MultiLocation { + (Parent, X1(Parachain(para_id.into()))).into() + } + pub fn account_id_of(seed: &str) -> $crate::AccountId { $crate::get_account_id_from_seed::(seed) } @@ -677,7 +756,7 @@ macro_rules! __impl_parachain { } fn prepare_for_xcmp() { - use $crate::NetworkComponent; + use $crate::{Network, NetworkComponent}; let para_id = Self::para_id(); ::ext_wrapper(|| { @@ -687,7 +766,10 @@ macro_rules! __impl_parachain { let _ = ::ParachainSystem::set_validation_data( ::RuntimeOrigin::none(), - Self::hrmp_channel_parachain_inherent_data(para_id.into(), 1), + ::Network::hrmp_channel_parachain_inherent_data( + para_id.into(), + 1, + ), ); // set `AnnouncedHrmpMessagesPerCandidate` ::ParachainSystem::on_initialize(block_number); @@ -705,6 +787,7 @@ macro_rules! decl_test_networks { pub struct $name:ident { relay_chain = $relay_chain:ty, parachains = vec![ $( $parachain:ty, )* ], + bridge = $bridge:ty } ), + @@ -721,16 +804,18 @@ macro_rules! decl_test_networks { $crate::DMP_DONE.with(|b| b.borrow_mut().remove(stringify!($name))); $crate::UPWARD_MESSAGES.with(|b| b.borrow_mut().remove(stringify!($name))); $crate::HORIZONTAL_MESSAGES.with(|b| b.borrow_mut().remove(stringify!($name))); + $crate::BRIDGED_MESSAGES.with(|b| b.borrow_mut().remove(stringify!($name))); $crate::RELAY_BLOCK_NUMBER.with(|b| b.borrow_mut().remove(stringify!($name))); <$relay_chain>::reset_ext(); $( <$parachain>::reset_ext(); )* - $( <$parachain>::prepare_for_xcmp(); )* } } impl $crate::Network for $name { - fn _init() { + type Bridge = $bridge; + + fn init() { // If Network has not been itialized yet, it gets initialized if $crate::INITIALIZED.with(|b| b.borrow_mut().get(stringify!($name)).is_none()) { $crate::INITIALIZED.with(|b| b.borrow_mut().insert(stringify!($name).to_string(), true)); @@ -738,42 +823,45 @@ macro_rules! decl_test_networks { $crate::DMP_DONE.with(|b| b.borrow_mut().insert(stringify!($name).to_string(), $crate::VecDeque::new())); $crate::UPWARD_MESSAGES.with(|b| b.borrow_mut().insert(stringify!($name).to_string(), $crate::VecDeque::new())); $crate::HORIZONTAL_MESSAGES.with(|b| b.borrow_mut().insert(stringify!($name).to_string(), $crate::VecDeque::new())); + $crate::BRIDGED_MESSAGES.with(|b| b.borrow_mut().insert(stringify!($name).to_string(), $crate::VecDeque::new())); $crate::RELAY_BLOCK_NUMBER.with(|b| b.borrow_mut().insert(stringify!($name).to_string(), 1)); - $crate::PARA_IDS.with(|b| b.borrow_mut().insert(stringify!($name).to_string(), Self::_para_ids())); + $crate::PARA_IDS.with(|b| b.borrow_mut().insert(stringify!($name).to_string(), Self::para_ids())); $( <$parachain>::prepare_for_xcmp(); )* } } - fn _para_ids() -> Vec { + fn para_ids() -> Vec { vec![$( <$parachain>::para_id().into(), )*] } - fn _relay_block_number() -> u32 { + fn relay_block_number() -> u32 { $crate::RELAY_BLOCK_NUMBER.with(|v| *v.clone().borrow().get(stringify!($name)).unwrap()) } - fn _set_relay_block_number(block_number: u32) { + fn set_relay_block_number(block_number: u32) { $crate::RELAY_BLOCK_NUMBER.with(|v| v.borrow_mut().insert(stringify!($name).to_string(), block_number)); } - fn _process_messages() { - while Self::_has_unprocessed_messages() { - Self::_process_upward_messages(); - Self::_process_horizontal_messages(); - Self::_process_downward_messages(); + fn process_messages() { + while Self::has_unprocessed_messages() { + Self::process_upward_messages(); + Self::process_horizontal_messages(); + Self::process_downward_messages(); + Self::process_bridged_messages(); } } - fn _has_unprocessed_messages() -> bool { + fn has_unprocessed_messages() -> bool { $crate::DOWNWARD_MESSAGES.with(|b| !b.borrow_mut().get_mut(stringify!($name)).unwrap().is_empty()) || $crate::HORIZONTAL_MESSAGES.with(|b| !b.borrow_mut().get_mut(stringify!($name)).unwrap().is_empty()) || $crate::UPWARD_MESSAGES.with(|b| !b.borrow_mut().get_mut(stringify!($name)).unwrap().is_empty()) + || $crate::BRIDGED_MESSAGES.with(|b| !b.borrow_mut().get_mut(stringify!($name)).unwrap().is_empty()) } - fn _process_downward_messages() { + fn process_downward_messages() { use $crate::{DmpMessageHandler, Bounded}; use polkadot_parachain::primitives::RelayChainBlockNumber; @@ -794,6 +882,7 @@ macro_rules! decl_test_networks { }).collect::)>>(); if msgs.len() != 0 { <$parachain>::handle_dmp_messages(msgs.clone().into_iter(), $crate::Weight::max_value()); + $crate::log::debug!(target: concat!("dmp::", stringify!($name)) , "DMP messages processed {:?} to para_id {:?}", msgs.clone(), &to_para_id); for m in msgs { $crate::DMP_DONE.with(|b| b.borrow_mut().get_mut(stringify!($name)).unwrap().push_back((to_para_id, m.0, m.1))); } @@ -803,7 +892,7 @@ macro_rules! decl_test_networks { } } - fn _process_horizontal_messages() { + fn process_horizontal_messages() { use $crate::{XcmpMessageHandler, Bounded}; while let Some((to_para_id, messages)) @@ -814,12 +903,13 @@ macro_rules! decl_test_networks { if $crate::PARA_IDS.with(|b| b.borrow_mut().get_mut(stringify!($name)).unwrap().contains(&to_para_id)) && para_id == to_para_id { <$parachain>::handle_xcmp_messages(iter.clone(), $crate::Weight::max_value()); + $crate::log::debug!(target: concat!("hrmp::", stringify!($name)) , "HRMP messages processed {:?} to para_id {:?}", &messages, &to_para_id); } )* } } - fn _process_upward_messages() { + fn process_upward_messages() { use $crate::{Bounded, ProcessMessage, WeightMeter}; use sp_core::Encode; while let Some((from_para_id, msg)) = $crate::UPWARD_MESSAGES.with(|b| b.borrow_mut().get_mut(stringify!($name)).unwrap().pop_front()) { @@ -830,10 +920,33 @@ macro_rules! decl_test_networks { &mut weight_meter, &mut msg.using_encoded(sp_core::blake2_256), ); + $crate::log::debug!(target: concat!("ump::", stringify!($name)) , "Upward message processed {:?} from para_id {:?}", &msg, &from_para_id); } } - fn _hrmp_channel_parachain_inherent_data( + fn process_bridged_messages() { + use $crate::Bridge; + // Make sure both, including the target `Network` are initialized + ::init(); + + while let Some(msg) = $crate::BRIDGED_MESSAGES.with(|b| b.borrow_mut().get_mut(stringify!($name)).unwrap().pop_front()) { + let dispatch_result = <::Target as TestExt>::ext_wrapper(|| { + <::Handler as BridgeMessageHandler>::dispatch_target_inbound_message(msg.clone()) + }); + + match dispatch_result { + Err(e) => panic!("Error {:?} processing bridged message: {:?}", e, msg.clone()), + Ok(()) => { + <::Source as TestExt>::ext_wrapper(|| { + <::Handler as BridgeMessageHandler>::notify_source_message_delivery(msg.id); + }); + $crate::log::debug!(target: concat!("bridge::", stringify!($name)) , "Bridged message processed {:?}", msg.clone()); + } + } + } + } + + fn hrmp_channel_parachain_inherent_data( para_id: u32, relay_parent_number: u32, ) -> $crate::ParachainInherentData { @@ -891,6 +1004,38 @@ macro_rules! decl_test_networks { }; } +#[macro_export] +macro_rules! decl_test_bridges { + ( + $( + pub struct $name:ident { + source = $source:ty, + target = $target:ty, + handler = $handler:ty + } + ), + + + ) => { + $( + #[derive(Debug)] + pub struct $name; + + impl $crate::Bridge for $name { + type Source = $source; + type Target = $target; + type Handler = $handler; + + fn init() { + use $crate::{NetworkComponent, Network}; + // Make sure source and target `Network` has been initialized + <$source as NetworkComponent>::Network::init(); + <$target as NetworkComponent>::Network::init(); + } + } + )+ + }; +} + #[macro_export] macro_rules! assert_expected_events { ( $chain:ident, vec![$( $event_pat:pat => { $($attr:ident : $condition:expr, )* }, )*] ) => { @@ -900,7 +1045,7 @@ macro_rules! assert_expected_events { let mut event_message: Vec = Vec::new(); let event_received = <$chain>::events().iter().any(|event| { - $crate::log::debug!(target: format!("events::{}", stringify!($chain)).to_lowercase().as_str(), "{:?}", event); + $crate::log::debug!(target: concat!("events::", stringify!($chain)), "{:?}", event); match event { $event_pat => { @@ -936,6 +1081,20 @@ macro_rules! bx { }; } +#[macro_export] +macro_rules! decl_test_sender_receiver_accounts_parameter_types { + ( $( $chain:ident { sender: $sender:expr, receiver: $receiver:expr }),+ ) => { + $crate::paste::paste! { + parameter_types! { + $( + pub [<$chain Sender>]: $crate::AccountId = <$chain>::account_id_of($sender); + pub [<$chain Receiver>]: $crate::AccountId = <$chain>::account_id_of($receiver); + )+ + } + } + }; +} + pub mod helpers { use super::Weight;