diff --git a/Cargo.lock b/Cargo.lock index ddb19c24e1f6..b1c4db58446c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -722,6 +722,9 @@ version = "0.9.420" dependencies = [ "asset-test-utils", "assets-common", + "bp-asset-hub-kusama", + "bp-asset-hub-polkadot", + "bp-bridge-hub-kusama", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", @@ -761,6 +764,7 @@ dependencies = [ "pallet-utility", "pallet-xcm", "pallet-xcm-benchmarks", + "pallet-xcm-bridge-hub-router", "parachain-info", "parachains-common", "parity-scale-codec", @@ -818,6 +822,9 @@ version = "0.9.420" dependencies = [ "asset-test-utils", "assets-common", + "bp-asset-hub-kusama", + "bp-asset-hub-polkadot", + "bp-bridge-hub-polkadot", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", @@ -853,6 +860,7 @@ dependencies = [ "pallet-utility", "pallet-xcm", "pallet-xcm-benchmarks", + "pallet-xcm-bridge-hub-router", "parachain-info", "parachains-common", "parity-scale-codec", @@ -996,6 +1004,7 @@ dependencies = [ "pallet-collator-selection", "pallet-session", "pallet-xcm", + "pallet-xcm-bridge-hub-router", "parachain-info", "parachains-common", "parachains-runtimes-test-utils", @@ -1007,6 +1016,7 @@ dependencies = [ "sp-runtime", "sp-std", "staging-xcm", + "staging-xcm-builder", "staging-xcm-executor", "substrate-wasm-builder", ] @@ -1815,7 +1825,19 @@ dependencies = [ name = "bridge-hub-kusama-runtime" version = "0.1.0" dependencies = [ + "bp-asset-hub-kusama", + "bp-bridge-hub-kusama", + "bp-bridge-hub-polkadot", + "bp-header-chain", + "bp-kusama", + "bp-messages", + "bp-parachains", + "bp-polkadot", + "bp-polkadot-core", + "bp-relayers", + "bp-runtime", "bridge-hub-test-utils", + "bridge-runtime-common", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", @@ -1837,6 +1859,10 @@ dependencies = [ "pallet-aura", "pallet-authorship", "pallet-balances", + "pallet-bridge-grandpa", + "pallet-bridge-messages", + "pallet-bridge-parachains", + "pallet-bridge-relayers", "pallet-collator-selection", "pallet-multisig", "pallet-session", @@ -1861,6 +1887,7 @@ dependencies = [ "sp-core", "sp-inherents", "sp-io", + "sp-keyring", "sp-offchain", "sp-runtime", "sp-session", @@ -1871,6 +1898,7 @@ dependencies = [ "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", + "static_assertions", "substrate-wasm-builder", ] @@ -1878,7 +1906,19 @@ dependencies = [ name = "bridge-hub-polkadot-runtime" version = "0.1.0" dependencies = [ + "bp-asset-hub-polkadot", + "bp-bridge-hub-kusama", + "bp-bridge-hub-polkadot", + "bp-header-chain", + "bp-kusama", + "bp-messages", + "bp-parachains", + "bp-polkadot", + "bp-polkadot-core", + "bp-relayers", + "bp-runtime", "bridge-hub-test-utils", + "bridge-runtime-common", "cumulus-pallet-aura-ext", "cumulus-pallet-dmp-queue", "cumulus-pallet-parachain-system", @@ -1899,6 +1939,10 @@ dependencies = [ "pallet-aura", "pallet-authorship", "pallet-balances", + "pallet-bridge-grandpa", + "pallet-bridge-messages", + "pallet-bridge-parachains", + "pallet-bridge-relayers", "pallet-collator-selection", "pallet-multisig", "pallet-session", @@ -1924,6 +1968,7 @@ dependencies = [ "sp-core", "sp-inherents", "sp-io", + "sp-keyring", "sp-offchain", "sp-runtime", "sp-session", @@ -1934,6 +1979,7 @@ dependencies = [ "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", + "static_assertions", "substrate-wasm-builder", ] @@ -2042,7 +2088,6 @@ dependencies = [ name = "bridge-hub-test-utils" version = "0.1.0" dependencies = [ - "assert_matches", "asset-test-utils", "bp-bridge-hub-rococo", "bp-bridge-hub-wococo", @@ -2080,6 +2125,7 @@ dependencies = [ "sp-io", "sp-keyring", "sp-runtime", + "sp-tracing", "staging-xcm", "staging-xcm-builder", "staging-xcm-executor", @@ -3626,6 +3672,7 @@ dependencies = [ name = "cumulus-pallet-xcmp-queue" version = "0.1.0" dependencies = [ + "bp-xcm-bridge-hub-router", "cumulus-pallet-parachain-system", "cumulus-primitives-core", "frame-benchmarking", diff --git a/bridges/primitives/chain-asset-hub-kusama/src/lib.rs b/bridges/primitives/chain-asset-hub-kusama/src/lib.rs index 94016c1da0cb..f60ade71d9ce 100644 --- a/bridges/primitives/chain-asset-hub-kusama/src/lib.rs +++ b/bridges/primitives/chain-asset-hub-kusama/src/lib.rs @@ -47,3 +47,6 @@ frame_support::parameter_types! { /// (initially was calculated `170733333` + `10%` by test `BridgeHubKusama::can_calculate_weight_for_paid_export_message_with_reserve_transfer`) pub const BridgeHubKusamaBaseFeeInDots: u128 = 187806666; } + +/// Identifier of AssetHubKusama in the Kusama relay chain. +pub const ASSET_HUB_KUSAMA_PARACHAIN_ID: u32 = 1000; diff --git a/bridges/primitives/chain-asset-hub-polkadot/src/lib.rs b/bridges/primitives/chain-asset-hub-polkadot/src/lib.rs index 486fba60e1f8..5d5ea82de4c3 100644 --- a/bridges/primitives/chain-asset-hub-polkadot/src/lib.rs +++ b/bridges/primitives/chain-asset-hub-polkadot/src/lib.rs @@ -47,3 +47,6 @@ frame_support::parameter_types! { /// (initially was calculated `51220000` + `10%` by test `BridgeHubPolkadot::can_calculate_weight_for_paid_export_message_with_reserve_transfer`) pub const BridgeHubPolkadotBaseFeeInDots: u128 = 56342000; } + +/// Identifier of AssetHubPolkadot in the Polkadot relay chain. +pub const ASSET_HUB_POLKADOT_PARACHAIN_ID: u32 = 1000; diff --git a/bridges/primitives/chain-bridge-hub-kusama/src/lib.rs b/bridges/primitives/chain-bridge-hub-kusama/src/lib.rs index 3a919648df47..80c233943fd8 100644 --- a/bridges/primitives/chain-bridge-hub-kusama/src/lib.rs +++ b/bridges/primitives/chain-bridge-hub-kusama/src/lib.rs @@ -78,5 +78,8 @@ pub const WITH_BRIDGE_HUB_KUSAMA_MESSAGES_PALLET_NAME: &str = "BridgeKusamaMessa /// chains. pub const WITH_BRIDGE_HUB_KUSAMA_RELAYERS_PALLET_NAME: &str = "BridgeRelayers"; +/// Pallet index of `BridgePolkadotMessages: pallet_bridge_messages::`. +pub const WITH_BRIDGE_POLKADOT_MESSAGES_PALLET_INDEX: u8 = 53; + decl_bridge_finality_runtime_apis!(bridge_hub_kusama); decl_bridge_messages_runtime_apis!(bridge_hub_kusama); diff --git a/bridges/primitives/chain-bridge-hub-polkadot/src/lib.rs b/bridges/primitives/chain-bridge-hub-polkadot/src/lib.rs index bf8d8e07c3a6..96d6cc7ea26b 100644 --- a/bridges/primitives/chain-bridge-hub-polkadot/src/lib.rs +++ b/bridges/primitives/chain-bridge-hub-polkadot/src/lib.rs @@ -69,5 +69,8 @@ pub const WITH_BRIDGE_HUB_POLKADOT_MESSAGES_PALLET_NAME: &str = "BridgePolkadotM /// chains. pub const WITH_BRIDGE_HUB_POLKADOT_RELAYERS_PALLET_NAME: &str = "BridgeRelayers"; +/// Pallet index of `BridgeKusamaMessages: pallet_bridge_messages::`. +pub const WITH_BRIDGE_KUSAMA_MESSAGES_PALLET_INDEX: u8 = 53; + decl_bridge_finality_runtime_apis!(bridge_hub_polkadot); decl_bridge_messages_runtime_apis!(bridge_hub_polkadot); diff --git a/cumulus/pallets/xcmp-queue/Cargo.toml b/cumulus/pallets/xcmp-queue/Cargo.toml index 5aab57da91b4..77d0551b5110 100644 --- a/cumulus/pallets/xcmp-queue/Cargo.toml +++ b/cumulus/pallets/xcmp-queue/Cargo.toml @@ -28,6 +28,9 @@ cumulus-primitives-core = { path = "../../primitives/core", default-features = f # Optional import for benchmarking frame-benchmarking = { path = "../../../substrate/frame/benchmarking", default-features = false, optional = true} +# Bridges +bp-xcm-bridge-hub-router = { path = "../../../bridges/primitives/xcm-bridge-hub-router", default-features = false, optional = true } + [dev-dependencies] # Substrate @@ -43,6 +46,7 @@ cumulus-pallet-parachain-system = { path = "../parachain-system", features = ["p [features] default = [ "std" ] std = [ + "bp-xcm-bridge-hub-router?/std", "codec/std", "cumulus-primitives-core/std", "frame-benchmarking?/std", @@ -77,3 +81,4 @@ try-runtime = [ "polkadot-runtime-common/try-runtime", "sp-runtime/try-runtime", ] +bridging = [ "bp-xcm-bridge-hub-router" ] diff --git a/cumulus/pallets/xcmp-queue/src/bridging.rs b/cumulus/pallets/xcmp-queue/src/bridging.rs new file mode 100644 index 000000000000..0fc3f1f39ea3 --- /dev/null +++ b/cumulus/pallets/xcmp-queue/src/bridging.rs @@ -0,0 +1,95 @@ +// Copyright (C) Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::{pallet, OutboundState}; +use cumulus_primitives_core::ParaId; +use frame_support::pallet_prelude::Get; + +/// Adapter implementation for `bp_xcm_bridge_hub_router::XcmChannelStatusProvider` which checks +/// both `OutboundXcmpStatus` and `InboundXcmpStatus` for defined `ParaId` if any of those is +/// suspended. +pub struct InAndOutXcmpChannelStatusProvider( + sp_std::marker::PhantomData<(SiblingBridgeHubParaId, Runtime)>, +); +impl, Runtime: crate::Config> + bp_xcm_bridge_hub_router::XcmChannelStatusProvider + for InAndOutXcmpChannelStatusProvider +{ + fn is_congested() -> bool { + // if the inbound channel with recipient is suspended, it means that we are unable to + // receive congestion reports from the bridge hub. So we assume the bridge pipeline is + // congested too + if pallet::Pallet::::is_inbound_channel_suspended(SiblingBridgeHubParaId::get()) { + return true + } + + // if the outbound channel with recipient is suspended, it means that one of further + // bridge queues (e.g. bridge queue between two bridge hubs) is overloaded, so we shall + // take larger fee for our outbound messages + OutXcmpChannelStatusProvider::::is_congested() + } +} + +/// Adapter implementation for `bp_xcm_bridge_hub_router::XcmChannelStatusProvider` which checks +/// only `OutboundXcmpStatus` for defined `SiblingParaId` if is suspended. +pub struct OutXcmpChannelStatusProvider( + sp_std::marker::PhantomData<(SiblingBridgeHubParaId, Runtime)>, +); +impl, Runtime: crate::Config> + bp_xcm_bridge_hub_router::XcmChannelStatusProvider + for OutXcmpChannelStatusProvider +{ + fn is_congested() -> bool { + let sibling_bridge_hub_id: ParaId = SiblingBridgeHubParaId::get(); + + // let's find the channel's state with the sibling parachain, + let Some((outbound_state, queued_pages)) = pallet::Pallet::::outbound_channel_state(sibling_bridge_hub_id) else { + return false + }; + // suspended channel => it is congested + if outbound_state == OutboundState::Suspended { + return true + } + + // TODO: https://github.com/paritytech/polkadot-sdk/pull/1556 - once this PR is merged, we may + // remove the following code. + // TODO: the following restriction is arguable, we may live without that, assuming that + // There can't be more than some `N` messages queued at the bridge queue (at the source BH) + // AND before accepting next (or next-after-next) delivery transaction, we'll receive the + // suspension signal from the target parachain and stop accepting delivery transactions. + + // It takes some time for target parachain to suspend inbound channel with the target BH and + // during that we will keep accepting new message delivery transactions. Let's also reject + // new deliveries if there are too many "pages" (concatenated XCM messages) in the target BH + // -> target parachain queue. + + // If the outbound channel has at least `N` pages enqueued, let's assume it is congested. + // Normally, the chain with a few opened HRMP channels, will "send" pages at every block. + // Having `N` pages means that for last `N` blocks we either have not sent any messages, + // or have sent signals. + + const MAX_QUEUED_PAGES_BEFORE_DEACTIVATION: u16 = 4; + if queued_pages > MAX_QUEUED_PAGES_BEFORE_DEACTIVATION { + return true + } + + false + } +} + +#[cfg(feature = "runtime-benchmarks")] +pub fn suspend_channel_for_benchmarks(target: ParaId) { + pallet::Pallet::::suspend_channel(target) +} diff --git a/cumulus/pallets/xcmp-queue/src/lib.rs b/cumulus/pallets/xcmp-queue/src/lib.rs index 1cb92f595186..4a1a643b3505 100644 --- a/cumulus/pallets/xcmp-queue/src/lib.rs +++ b/cumulus/pallets/xcmp-queue/src/lib.rs @@ -35,6 +35,8 @@ mod tests; #[cfg(feature = "runtime-benchmarks")] mod benchmarking; +#[cfg(feature = "bridging")] +pub mod bridging; pub mod weights; pub use weights::WeightInfo; @@ -947,6 +949,24 @@ impl Pallet { } }); } + + #[cfg(feature = "bridging")] + fn is_inbound_channel_suspended(sender: ParaId) -> bool { + >::get() + .iter() + .find(|c| c.sender == sender) + .map(|c| c.state == InboundState::Suspended) + .unwrap_or(false) + } + + #[cfg(feature = "bridging")] + /// Returns tuple of `OutboundState` and number of queued pages. + fn outbound_channel_state(target: ParaId) -> Option<(OutboundState, u16)> { + >::get().iter().find(|c| c.recipient == target).map(|c| { + let queued_pages = c.last_index.saturating_sub(c.first_index); + (c.state, queued_pages) + }) + } } impl XcmpMessageHandler for Pallet { diff --git a/cumulus/parachains/common/src/xcm_config.rs b/cumulus/parachains/common/src/xcm_config.rs index 146671441453..7dee75975f97 100644 --- a/cumulus/parachains/common/src/xcm_config.rs +++ b/cumulus/parachains/common/src/xcm_config.rs @@ -14,14 +14,22 @@ // limitations under the License. use crate::impls::AccountIdOf; +use codec::Decode; use core::marker::PhantomData; use frame_support::{ - traits::{fungibles::Inspect, tokens::ConversionToAssetBalance, ContainsPair}, + ensure, + traits::{ + fungibles::Inspect, tokens::ConversionToAssetBalance, Contains, ContainsPair, + ProcessMessageError, + }, weights::Weight, + DefaultNoBound, }; use log; use sp_runtime::traits::Get; use xcm::latest::prelude::*; +use xcm_builder::{CreateMatcher, ExporterFor, MatchXcm}; +use xcm_executor::traits::ShouldExecute; /// A `ChargeFeeInFungibles` implementation that converts the output of /// a given WeightToFee implementation an amount charged in @@ -78,3 +86,270 @@ impl> ContainsPair matches!(asset.id, Concrete(ref id) if id == origin && origin == &Location::get()) } } + +/// Trait for matching `Location`. +pub trait MatchesLocation { + fn matches(&self, location: &Location) -> bool; +} + +/// Simple `Location` filter utility. +#[derive(Debug, DefaultNoBound)] +pub struct LocationFilter { + /// Requested location equals to `Location`. + pub equals_any: sp_std::vec::Vec, + /// Requested location starts with `Location`. + pub starts_with_any: sp_std::vec::Vec, +} + +impl LocationFilter { + pub fn add_equals(mut self, filter: Location) -> Self { + self.equals_any.push(filter); + self + } + pub fn add_starts_with(mut self, filter: Location) -> Self { + self.starts_with_any.push(filter); + self + } +} + +/// `MatchesLocation` implementation which works with `MultiLocation`. +impl MatchesLocation for LocationFilter { + fn matches(&self, location: &MultiLocation) -> bool { + for filter in &self.equals_any { + if location.eq(filter) { + return true + } + } + for filter in &self.starts_with_any { + if location.starts_with(filter) { + return true + } + } + false + } +} + +/// `MatchesLocation` implementation which works with `InteriorMultiLocation`. +impl MatchesLocation for LocationFilter { + fn matches(&self, location: &InteriorMultiLocation) -> bool { + for filter in &self.equals_any { + if location.eq(filter) { + return true + } + } + for filter in &self.starts_with_any { + if location.starts_with(filter) { + return true + } + } + false + } +} + +/// `FilteredNetworkExportTable` is adapter for `ExporterFor` implementation +/// which tries to find (`bridge_location`, `fees`) for requested `network` and `remote_location`. +/// +/// Inspired by `xcm_builder::NetworkExportTable`: +/// the main difference is that `NetworkExportTable` does not check `remote_location`. +pub struct FilteredNetworkExportTable(sp_std::marker::PhantomData); +impl< + T: Get< + sp_std::vec::Vec<( + NetworkId, + LocationFilter, + MultiLocation, + Option, + )>, + >, + > ExporterFor for FilteredNetworkExportTable +{ + fn exporter_for( + network: &NetworkId, + remote_location: &InteriorMultiLocation, + _: &Xcm<()>, + ) -> Option<(MultiLocation, Option)> { + T::get() + .into_iter() + .find(|(ref j, location_filter, ..)| { + j == network && location_filter.matches(remote_location) + }) + .map(|(_, _, bridge_location, p)| (bridge_location, p)) + } +} + +/// Allows execution from `origin` (only with `OriginKind::Xcm`) if it is contained in +/// `AllowedOrigin` and if it is just a straight `Transact` which passes `AllowedCall` matcher. +pub struct AllowUnpaidTransactsFrom( + sp_std::marker::PhantomData<(RuntimeCall, AllowedCall, AllowedOrigin)>, +); +impl< + RuntimeCall: Decode, + AllowedCall: Contains, + AllowedOrigin: Contains, + > ShouldExecute for AllowUnpaidTransactsFrom +{ + fn should_execute( + origin: &MultiLocation, + instructions: &mut [Instruction], + _max_weight: Weight, + _properties: &mut xcm_executor::traits::Properties, + ) -> Result<(), ProcessMessageError> { + log::trace!( + target: "xcm::barriers", + "AllowUnpaidTransactFrom origin: {:?}, instructions: {:?}, max_weight: {:?}, properties: {:?}", + origin, instructions, _max_weight, _properties, + ); + + // we only allow from configured origins + ensure!(AllowedOrigin::contains(origin), ProcessMessageError::Unsupported); + + // we expect an XCM program with single `Transact` call + instructions + .matcher() + .assert_remaining_insts(1)? + .match_next_inst(|inst| match inst { + Transact { origin_kind: OriginKind::Xcm, call: encoded_call, .. } => { + // Generic `Call` to `RuntimeCall` conversion - don't know if there's a way to + // do that properly? + let runtime_call: RuntimeCall = encoded_call + .clone() + .into::() + .try_into() + .map_err(|_| ProcessMessageError::BadFormat)?; + + ensure!(AllowedCall::contains(&runtime_call), ProcessMessageError::Unsupported); + + Ok(()) + }, + _ => Err(ProcessMessageError::BadFormat), + })?; + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use codec::{Decode, Encode}; + + #[test] + fn filtered_network_export_table_works() { + frame_support::parameter_types! { + pub BridgeLocation: MultiLocation = MultiLocation::new(1, X1(Parachain(1234))); + + pub BridgeTable: sp_std::vec::Vec<(NetworkId, LocationFilter, MultiLocation, Option)> = sp_std::vec![ + ( + Kusama, + LocationFilter::default() + .add_equals(X1(Parachain(2000))) + .add_equals(X1(Parachain(3000))) + .add_equals(X1(Parachain(4000))), + BridgeLocation::get(), + None + ) + ]; + } + + let test_data = vec![ + (Polkadot, X1(Parachain(1000)), None), + (Polkadot, X1(Parachain(2000)), None), + (Polkadot, X1(Parachain(3000)), None), + (Polkadot, X1(Parachain(4000)), None), + (Polkadot, X1(Parachain(5000)), None), + (Kusama, X1(Parachain(1000)), None), + (Kusama, X1(Parachain(2000)), Some((BridgeLocation::get(), None))), + (Kusama, X1(Parachain(3000)), Some((BridgeLocation::get(), None))), + (Kusama, X1(Parachain(4000)), Some((BridgeLocation::get(), None))), + (Kusama, X1(Parachain(5000)), None), + ]; + + for (network, remote_location, expected_result) in test_data { + assert_eq!( + FilteredNetworkExportTable::::exporter_for( + &network, + &remote_location, + &Xcm::default() + ), + expected_result, + ) + } + } + + #[test] + fn allow_unpaid_transacts_from_works() { + #[derive(Encode, Decode)] + enum RuntimeCall { + CallA, + CallB, + } + frame_support::match_types! { + pub type AcceptOnlyFromSibling1002: impl Contains = { + MultiLocation { parents: 1, interior: X1(Parachain(1002)) } + }; + pub type AcceptOnlyRuntimeCallA: impl Contains = { RuntimeCall::CallA }; + } + + fn transact(origin_kind: OriginKind, encoded_data: impl Encode) -> Instruction<()> { + Transact { + origin_kind, + require_weight_at_most: Default::default(), + call: encoded_data.encode().into(), + } + } + + type Barrier = AllowUnpaidTransactsFrom< + RuntimeCall, + AcceptOnlyRuntimeCallA, + AcceptOnlyFromSibling1002, + >; + + let test_data: Vec<(MultiLocation, Vec>, Result<(), ProcessMessageError>)> = vec![ + // success case + ( + MultiLocation { parents: 1, interior: X1(Parachain(1002)) }, + vec![transact(OriginKind::Xcm, RuntimeCall::CallA)], + Ok(()), + ), + // invalid message - more instruction than just one `Transact` + ( + MultiLocation { parents: 1, interior: X1(Parachain(1002)) }, + vec![transact(OriginKind::Xcm, RuntimeCall::CallA), ClearOrigin], + Err(ProcessMessageError::BadFormat), + ), + // invalid `OriginKind` + ( + MultiLocation { parents: 1, interior: X1(Parachain(1002)) }, + vec![transact(OriginKind::Native, RuntimeCall::CallA)], + Err(ProcessMessageError::BadFormat), + ), + // unsupported call + ( + MultiLocation { parents: 1, interior: X1(Parachain(1002)) }, + vec![transact(OriginKind::Xcm, RuntimeCall::CallB)], + Err(ProcessMessageError::Unsupported), + ), + // unsupported origin + ( + MultiLocation { parents: 1, interior: X1(Parachain(2105)) }, + vec![transact(OriginKind::Xcm, RuntimeCall::CallA)], + Err(ProcessMessageError::Unsupported), + ), + ]; + + for (origin, mut xcm, expected_result) in test_data { + assert_eq!( + Barrier::should_execute( + &origin, + &mut xcm, + Default::default(), + &mut xcm_executor::traits::Properties { + weight_credit: Default::default(), + message_id: None, + }, + ), + expected_result, + ) + } + } +} diff --git a/cumulus/parachains/integration-tests/emulated/common/src/constants.rs b/cumulus/parachains/integration-tests/emulated/common/src/constants.rs index 8725ebd140b9..b2f6915c0a90 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/constants.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/constants.rs @@ -966,6 +966,14 @@ pub mod bridge_hub_kusama { safe_xcm_version: Some(SAFE_XCM_VERSION), ..Default::default() }, + bridge_polkadot_grandpa: bridge_hub_kusama_runtime::BridgePolkadotGrandpaConfig { + owner: Some(get_account_id_from_seed::(accounts::BOB)), + ..Default::default() + }, + bridge_polkadot_messages: bridge_hub_kusama_runtime::BridgePolkadotMessagesConfig { + owner: Some(get_account_id_from_seed::(accounts::BOB)), + ..Default::default() + }, ..Default::default() }; @@ -1023,6 +1031,14 @@ pub mod bridge_hub_polkadot { safe_xcm_version: Some(SAFE_XCM_VERSION), ..Default::default() }, + bridge_kusama_grandpa: bridge_hub_polkadot_runtime::BridgeKusamaGrandpaConfig { + owner: Some(get_account_id_from_seed::(accounts::BOB)), + ..Default::default() + }, + bridge_kusama_messages: bridge_hub_polkadot_runtime::BridgeKusamaMessagesConfig { + owner: Some(get_account_id_from_seed::(accounts::BOB)), + ..Default::default() + }, ..Default::default() }; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-kusama/Cargo.toml index 1d0c7bc98563..99bf7bc1733d 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/Cargo.toml @@ -71,7 +71,7 @@ cumulus-pallet-dmp-queue = { path = "../../../../pallets/dmp-queue", default-fea cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook",] } cumulus-pallet-session-benchmarking = { path = "../../../../pallets/session-benchmarking", default-features = false} cumulus-pallet-xcm = { path = "../../../../pallets/xcm", default-features = false } -cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false } +cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false, features = ["bridging"] } cumulus-primitives-core = { path = "../../../../primitives/core", default-features = false } cumulus-primitives-utility = { path = "../../../../primitives/utility", default-features = false } pallet-collator-selection = { path = "../../../../pallets/collator-selection", default-features = false } @@ -79,6 +79,12 @@ parachain-info = { path = "../../../pallets/parachain-info", default-features = parachains-common = { path = "../../../common", default-features = false } assets-common = { path = "../common", default-features = false } +# Bridges +pallet-xcm-bridge-hub-router = { path = "../../../../../bridges/modules/xcm-bridge-hub-router", default-features = false } +bp-asset-hub-kusama = { path = "../../../../../bridges/primitives/chain-asset-hub-kusama", default-features = false } +bp-asset-hub-polkadot = { path = "../../../../../bridges/primitives/chain-asset-hub-polkadot", default-features = false } +bp-bridge-hub-kusama = { path = "../../../../../bridges/primitives/chain-bridge-hub-kusama", default-features = false } + [dev-dependencies] asset-test-utils = { path = "../test-utils" } @@ -118,6 +124,7 @@ runtime-benchmarks = [ "pallet-uniques/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", + "pallet-xcm-bridge-hub-router/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "parachains-common/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", @@ -153,6 +160,7 @@ try-runtime = [ "pallet-transaction-payment/try-runtime", "pallet-uniques/try-runtime", "pallet-utility/try-runtime", + "pallet-xcm-bridge-hub-router/try-runtime", "pallet-xcm/try-runtime", "parachain-info/try-runtime", "polkadot-runtime-common/try-runtime", @@ -160,6 +168,9 @@ try-runtime = [ ] std = [ "assets-common/std", + "bp-asset-hub-kusama/std", + "bp-asset-hub-polkadot/std", + "bp-bridge-hub-kusama/std", "codec/std", "cumulus-pallet-aura-ext/std", "cumulus-pallet-dmp-queue/std", @@ -198,6 +209,7 @@ std = [ "pallet-uniques/std", "pallet-utility/std", "pallet-xcm-benchmarks?/std", + "pallet-xcm-bridge-hub-router/std", "pallet-xcm/std", "parachain-info/std", "parachains-common/std", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs index 828d1b4750a3..2cea4c1939f0 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/lib.rs @@ -815,6 +815,38 @@ impl pallet_nfts::Config for Runtime { type Helper = (); } +/// XCM router instance to BridgeHub with bridging capabilities for `Polkadot` global consensus with +/// dynamic fees and back-pressure. +pub type ToPolkadotXcmRouterInstance = pallet_assets::Instance1; +impl pallet_xcm_bridge_hub_router::Config for Runtime { + type WeightInfo = weights::pallet_xcm_bridge_hub_router::WeightInfo; + + type UniversalLocation = xcm_config::UniversalLocation; + type BridgedNetworkId = xcm_config::bridging::PolkadotNetwork; + type Bridges = xcm_config::bridging::FilteredNetworkExportTable; + + #[cfg(not(feature = "runtime-benchmarks"))] + type BridgeHubOrigin = + EnsureXcm>; + #[cfg(feature = "runtime-benchmarks")] + type BridgeHubOrigin = EitherOfDiverse< + // for running benchmarks + EnsureRoot, + // for running tests with `--feature runtime-benchmarks` + EnsureXcm>, + >; + + type ToBridgeHubSender = XcmpQueue; + type WithBridgeHubChannel = + cumulus_pallet_xcmp_queue::bridging::InAndOutXcmpChannelStatusProvider< + xcm_config::bridging::BridgeHubKusamaParaId, + Runtime, + >; + + type ByteFee = xcm_config::bridging::XcmBridgeHubRouterByteFee; + type FeeAsset = xcm_config::bridging::XcmBridgeHubRouterFeeAssetId; +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime @@ -851,6 +883,9 @@ construct_runtime!( Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 41, Proxy: pallet_proxy::{Pallet, Call, Storage, Event} = 42, + // Bridge utilities. + ToPolkadotXcmRouter: pallet_xcm_bridge_hub_router::::{Pallet, Storage, Call} = 43, + // The main stage. Assets: pallet_assets::::{Pallet, Call, Storage, Event} = 50, Uniques: pallet_uniques::{Pallet, Call, Storage, Event} = 51, @@ -924,6 +959,7 @@ mod benches { [pallet_timestamp, Timestamp] [pallet_collator_selection, CollatorSelection] [cumulus_pallet_xcmp_queue, XcmpQueue] + [pallet_xcm_bridge_hub_router, XcmBridgeHubRouterBench] // XCM [pallet_xcm, PolkadotXcm] // NOTE: Make sure you point to the individual modules below. @@ -1163,6 +1199,7 @@ impl_runtime_apis! { use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; + use pallet_xcm_bridge_hub_router::benchmarking::Pallet as XcmBridgeHubRouterBench; // This is defined once again in dispatch_benchmark, because list_benchmarks! // and add_benchmarks! are macros exported by define_benchmarks! macros and those types @@ -1206,6 +1243,25 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} + use pallet_xcm_bridge_hub_router::benchmarking::{ + Pallet as XcmBridgeHubRouterBench, + Config as XcmBridgeHubRouterConfig, + }; + + impl XcmBridgeHubRouterConfig for Runtime { + fn make_congested() { + cumulus_pallet_xcmp_queue::bridging::suspend_channel_for_benchmarks::( + xcm_config::bridging::BridgeHubKusamaParaId::get().into() + ); + } + fn ensure_bridged_target_destination() -> MultiLocation { + ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests( + xcm_config::bridging::BridgeHubKusamaParaId::get().into() + ); + xcm_config::bridging::AssetHubPolkadot::get() + } + } + use xcm::latest::prelude::*; use xcm_config::{KsmLocation, MaxAssetsIntoHolding}; use pallet_xcm_benchmarks::asset_instance_from; @@ -1279,7 +1335,10 @@ impl_runtime_apis! { } fn universal_alias() -> Result<(MultiLocation, Junction), BenchmarkError> { - Err(BenchmarkError::Skip) + match xcm_config::bridging::BridgingBenchmarksHelper::prepare_universal_alias() { + Some(alias) => Ok(alias), + None => Err(BenchmarkError::Skip) + } } fn transact_origin_and_runtime_call() -> Result<(MultiLocation, RuntimeCall), BenchmarkError> { diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/mod.rs index 281c013b3372..a857dc620622 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/mod.rs @@ -33,6 +33,7 @@ pub mod pallet_timestamp; pub mod pallet_uniques; pub mod pallet_utility; pub mod pallet_xcm; +pub mod pallet_xcm_bridge_hub_router; pub mod paritydb_weights; pub mod rocksdb_weights; pub mod xcm; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/pallet_xcm_bridge_hub_router.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/pallet_xcm_bridge_hub_router.rs new file mode 100644 index 000000000000..8fc21a35bd61 --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/pallet_xcm_bridge_hub_router.rs @@ -0,0 +1,118 @@ +// 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 . + +//! Autogenerated weights for `pallet_xcm_bridge_hub_router` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-08-17, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-aahe6cbd-project-238-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-kusama-dev")`, DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot-parachain +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/cumulus/.git/.artifacts/bench.json +// --pallet=pallet_xcm_bridge_hub_router +// --chain=asset-hub-kusama-dev +// --header=./file_header.txt +// --output=./parachains/runtimes/assets/asset-hub-kusama/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_xcm_bridge_hub_router`. +pub struct WeightInfo(PhantomData); +impl pallet_xcm_bridge_hub_router::WeightInfo for WeightInfo { + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmpQueue::InboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::InboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ToPolkadotXcmRouter::Bridge` (r:1 w:1) + /// Proof: `ToPolkadotXcmRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: 512, mode: `MaxEncodedLen`) + fn on_initialize_when_non_congested() -> Weight { + // Proof Size summary in bytes: + // Measured: `159` + // Estimated: `1644` + // Minimum execution time: 9_957_000 picoseconds. + Weight::from_parts(10_409_000, 0) + .saturating_add(Weight::from_parts(0, 1644)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn on_initialize_when_congested() -> Weight { + // Proof Size summary in bytes: + // Measured: `111` + // Estimated: `1596` + // Minimum execution time: 3_274_000 picoseconds. + Weight::from_parts(3_445_000, 0) + .saturating_add(Weight::from_parts(0, 1596)) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: `ToPolkadotXcmRouter::Bridge` (r:1 w:1) + /// Proof: `ToPolkadotXcmRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: 512, mode: `MaxEncodedLen`) + fn report_bridge_status() -> Weight { + // Proof Size summary in bytes: + // Measured: `83` + // Estimated: `1502` + // Minimum execution time: 11_282_000 picoseconds. + Weight::from_parts(11_712_000, 0) + .saturating_add(Weight::from_parts(0, 1502)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) + /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x0973fe64c85043ba1c965cbc38eb63c7` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x0973fe64c85043ba1c965cbc38eb63c7` (r:1 w:0) + /// Storage: `ToPolkadotXcmRouter::Bridge` (r:1 w:1) + /// Proof: `ToPolkadotXcmRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: 512, mode: `MaxEncodedLen`) + /// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) + /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) + /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) + /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParachainSystem::RelevantMessagingState` (r:1 w:0) + /// Proof: `ParachainSystem::RelevantMessagingState` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:1) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmpQueue::OutboundXcmpMessages` (r:0 w:1) + /// Proof: `XcmpQueue::OutboundXcmpMessages` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn send_message() -> Weight { + // Proof Size summary in bytes: + // Measured: `355` + // Estimated: `3820` + // Minimum execution time: 49_615_000 picoseconds. + Weight::from_parts(50_859_000, 0) + .saturating_add(Weight::from_parts(0, 3820)) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(4)) + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/xcm/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/xcm/mod.rs index 9aff4902d15b..4bc3209a4e0f 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/xcm/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/xcm/mod.rs @@ -220,7 +220,7 @@ impl XcmWeightInfo for AssetHubKusamaXcmWeight { XcmGeneric::::clear_transact_status() } fn universal_origin(_: &Junction) -> Weight { - Weight::MAX + XcmGeneric::::universal_origin() } fn export_message(_: &NetworkId, _: &Junctions, _: &Xcm<()>) -> Weight { Weight::MAX diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/xcm/pallet_xcm_benchmarks_generic.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/xcm/pallet_xcm_benchmarks_generic.rs index 625549ecfccf..6ab849e50a65 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/xcm/pallet_xcm_benchmarks_generic.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/weights/xcm/pallet_xcm_benchmarks_generic.rs @@ -312,6 +312,16 @@ impl WeightInfo { // Minimum execution time: 2_886_000 picoseconds. Weight::from_parts(3_015_000, 0) } + // Storage: `ParachainInfo::ParachainId` (r:1 w:0) + // Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + pub fn universal_origin() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `1489` + // Minimum execution time: 5_088_000 picoseconds. + Weight::from_parts(5_253_000, 1489) + .saturating_add(T::DbWeight::get().reads(1)) + } pub fn set_fees_mode() -> Weight { // Proof Size summary in bytes: // Measured: `0` diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs index 0c197598f889..6ec716a4e453 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/src/xcm_config.rs @@ -14,11 +14,11 @@ // limitations under the License. use super::{ - AccountId, AllPalletsWithSystem, Assets, Authorship, Balance, Balances, ParachainInfo, - ParachainSystem, PolkadotXcm, PoolAssets, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, + AccountId, AllPalletsWithSystem, Assets, Authorship, Balance, Balances, ForeignAssets, + ForeignAssetsInstance, ParachainInfo, ParachainSystem, PolkadotXcm, PoolAssets, Runtime, + RuntimeCall, RuntimeEvent, RuntimeOrigin, ToPolkadotXcmRouter, TransactionByteFee, TrustBackedAssetsInstance, WeightToFee, XcmpQueue, }; -use crate::ForeignAssets; use assets_common::{ local_and_foreign_assets::MatchesLocalAndForeignAssetsMultiLocation, matching::{ @@ -27,11 +27,14 @@ use assets_common::{ }; use frame_support::{ match_types, parameter_types, - traits::{ConstU32, Contains, Everything, Nothing, PalletInfoAccess}, + traits::{ConstU32, Contains, Everything, EverythingBut, Nothing, PalletInfoAccess}, }; use frame_system::EnsureRoot; use pallet_xcm::XcmPassthrough; -use parachains_common::{impls::ToStakingPot, xcm_config::AssetFeeAsExistentialDepositMultiplier}; +use parachains_common::{ + impls::ToStakingPot, + xcm_config::{AllowUnpaidTransactsFrom, AssetFeeAsExistentialDepositMultiplier}, +}; use polkadot_parachain_primitives::primitives::Sibling; use sp_runtime::traits::ConvertInto; use xcm::latest::prelude::*; @@ -39,11 +42,11 @@ use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, DenyReserveTransferToRelayChain, DenyThenTry, DescribeAllTerminal, DescribeFamily, - EnsureXcmOrigin, FungiblesAdapter, HashedDescription, IsConcrete, LocalMint, NativeAsset, - NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, - SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, - WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, + EnsureXcmOrigin, FungiblesAdapter, GlobalConsensusParachainConvertsFor, HashedDescription, + IsConcrete, LocalMint, NativeAsset, NoChecking, ParentAsSuperuser, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, }; use xcm_executor::{traits::WithOriginFilter, XcmExecutor}; @@ -80,6 +83,9 @@ pub type LocationToAccountId = ( AccountId32Aliases, // Foreign locations alias into accounts according to a hash of their standard description. HashedDescription>, + // Different global consensus parachain sovereign account. + // (Used for over-bridge transfers and reserve processing) + GlobalConsensusParachainConvertsFor, ); /// Means for transacting the native currency on this chain. @@ -249,6 +255,14 @@ impl Contains for SafeCallFilter { } } + // Allow to change dedicated storage items (called by governance-like) + match call { + RuntimeCall::System(frame_system::Call::set_storage { items }) + if items.iter().all(|(k, _)| k.eq(&bridging::XcmBridgeHubRouterByteFee::key())) => + return true, + _ => (), + }; + matches!( call, RuntimeCall::PolkadotXcm(pallet_xcm::Call::force_xcm_version { .. }) | @@ -433,6 +447,8 @@ impl Contains for SafeCallFilter { pallet_uniques::Call::set_collection_max_supply { .. } | pallet_uniques::Call::set_price { .. } | pallet_uniques::Call::buy_item { .. } + ) | RuntimeCall::ToPolkadotXcmRouter( + pallet_xcm_bridge_hub_router::Call::report_bridge_status { .. } ) ) } @@ -455,6 +471,8 @@ pub type Barrier = TrailingSetTopicAsId< AllowExplicitUnpaidExecutionFrom, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, + // Allows Transacts with `report_bridge_status` from sibling BridgeHub. + bridging::AllowUnpaidStatusReportsFromSiblingBridgeHub, ), UniversalLocation, ConstU32<8>, @@ -463,6 +481,7 @@ pub type Barrier = TrailingSetTopicAsId< >, >; +/// Multiplier used for dedicated `TakeFirstAssetTrader` with `Assets` instance. pub type AssetFeeAsExistentialDepositMultiplierFeeCharger = AssetFeeAsExistentialDepositMultiplier< Runtime, WeightToFee, @@ -470,16 +489,25 @@ pub type AssetFeeAsExistentialDepositMultiplierFeeCharger = AssetFeeAsExistentia TrustBackedAssetsInstance, >; +/// Multiplier used for dedicated `TakeFirstAssetTrader` with `ForeignAssets` instance. +pub type ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger = + AssetFeeAsExistentialDepositMultiplier< + Runtime, + WeightToFee, + pallet_assets::BalanceToAssetBalance, + ForeignAssetsInstance, + >; + pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { type RuntimeCall = RuntimeCall; type XcmSender = XcmRouter; type AssetTransactor = AssetTransactors; type OriginConverter = XcmOriginToTransactDispatchOrigin; - // Asset Hub Kusama does not recognize a reserve location for any asset. This does not prevent - // Asset Hub acting _as_ a reserve location for KSM and assets created under `pallet-assets`. - // For KSM, users must use teleport where allowed (e.g. with the Relay Chain). - type IsReserve = (); + // Asset Hub trusts only particular configured bridge locations as reserve locations. + // Asset Hub may _act_ as a reserve location for KSM and assets created under `pallet-assets`. + // Users must use teleport where allowed (e.g. KSM with the Relay Chain). + type IsReserve = bridging::IsTrustedBridgedReserveLocationForConcreteAsset; // We allow: // - teleportation of KSM // - teleportation of sibling parachain's assets (as ForeignCreators) @@ -496,6 +524,8 @@ impl xcm_executor::Config for XcmConfig { >; type Trader = ( UsingComponents>, + // This trader allows to pay with `is_sufficient=true` "Trust Backed" assets from dedicated + // `pallet_assets` instance - `Assets`. cumulus_primitives_utility::TakeFirstAssetTrader< AccountId, AssetFeeAsExistentialDepositMultiplierFeeCharger, @@ -507,6 +537,19 @@ impl xcm_executor::Config for XcmConfig { XcmAssetFeesReceiver, >, >, + // This trader allows to pay with `is_sufficient=true` "Foreign" assets from dedicated + // `pallet_assets` instance - `ForeignAssets`. + cumulus_primitives_utility::TakeFirstAssetTrader< + AccountId, + ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger, + ForeignAssetsConvertedConcreteId, + ForeignAssets, + cumulus_primitives_utility::XcmFeesTo32ByteAccount< + ForeignFungiblesTransactor, + AccountId, + XcmAssetFeesReceiver, + >, + >, ); type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; @@ -516,9 +559,10 @@ impl xcm_executor::Config for XcmConfig { type MaxAssetsIntoHolding = MaxAssetsIntoHolding; type AssetLocker = (); type AssetExchanger = (); + // TODO:check-parameter: change and assert in tests when (https://github.com/paritytech/polkadot/pull/7005) merged type FeeManager = (); type MessageExporter = (); - type UniversalAliases = Nothing; + type UniversalAliases = bridging::UniversalAliases; type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; @@ -528,13 +572,21 @@ impl xcm_executor::Config for XcmConfig { /// Forms the basis for local origins sending/executing XCMs. pub type LocalOriginToLocation = SignedToAccountId32; -/// The means for routing XCM messages which are not for local execution into the right message -/// queues. -pub type XcmRouter = WithUniqueTopic<( +/// For routing XCM messages which do not cross local consensus boundary. +type LocalXcmRouter = ( // Two routers - use UMP to communicate with the relay chain: cumulus_primitives_utility::ParentAsUmp, // ..and XCMP to communicate with the sibling chains. XcmpQueue, +); + +/// The means for routing XCM messages which are not for local execution into the right message +/// queues. +pub type XcmRouter = WithUniqueTopic<( + LocalXcmRouter, + // Router which wraps and sends xcm to BridgeHub to be delivered to the Polkadot + // GlobalConsensus + ToPolkadotXcmRouter, )>; #[cfg(feature = "runtime-benchmarks")] @@ -554,7 +606,9 @@ impl pallet_xcm::Config for Runtime { type XcmExecuteFilter = Nothing; type XcmExecutor = XcmExecutor; type XcmTeleportFilter = Everything; - type XcmReserveTransferFilter = Everything; + // Allow reserve based transfer to everywhere except for bridging, here we strictly check what + // assets are allowed. + type XcmReserveTransferFilter = EverythingBut; type Weigher = WeightInfoBounds< crate::weights::xcm::AssetHubKusamaXcmWeight, RuntimeCall, @@ -624,3 +678,143 @@ where sp_std::boxed::Box::new(Self::asset_id(asset_id)) } } + +/// All configuration related to bridging +pub mod bridging { + use super::*; + use assets_common::{matching, matching::*}; + use parachains_common::xcm_config::LocationFilter; + use sp_std::collections::btree_set::BTreeSet; + + parameter_types! { + pub BridgeHubKusamaParaId: u32 = 1002; + pub BridgeHubKusama: MultiLocation = MultiLocation::new(1, X1(Parachain(BridgeHubKusamaParaId::get()))); + pub BridgeHubKusamaWithBridgeHubPolkadotInstance: MultiLocation = MultiLocation::new( + 1, + X2( + Parachain(BridgeHubKusamaParaId::get()), + PalletInstance(bp_bridge_hub_kusama::WITH_BRIDGE_POLKADOT_MESSAGES_PALLET_INDEX) + ) + ); + pub const PolkadotNetwork: NetworkId = NetworkId::Polkadot; + pub AssetHubPolkadot: MultiLocation = MultiLocation::new(2, X2(GlobalConsensus(PolkadotNetwork::get()), Parachain(bp_asset_hub_polkadot::ASSET_HUB_POLKADOT_PARACHAIN_ID))); + pub DotLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(PolkadotNetwork::get()))); + + /// Router expects payment with this `AssetId`. + /// (`AssetId` has to be aligned with `BridgeTable`) + pub XcmBridgeHubRouterFeeAssetId: AssetId = KsmLocation::get().into(); + /// Price per byte - can be adjusted via governance `set_storage` call. + pub storage XcmBridgeHubRouterByteFee: Balance = TransactionByteFee::get(); + + /// Set up exporters configuration. + /// `Option` represents static "base fee" which is used for total delivery fee calculation. + pub BridgeTable: sp_std::vec::Vec<(NetworkId, LocationFilter, MultiLocation, Option)> = sp_std::vec![ + ( + PolkadotNetwork::get(), + LocationFilter::default() + // allow to bridge to AssetHubPolkadot + .add_equals(AssetHubPolkadot::get().interior.split_global().expect("invalid configuration for AssetHubPolkadot").1), + // and nothing else + BridgeHubKusama::get(), + // base delivery fee to local `BridgeHub` + Some(( + XcmBridgeHubRouterFeeAssetId::get(), + bp_asset_hub_kusama::BridgeHubKusamaBaseFeeInDots::get(), + ).into()) + ) + ]; + + /// Set up trusted bridged reserve locations. + /// Locations from which the runtime accepts reserved assets. + pub TrustedBridgedReserveLocations: sp_std::vec::Vec = sp_std::vec![ + // trust assets from AssetHubPolkadot + ( + AssetHubPolkadot::get(), + LocationFilter::default() + // allow receive DOT + .add_equals(DotLocation::get()) + // and nothing else + ) + ]; + + /// Allowed reserve transfer assets per destination. + /// Means that runtime allows to transfer reserve assets to these locations. + pub AllowedReserveTransferAssetsLocations: sp_std::vec::Vec = sp_std::vec![ + // allow to transfer assets to AssetHubPolkadot + ( + AssetHubPolkadot::get(), + LocationFilter::default() + // allow send only KSM + .add_equals(KsmLocation::get()) + // and nothing else + ) + ]; + + /// Universal aliases + pub UniversalAliases: BTreeSet<(MultiLocation, Junction)> = BTreeSet::from_iter( + sp_std::vec![ + (BridgeHubKusamaWithBridgeHubPolkadotInstance::get(), GlobalConsensus(PolkadotNetwork::get())) + ] + ); + + } + + impl Contains<(MultiLocation, Junction)> for UniversalAliases { + fn contains(alias: &(MultiLocation, Junction)) -> bool { + UniversalAliases::get().contains(alias) + } + } + + pub type FilteredNetworkExportTable = + parachains_common::xcm_config::FilteredNetworkExportTable; + + /// Reserve locations filter for `xcm_executor::Config::IsReserve`. + pub type IsTrustedBridgedReserveLocationForConcreteAsset = + matching::IsTrustedBridgedReserveLocationForConcreteAsset< + UniversalLocation, + TrustedBridgedReserveLocations, + >; + + /// Filter out those assets which are not allowed for bridged reserve based transfer. + /// Filter is made of (asset, location) and used by + /// `pallet_xcm::Config::XcmReserveTransferFilter`. + pub type DisallowForReserveTransfer = ExcludeOnlyForRemoteDestination< + UniversalLocation, + FilteredNetworkExportTable, + DisallowConcreteAssetUnless, + >; + + impl Contains for ToPolkadotXcmRouter { + fn contains(call: &RuntimeCall) -> bool { + matches!( + call, + RuntimeCall::ToPolkadotXcmRouter( + pallet_xcm_bridge_hub_router::Call::report_bridge_status { .. } + ) + ) + } + } + + /// Barrier for `pallet_xcm_bridge_hub_router::Pallet` to receive congestion statuses from + /// sibling BridgeHub. + pub type AllowUnpaidStatusReportsFromSiblingBridgeHub = + AllowUnpaidTransactsFrom>; + + /// Benchmarks helper for bridging configuration. + #[cfg(feature = "runtime-benchmarks")] + pub struct BridgingBenchmarksHelper; + + #[cfg(feature = "runtime-benchmarks")] + impl BridgingBenchmarksHelper { + pub fn prepare_universal_alias() -> Option<(MultiLocation, Junction)> { + let alias = UniversalAliases::get().into_iter().find_map(|(location, junction)| { + match BridgeHubKusamaWithBridgeHubPolkadotInstance::get().eq(&location) { + true => Some((location, junction)), + false => None, + } + }); + assert!(alias.is_some(), "we expect here BridgeHubKusama to Polkadot mapping at least"); + Some(alias.unwrap()) + } + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs index 7d49b56e461a..4608ff78106b 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-kusama/tests/tests.rs @@ -21,17 +21,21 @@ use asset_hub_kusama_runtime::xcm_config::{ AssetFeeAsExistentialDepositMultiplierFeeCharger, KsmLocation, TrustBackedAssetsPalletLocation, }; pub use asset_hub_kusama_runtime::{ - xcm_config::{CheckingAccount, ForeignCreatorsSovereignAccountOf, XcmConfig}, + xcm_config::{ + self, bridging, CheckingAccount, ForeignCreatorsSovereignAccountOf, LocationToAccountId, + XcmConfig, + }, AllPalletsWithoutSystem, AssetDeposit, Assets, Balances, ExistentialDeposit, ForeignAssets, ForeignAssetsInstance, MetadataDepositBase, MetadataDepositPerByte, ParachainSystem, Runtime, - RuntimeCall, RuntimeEvent, SessionKeys, System, TrustBackedAssetsInstance, + RuntimeCall, RuntimeEvent, SessionKeys, System, ToPolkadotXcmRouterInstance, + TrustBackedAssetsInstance, XcmpQueue, }; -use asset_test_utils::{CollatorSessionKeys, ExtBuilder}; +use asset_test_utils::{CollatorSessionKey, CollatorSessionKeys, ExtBuilder}; use codec::{Decode, Encode}; use cumulus_primitives_utility::ChargeWeightInFungibles; use frame_support::{ assert_noop, assert_ok, - traits::fungibles::InspectEnumerable, + traits::{fungibles::InspectEnumerable, Contains}, weights::{Weight, WeightToFee as WeightToFeeT}, }; use parachains_common::{ @@ -49,14 +53,18 @@ type AssetIdForTrustBackedAssetsConvert = type RuntimeHelper = asset_test_utils::RuntimeHelper; -fn collator_session_keys() -> CollatorSessionKeys { - CollatorSessionKeys::new( - AccountId::from(ALICE), - AccountId::from(ALICE), - SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) }, +fn collator_session_key(account: [u8; 32]) -> CollatorSessionKey { + CollatorSessionKey::new( + AccountId::from(account), + AccountId::from(account), + SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(account)) }, ) } +fn collator_session_keys() -> CollatorSessionKeys { + CollatorSessionKeys::default().add(collator_session_key(ALICE)) +} + #[test] fn test_asset_xcm_trader() { ExtBuilder::::default() @@ -632,3 +640,273 @@ asset_test_utils::include_create_and_manage_foreign_assets_for_local_consensus_p assert_eq!(ForeignAssets::asset_ids().collect::>().len(), 1); }) ); + +fn bridging_to_asset_hub_polkadot() -> asset_test_utils::test_cases_over_bridge::TestBridgingConfig +{ + asset_test_utils::test_cases_over_bridge::TestBridgingConfig { + bridged_network: bridging::PolkadotNetwork::get(), + local_bridge_hub_para_id: bridging::BridgeHubKusamaParaId::get(), + local_bridge_hub_location: bridging::BridgeHubKusama::get(), + bridged_target_location: bridging::AssetHubPolkadot::get(), + } +} + +#[test] +fn limited_reserve_transfer_assets_for_native_asset_over_bridge_works() { + asset_test_utils::test_cases_over_bridge::limited_reserve_transfer_assets_for_native_asset_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + XcmpQueue, + LocationToAccountId, + >( + collator_session_keys(), + ExistentialDeposit::get(), + AccountId::from(ALICE), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event), + _ => None, + } + }), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), + _ => None, + } + }), + bridging_to_asset_hub_polkadot, + WeightLimit::Unlimited, + Some(xcm_config::bridging::XcmBridgeHubRouterFeeAssetId::get()), + ) +} + +#[test] +fn receive_reserve_asset_deposited_dot_from_asset_hub_polkadot_works() { + const BLOCK_AUTHOR_ACCOUNT: [u8; 32] = [13; 32]; + asset_test_utils::test_cases_over_bridge::receive_reserve_asset_deposited_from_different_consensus_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + LocationToAccountId, + ForeignAssetsInstance, + >( + collator_session_keys().add(collator_session_key(BLOCK_AUTHOR_ACCOUNT)), + ExistentialDeposit::get(), + AccountId::from([73; 32]), + AccountId::from(BLOCK_AUTHOR_ACCOUNT), + // receiving DOTs + (MultiLocation { parents: 2, interior: X1(GlobalConsensus(Polkadot)) }, 1000000000000, 1_00_000_000), + bridging_to_asset_hub_polkadot, + (X1(PalletInstance(53)), GlobalConsensus(Polkadot), X1(Parachain(1000))) + ) +} + +/// Tests expected configuration of isolated `pallet_xcm::Config::XcmReserveTransferFilter`. +#[test] +fn xcm_reserve_transfer_filter_works() { + // prepare assets + let only_native_assets = || vec![MultiAsset::from((KsmLocation::get(), 1000))]; + let only_trust_backed_assets = || { + vec![MultiAsset::from(( + AssetIdForTrustBackedAssetsConvert::convert_back(&12345).unwrap(), + 2000, + ))] + }; + let only_sibling_foreign_assets = + || vec![MultiAsset::from((MultiLocation::new(1, X1(Parachain(12345))), 3000))]; + let only_different_global_consensus_foreign_assets = || { + vec![MultiAsset::from(( + MultiLocation::new(2, X2(GlobalConsensus(Polkadot), Parachain(12345))), + 4000, + ))] + }; + + // prepare destinations + let relaychain = MultiLocation::parent(); + let sibling_parachain = MultiLocation::new(1, X1(Parachain(54321))); + let different_global_consensus_parachain_other_than_asset_hub_polkadot = + MultiLocation::new(2, X2(GlobalConsensus(Polkadot), Parachain(12345))); + let bridged_asset_hub = bridging::AssetHubPolkadot::get(); + + // prepare expected test data sets: (destination, assets, expected_result) + let test_data = vec![ + (relaychain, only_native_assets(), true), + (relaychain, only_trust_backed_assets(), true), + (relaychain, only_sibling_foreign_assets(), true), + (relaychain, only_different_global_consensus_foreign_assets(), true), + (sibling_parachain, only_native_assets(), true), + (sibling_parachain, only_trust_backed_assets(), true), + (sibling_parachain, only_sibling_foreign_assets(), true), + (sibling_parachain, only_different_global_consensus_foreign_assets(), true), + ( + different_global_consensus_parachain_other_than_asset_hub_polkadot, + only_native_assets(), + false, + ), + ( + different_global_consensus_parachain_other_than_asset_hub_polkadot, + only_trust_backed_assets(), + false, + ), + ( + different_global_consensus_parachain_other_than_asset_hub_polkadot, + only_sibling_foreign_assets(), + false, + ), + ( + different_global_consensus_parachain_other_than_asset_hub_polkadot, + only_different_global_consensus_foreign_assets(), + false, + ), + (bridged_asset_hub, only_native_assets(), true), + (bridged_asset_hub, only_trust_backed_assets(), false), + (bridged_asset_hub, only_sibling_foreign_assets(), false), + (bridged_asset_hub, only_different_global_consensus_foreign_assets(), false), + ]; + + // lets test filter with test data + ExtBuilder::::default() + .with_collators(collator_session_keys().collators()) + .with_session_keys(collator_session_keys().session_keys()) + .build() + .execute_with(|| { + type XcmReserveTransferFilter = + ::XcmReserveTransferFilter; + for (dest, assets, expected_result) in test_data { + assert_eq!( + expected_result, + XcmReserveTransferFilter::contains(&(dest, assets.clone())), + "expected_result: {} for dest: {:?} and assets: {:?}", + expected_result, + dest, + assets + ); + } + }) +} + +#[test] +fn change_xcm_bridge_hub_router_byte_fee_by_governance_works() { + asset_test_utils::test_cases::change_storage_constant_by_governance_works::< + Runtime, + bridging::XcmBridgeHubRouterByteFee, + Balance, + >( + collator_session_keys(), + 1000, + Box::new(|call| RuntimeCall::System(call).encode()), + || { + ( + bridging::XcmBridgeHubRouterByteFee::key().to_vec(), + bridging::XcmBridgeHubRouterByteFee::get(), + ) + }, + |old_value| { + if let Some(new_value) = old_value.checked_add(1) { + new_value + } else { + old_value.checked_sub(1).unwrap() + } + }, + ) +} + +#[test] +fn test_report_bridge_status_call_compatibility() { + // if this test fails, make sure `bp_asset_hub_kusama` has valid encoding + assert_eq!( + RuntimeCall::ToPolkadotXcmRouter( + pallet_xcm_bridge_hub_router::Call::report_bridge_status { + bridge_id: Default::default(), + is_congested: true, + } + ) + .encode(), + bp_asset_hub_kusama::Call::ToPolkadotXcmRouter( + bp_asset_hub_kusama::XcmBridgeHubRouterCall::report_bridge_status { + bridge_id: Default::default(), + is_congested: true, + } + ) + .encode() + ) +} + +#[test] +fn report_bridge_status_from_xcm_bridge_router_works() { + asset_test_utils::test_cases_over_bridge::report_bridge_status_from_xcm_bridge_router_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + XcmpQueue, + LocationToAccountId, + ToPolkadotXcmRouterInstance, + >( + collator_session_keys(), + ExistentialDeposit::get(), + AccountId::from(ALICE), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event), + _ => None, + } + }), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), + _ => None, + } + }), + bridging_to_asset_hub_polkadot, + WeightLimit::Unlimited, + Some(xcm_config::bridging::XcmBridgeHubRouterFeeAssetId::get()), + || { + sp_std::vec![Transact { + origin_kind: OriginKind::Xcm, + require_weight_at_most: + bp_asset_hub_kusama::XcmBridgeHubRouterTransactCallMaxWeight::get(), + call: bp_asset_hub_kusama::Call::ToPolkadotXcmRouter( + bp_asset_hub_kusama::XcmBridgeHubRouterCall::report_bridge_status { + bridge_id: Default::default(), + is_congested: true, + } + ) + .encode() + .into(), + }] + .into() + }, + || { + sp_std::vec![Transact { + origin_kind: OriginKind::Xcm, + require_weight_at_most: + bp_asset_hub_kusama::XcmBridgeHubRouterTransactCallMaxWeight::get(), + call: bp_asset_hub_kusama::Call::ToPolkadotXcmRouter( + bp_asset_hub_kusama::XcmBridgeHubRouterCall::report_bridge_status { + bridge_id: Default::default(), + is_congested: false, + } + ) + .encode() + .into(), + }] + .into() + }, + ) +} + +#[test] +fn check_sane_weight_report_bridge_status() { + use pallet_xcm_bridge_hub_router::WeightInfo; + let actual = >::WeightInfo::report_bridge_status(); + let max_weight = bp_asset_hub_kusama::XcmBridgeHubRouterTransactCallMaxWeight::get(); + assert!( + actual.all_lte(max_weight), + "max_weight: {:?} should be adjusted to actual {:?}", + max_weight, + actual + ); +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/Cargo.toml index 4a6ce4cbf593..2c94f4fe5574 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/Cargo.toml @@ -66,7 +66,7 @@ cumulus-pallet-dmp-queue = { path = "../../../../pallets/dmp-queue", default-fea cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook",] } cumulus-pallet-session-benchmarking = { path = "../../../../pallets/session-benchmarking", default-features = false} cumulus-pallet-xcm = { path = "../../../../pallets/xcm", default-features = false } -cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false } +cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false, features = ["bridging"] } cumulus-primitives-core = { path = "../../../../primitives/core", default-features = false } cumulus-primitives-utility = { path = "../../../../primitives/utility", default-features = false } pallet-collator-selection = { path = "../../../../pallets/collator-selection", default-features = false } @@ -74,6 +74,12 @@ parachain-info = { path = "../../../pallets/parachain-info", default-features = parachains-common = { path = "../../../common", default-features = false } assets-common = { path = "../common", default-features = false } +# Bridges +pallet-xcm-bridge-hub-router = { path = "../../../../../bridges/modules/xcm-bridge-hub-router", default-features = false } +bp-asset-hub-polkadot = { path = "../../../../../bridges/primitives/chain-asset-hub-polkadot", default-features = false } +bp-asset-hub-kusama = { path = "../../../../../bridges/primitives/chain-asset-hub-kusama", default-features = false } +bp-bridge-hub-polkadot = { path = "../../../../../bridges/primitives/chain-bridge-hub-polkadot", default-features = false } + [dev-dependencies] hex-literal = "0.4.1" asset-test-utils = { path = "../test-utils" } @@ -105,6 +111,7 @@ runtime-benchmarks = [ "pallet-uniques/runtime-benchmarks", "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", + "pallet-xcm-bridge-hub-router/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "parachains-common/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", @@ -137,6 +144,7 @@ try-runtime = [ "pallet-transaction-payment/try-runtime", "pallet-uniques/try-runtime", "pallet-utility/try-runtime", + "pallet-xcm-bridge-hub-router/try-runtime", "pallet-xcm/try-runtime", "parachain-info/try-runtime", "polkadot-runtime-common/try-runtime", @@ -144,6 +152,9 @@ try-runtime = [ ] std = [ "assets-common/std", + "bp-asset-hub-kusama/std", + "bp-asset-hub-polkadot/std", + "bp-bridge-hub-polkadot/std", "codec/std", "cumulus-pallet-aura-ext/std", "cumulus-pallet-dmp-queue/std", @@ -178,6 +189,7 @@ std = [ "pallet-uniques/std", "pallet-utility/std", "pallet-xcm-benchmarks?/std", + "pallet-xcm-bridge-hub-router/std", "pallet-xcm/std", "parachain-info/std", "parachains-common/std", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs index 0051af21f9a3..725f9f1aee0c 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/lib.rs @@ -569,7 +569,6 @@ parameter_types! { } impl cumulus_pallet_xcmp_queue::Config for Runtime { - type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; type RuntimeEvent = RuntimeEvent; type XcmExecutor = XcmExecutor; type ChannelInfo = ParachainSystem; @@ -581,6 +580,7 @@ impl cumulus_pallet_xcmp_queue::Config for Runtime { >; type ControllerOriginConverter = XcmOriginToTransactDispatchOrigin; type PriceForSiblingDelivery = (); + type WeightInfo = weights::cumulus_pallet_xcmp_queue::WeightInfo; } impl cumulus_pallet_dmp_queue::Config for Runtime { @@ -729,6 +729,38 @@ impl pallet_nfts::Config for Runtime { type Helper = (); } +/// XCM router instance to BridgeHub with bridging capabilities for `Kusama` global consensus with +/// dynamic fees and back-pressure. +pub type ToKusamaXcmRouterInstance = pallet_assets::Instance1; +impl pallet_xcm_bridge_hub_router::Config for Runtime { + type WeightInfo = weights::pallet_xcm_bridge_hub_router::WeightInfo; + + type UniversalLocation = xcm_config::UniversalLocation; + type BridgedNetworkId = xcm_config::bridging::KusamaNetwork; + type Bridges = xcm_config::bridging::FilteredNetworkExportTable; + + #[cfg(not(feature = "runtime-benchmarks"))] + type BridgeHubOrigin = + EnsureXcm>; + #[cfg(feature = "runtime-benchmarks")] + type BridgeHubOrigin = EitherOfDiverse< + // for running benchmarks + EnsureRoot, + // for running tests with `--feature runtime-benchmarks` + EnsureXcm>, + >; + + type ToBridgeHubSender = XcmpQueue; + type WithBridgeHubChannel = + cumulus_pallet_xcmp_queue::bridging::InAndOutXcmpChannelStatusProvider< + xcm_config::bridging::BridgeHubPolkadotParaId, + Runtime, + >; + + type ByteFee = xcm_config::bridging::XcmBridgeHubRouterByteFee; + type FeeAsset = xcm_config::bridging::XcmBridgeHubRouterFeeAssetId; +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime @@ -765,6 +797,9 @@ construct_runtime!( Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 41, Proxy: pallet_proxy::{Pallet, Call, Storage, Event} = 42, + // Bridge utilities. + ToKusamaXcmRouter: pallet_xcm_bridge_hub_router::::{Pallet, Storage, Call} = 43, + // The main stage. Assets: pallet_assets::::{Pallet, Call, Storage, Event} = 50, Uniques: pallet_uniques::{Pallet, Call, Storage, Event} = 51, @@ -828,6 +863,7 @@ mod benches { [pallet_timestamp, Timestamp] [pallet_collator_selection, CollatorSelection] [cumulus_pallet_xcmp_queue, XcmpQueue] + [pallet_xcm_bridge_hub_router, XcmBridgeHubRouterBench] // XCM [pallet_xcm, PolkadotXcm] // NOTE: Make sure you point to the individual modules below. @@ -1043,6 +1079,7 @@ impl_runtime_apis! { use frame_support::traits::StorageInfoTrait; use frame_system_benchmarking::Pallet as SystemBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; + use pallet_xcm_bridge_hub_router::benchmarking::Pallet as XcmBridgeHubRouterBench; // This is defined once again in dispatch_benchmark, because list_benchmarks! // and add_benchmarks! are macros exported by define_benchmarks! macros and those types @@ -1085,6 +1122,25 @@ impl_runtime_apis! { use cumulus_pallet_session_benchmarking::Pallet as SessionBench; impl cumulus_pallet_session_benchmarking::Config for Runtime {} + use pallet_xcm_bridge_hub_router::benchmarking::{ + Pallet as XcmBridgeHubRouterBench, + Config as XcmBridgeHubRouterConfig, + }; + + impl XcmBridgeHubRouterConfig for Runtime { + fn make_congested() { + cumulus_pallet_xcmp_queue::bridging::suspend_channel_for_benchmarks::( + xcm_config::bridging::BridgeHubPolkadotParaId::get().into() + ); + } + fn ensure_bridged_target_destination() -> MultiLocation { + ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests( + xcm_config::bridging::BridgeHubPolkadotParaId::get().into() + ); + xcm_config::bridging::AssetHubKusama::get() + } + } + use xcm::latest::prelude::*; use xcm_config::{DotLocation, MaxAssetsIntoHolding}; use pallet_xcm_benchmarks::asset_instance_from; @@ -1158,7 +1214,10 @@ impl_runtime_apis! { } fn universal_alias() -> Result<(MultiLocation, Junction), BenchmarkError> { - Err(BenchmarkError::Skip) + match xcm_config::bridging::BridgingBenchmarksHelper::prepare_universal_alias() { + Some(alias) => Ok(alias), + None => Err(BenchmarkError::Skip) + } } fn transact_origin_and_runtime_call() -> Result<(MultiLocation, RuntimeCall), BenchmarkError> { diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/mod.rs index 3eb3b925e651..18255317e233 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/mod.rs @@ -30,6 +30,7 @@ pub mod pallet_timestamp; pub mod pallet_uniques; pub mod pallet_utility; pub mod pallet_xcm; +pub mod pallet_xcm_bridge_hub_router; pub mod paritydb_weights; pub mod rocksdb_weights; pub mod xcm; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/pallet_xcm_bridge_hub_router.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/pallet_xcm_bridge_hub_router.rs new file mode 100644 index 000000000000..2fdc9747f81f --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/pallet_xcm_bridge_hub_router.rs @@ -0,0 +1,118 @@ +// 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 . + +//! Autogenerated weights for `pallet_xcm_bridge_hub_router` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-08-17, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-aahe6cbd-project-238-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-polkadot-dev")`, DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot-parachain +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/builds/parity/mirrors/cumulus/.git/.artifacts/bench.json +// --pallet=pallet_xcm_bridge_hub_router +// --chain=asset-hub-polkadot-dev +// --header=./file_header.txt +// --output=./parachains/runtimes/assets/asset-hub-polkadot/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_xcm_bridge_hub_router`. +pub struct WeightInfo(PhantomData); +impl pallet_xcm_bridge_hub_router::WeightInfo for WeightInfo { + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmpQueue::InboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::InboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ToKusamaXcmRouter::Bridge` (r:1 w:1) + /// Proof: `ToKusamaXcmRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: 512, mode: `MaxEncodedLen`) + fn on_initialize_when_non_congested() -> Weight { + // Proof Size summary in bytes: + // Measured: `193` + // Estimated: `1678` + // Minimum execution time: 9_963_000 picoseconds. + Weight::from_parts(10_410_000, 0) + .saturating_add(Weight::from_parts(0, 1678)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + fn on_initialize_when_congested() -> Weight { + // Proof Size summary in bytes: + // Measured: `111` + // Estimated: `1596` + // Minimum execution time: 3_322_000 picoseconds. + Weight::from_parts(3_513_000, 0) + .saturating_add(Weight::from_parts(0, 1596)) + .saturating_add(T::DbWeight::get().reads(1)) + } + /// Storage: `ToKusamaXcmRouter::Bridge` (r:1 w:1) + /// Proof: `ToKusamaXcmRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: 512, mode: `MaxEncodedLen`) + fn report_bridge_status() -> Weight { + // Proof Size summary in bytes: + // Measured: `117` + // Estimated: `1502` + // Minimum execution time: 11_296_000 picoseconds. + Weight::from_parts(11_778_000, 0) + .saturating_add(Weight::from_parts(0, 1502)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) + /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x0973fe64c85043ba1c965cbc38eb63c7` (r:1 w:0) + /// Proof: UNKNOWN KEY `0x0973fe64c85043ba1c965cbc38eb63c7` (r:1 w:0) + /// Storage: `ToKusamaXcmRouter::Bridge` (r:1 w:1) + /// Proof: `ToKusamaXcmRouter::Bridge` (`max_values`: Some(1), `max_size`: Some(17), added: 512, mode: `MaxEncodedLen`) + /// Storage: `PolkadotXcm::SupportedVersion` (r:1 w:0) + /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::VersionDiscoveryQueue` (r:1 w:1) + /// Proof: `PolkadotXcm::VersionDiscoveryQueue` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `PolkadotXcm::SafeXcmVersion` (r:1 w:0) + /// Proof: `PolkadotXcm::SafeXcmVersion` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `ParachainSystem::RelevantMessagingState` (r:1 w:0) + /// Proof: `ParachainSystem::RelevantMessagingState` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:1) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: None, mode: `Measured`) + /// Storage: `XcmpQueue::OutboundXcmpMessages` (r:0 w:1) + /// Proof: `XcmpQueue::OutboundXcmpMessages` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn send_message() -> Weight { + // Proof Size summary in bytes: + // Measured: `355` + // Estimated: `3820` + // Minimum execution time: 50_336_000 picoseconds. + Weight::from_parts(51_994_000, 0) + .saturating_add(Weight::from_parts(0, 3820)) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(4)) + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/xcm/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/xcm/mod.rs index 55fed809e2b7..6a525df07cf1 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/xcm/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/xcm/mod.rs @@ -220,7 +220,7 @@ impl XcmWeightInfo for AssetHubPolkadotXcmWeight { XcmGeneric::::clear_transact_status() } fn universal_origin(_: &Junction) -> Weight { - Weight::MAX + XcmGeneric::::universal_origin() } fn export_message(_: &NetworkId, _: &Junctions, _: &Xcm<()>) -> Weight { Weight::MAX diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/xcm/pallet_xcm_benchmarks_generic.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/xcm/pallet_xcm_benchmarks_generic.rs index 061992691a60..961857553da3 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/xcm/pallet_xcm_benchmarks_generic.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/weights/xcm/pallet_xcm_benchmarks_generic.rs @@ -312,6 +312,16 @@ impl WeightInfo { // Minimum execution time: 2_845_000 picoseconds. Weight::from_parts(2_970_000, 0) } + // Storage: `ParachainInfo::ParachainId` (r:1 w:0) + // Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + pub fn universal_origin() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `1489` + // Minimum execution time: 4_942_000 picoseconds. + Weight::from_parts(5_195_000, 1489) + .saturating_add(T::DbWeight::get().reads(1)) + } pub fn set_fees_mode() -> Weight { // Proof Size summary in bytes: // Measured: `0` diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs index 65cf62a610f4..c3610656e851 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/src/xcm_config.rs @@ -16,18 +16,22 @@ use super::{ AccountId, AllPalletsWithSystem, Assets, Authorship, Balance, Balances, ForeignAssets, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, - TrustBackedAssetsInstance, WeightToFee, XcmpQueue, + ToKusamaXcmRouter, TransactionByteFee, TrustBackedAssetsInstance, WeightToFee, XcmpQueue, }; +use crate::ForeignAssetsInstance; use assets_common::matching::{ FromSiblingParachain, IsForeignConcreteAsset, StartsWith, StartsWithExplicitGlobalConsensus, }; use frame_support::{ match_types, parameter_types, - traits::{ConstU32, Contains, Everything, Nothing, PalletInfoAccess}, + traits::{ConstU32, Contains, Everything, EverythingBut, Nothing, PalletInfoAccess}, }; use frame_system::EnsureRoot; use pallet_xcm::XcmPassthrough; -use parachains_common::{impls::ToStakingPot, xcm_config::AssetFeeAsExistentialDepositMultiplier}; +use parachains_common::{ + impls::ToStakingPot, + xcm_config::{AllowUnpaidTransactsFrom, AssetFeeAsExistentialDepositMultiplier}, +}; use polkadot_parachain_primitives::primitives::Sibling; use sp_runtime::traits::ConvertInto; use xcm::latest::prelude::*; @@ -35,11 +39,11 @@ use xcm_builder::{ AccountId32Aliases, AllowExplicitUnpaidExecutionFrom, AllowKnownQueryResponses, AllowSubscriptionsFrom, AllowTopLevelPaidExecutionFrom, CurrencyAdapter, DenyReserveTransferToRelayChain, DenyThenTry, DescribeFamily, DescribePalletTerminal, - EnsureXcmOrigin, FungiblesAdapter, HashedDescription, IsConcrete, LocalMint, NativeAsset, - NoChecking, ParentAsSuperuser, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, - SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, - SovereignSignedViaLocation, TakeWeightCredit, TrailingSetTopicAsId, UsingComponents, - WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, + EnsureXcmOrigin, FungiblesAdapter, GlobalConsensusParachainConvertsFor, HashedDescription, + IsConcrete, LocalMint, NativeAsset, NoChecking, ParentAsSuperuser, ParentIsPreset, + RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, + SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeWeightCredit, + TrailingSetTopicAsId, UsingComponents, WeightInfoBounds, WithComputedOrigin, WithUniqueTopic, }; use xcm_executor::{traits::WithOriginFilter, XcmExecutor}; @@ -70,6 +74,9 @@ pub type LocationToAccountId = ( // Foreign chain account alias into local accounts according to a hash of their standard // description. HashedDescription>, + // Different global consensus parachain sovereign account. + // (Used for over-bridge transfers and reserve processing) + GlobalConsensusParachainConvertsFor, ); /// Means for transacting the native currency on this chain. @@ -208,6 +215,14 @@ impl Contains for SafeCallFilter { } } + // Allow to change dedicated storage items (called by governance-like) + match call { + RuntimeCall::System(frame_system::Call::set_storage { items }) + if items.iter().all(|(k, _)| k.eq(&bridging::XcmBridgeHubRouterByteFee::key())) => + return true, + _ => (), + }; + matches!( call, RuntimeCall::PolkadotXcm(pallet_xcm::Call::force_xcm_version { .. }) | @@ -350,7 +365,9 @@ impl Contains for SafeCallFilter { pallet_uniques::Call::set_accept_ownership { .. } | pallet_uniques::Call::set_collection_max_supply { .. } | pallet_uniques::Call::set_price { .. } | - pallet_uniques::Call::buy_item { .. } + pallet_uniques::Call::buy_item { .. }, + ) | RuntimeCall::ToKusamaXcmRouter( + pallet_xcm_bridge_hub_router::Call::report_bridge_status { .. } ) ) } @@ -379,6 +396,8 @@ pub type Barrier = TrailingSetTopicAsId< )>, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, + // Allows Transacts with `report_bridge_status` from sibling BridgeHub. + bridging::AllowUnpaidStatusReportsFromSiblingBridgeHub, ), UniversalLocation, ConstU32<8>, @@ -387,6 +406,7 @@ pub type Barrier = TrailingSetTopicAsId< >, >; +/// Multiplier used for dedicated `TakeFirstAssetTrader` with `Assets` instance. pub type AssetFeeAsExistentialDepositMultiplierFeeCharger = AssetFeeAsExistentialDepositMultiplier< Runtime, WeightToFee, @@ -394,16 +414,25 @@ pub type AssetFeeAsExistentialDepositMultiplierFeeCharger = AssetFeeAsExistentia TrustBackedAssetsInstance, >; +/// Multiplier used for dedicated `TakeFirstAssetTrader` with `ForeignAssets` instance. +pub type ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger = + AssetFeeAsExistentialDepositMultiplier< + Runtime, + WeightToFee, + pallet_assets::BalanceToAssetBalance, + ForeignAssetsInstance, + >; + pub struct XcmConfig; impl xcm_executor::Config for XcmConfig { type RuntimeCall = RuntimeCall; type XcmSender = XcmRouter; type AssetTransactor = AssetTransactors; type OriginConverter = XcmOriginToTransactDispatchOrigin; - // Asset Hub Polkadot does not recognize a reserve location for any asset. This does not prevent - // Asset Hub acting _as_ a reserve location for DOT and assets created under `pallet-assets`. - // For DOT, users must use teleport where allowed (e.g. with the Relay Chain). - type IsReserve = (); + // Asset Hub trusts only particular configured bridge locations as reserve locations. + // Asset Hub may _act_ as a reserve location for DOT and assets created under `pallet-assets`. + // Users must use teleport where allowed (e.g. DOT with the Relay Chain). + type IsReserve = bridging::IsTrustedBridgedReserveLocationForConcreteAsset; // We allow: // - teleportation of DOT // - teleportation of sibling parachain's assets (as ForeignCreators) @@ -420,6 +449,8 @@ impl xcm_executor::Config for XcmConfig { >; type Trader = ( UsingComponents>, + // This trader allows to pay with `is_sufficient=true` "Trust Backed" assets from dedicated + // `pallet_assets` instance - `Assets`. cumulus_primitives_utility::TakeFirstAssetTrader< AccountId, AssetFeeAsExistentialDepositMultiplierFeeCharger, @@ -431,6 +462,19 @@ impl xcm_executor::Config for XcmConfig { XcmAssetFeesReceiver, >, >, + // This trader allows to pay with `is_sufficient=true` "Foreign" assets from dedicated + // `pallet_assets` instance - `ForeignAssets`. + cumulus_primitives_utility::TakeFirstAssetTrader< + AccountId, + ForeignAssetFeeAsExistentialDepositMultiplierFeeCharger, + ForeignAssetsConvertedConcreteId, + ForeignAssets, + cumulus_primitives_utility::XcmFeesTo32ByteAccount< + ForeignFungiblesTransactor, + AccountId, + XcmAssetFeesReceiver, + >, + >, ); type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; @@ -440,9 +484,10 @@ impl xcm_executor::Config for XcmConfig { type MaxAssetsIntoHolding = MaxAssetsIntoHolding; type AssetLocker = (); type AssetExchanger = (); + // TODO:check-parameter: change and assert in tests when (https://github.com/paritytech/polkadot/pull/7005) merged type FeeManager = (); type MessageExporter = (); - type UniversalAliases = Nothing; + type UniversalAliases = bridging::UniversalAliases; type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; type Aliasers = Nothing; @@ -452,13 +497,20 @@ impl xcm_executor::Config for XcmConfig { /// Forms the basis for local origins sending/executing XCMs. pub type LocalOriginToLocation = SignedToAccountId32; -/// The means for routing XCM messages which are not for local execution into the right message -/// queues. -pub type XcmRouter = WithUniqueTopic<( +/// For routing XCM messages which do not cross local consensus boundary. +type LocalXcmRouter = ( // Two routers - use UMP to communicate with the relay chain: cumulus_primitives_utility::ParentAsUmp, // ..and XCMP to communicate with the sibling chains. XcmpQueue, +); + +/// The means for routing XCM messages which are not for local execution into the right message +/// queues. +pub type XcmRouter = WithUniqueTopic<( + LocalXcmRouter, + // Router which wraps and sends XCM to BridgeHub to be delivered to the Kusama GlobalConsensus + ToKusamaXcmRouter, )>; #[cfg(feature = "runtime-benchmarks")] @@ -478,7 +530,9 @@ impl pallet_xcm::Config for Runtime { type XcmExecuteFilter = Nothing; type XcmExecutor = XcmExecutor; type XcmTeleportFilter = Everything; - type XcmReserveTransferFilter = Everything; + // Allow reserve based transfer to everywhere except for bridging, here we strictly check what + // assets are allowed. + type XcmReserveTransferFilter = EverythingBut; type Weigher = WeightInfoBounds< crate::weights::xcm::AssetHubPolkadotXcmWeight, RuntimeCall, @@ -536,3 +590,142 @@ fn foreign_pallet_has_correct_local_account() { let address = Ss58Codec::to_ss58check_with_version(&account, polkadot); assert_eq!(address, "13w7NdvSR1Af8xsQTArDtZmVvjE8XhWNdL4yed3iFHrUNCnS"); } + +/// All configuration related to bridging +pub mod bridging { + use super::*; + use assets_common::{matching, matching::*}; + use parachains_common::xcm_config::LocationFilter; + use sp_std::collections::btree_set::BTreeSet; + + parameter_types! { + pub BridgeHubPolkadotParaId: u32 = 1002; + pub BridgeHubPolkadot: MultiLocation = MultiLocation::new(1, X1(Parachain(BridgeHubPolkadotParaId::get()))); + pub BridgeHubPolkadotWithBridgeHubKusamaInstance: MultiLocation = MultiLocation::new( + 1, + X2( + Parachain(BridgeHubPolkadotParaId::get()), + PalletInstance(bp_bridge_hub_polkadot::WITH_BRIDGE_KUSAMA_MESSAGES_PALLET_INDEX) + ) + ); + pub const KusamaNetwork: NetworkId = NetworkId::Kusama; + pub AssetHubKusama: MultiLocation = MultiLocation::new(2, X2(GlobalConsensus(KusamaNetwork::get()), Parachain(bp_asset_hub_kusama::ASSET_HUB_KUSAMA_PARACHAIN_ID))); + pub KsmLocation: MultiLocation = MultiLocation::new(2, X1(GlobalConsensus(KusamaNetwork::get()))); + + /// Router expects payment with this `AssetId`. + /// (`AssetId` has to be aligned with `BridgeTable`) + pub XcmBridgeHubRouterFeeAssetId: AssetId = DotLocation::get().into(); + /// Price per byte - can be adjusted via governance `set_storage` call. + pub storage XcmBridgeHubRouterByteFee: Balance = TransactionByteFee::get(); + + /// Set up exporters configuration. + /// `Option` represents static "base fee" which is used for total delivery fee calculation. + pub BridgeTable: sp_std::vec::Vec<(NetworkId, LocationFilter, MultiLocation, Option)> = sp_std::vec![ + ( + KusamaNetwork::get(), + LocationFilter::default() + // allow to bridge to AssetHubKusama + .add_equals(AssetHubKusama::get().interior.split_global().expect("invalid configuration for AssetHubKusama").1), + // and nothing else + BridgeHubPolkadot::get(), + // base delivery fee to local `BridgeHub` + Some(( + XcmBridgeHubRouterFeeAssetId::get(), + bp_asset_hub_polkadot::BridgeHubPolkadotBaseFeeInDots::get() + ).into()) + ) + ]; + + /// Set up trusted bridged reserve locations. + /// Locations from which the runtime accepts reserved assets. + pub TrustedBridgedReserveLocations: sp_std::vec::Vec = sp_std::vec![ + // trust assets from AssetHubKusama + ( + AssetHubKusama::get(), + LocationFilter::default() + // allow receive KSM + .add_equals(KsmLocation::get()) + // and nothing else + ) + ]; + + /// Allowed reserve transfer assets per destination. + /// Means that runtime allows to transfer reserve assets to these locations. + pub AllowedReserveTransferAssetsLocations: sp_std::vec::Vec = sp_std::vec![ + // allow to transfer assets to AssetHubKusama + ( + AssetHubKusama::get(), + LocationFilter::default() + // allow send only DOT + .add_equals(DotLocation::get()) + // and nothing else + ) + ]; + + /// Universal aliases + pub UniversalAliases: BTreeSet<(MultiLocation, Junction)> = BTreeSet::from_iter( + sp_std::vec![ + (BridgeHubPolkadotWithBridgeHubKusamaInstance::get(), GlobalConsensus(KusamaNetwork::get())) + ] + ); + } + + impl Contains<(MultiLocation, Junction)> for UniversalAliases { + fn contains(alias: &(MultiLocation, Junction)) -> bool { + UniversalAliases::get().contains(alias) + } + } + + pub type FilteredNetworkExportTable = + parachains_common::xcm_config::FilteredNetworkExportTable; + + /// Reserve locations filter for `xcm_executor::Config::IsReserve`. + pub type IsTrustedBridgedReserveLocationForConcreteAsset = + matching::IsTrustedBridgedReserveLocationForConcreteAsset< + UniversalLocation, + TrustedBridgedReserveLocations, + >; + + /// Filter out those assets which are not allowed for bridged reserve based transfer. + /// Filter is made of (asset, location) and used by + /// `pallet_xcm::Config::XcmReserveTransferFilter`. + pub type DisallowForReserveTransfer = ExcludeOnlyForRemoteDestination< + UniversalLocation, + FilteredNetworkExportTable, + DisallowConcreteAssetUnless, + >; + + impl Contains for ToKusamaXcmRouter { + fn contains(call: &RuntimeCall) -> bool { + matches!( + call, + RuntimeCall::ToKusamaXcmRouter( + pallet_xcm_bridge_hub_router::Call::report_bridge_status { .. } + ) + ) + } + } + + /// Barrier for `pallet_xcm_bridge_hub_router::Pallet` to receive congestion statuses from + /// sibling BridgeHub. + pub type AllowUnpaidStatusReportsFromSiblingBridgeHub = + AllowUnpaidTransactsFrom>; + + /// Benchmarks helper for bridging configuration. + #[cfg(feature = "runtime-benchmarks")] + pub struct BridgingBenchmarksHelper; + + #[cfg(feature = "runtime-benchmarks")] + impl BridgingBenchmarksHelper { + pub fn prepare_universal_alias() -> Option<(MultiLocation, Junction)> { + let alias = UniversalAliases::get().into_iter().find_map(|(location, junction)| { + match BridgeHubPolkadotWithBridgeHubKusamaInstance::get().eq(&location) { + true => Some((location, junction)), + false => None, + } + }); + assert!(alias.is_some(), "we expect here BridgeHubPolkadot to Kusama mapping at least"); + Some(alias.unwrap()) + } + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs index 7200ebc16a28..7c9b00903ea9 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-polkadot/tests/tests.rs @@ -18,20 +18,22 @@ //! Tests for the Statemint (Polkadot Assets Hub) chain. use asset_hub_polkadot_runtime::xcm_config::{ - AssetFeeAsExistentialDepositMultiplierFeeCharger, CheckingAccount, DotLocation, - ForeignCreatorsSovereignAccountOf, TrustBackedAssetsPalletLocation, XcmConfig, + bridging, AssetFeeAsExistentialDepositMultiplierFeeCharger, CheckingAccount, DotLocation, + ForeignCreatorsSovereignAccountOf, LocationToAccountId, TrustBackedAssetsPalletLocation, + XcmConfig, }; pub use asset_hub_polkadot_runtime::{ - AllPalletsWithoutSystem, AssetDeposit, Assets, Balances, ExistentialDeposit, ForeignAssets, - ForeignAssetsInstance, MetadataDepositBase, MetadataDepositPerByte, ParachainSystem, Runtime, - RuntimeCall, RuntimeEvent, SessionKeys, System, TrustBackedAssetsInstance, + xcm_config, AllPalletsWithoutSystem, AssetDeposit, Assets, Balances, ExistentialDeposit, + ForeignAssets, ForeignAssetsInstance, MetadataDepositBase, MetadataDepositPerByte, + ParachainSystem, Runtime, RuntimeCall, RuntimeEvent, SessionKeys, System, + ToKusamaXcmRouterInstance, TrustBackedAssetsInstance, XcmpQueue, }; -use asset_test_utils::{CollatorSessionKeys, ExtBuilder}; +use asset_test_utils::{CollatorSessionKey, CollatorSessionKeys, ExtBuilder}; use codec::{Decode, Encode}; use cumulus_primitives_utility::ChargeWeightInFungibles; use frame_support::{ assert_noop, assert_ok, - traits::fungibles::InspectEnumerable, + traits::{fungibles::InspectEnumerable, Contains}, weights::{Weight, WeightToFee as WeightToFeeT}, }; use parachains_common::{ @@ -50,14 +52,18 @@ type AssetIdForTrustBackedAssetsConvert = type RuntimeHelper = asset_test_utils::RuntimeHelper; -fn collator_session_keys() -> CollatorSessionKeys { - CollatorSessionKeys::new( - AccountId::from(ALICE), - AccountId::from(ALICE), - SessionKeys { aura: AuraId::from(sp_core::ed25519::Public::from_raw(ALICE)) }, +fn collator_session_key(account: [u8; 32]) -> CollatorSessionKey { + CollatorSessionKey::new( + AccountId::from(account), + AccountId::from(account), + SessionKeys { aura: AuraId::from(sp_core::ed25519::Public::from_raw(account)) }, ) } +fn collator_session_keys() -> CollatorSessionKeys { + CollatorSessionKeys::default().add(collator_session_key(ALICE)) +} + #[test] fn test_asset_xcm_trader() { ExtBuilder::::default() @@ -657,3 +663,270 @@ asset_test_utils::include_create_and_manage_foreign_assets_for_local_consensus_p assert_eq!(ForeignAssets::asset_ids().collect::>().len(), 1); }) ); + +fn bridging_to_asset_hub_kusama() -> asset_test_utils::test_cases_over_bridge::TestBridgingConfig { + asset_test_utils::test_cases_over_bridge::TestBridgingConfig { + bridged_network: bridging::KusamaNetwork::get(), + local_bridge_hub_para_id: bridging::BridgeHubPolkadotParaId::get(), + local_bridge_hub_location: bridging::BridgeHubPolkadot::get(), + bridged_target_location: bridging::AssetHubKusama::get(), + } +} + +#[test] +fn limited_reserve_transfer_assets_for_native_asset_over_bridge_works() { + asset_test_utils::test_cases_over_bridge::limited_reserve_transfer_assets_for_native_asset_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + XcmpQueue, + LocationToAccountId, + >( + collator_session_keys(), + ExistentialDeposit::get(), + AccountId::from(ALICE), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event), + _ => None, + } + }), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), + _ => None, + } + }), + bridging_to_asset_hub_kusama, + WeightLimit::Unlimited, + Some(xcm_config::bridging::XcmBridgeHubRouterFeeAssetId::get()), + ) +} + +#[test] +fn receive_reserve_asset_deposited_ksm_from_asset_hub_kusama_works() { + const BLOCK_AUTHOR_ACCOUNT: [u8; 32] = [13; 32]; + asset_test_utils::test_cases_over_bridge::receive_reserve_asset_deposited_from_different_consensus_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + LocationToAccountId, + ForeignAssetsInstance, + >( + collator_session_keys().add(collator_session_key(BLOCK_AUTHOR_ACCOUNT)), + ExistentialDeposit::get(), + AccountId::from([73; 32]), + AccountId::from(BLOCK_AUTHOR_ACCOUNT), + // receiving KSMs + (MultiLocation { parents: 2, interior: X1(GlobalConsensus(Kusama)) }, 1000000000000, 10_000_000_000), + bridging_to_asset_hub_kusama, + (X1(PalletInstance(53)), GlobalConsensus(Kusama), X1(Parachain(1000))) + ) +} + +/// Tests expected configuration of isolated `pallet_xcm::Config::XcmReserveTransferFilter`. +#[test] +fn xcm_reserve_transfer_filter_works() { + // prepare assets + let only_native_assets = || vec![MultiAsset::from((DotLocation::get(), 1000))]; + let only_trust_backed_assets = || { + vec![MultiAsset::from(( + AssetIdForTrustBackedAssetsConvert::convert_back(&12345).unwrap(), + 2000, + ))] + }; + let only_sibling_foreign_assets = + || vec![MultiAsset::from((MultiLocation::new(1, X1(Parachain(12345))), 3000))]; + let only_different_global_consensus_foreign_assets = || { + vec![MultiAsset::from(( + MultiLocation::new(2, X2(GlobalConsensus(Kusama), Parachain(12345))), + 4000, + ))] + }; + + // prepare destinations + let relaychain = MultiLocation::parent(); + let sibling_parachain = MultiLocation::new(1, X1(Parachain(54321))); + let different_global_consensus_parachain_other_than_asset_hub_kusama = + MultiLocation::new(2, X2(GlobalConsensus(Kusama), Parachain(12345))); + let bridged_asset_hub = bridging::AssetHubKusama::get(); + + // prepare expected test data sets: (destination, assets, expected_result) + let test_data = vec![ + (relaychain, only_native_assets(), true), + (relaychain, only_trust_backed_assets(), true), + (relaychain, only_sibling_foreign_assets(), true), + (relaychain, only_different_global_consensus_foreign_assets(), true), + (sibling_parachain, only_native_assets(), true), + (sibling_parachain, only_trust_backed_assets(), true), + (sibling_parachain, only_sibling_foreign_assets(), true), + (sibling_parachain, only_different_global_consensus_foreign_assets(), true), + ( + different_global_consensus_parachain_other_than_asset_hub_kusama, + only_native_assets(), + false, + ), + ( + different_global_consensus_parachain_other_than_asset_hub_kusama, + only_trust_backed_assets(), + false, + ), + ( + different_global_consensus_parachain_other_than_asset_hub_kusama, + only_sibling_foreign_assets(), + false, + ), + ( + different_global_consensus_parachain_other_than_asset_hub_kusama, + only_different_global_consensus_foreign_assets(), + false, + ), + (bridged_asset_hub, only_native_assets(), true), + (bridged_asset_hub, only_trust_backed_assets(), false), + (bridged_asset_hub, only_sibling_foreign_assets(), false), + (bridged_asset_hub, only_different_global_consensus_foreign_assets(), false), + ]; + + // lets test filter with test data + ExtBuilder::::default() + .with_collators(collator_session_keys().collators()) + .with_session_keys(collator_session_keys().session_keys()) + .build() + .execute_with(|| { + type XcmReserveTransferFilter = + ::XcmReserveTransferFilter; + for (dest, assets, expected_result) in test_data { + assert_eq!( + expected_result, + XcmReserveTransferFilter::contains(&(dest, assets.clone())), + "expected_result: {} for dest: {:?} and assets: {:?}", + expected_result, + dest, + assets + ); + } + }) +} + +#[test] +fn change_xcm_bridge_hub_router_byte_fee_by_governance_works() { + asset_test_utils::test_cases::change_storage_constant_by_governance_works::< + Runtime, + bridging::XcmBridgeHubRouterByteFee, + Balance, + >( + collator_session_keys(), + 1000, + Box::new(|call| RuntimeCall::System(call).encode()), + || { + ( + bridging::XcmBridgeHubRouterByteFee::key().to_vec(), + bridging::XcmBridgeHubRouterByteFee::get(), + ) + }, + |old_value| { + if let Some(new_value) = old_value.checked_add(1) { + new_value + } else { + old_value.checked_sub(1).unwrap() + } + }, + ) +} + +#[test] +fn test_report_bridge_status_call_compatibility() { + // if this test fails, make sure `bp_asset_hub_polkadot` has valid encoding + assert_eq!( + RuntimeCall::ToKusamaXcmRouter(pallet_xcm_bridge_hub_router::Call::report_bridge_status { + bridge_id: Default::default(), + is_congested: true, + }) + .encode(), + bp_asset_hub_polkadot::Call::ToKusamaXcmRouter( + bp_asset_hub_polkadot::XcmBridgeHubRouterCall::report_bridge_status { + bridge_id: Default::default(), + is_congested: true, + } + ) + .encode() + ) +} + +#[test] +fn report_bridge_status_from_xcm_bridge_router_works() { + asset_test_utils::test_cases_over_bridge::report_bridge_status_from_xcm_bridge_router_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + XcmpQueue, + LocationToAccountId, + ToKusamaXcmRouterInstance, + >( + collator_session_keys(), + ExistentialDeposit::get(), + AccountId::from(ALICE), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::PolkadotXcm(event)) => Some(event), + _ => None, + } + }), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), + _ => None, + } + }), + bridging_to_asset_hub_kusama, + WeightLimit::Unlimited, + Some(xcm_config::bridging::XcmBridgeHubRouterFeeAssetId::get()), + || { + sp_std::vec![Transact { + origin_kind: OriginKind::Xcm, + require_weight_at_most: + bp_asset_hub_polkadot::XcmBridgeHubRouterTransactCallMaxWeight::get(), + call: bp_asset_hub_polkadot::Call::ToKusamaXcmRouter( + bp_asset_hub_polkadot::XcmBridgeHubRouterCall::report_bridge_status { + bridge_id: Default::default(), + is_congested: true, + } + ) + .encode() + .into(), + }] + .into() + }, + || { + sp_std::vec![Transact { + origin_kind: OriginKind::Xcm, + require_weight_at_most: + bp_asset_hub_polkadot::XcmBridgeHubRouterTransactCallMaxWeight::get(), + call: bp_asset_hub_polkadot::Call::ToKusamaXcmRouter( + bp_asset_hub_polkadot::XcmBridgeHubRouterCall::report_bridge_status { + bridge_id: Default::default(), + is_congested: false, + } + ) + .encode() + .into(), + }] + .into() + }, + ) +} + +#[test] +fn check_sane_weight_report_bridge_status() { + use pallet_xcm_bridge_hub_router::WeightInfo; + let actual = >::WeightInfo::report_bridge_status(); + let max_weight = bp_asset_hub_polkadot::XcmBridgeHubRouterTransactCallMaxWeight::get(); + assert!( + actual.all_lte(max_weight), + "max_weight: {:?} should be adjusted to actual {:?}", + max_weight, + actual + ); +} diff --git a/cumulus/parachains/runtimes/assets/common/src/matching.rs b/cumulus/parachains/runtimes/assets/common/src/matching.rs index 08d391170014..5854ccf2e81f 100644 --- a/cumulus/parachains/runtimes/assets/common/src/matching.rs +++ b/cumulus/parachains/runtimes/assets/common/src/matching.rs @@ -18,10 +18,12 @@ use frame_support::{ pallet_prelude::Get, traits::{Contains, ContainsPair}, }; +use parachains_common::xcm_config::{LocationFilter, MatchesLocation}; use xcm::{ latest::prelude::{MultiAsset, MultiLocation}, prelude::*, }; +use xcm_builder::{ensure_is_remote, ExporterFor}; pub struct StartsWith(sp_std::marker::PhantomData); impl> Contains for StartsWith { @@ -82,3 +84,154 @@ impl> ContainsPair } } } + +/// Adapter verifies if it is allowed to receive `MultiAsset` from `MultiLocation`. +/// +/// Note: `MultiLocation` has to be from different global consensus. +pub struct IsTrustedBridgedReserveLocationForConcreteAsset( + sp_std::marker::PhantomData<(UniversalLocation, Reserves)>, +); +impl< + UniversalLocation: Get, + Reserves: Get>, + > ContainsPair + for IsTrustedBridgedReserveLocationForConcreteAsset +{ + fn contains(asset: &MultiAsset, origin: &MultiLocation) -> bool { + let universal_source = UniversalLocation::get(); + log::trace!( + target: "xcm::contains", + "IsTrustedBridgedReserveLocationForConcreteAsset asset: {:?}, origin: {:?}, universal_source: {:?}", + asset, origin, universal_source + ); + + // check remote origin + let _ = match ensure_is_remote(universal_source, *origin) { + Ok(devolved) => devolved, + Err(_) => { + log::trace!( + target: "xcm::contains", + "IsTrustedBridgedReserveLocationForConcreteAsset origin: {:?} is not remote to the universal_source: {:?}", + origin, universal_source + ); + return false + }, + }; + + // check asset location + let asset_location = match &asset.id { + Concrete(location) => location, + _ => return false, + }; + + // check asset according to the configured reserve locations + for (reserve_location, asset_filter) in Reserves::get() { + if origin.eq(&reserve_location) && asset_filter.matches(asset_location) { + return true + } + } + + false + } +} + +/// Disallow all assets the are either not `Concrete`, or not explicitly allowed by +/// `LocationAssetFilters`, iff `dest` matches any location in `LocationAssetFilters`. +/// +/// Returns `false` regardless of `assets`, if `dest` does not match any location in +/// `LocationAssetFilters`. Otherwise, returns `true` if asset is either not `Concrete` or is not +/// explicitly allowed by `LocationAssetFilters`, otherwise returns `false`. +pub struct DisallowConcreteAssetUnless( + sp_std::marker::PhantomData, +); +impl>> + Contains<(MultiLocation, sp_std::vec::Vec)> + for DisallowConcreteAssetUnless +{ + fn contains((dest, assets): &(MultiLocation, sp_std::vec::Vec)) -> bool { + for (allowed_dest, asset_filter) in LocationAssetFilters::get().iter() { + // we only disallow `assets` on explicitly configured destinations + if !allowed_dest.eq(dest) { + continue + } + + // check all assets + for asset in assets { + let asset_location = match &asset.id { + Concrete(location) => location, + _ => return true, + }; + + if !asset_filter.matches(asset_location) { + // if asset does not match filter, disallow it + return true + } + } + } + + // if we got here, allow it + false + } +} + +/// Adapter for `Contains<(MultiLocation, sp_std::vec::Vec)>` which returns `true` +/// iff `Exporters` contains exporter for **remote** `MultiLocation` _and_ +///`assets` also pass`Filter`, otherwise returns `false`. +/// +/// Note: Assumes that `Exporters` do not depend on `XCM program` and works for `Xcm::default()`. +pub struct ExcludeOnlyForRemoteDestination( + sp_std::marker::PhantomData<(UniversalLocation, Exporters, Exclude)>, +); +impl Contains<(MultiLocation, sp_std::vec::Vec)> + for ExcludeOnlyForRemoteDestination +where + UniversalLocation: Get, + Exporters: ExporterFor, + Exclude: Contains<(MultiLocation, sp_std::vec::Vec)>, +{ + fn contains(dest_and_assets: &(MultiLocation, sp_std::vec::Vec)) -> bool { + let universal_source = UniversalLocation::get(); + log::trace!( + target: "xcm::contains", + "ExcludeOnlyForRemoteDestination dest: {:?}, assets: {:?}, universal_source: {:?}", + dest_and_assets.0, dest_and_assets.1, universal_source + ); + + // check if it is remote destination + match ensure_is_remote(universal_source, dest_and_assets.0) { + Ok((remote_network, remote_destination)) => { + if Exporters::exporter_for(&remote_network, &remote_destination, &Xcm::default()) + .is_some() + { + // destination is remote, and has configured exporter, now check filter + Exclude::contains(dest_and_assets) + } else { + log::trace!( + target: "xcm::contains", + "ExcludeOnlyForRemoteDestination no exporter for dest: {:?}", + dest_and_assets.0 + ); + // no exporter means that we exclude by default + true + } + }, + Err(_) => { + log::trace!( + target: "xcm::contains", + "ExcludeOnlyForRemoteDestination dest: {:?} is not remote to the universal_source: {:?}", + dest_and_assets.0, universal_source + ); + // not a remote destination, do not exclude + false + }, + } + } +} + +/// A type alias for referring to the `LocationFilter`. +/// (`MultiLocation` represents here `AssetId::Concrete(location)`). +pub type AssetFilter = LocationFilter; + +/// A type alias for referring to the `MultiLocation` with `AssetFilter` capabilities. +/// E.g. for `MultiLocation` we can accept assets that match `AssetFilter`. +pub type LocationWithAssetFilter = (MultiLocation, AssetFilter); diff --git a/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml b/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml index 0a27535ed22b..30d3cf90b47f 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/test-utils/Cargo.toml @@ -35,10 +35,14 @@ parachains-runtimes-test-utils = { path = "../../test-utils", default-features = # Polkadot xcm = { package = "staging-xcm", path = "../../../../../polkadot/xcm", default-features = false} +xcm-builder = { package = "staging-xcm-builder", path = "../../../../../polkadot/xcm/xcm-builder", default-features = false} xcm-executor = { package = "staging-xcm-executor", path = "../../../../../polkadot/xcm/xcm-executor", default-features = false} pallet-xcm = { path = "../../../../../polkadot/xcm/pallet-xcm", default-features = false} polkadot-parachain-primitives = { path = "../../../../../polkadot/parachain", default-features = false} +# Bridges +pallet-xcm-bridge-hub-router = { path = "../../../../../bridges/modules/xcm-bridge-hub-router", default-features = false } + [dev-dependencies] hex-literal = "0.4.1" @@ -61,6 +65,7 @@ std = [ "pallet-balances/std", "pallet-collator-selection/std", "pallet-session/std", + "pallet-xcm-bridge-hub-router/std", "pallet-xcm/std", "parachain-info/std", "parachains-common/std", @@ -71,6 +76,7 @@ std = [ "sp-io/std", "sp-runtime/std", "sp-std/std", + "xcm-builder/std", "xcm-executor/std", "xcm/std", ] diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs b/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs index 7177726e0704..3c62faf3d5ec 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/lib.rs @@ -17,4 +17,5 @@ //! Module contains predefined test-case scenarios for `Runtime` with various assets. pub mod test_cases; +pub mod test_cases_over_bridge; pub use parachains_runtimes_test_utils::*; diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs index 7a8d571403c6..6503d7e6a736 100644 --- a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases.rs @@ -78,6 +78,7 @@ pub fn teleports_for_native_asset_works< Into<<::RuntimeOrigin as OriginTrait>::AccountId>, <::Lookup as StaticLookup>::Source: From<::AccountId>, + ::AccountId: From, XcmConfig: xcm_executor::Config, CheckingAccount: Get>, HrmpChannelOpener: frame_support::inherent::ProvideInherent< @@ -96,7 +97,7 @@ pub fn teleports_for_native_asset_works< let included_head = RuntimeHelper::::run_to_block( 2, - AccountId::from(alice), + AccountId::from(alice).into(), ); // check Balances before assert_eq!(>::free_balance(&target_account), 0.into()); @@ -346,6 +347,7 @@ pub fn teleports_for_foreign_assets_works< Into<<::RuntimeOrigin as OriginTrait>::AccountId>, <::Lookup as StaticLookup>::Source: From<::AccountId>, + ::AccountId: From, ForeignAssetsPalletInstance: 'static, { // foreign parachain with the same consenus currency as asset @@ -391,7 +393,7 @@ pub fn teleports_for_foreign_assets_works< let included_head = RuntimeHelper::::run_to_block( 2, - AccountId::from(alice), + AccountId::from(alice).into(), ); // checks target_account before assert_eq!( @@ -1005,6 +1007,7 @@ macro_rules! include_asset_transactor_transfer_with_pallet_assets_instance_works } ); +/// Test-case makes sure that `Runtime` can create and manage `ForeignAssets` pub fn create_and_manage_foreign_assets_for_local_consensus_parachain_assets_works< Runtime, XcmConfig, diff --git a/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs new file mode 100644 index 000000000000..39a77d8cdea2 --- /dev/null +++ b/cumulus/parachains/runtimes/assets/test-utils/src/test_cases_over_bridge.rs @@ -0,0 +1,621 @@ +// Copyright (C) 2023 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//! Module contains predefined test-case scenarios for `Runtime` with various assets transferred +//! over a bridge. + +use codec::Encode; +use cumulus_primitives_core::XcmpMessageSource; +use frame_support::{ + assert_ok, + traits::{Currency, OnFinalize, OnInitialize, OriginTrait, ProcessMessageError}, +}; +use frame_system::pallet_prelude::BlockNumberFor; +use parachains_common::{AccountId, Balance}; +use parachains_runtimes_test_utils::{ + mock_open_hrmp_channel, AccountIdOf, BalanceOf, CollatorSessionKeys, ExtBuilder, RuntimeHelper, + ValidatorIdOf, XcmReceivedFrom, +}; +use sp_runtime::traits::StaticLookup; +use xcm::{latest::prelude::*, VersionedMultiAssets}; +use xcm_builder::{CreateMatcher, MatchXcm}; +use xcm_executor::{traits::ConvertLocation, XcmExecutor}; + +pub struct TestBridgingConfig { + pub bridged_network: NetworkId, + pub local_bridge_hub_para_id: u32, + pub local_bridge_hub_location: MultiLocation, + pub bridged_target_location: MultiLocation, +} + +/// Test-case makes sure that `Runtime` can initiate **reserve transfer assets** over bridge. +pub fn limited_reserve_transfer_assets_for_native_asset_works< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + HrmpChannelOpener, + HrmpChannelSource, + LocationToAccountId, +>( + collator_session_keys: CollatorSessionKeys, + existential_deposit: BalanceOf, + alice_account: AccountIdOf, + unwrap_pallet_xcm_event: Box) -> Option>>, + unwrap_xcmp_queue_event: Box< + dyn Fn(Vec) -> Option>, + >, + prepare_configuration: fn() -> TestBridgingConfig, + weight_limit: WeightLimit, + maybe_paid_export_message: Option, +) where + Runtime: frame_system::Config + + pallet_balances::Config + + pallet_session::Config + + pallet_xcm::Config + + parachain_info::Config + + pallet_collator_selection::Config + + cumulus_pallet_parachain_system::Config + + cumulus_pallet_xcmp_queue::Config, + AllPalletsWithoutSystem: + OnInitialize> + OnFinalize>, + AccountIdOf: Into<[u8; 32]>, + ValidatorIdOf: From>, + BalanceOf: From, + ::Balance: From + Into, + XcmConfig: xcm_executor::Config, + LocationToAccountId: ConvertLocation>, + ::AccountId: + Into<<::RuntimeOrigin as OriginTrait>::AccountId>, + <::Lookup as StaticLookup>::Source: + From<::AccountId>, + ::AccountId: From, + HrmpChannelOpener: frame_support::inherent::ProvideInherent< + Call = cumulus_pallet_parachain_system::Call, + >, + HrmpChannelSource: XcmpMessageSource, +{ + let runtime_para_id = 1000; + ExtBuilder::::default() + .with_collators(collator_session_keys.collators()) + .with_session_keys(collator_session_keys.session_keys()) + .with_tracing() + .with_safe_xcm_version(3) + .with_para_id(runtime_para_id.into()) + .build() + .execute_with(|| { + let mut alice = [0u8; 32]; + alice[0] = 1; + let included_head = RuntimeHelper::::run_to_block( + 2, + AccountId::from(alice).into(), + ); + + // prepare bridge config + let TestBridgingConfig { + bridged_network, + local_bridge_hub_para_id, + bridged_target_location: target_location_from_different_consensus, + .. + } = prepare_configuration(); + + let reserve_account = + LocationToAccountId::convert_location(&target_location_from_different_consensus) + .expect("Sovereign account for reserves"); + let balance_to_transfer = 1_000_000_000_000_u128; + let native_asset = MultiLocation::parent(); + + // open HRMP to bridge hub + mock_open_hrmp_channel::( + runtime_para_id.into(), + local_bridge_hub_para_id.into(), + included_head, + &alice, + ); + + // drip ED to account + let alice_account_init_balance = existential_deposit + balance_to_transfer.into(); + let _ = >::deposit_creating( + &alice_account, + alice_account_init_balance, + ); + // SA of target location needs to have at least ED, otherwise making reserve fails + let _ = >::deposit_creating( + &reserve_account, + existential_deposit, + ); + + // we just check here, that user retains enough balance after withdrawal + // and also we check if `balance_to_transfer` is more than `existential_deposit`, + assert!( + (>::free_balance(&alice_account) - + balance_to_transfer.into()) >= + existential_deposit + ); + // SA has just ED + assert_eq!( + >::free_balance(&reserve_account), + existential_deposit + ); + + // local native asset (pallet_balances) + let asset_to_transfer = MultiAsset { + fun: Fungible(balance_to_transfer.into()), + id: Concrete(native_asset), + }; + + // destination is (some) account relative to the destination different consensus + let target_destination_account = MultiLocation { + parents: 0, + interior: X1(AccountId32 { + network: Some(bridged_network), + id: sp_runtime::AccountId32::new([3; 32]).into(), + }), + }; + + // do pallet_xcm call reserve transfer + assert_ok!(>::limited_reserve_transfer_assets( + RuntimeHelper::::origin_of(alice_account.clone()), + Box::new(target_location_from_different_consensus.into_versioned()), + Box::new(target_destination_account.into_versioned()), + Box::new(VersionedMultiAssets::from(MultiAssets::from(asset_to_transfer))), + 0, + weight_limit, + )); + + // check alice account decreased by balance_to_transfer + // TODO:check-parameter: change and assert in tests when (https://github.com/paritytech/polkadot/pull/7005) merged + assert_eq!( + >::free_balance(&alice_account), + alice_account_init_balance - balance_to_transfer.into() + ); + + // check reserve account + // check reserve account increased by balance_to_transfer + assert_eq!( + >::free_balance(&reserve_account), + existential_deposit + balance_to_transfer.into() + ); + + // check events + // check pallet_xcm attempted + RuntimeHelper::::assert_pallet_xcm_event_outcome( + &unwrap_pallet_xcm_event, + |outcome| { + assert_ok!(outcome.ensure_complete()); + }, + ); + + // check that xcm was sent + let xcm_sent_message_hash = >::events() + .into_iter() + .filter_map(|e| unwrap_xcmp_queue_event(e.event.encode())) + .find_map(|e| match e { + cumulus_pallet_xcmp_queue::Event::XcmpMessageSent { message_hash } => + Some(message_hash), + _ => None, + }); + + // read xcm + let xcm_sent = RuntimeHelper::::take_xcm( + local_bridge_hub_para_id.into(), + ) + .unwrap(); + + assert_eq!( + xcm_sent_message_hash, + Some(xcm_sent.using_encoded(sp_io::hashing::blake2_256)) + ); + let mut xcm_sent: Xcm<()> = xcm_sent.try_into().expect("versioned xcm"); + + // check sent XCM ExportMessage to BridgeHub + + // 1. check paid or unpaid + if let Some(expected_fee_asset_id) = maybe_paid_export_message { + xcm_sent + .0 + .matcher() + .match_next_inst(|instr| match instr { + WithdrawAsset(_) => Ok(()), + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("contains WithdrawAsset") + .match_next_inst(|instr| match instr { + BuyExecution { fees, .. } if fees.id.eq(&expected_fee_asset_id) => Ok(()), + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("contains BuyExecution") + } else { + xcm_sent + .0 + .matcher() + .match_next_inst(|instr| match instr { + // first instruction could be UnpaidExecution (because we could have + // explicit unpaid execution on BridgeHub) + UnpaidExecution { weight_limit, check_origin } + if weight_limit == &Unlimited && check_origin.is_none() => + Ok(()), + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("contains UnpaidExecution") + } + // 2. check ExportMessage + .match_next_inst(|instr| match instr { + // second instruction is ExportMessage + ExportMessage { network, destination, xcm: inner_xcm } => { + assert_eq!(network, &bridged_network); + let (_, target_location_junctions_without_global_consensus) = + target_location_from_different_consensus + .interior + .split_global() + .expect("split works"); + assert_eq!(destination, &target_location_junctions_without_global_consensus); + assert_matches_pallet_xcm_reserve_transfer_assets_instructions(inner_xcm); + Ok(()) + }, + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("contains ExportMessage"); + }) +} + +pub fn receive_reserve_asset_deposited_from_different_consensus_works< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + LocationToAccountId, + ForeignAssetsPalletInstance, +>( + collator_session_keys: CollatorSessionKeys, + existential_deposit: BalanceOf, + target_account: AccountIdOf, + block_author_account: AccountIdOf, + ( + foreign_asset_id_multilocation, + transfered_foreign_asset_id_amount, + foreign_asset_id_minimum_balance, + ): (MultiLocation, u128, u128), + prepare_configuration: fn() -> TestBridgingConfig, + (bridge_instance, universal_origin, descend_origin): (Junctions, Junction, Junctions), /* bridge adds origin manipulation on the way */ +) where + Runtime: frame_system::Config + + pallet_balances::Config + + pallet_session::Config + + pallet_xcm::Config + + parachain_info::Config + + pallet_collator_selection::Config + + cumulus_pallet_parachain_system::Config + + cumulus_pallet_xcmp_queue::Config + + pallet_assets::Config, + AllPalletsWithoutSystem: + OnInitialize> + OnFinalize>, + AccountIdOf: Into<[u8; 32]>, + ValidatorIdOf: From>, + BalanceOf: From, + XcmConfig: xcm_executor::Config, + LocationToAccountId: ConvertLocation>, + >::AssetId: + From + Into, + >::AssetIdParameter: + From + Into, + >::Balance: + From + Into + From, + ::AccountId: + Into<<::RuntimeOrigin as OriginTrait>::AccountId>, + <::Lookup as StaticLookup>::Source: + From<::AccountId>, + ForeignAssetsPalletInstance: 'static, +{ + ExtBuilder::::default() + .with_collators(collator_session_keys.collators()) + .with_session_keys(collator_session_keys.session_keys()) + .with_tracing() + .build() + .execute_with(|| { + // Set account as block author, who will receive fees + RuntimeHelper::::run_to_block( + 2, + block_author_account.clone(), + ); + + // prepare bridge config + let TestBridgingConfig { local_bridge_hub_location, .. } = prepare_configuration(); + + // drip 'ED' user target account + let _ = >::deposit_creating( + &target_account, + existential_deposit, + ); + + // sovereign account as foreign asset owner (can be whoever for this scenario, doesnt + // matter) + let sovereign_account_as_owner_of_foreign_asset = + LocationToAccountId::convert_location(&MultiLocation::parent()).unwrap(); + + // staking pot account for collecting local native fees from `BuyExecution` + let staking_pot = >::account_id(); + let _ = >::deposit_creating( + &staking_pot, + existential_deposit, + ); + + // create foreign asset for wrapped/derivated representation + assert_ok!( + >::force_create( + RuntimeHelper::::root_origin(), + foreign_asset_id_multilocation.into(), + sovereign_account_as_owner_of_foreign_asset.clone().into(), + true, // is_sufficient=true + foreign_asset_id_minimum_balance.into() + ) + ); + + // Balances before + assert_eq!( + >::free_balance(&target_account), + existential_deposit.clone() + ); + assert_eq!( + >::free_balance(&block_author_account), + 0.into() + ); + assert_eq!( + >::free_balance(&staking_pot), + existential_deposit.clone() + ); + + // ForeignAssets balances before + assert_eq!( + >::balance( + foreign_asset_id_multilocation.into(), + &target_account + ), + 0.into() + ); + assert_eq!( + >::balance( + foreign_asset_id_multilocation.into(), + &block_author_account + ), + 0.into() + ); + assert_eq!( + >::balance( + foreign_asset_id_multilocation.into(), + &staking_pot + ), + 0.into() + ); + + // Call received XCM execution + let xcm = Xcm(vec![ + DescendOrigin(bridge_instance), + UniversalOrigin(universal_origin), + DescendOrigin(descend_origin), + ReserveAssetDeposited(MultiAssets::from(vec![MultiAsset { + id: Concrete(foreign_asset_id_multilocation), + fun: Fungible(transfered_foreign_asset_id_amount), + }])), + ClearOrigin, + BuyExecution { + fees: MultiAsset { + id: Concrete(foreign_asset_id_multilocation), + fun: Fungible(transfered_foreign_asset_id_amount), + }, + weight_limit: Unlimited, + }, + DepositAsset { + assets: Wild(AllCounted(1)), + beneficiary: MultiLocation { + parents: 0, + interior: X1(AccountId32 { + network: None, + id: target_account.clone().into(), + }), + }, + }, + SetTopic([ + 220, 188, 144, 32, 213, 83, 111, 175, 44, 210, 111, 19, 90, 165, 191, 112, 140, + 247, 192, 124, 42, 17, 153, 141, 114, 34, 189, 20, 83, 69, 237, 173, + ]), + ]); + assert_matches_pallet_xcm_reserve_transfer_assets_instructions(&mut xcm.clone()); + + let hash = xcm.using_encoded(sp_io::hashing::blake2_256); + + // execute xcm as XcmpQueue would do + let outcome = XcmExecutor::::execute_xcm( + local_bridge_hub_location, + xcm, + hash, + RuntimeHelper::::xcm_max_weight( + XcmReceivedFrom::Sibling, + ), + ); + assert_eq!(outcome.ensure_complete(), Ok(())); + + // author actual balance after (received fees from Trader for ForeignAssets) + let author_received_fees = + >::balance( + foreign_asset_id_multilocation.into(), + &block_author_account, + ); + + // Balances after (untouched) + assert_eq!( + >::free_balance(&target_account), + existential_deposit.clone() + ); + assert_eq!( + >::free_balance(&block_author_account), + 0.into() + ); + assert_eq!( + >::free_balance(&staking_pot), + existential_deposit.clone() + ); + + // ForeignAssets balances after + assert_eq!( + >::balance( + foreign_asset_id_multilocation.into(), + &target_account + ), + (transfered_foreign_asset_id_amount - author_received_fees.into()).into() + ); + assert_eq!( + >::balance( + foreign_asset_id_multilocation.into(), + &block_author_account + ), + author_received_fees + ); + assert_eq!( + >::balance( + foreign_asset_id_multilocation.into(), + &staking_pot + ), + 0.into() + ); + }) +} + +fn assert_matches_pallet_xcm_reserve_transfer_assets_instructions( + xcm: &mut Xcm, +) { + let _ = xcm + .0 + .matcher() + .skip_inst_while(|inst| !matches!(inst, ReserveAssetDeposited(..))) + .expect("no instruction ReserveAssetDeposited?") + .match_next_inst(|instr| match instr { + ReserveAssetDeposited(..) => Ok(()), + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("expected instruction ReserveAssetDeposited") + .match_next_inst(|instr| match instr { + ClearOrigin => Ok(()), + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("expected instruction ClearOrigin") + .match_next_inst(|instr| match instr { + BuyExecution { .. } => Ok(()), + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("expected instruction BuyExecution") + .match_next_inst(|instr| match instr { + DepositAsset { .. } => Ok(()), + _ => Err(ProcessMessageError::BadFormat), + }) + .expect("expected instruction DepositAsset"); +} + +pub fn report_bridge_status_from_xcm_bridge_router_works< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + HrmpChannelOpener, + HrmpChannelSource, + LocationToAccountId, + XcmBridgeHubRouterInstance, +>( + collator_session_keys: CollatorSessionKeys, + existential_deposit: BalanceOf, + alice_account: AccountIdOf, + unwrap_pallet_xcm_event: Box) -> Option>>, + unwrap_xcmp_queue_event: Box< + dyn Fn(Vec) -> Option>, + >, + prepare_configuration: fn() -> TestBridgingConfig, + weight_limit: WeightLimit, + maybe_paid_export_message: Option, + congested_message: fn() -> Xcm, + uncongested_message: fn() -> Xcm, +) where + Runtime: frame_system::Config + + pallet_balances::Config + + pallet_session::Config + + pallet_xcm::Config + + parachain_info::Config + + pallet_collator_selection::Config + + cumulus_pallet_parachain_system::Config + + cumulus_pallet_xcmp_queue::Config + + pallet_xcm_bridge_hub_router::Config, + AllPalletsWithoutSystem: + OnInitialize> + OnFinalize>, + AccountIdOf: Into<[u8; 32]>, + ValidatorIdOf: From>, + BalanceOf: From, + ::Balance: From + Into, + XcmConfig: xcm_executor::Config, + LocationToAccountId: ConvertLocation>, + ::AccountId: + Into<<::RuntimeOrigin as OriginTrait>::AccountId>, + <::Lookup as StaticLookup>::Source: + From<::AccountId>, + ::AccountId: From, + HrmpChannelOpener: frame_support::inherent::ProvideInherent< + Call = cumulus_pallet_parachain_system::Call, + >, + HrmpChannelSource: XcmpMessageSource, + XcmBridgeHubRouterInstance: 'static, +{ + ExtBuilder::::default() + .with_collators(collator_session_keys.collators()) + .with_session_keys(collator_session_keys.session_keys()) + .with_tracing() + .build() + .execute_with(|| { + // check transfer works + limited_reserve_transfer_assets_for_native_asset_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + HrmpChannelOpener, + HrmpChannelSource, + LocationToAccountId, + >( + collator_session_keys, + existential_deposit, + alice_account, + unwrap_pallet_xcm_event, + unwrap_xcmp_queue_event, + prepare_configuration, + weight_limit, + maybe_paid_export_message, + ); + + let report_brigde_status = |is_congested: bool| { + // prepare bridge config + let TestBridgingConfig { local_bridge_hub_location, .. } = prepare_configuration(); + + // Call received XCM execution + let xcm = if is_congested { congested_message() } else { uncongested_message() }; + let hash = xcm.using_encoded(sp_io::hashing::blake2_256); + + // execute xcm as XcmpQueue would do + let outcome = XcmExecutor::::execute_xcm( + local_bridge_hub_location, + xcm, + hash, + RuntimeHelper::::xcm_max_weight(XcmReceivedFrom::Sibling), + ); + assert_eq!(outcome.ensure_complete(), Ok(())); + assert_eq!(is_congested, pallet_xcm_bridge_hub_router::Pallet::::bridge().is_congested); + }; + + report_brigde_status(true); + report_brigde_status(false); + }) +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/README.md b/cumulus/parachains/runtimes/bridge-hubs/README.md index 487c601ef840..4a4f6f8e8d50 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/README.md +++ b/cumulus/parachains/runtimes/bridge-hubs/README.md @@ -2,13 +2,16 @@ - [Requirements for local run/testing](#requirements-for-local-runtesting) - [How to test local Rococo <-> Wococo bridge](#how-to-test-local-rococo---wococo-bridge) - [Run chains (Rococo + BridgeHub, Wococo + BridgeHub) with - zombienet](#run-chains-rococo--bridgehub-wococo--bridgehub-with-zombienet) + zombienet](#run-chains-rococo--bridgehub--assethub-wococo--bridgehub--assethub-with-zombienet) - [Run relayer (BridgeHubRococo, BridgeHubWococo)](#run-relayer-bridgehubrococo-bridgehubwococo) - [Run with script (alternative 1)](#run-with-script-alternative-1) - [Run with binary (alternative 2)](#run-with-binary-alternative-2) - [Send messages - transfer asset over bridge](#send-messages---transfer-asset-over-bridge) - [How to test live BridgeHubRococo/BridgeHubWococo](#how-to-test-live-bridgehubrococobridgehubwococo) - [How to test local BridgeHubKusama/BridgeHubPolkadot](#how-to-test-local-bridgehubkusamabridgehubpolkadot) + - [1. Run chains (Kusama + BridgeHub + AssetHub, Polkadot + BridgeHub + AssetHub) with zombienet](#1-run-chains-kusama--bridgehub--assethub-polkadot--bridgehub--assethub-with-zombienet) + - [2. Init bridge and run relayer (BridgeHubKusama, BridgeHubPolkadot)](#2-init-bridge-and-run-relayer-bridgehubkusama-bridgehubpolkadot) + - [Send messages - transfer asset over bridge (DOTs/KSMs)](#4-send-messages---transfer-asset-over-bridge-dotsksms) # Bridge-hub Parachains @@ -42,17 +45,29 @@ Copy the apropriate binary (zombienet-linux) from the latest release to ~/local_ --- # 2. Build polkadot binary -git clone https://github.com/paritytech/polkadot.git -cd polkadot -# if you want to test Kusama/Polkadot bridge, we need "sudo pallet + fast-runtime", -# so please, find the latest polkadot's repository branch `it/release-vX.Y.Z-fast-sudo` -# e.g: -# git checkout -b it/release-v0.9.43-fast-sudo --track origin/it/release-v0.9.43-fast-sudo +# If you want to test Kusama/Polkadot bridge, we need "sudo pallet + fast-runtime", +# so we need to use sudofi in polkadot directory. +# +# Install sudofi: (skip if already installed) +# cd +# git clone https://github.com/paritytech/parachain-utils.git +# cd parachain-utils # -> this is +# cargo build --release --bin sudofi +# +# cd /polkadot +# /target/release/sudofi -cargo build --release --features fast-runtime +cd +cargo build --release --features fast-runtime --bin polkadot cp target/release/polkadot ~/local_bridge_testing/bin/polkadot +cargo build --release --features fast-runtime --bin polkadot-prepare-worker +cp target/release/polkadot-prepare-worker ~/local_bridge_testing/bin/polkadot-prepare-worker + +cargo build --release --features fast-runtime --bin polkadot-execute-worker +cp target/release/polkadot-execute-worker ~/local_bridge_testing/bin/polkadot-execute-worker + --- # 3. Build substrate-relay binary @@ -71,41 +86,14 @@ cp target/release/substrate-relay ~/local_bridge_testing/bin/substrate-relay --- # 4. Build cumulus polkadot-parachain binary -cd +cd -# checkout desired branch or use master: -# git checkout -b master --track origin/master - -cargo build --release --locked --bin polkadot-parachain +cargo build --release -p polkadot-parachain-bin cp target/release/polkadot-parachain ~/local_bridge_testing/bin/polkadot-parachain cp target/release/polkadot-parachain ~/local_bridge_testing/bin/polkadot-parachain-asset-hub - - - -# !!! READ HERE (TODO remove once all mentioned branches bellow are merged) -# The use case "moving assets over bridge" is not merged yet and is implemented in separate branches. -# So, if you want to try it, you need to checkout different branch and continue with these instructions there. - -# For Kusama/Polkadot local bridge testing: -# -# build BridgeHubs (polkadot-parachain) from branch: -# git checkout -b bridge-hub-kusama-polkadot --track origin/bridge-hub-kusama-polkadot -# cargo build --release --locked --bin polkadot-parachain -# cp target/release/polkadot-parachain ~/local_bridge_testing/bin/polkadot-parachain -# -# build AssetHubs (polkadot-parachain-asset-hub) from branch: -# git checkout -b bko-transfer-asset-via-bridge-pallet-xcm --track origin/bko-transfer-asset-via-bridge-pallet-xcm -# cargo build --release --locked --bin polkadot-parachain -# cp target/release/polkadot-parachain ~/local_bridge_testing/bin/polkadot-parachain-asset-hub - -# For Rococo/Wococo local bridge testing: -# -# build AssetHubs (polkadot-parachain-asset-hub) from branch: -# git checkout -b bko-transfer-asset-via-bridge-pallet-xcm-ro-wo --track origin/bko-transfer-asset-via-bridge-pallet-xcm-ro-wo -# cargo build --release --locked --bin polkadot-parachain -# cp target/release/polkadot-parachain ~/local_bridge_testing/bin/polkadot-parachain-asset-hub ``` + ## How to test local Rococo <-> Wococo bridge ### Run chains (Rococo + BridgeHub + AssetHub, Wococo + BridgeHub + AssetHub) with zombienet @@ -227,7 +215,74 @@ is going to be replaced by `pallet_xcm` usage) https://polkadot.js.org/apps/?rpc=wss%3A%2F%2Fwococo-wockmint-rpc.polkadot.io#/explorer - BridgeHubRococo (see `bridgeWococoMessages.MessagesDelivered`) - ## How to test local BridgeHubKusama/BridgeHubPolkadot -TODO: see `# !!! READ HERE` above +Check [requirements](#requirements-for-local-runtesting) for "sudo pallet + fast-runtime". + +### 1. Run chains (Kusama + BridgeHub + AssetHub, Polkadot + BridgeHub + AssetHub) with zombienet + + +``` +cd + +# Kusama + BridgeHubKusama + AssetHubKusama +POLKADOT_BINARY_PATH=~/local_bridge_testing/bin/polkadot \ +POLKADOT_PARACHAIN_BINARY_PATH=~/local_bridge_testing/bin/polkadot-parachain \ +POLKADOT_PARACHAIN_BINARY_PATH_FOR_ASSET_HUB_KUSAMA=~/local_bridge_testing/bin/polkadot-parachain-asset-hub \ + ~/local_bridge_testing/bin/zombienet-linux --provider native spawn ./cumulus/zombienet/bridge-hubs/bridge_hub_kusama_local_network.toml +``` + +``` +cd + +# Polkadot + BridgeHubPolkadot + AssetHubPolkadot +POLKADOT_BINARY_PATH=~/local_bridge_testing/bin/polkadot \ +POLKADOT_PARACHAIN_BINARY_PATH=~/local_bridge_testing/bin/polkadot-parachain \ +POLKADOT_PARACHAIN_BINARY_PATH_FOR_ASSET_HUB_POLKADOT=~/local_bridge_testing/bin/polkadot-parachain-asset-hub \ + ~/local_bridge_testing/bin/zombienet-linux --provider native spawn ./cumulus/zombienet/bridge-hubs/bridge_hub_polkadot_local_network.toml +``` + +### 2. Init bridge and run relayer (BridgeHubKusama, BridgeHubPolkadot) + +``` +cd + +./cumulus/scripts/bridges_kusama_polkadot.sh run-relay +``` + +### 3. Initialize transfer asset over bridge (DOTs/KSMs) + +This initialization does several things: +- creates `ForeignAssets` for wrappedDOTs/wrappedKSMs +- drips SA for AssetHubKusama on AssetHubPolkadot (and vice versa) which holds reserved assets on source chains +``` +cd + +./cumulus/scripts/bridges_kusama_polkadot.sh init-asset-hub-kusama-local +./cumulus/scripts/bridges_kusama_polkadot.sh init-bridge-hub-kusama-local +./cumulus/scripts/bridges_kusama_polkadot.sh init-asset-hub-polkadot-local +./cumulus/scripts/bridges_kusama_polkadot.sh init-bridge-hub-polkadot-local +``` + +### 4. Send messages - transfer asset over bridge (DOTs/KSMs) + +Do (asset) transfers: +``` +cd + +# 2.5 KSMs from Kusama's Asset Hub to Polkadot's. +./cumulus/scripts/bridges_kusama_polkadot.sh reserve-transfer-assets-from-asset-hub-kusama-local +``` +``` +cd + +# 30 DOTs from Polkadot's Asset Hub to Kusama's. +./cumulus/scripts/bridges_kusama_polkadot.sh reserve-transfer-assets-from-asset-hub-polkadot-local +``` + +- open explorers: (see zombienets) + - AssetHubKusama (see events `xcmpQueue.XcmpMessageSent`, `polkadotXcm.Attempted`) https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:9910#/explorer + - BridgeHubKusama (see `bridgePolkadotMessages.MessageAccepted`) https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:8943#/explorer + - BridgeHubPolkadot (see `bridgeKusamaMessages.MessagesReceived`, `xcmpQueue.XcmpMessageSent`) https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:8945#/explorer + - AssetHubPolkadot (see `foreignAssets.Issued`, `xcmpQueue.Success`) https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:9010#/explorer + - BridgeHubKusama (see `bridgePolkadotMessages.MessagesDelivered`) https://polkadot.js.org/apps/?rpc=ws://127.0.0.1:8943#/explorer diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/Cargo.toml index 67c3fa37df04..5808127b5852 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/Cargo.toml @@ -64,19 +64,51 @@ cumulus-pallet-dmp-queue = { path = "../../../../pallets/dmp-queue", default-fea cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook",] } cumulus-pallet-session-benchmarking = { path = "../../../../pallets/session-benchmarking", default-features = false} cumulus-pallet-xcm = { path = "../../../../pallets/xcm", default-features = false } -cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false } +cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false, features = ["bridging"] } cumulus-primitives-core = { path = "../../../../primitives/core", default-features = false } cumulus-primitives-utility = { path = "../../../../primitives/utility", default-features = false } pallet-collator-selection = { path = "../../../../pallets/collator-selection", default-features = false } parachain-info = { path = "../../../pallets/parachain-info", default-features = false } parachains-common = { path = "../../../common", default-features = false } +# Bridges +bp-asset-hub-kusama = { path = "../../../../../bridges/primitives/chain-asset-hub-kusama", default-features = false } +bp-bridge-hub-kusama = { path = "../../../../../bridges/primitives/chain-bridge-hub-kusama", default-features = false } +bp-bridge-hub-polkadot = { path = "../../../../../bridges/primitives/chain-bridge-hub-polkadot", default-features = false } +bp-header-chain = { path = "../../../../../bridges/primitives/header-chain", default-features = false } +bp-messages = { path = "../../../../../bridges/primitives/messages", default-features = false } +bp-parachains = { path = "../../../../../bridges/primitives/parachains", default-features = false } +bp-polkadot-core = { path = "../../../../../bridges/primitives/polkadot-core", default-features = false } +bp-relayers = { path = "../../../../../bridges/primitives/relayers", default-features = false } +bp-runtime = { path = "../../../../../bridges/primitives/runtime", default-features = false } +bp-polkadot = { path = "../../../../../bridges/primitives/chain-polkadot", default-features = false } +bridge-runtime-common = { path = "../../../../../bridges/bin/runtime-common", default-features = false } +pallet-bridge-grandpa = { path = "../../../../../bridges/modules/grandpa", default-features = false } +pallet-bridge-messages = { path = "../../../../../bridges/modules/messages", default-features = false } +pallet-bridge-parachains = { path = "../../../../../bridges/modules/parachains", default-features = false } +pallet-bridge-relayers = { path = "../../../../../bridges/modules/relayers", default-features = false } + [dev-dependencies] +static_assertions = "1.1" bridge-hub-test-utils = { path = "../test-utils" } +bridge-runtime-common = { path = "../../../../../bridges/bin/runtime-common", features = ["integrity-test"] } +bp-kusama = { path = "../../../../../bridges/primitives/chain-kusama" } +sp-keyring = { path = "../../../../../substrate/primitives/keyring" } [features] default = [ "std" ] std = [ + "bp-asset-hub-kusama/std", + "bp-bridge-hub-kusama/std", + "bp-bridge-hub-polkadot/std", + "bp-header-chain/std", + "bp-messages/std", + "bp-parachains/std", + "bp-polkadot-core/std", + "bp-polkadot/std", + "bp-relayers/std", + "bp-runtime/std", + "bridge-runtime-common/std", "codec/std", "cumulus-pallet-aura-ext/std", "cumulus-pallet-dmp-queue/std", @@ -98,6 +130,10 @@ std = [ "pallet-aura/std", "pallet-authorship/std", "pallet-balances/std", + "pallet-bridge-grandpa/std", + "pallet-bridge-messages/std", + "pallet-bridge-parachains/std", + "pallet-bridge-relayers/std", "pallet-collator-selection/std", "pallet-multisig/std", "pallet-session/std", @@ -134,6 +170,7 @@ std = [ ] runtime-benchmarks = [ + "bridge-runtime-common/runtime-benchmarks", "cumulus-pallet-parachain-system/runtime-benchmarks", "cumulus-pallet-session-benchmarking/runtime-benchmarks", "cumulus-pallet-xcmp-queue/runtime-benchmarks", @@ -143,6 +180,10 @@ runtime-benchmarks = [ "frame-system-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", + "pallet-bridge-grandpa/runtime-benchmarks", + "pallet-bridge-messages/runtime-benchmarks", + "pallet-bridge-parachains/runtime-benchmarks", + "pallet-bridge-relayers/runtime-benchmarks", "pallet-collator-selection/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", @@ -170,6 +211,10 @@ try-runtime = [ "pallet-aura/try-runtime", "pallet-authorship/try-runtime", "pallet-balances/try-runtime", + "pallet-bridge-grandpa/try-runtime", + "pallet-bridge-messages/try-runtime", + "pallet-bridge-parachains/try-runtime", + "pallet-bridge-relayers/try-runtime", "pallet-collator-selection/try-runtime", "pallet-multisig/try-runtime", "pallet-session/try-runtime", diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/bridge_hub_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/bridge_hub_config.rs new file mode 100644 index 000000000000..d0b999dc6732 --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/bridge_hub_config.rs @@ -0,0 +1,270 @@ +// Copyright 2022 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 . + +//! Kusama BridgeHub definitions. + +use crate::{ + BridgeParachainPolkadotInstance, BridgePolkadotMessages, Runtime, + WithBridgeHubPolkadotMessagesInstance, XcmRouter, +}; +use bp_messages::LaneId; +use bridge_runtime_common::{ + messages, + messages::{ + source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, + MessageBridge, ThisChainWithMessages, UnderlyingChainProvider, + }, + messages_xcm_extension::{SenderAndLane, XcmBlobHauler, XcmBlobHaulerAdapter}, + refund_relayer_extension::{ + ActualFeeRefund, RefundBridgedParachainMessages, RefundableMessagesLane, + RefundableParachain, + }, +}; +use codec::Encode; +use frame_support::{parameter_types, traits::PalletInfoAccess}; +use sp_runtime::RuntimeDebug; +use xcm::{latest::prelude::*, prelude::NetworkId}; +use xcm_builder::{BridgeBlobDispatcher, HaulBlobExporter}; + +parameter_types! { + pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce = + bp_bridge_hub_kusama::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce = + bp_bridge_hub_kusama::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + pub const BridgeHubPolkadotChainId: bp_runtime::ChainId = bp_runtime::BRIDGE_HUB_POLKADOT_CHAIN_ID; + pub BridgePolkadotMessagesPalletInstance: InteriorMultiLocation = X1(PalletInstance(::index() as u8)); + pub PolkadotGlobalConsensusNetwork: NetworkId = NetworkId::Polkadot; + // see the `FEE_BOOST_PER_MESSAGE` constant to get the meaning of this value + pub PriorityBoostPerMessage: u64 = 91_022_222_222_222; + + pub AssetHubKusamaParaId: cumulus_primitives_core::ParaId = bp_asset_hub_kusama::ASSET_HUB_KUSAMA_PARACHAIN_ID.into(); + + pub FromAssetHubKusamaToAssetHubPolkadotRoute: SenderAndLane = SenderAndLane::new( + ParentThen(X1(Parachain(AssetHubKusamaParaId::get().into()))).into(), + ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID, + ); + + pub CongestedMessage: Xcm<()> = sp_std::vec![Transact { + origin_kind: OriginKind::Xcm, + require_weight_at_most: bp_asset_hub_kusama::XcmBridgeHubRouterTransactCallMaxWeight::get(), + call: bp_asset_hub_kusama::Call::ToPolkadotXcmRouter( + bp_asset_hub_kusama::XcmBridgeHubRouterCall::report_bridge_status { + bridge_id: Default::default(), + is_congested: true, + } + ).encode().into(), + }].into(); + + pub UncongestedMessage: Xcm<()> = sp_std::vec![Transact { + origin_kind: OriginKind::Xcm, + require_weight_at_most: bp_asset_hub_kusama::XcmBridgeHubRouterTransactCallMaxWeight::get(), + call: bp_asset_hub_kusama::Call::ToPolkadotXcmRouter( + bp_asset_hub_kusama::XcmBridgeHubRouterCall::report_bridge_status { + bridge_id: Default::default(), + is_congested: false, + } + ).encode().into(), + }].into(); +} + +/// Proof of messages, coming from BridgeHubPolkadot. +pub type FromBridgeHubPolkadotMessagesProof = + FromBridgedChainMessagesProof; +/// Message delivery proof for `BridgeHubPolkadot` messages. +pub type ToBridgeHubPolkadotMessagesDeliveryProof = + FromBridgedChainMessagesDeliveryProof; + +/// Dispatches received XCM messages from other bridge +pub type OnThisChainBlobDispatcher = + BridgeBlobDispatcher; + +/// Export XCM messages to be relayed to the other side. +pub type ToBridgeHubPolkadotHaulBlobExporter = HaulBlobExporter< + XcmBlobHaulerAdapter, + PolkadotGlobalConsensusNetwork, + (), +>; +pub struct ToBridgeHubPolkadotXcmBlobHauler; +impl XcmBlobHauler for ToBridgeHubPolkadotXcmBlobHauler { + type Runtime = Runtime; + type MessagesInstance = WithBridgeHubPolkadotMessagesInstance; + type SenderAndLane = FromAssetHubKusamaToAssetHubPolkadotRoute; + + type ToSourceChainSender = crate::XcmRouter; + type CongestedMessage = CongestedMessage; + type UncongestedMessage = UncongestedMessage; +} + +/// On messages delivered callback. +pub type OnMessagesDelivered = XcmBlobHaulerAdapter; + +/// Messaging Bridge configuration for ThisChain -> BridgeHubPolkadot +pub struct WithBridgeHubPolkadotMessageBridge; +impl MessageBridge for WithBridgeHubPolkadotMessageBridge { + const BRIDGED_MESSAGES_PALLET_NAME: &'static str = + bp_bridge_hub_kusama::WITH_BRIDGE_HUB_KUSAMA_MESSAGES_PALLET_NAME; + type ThisChain = ThisChain; + type BridgedChain = BridgeHubPolkadot; + type BridgedHeaderChain = pallet_bridge_parachains::ParachainHeaders< + Runtime, + BridgeParachainPolkadotInstance, + bp_bridge_hub_polkadot::BridgeHubPolkadot, + >; +} + +/// Message verifier for BridgeHubPolkadot messages sent from ThisChain +pub type ToBridgeHubPolkadotMessageVerifier = + messages::source::FromThisChainMessageVerifier; + +/// Maximal outbound payload size of ThisChain -> BridgeHubPolkadot messages. +pub type ToBridgeHubPolkadotMaximalOutboundPayloadSize = + messages::source::FromThisChainMaximalOutboundPayloadSize; + +/// BridgeHubPolkadot chain from message lane point of view. +#[derive(RuntimeDebug, Clone, Copy)] +pub struct BridgeHubPolkadot; + +impl UnderlyingChainProvider for BridgeHubPolkadot { + type Chain = bp_bridge_hub_polkadot::BridgeHubPolkadot; +} + +impl messages::BridgedChainWithMessages for BridgeHubPolkadot {} + +/// ThisChain chain from message lane point of view. +#[derive(RuntimeDebug, Clone, Copy)] +pub struct ThisChain; + +impl UnderlyingChainProvider for ThisChain { + type Chain = bp_bridge_hub_kusama::BridgeHubKusama; +} + +impl ThisChainWithMessages for ThisChain { + type RuntimeOrigin = crate::RuntimeOrigin; +} + +// TODO: rework once dynamic lanes are supported (https://github.com/paritytech/parity-bridges-common/issues/1760) +/// Signed extension that refunds relayers that are delivering messages from the Polkadot BridgeHub. +pub type BridgeRefundBridgeHubPolkadotMessages = RefundBridgedParachainMessages< + Runtime, + RefundableParachain, + RefundableMessagesLane< + WithBridgeHubPolkadotMessagesInstance, + AssetHubKusamaToAssetHubPolkadotMessageLane, + >, + ActualFeeRefund, + PriorityBoostPerMessage, + StrBridgeRefundBridgeHubPolkadotMessages, +>; +bp_runtime::generate_static_str_provider!(BridgeRefundBridgeHubPolkadotMessages); + +// TODO: rework once dynamic lanes are supported (https://github.com/paritytech/parity-bridges-common/issues/1760) +// now we support only StatemineToStatemint +/// Lanes setup +pub const ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID: LaneId = LaneId([0, 0, 0, 0]); +parameter_types! { + pub ActiveOutboundLanesToBridgeHubPolkadot: &'static [bp_messages::LaneId] = &[ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID]; + pub const AssetHubKusamaToAssetHubPolkadotMessageLane: bp_messages::LaneId = ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID; +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::BridgeGrandpaPolkadotInstance; + use bridge_runtime_common::{ + assert_complete_bridge_types, + integrity::{ + assert_complete_bridge_constants, check_message_lane_weights, + AssertBridgeMessagesPalletConstants, AssertBridgePalletNames, AssertChainConstants, + AssertCompleteBridgeConstants, + }, + }; + use parachains_common::{kusama, Balance}; + + /// Every additional message in the message delivery transaction boosts its priority. + /// So the priority of transaction with `N+1` messages is larger than priority of + /// transaction with `N` messages by the `PriorityBoostPerMessage`. + /// + /// Economically, it is an equivalent of adding tip to the transaction with `N` messages. + /// The `FEE_BOOST_PER_MESSAGE` constant is the value of this tip. + /// + /// We want this tip to be large enough (delivery transactions with more messages = less + /// operational costs and a faster bridge), so this value should be significant. + const FEE_BOOST_PER_MESSAGE: Balance = kusama::currency::UNITS; + + #[test] + fn ensure_lane_weights_are_correct() { + check_message_lane_weights::< + bp_bridge_hub_kusama::BridgeHubKusama, + Runtime, + WithBridgeHubPolkadotMessagesInstance, + >( + bp_bridge_hub_polkadot::EXTRA_STORAGE_PROOF_SIZE, + bp_bridge_hub_kusama::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + bp_bridge_hub_kusama::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + true, + ); + } + + #[test] + fn ensure_bridge_integrity() { + assert_complete_bridge_types!( + runtime: Runtime, + with_bridged_chain_grandpa_instance: BridgeGrandpaPolkadotInstance, + with_bridged_chain_messages_instance: WithBridgeHubPolkadotMessagesInstance, + bridge: WithBridgeHubPolkadotMessageBridge, + this_chain: bp_kusama::Kusama, + bridged_chain: bp_polkadot::Polkadot, + ); + + assert_complete_bridge_constants::< + Runtime, + BridgeGrandpaPolkadotInstance, + WithBridgeHubPolkadotMessagesInstance, + WithBridgeHubPolkadotMessageBridge, + >(AssertCompleteBridgeConstants { + this_chain_constants: AssertChainConstants { + block_length: bp_bridge_hub_kusama::BlockLength::get(), + block_weights: bp_bridge_hub_kusama::BlockWeights::get(), + }, + messages_pallet_constants: AssertBridgeMessagesPalletConstants { + max_unrewarded_relayers_in_bridged_confirmation_tx: + bp_bridge_hub_polkadot::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + max_unconfirmed_messages_in_bridged_confirmation_tx: + bp_bridge_hub_polkadot::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + bridged_chain_id: bp_runtime::BRIDGE_HUB_POLKADOT_CHAIN_ID, + }, + pallet_names: AssertBridgePalletNames { + with_this_chain_messages_pallet_name: + bp_bridge_hub_kusama::WITH_BRIDGE_HUB_KUSAMA_MESSAGES_PALLET_NAME, + with_bridged_chain_grandpa_pallet_name: + bp_polkadot::WITH_POLKADOT_GRANDPA_PALLET_NAME, + with_bridged_chain_messages_pallet_name: + bp_bridge_hub_polkadot::WITH_BRIDGE_HUB_POLKADOT_MESSAGES_PALLET_NAME, + }, + }); + + bridge_runtime_common::priority_calculator::ensure_priority_boost_is_sane::< + Runtime, + WithBridgeHubPolkadotMessagesInstance, + PriorityBoostPerMessage, + >(FEE_BOOST_PER_MESSAGE); + + assert_eq!( + BridgePolkadotMessagesPalletInstance::get(), + X1(PalletInstance(bp_bridge_hub_kusama::WITH_BRIDGE_POLKADOT_MESSAGES_PALLET_INDEX)) + ); + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/lib.rs index 54b15e6b327b..a2c39872088e 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/lib.rs @@ -22,6 +22,7 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +pub mod bridge_hub_config; mod weights; pub mod xcm_config; @@ -59,6 +60,9 @@ use xcm_config::{ FellowshipLocation, GovernanceLocation, XcmConfig, XcmOriginToTransactDispatchOrigin, }; +use bp_parachains::SingleParaStoredHeaderDataBuilder; +use bp_runtime::HeaderId; + #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; @@ -73,7 +77,19 @@ use parachains_common::{ HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION, }; -// XCM Imports +use crate::{ + bridge_hub_config::{ + BridgeRefundBridgeHubPolkadotMessages, OnThisChainBlobDispatcher, + WithBridgeHubPolkadotMessageBridge, + }, + xcm_config::{UniversalLocation, XcmRouter}, +}; + +use bridge_runtime_common::{ + messages::{source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter}, + messages_xcm_extension::{XcmAsPlainPayload, XcmBlobMessageDispatch}, +}; + use xcm::latest::prelude::BodyId; use xcm_executor::XcmExecutor; @@ -99,6 +115,8 @@ pub type SignedExtra = ( frame_system::CheckNonce, frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, + BridgeRejectObsoleteHeadersAndMessages, + BridgeRefundBridgeHubPolkadotMessages, ); /// Unchecked extrinsic type as expected by this runtime. @@ -401,6 +419,108 @@ impl pallet_utility::Config for Runtime { type WeightInfo = weights::pallet_utility::WeightInfo; } +// Add bridge pallets (GPA) +/// Add GRANDPA bridge pallet to track Polkadot relay chain on Kusama BridgeHub +pub type BridgeGrandpaPolkadotInstance = pallet_bridge_grandpa::Instance1; +impl pallet_bridge_grandpa::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type BridgedChain = bp_polkadot::Polkadot; + type MaxFreeMandatoryHeadersPerBlock = ConstU32<4>; + type HeadersToKeep = RelayChainHeadersToKeep; + type WeightInfo = weights::pallet_bridge_grandpa::WeightInfo; +} + +parameter_types! { + pub const RelayChainHeadersToKeep: u32 = 600; + pub const ParachainHeadsToKeep: u32 = 300; + /// Delay (in blocks) before registered relayer could get its stake back. It guarantees + /// that all pending delivery transactions are either dropped or mined and relayer is + /// slashed in case of misbehavior. So this value should be large enough (e.g. 24 hours). + pub const RelayerStakeLease: u32 = parachains_common::DAYS; + pub const PolkadotBridgeParachainPalletName: &'static str = bp_polkadot::PARAS_PALLET_NAME; + pub const MaxPolkadotParaHeadDataSize: u32 = bp_polkadot::MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE; + + pub const RelayerStakeReserveId: [u8; 8] = *b"brdgrlrs"; + // Just initial value, and concrete values will be set up by governance call (`set_storage`) with `initialize` bridge call as a part of cutover plan (https://github.com/paritytech/parity-bridges-common/issues/1730) + pub storage DeliveryRewardInBalance: u64 = 1_000_000; +} + +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub storage RequiredStakeForStakeAndSlash: Balance = 1; +} +#[cfg(not(feature = "runtime-benchmarks"))] +parameter_types! { + // Just initial value, and concrete values will be set up by governance call (`set_storage`) with `initialize` bridge call as a part of cutover plan (https://github.com/paritytech/parity-bridges-common/issues/1730) + pub storage RequiredStakeForStakeAndSlash: Balance = Balance::MAX; +} + +/// Add parachain bridge pallet to track Polkadot BridgeHub parachain +pub type BridgeParachainPolkadotInstance = pallet_bridge_parachains::Instance1; +impl pallet_bridge_parachains::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = weights::pallet_bridge_parachains::WeightInfo; + type BridgesGrandpaPalletInstance = BridgeGrandpaPolkadotInstance; + type ParasPalletName = PolkadotBridgeParachainPalletName; + type ParaStoredHeaderDataBuilder = + SingleParaStoredHeaderDataBuilder; + type HeadsToKeep = ParachainHeadsToKeep; + type MaxParaHeadDataSize = MaxPolkadotParaHeadDataSize; +} + +/// Add XCM messages support for Kusama<->Polkadot XCM messages +pub type WithBridgeHubPolkadotMessagesInstance = pallet_bridge_messages::Instance1; +impl pallet_bridge_messages::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = weights::pallet_bridge_messages::WeightInfo; + type BridgedChainId = bridge_hub_config::BridgeHubPolkadotChainId; + type ActiveOutboundLanes = bridge_hub_config::ActiveOutboundLanesToBridgeHubPolkadot; + type MaxUnrewardedRelayerEntriesAtInboundLane = + bridge_hub_config::MaxUnrewardedRelayerEntriesAtInboundLane; + type MaxUnconfirmedMessagesAtInboundLane = + bridge_hub_config::MaxUnconfirmedMessagesAtInboundLane; + type MaximalOutboundPayloadSize = + bridge_hub_config::ToBridgeHubPolkadotMaximalOutboundPayloadSize; + type OutboundPayload = XcmAsPlainPayload; + type InboundPayload = XcmAsPlainPayload; + type InboundRelayer = AccountId; + type DeliveryPayments = (); + type TargetHeaderChain = TargetHeaderChainAdapter; + type LaneMessageVerifier = bridge_hub_config::ToBridgeHubPolkadotMessageVerifier; + type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< + Runtime, + WithBridgeHubPolkadotMessagesInstance, + DeliveryRewardInBalance, + >; + type SourceHeaderChain = SourceHeaderChainAdapter; + type MessageDispatch = XcmBlobMessageDispatch< + OnThisChainBlobDispatcher, + Self::WeightInfo, + cumulus_pallet_xcmp_queue::bridging::OutXcmpChannelStatusProvider< + bridge_hub_config::AssetHubKusamaParaId, + Runtime, + >, + >; + type OnMessagesDelivered = bridge_hub_config::OnMessagesDelivered; +} + +/// Allows collect and claim rewards for relayers +impl pallet_bridge_relayers::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Reward = Balance; + type PaymentProcedure = + bp_relayers::PayRewardFromAccount, AccountId>; + type StakeAndSlash = pallet_bridge_relayers::StakeAndSlashNamed< + AccountId, + BlockNumber, + Balances, + RelayerStakeReserveId, + RequiredStakeForStakeAndSlash, + RelayerStakeLease, + >; + type WeightInfo = weights::pallet_bridge_relayers::WeightInfo; +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime @@ -433,9 +553,25 @@ construct_runtime!( // Handy utilities. Utility: pallet_utility::{Pallet, Call, Event} = 40, Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 41, + + // Kusama<>Polkadot bridge pallets// Bridging pallets + BridgePolkadotGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Storage, Event, Config} = 51, + BridgePolkadotParachain: pallet_bridge_parachains::::{Pallet, Call, Storage, Event} = 52, + BridgePolkadotMessages: pallet_bridge_messages::::{Pallet, Call, Storage, Event, Config} = 53, + BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event} = 54, } ); +bridge_runtime_common::generate_bridge_reject_obsolete_headers_and_messages! { + RuntimeCall, AccountId, + // Grandpa + BridgePolkadotGrandpa, + // Parachains + BridgePolkadotParachain, + // Messages + BridgePolkadotMessages +} + #[cfg(feature = "runtime-benchmarks")] #[macro_use] extern crate frame_benchmarking; @@ -456,6 +592,12 @@ mod benches { // NOTE: Make sure you point to the individual modules below. [pallet_xcm_benchmarks::fungible, XcmBalances] [pallet_xcm_benchmarks::generic, XcmGeneric] + // Bridge pallets for Polkadot + [pallet_bridge_grandpa, BridgePolkadotGrandpa] + [pallet_bridge_parachains, BridgeParachainsBench::] + [pallet_bridge_messages, BridgeMessagesBench::] + // Bridge relayer pallets + [pallet_bridge_relayers, BridgeRelayersBench::] ); } @@ -603,6 +745,49 @@ impl_runtime_apis! { } } + impl bp_polkadot::PolkadotFinalityApi for Runtime { + fn best_finalized() -> Option> { + BridgePolkadotGrandpa::best_finalized() + } + fn synced_headers_grandpa_info( + ) -> Vec> { + BridgePolkadotGrandpa::synced_headers_grandpa_info() + } + } + + impl bp_bridge_hub_polkadot::BridgeHubPolkadotFinalityApi for Runtime { + fn best_finalized() -> Option> { + BridgePolkadotParachain::best_parachain_head_id::< + bp_bridge_hub_polkadot::BridgeHubPolkadot + >().unwrap_or(None) + } + } + + impl bp_bridge_hub_polkadot::FromBridgeHubPolkadotInboundLaneApi for Runtime { + fn message_details( + lane: bp_messages::LaneId, + messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, + ) -> Vec { + bridge_runtime_common::messages_api::inbound_message_details::< + Runtime, + WithBridgeHubPolkadotMessagesInstance, + >(lane, messages) + } + } + + impl bp_bridge_hub_polkadot::ToBridgeHubPolkadotOutboundLaneApi for Runtime { + fn message_details( + lane: bp_messages::LaneId, + begin: bp_messages::MessageNonce, + end: bp_messages::MessageNonce, + ) -> Vec { + bridge_runtime_common::messages_api::outbound_message_details::< + Runtime, + WithBridgeHubPolkadotMessagesInstance, + >(lane, begin, end) + } + } + #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime for Runtime { fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { @@ -639,6 +824,10 @@ impl_runtime_apis! { type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::; type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::; + use pallet_bridge_parachains::benchmarking::Pallet as BridgeParachainsBench; + use pallet_bridge_messages::benchmarking::Pallet as BridgeMessagesBench; + use pallet_bridge_relayers::benchmarking::Pallet as BridgeRelayersBench; + let mut list = Vec::::new(); list_benchmarks!(list, extra); @@ -748,7 +937,7 @@ impl_runtime_apis! { fn export_message_origin_and_destination( ) -> Result<(MultiLocation, NetworkId, InteriorMultiLocation), BenchmarkError> { - Err(BenchmarkError::Skip) + Ok((KsmRelayLocation::get(), bridge_hub_config::PolkadotGlobalConsensusNetwork::get(), X1(Parachain(100)))) } fn alias_origin() -> Result<(MultiLocation, MultiLocation), BenchmarkError> { @@ -759,6 +948,106 @@ impl_runtime_apis! { type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::; type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::; + use bridge_runtime_common::messages_benchmarking::{ + generate_xcm_builder_bridge_message_sample, + prepare_message_delivery_proof_from_parachain, + prepare_message_proof_from_parachain + }; + use pallet_bridge_messages::benchmarking::{ + Config as BridgeMessagesConfig, + Pallet as BridgeMessagesBench, + MessageDeliveryProofParams, + MessageProofParams, + }; + impl BridgeMessagesConfig for Runtime { + fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool { + let bench_lane_id = >::bench_lane_id(); + let bridged_chain_id = bp_runtime::BRIDGE_HUB_POLKADOT_CHAIN_ID; + pallet_bridge_relayers::Pallet::::relayer_reward( + relayer, + bp_relayers::RewardsAccountParams::new( + bench_lane_id, + bridged_chain_id, + bp_relayers::RewardsAccountOwner::BridgedChain + ) + ).is_some() + } + fn prepare_message_proof( + params: MessageProofParams, + ) -> (bridge_hub_config::FromBridgeHubPolkadotMessagesProof, Weight) { + use cumulus_primitives_core::XcmpMessageSource; + assert!(XcmpQueue::take_outbound_messages(usize::MAX).is_empty()); + ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(42.into()); + prepare_message_proof_from_parachain::< + Runtime, + BridgeGrandpaPolkadotInstance, + bridge_hub_config::WithBridgeHubPolkadotMessageBridge, + >(params, generate_xcm_builder_bridge_message_sample(X2(GlobalConsensus(xcm_config::RelayNetwork::get().unwrap()), Parachain(42)))) + } + fn prepare_message_delivery_proof( + params: MessageDeliveryProofParams, + ) -> bridge_hub_config::ToBridgeHubPolkadotMessagesDeliveryProof { + prepare_message_delivery_proof_from_parachain::< + Runtime, + BridgeGrandpaPolkadotInstance, + bridge_hub_config::WithBridgeHubPolkadotMessageBridge, + >(params) + } + fn is_message_successfully_dispatched(_nonce: bp_messages::MessageNonce) -> bool { + use cumulus_primitives_core::XcmpMessageSource; + !XcmpQueue::take_outbound_messages(usize::MAX).is_empty() + } + } + + use bridge_runtime_common::parachains_benchmarking::prepare_parachain_heads_proof; + use pallet_bridge_parachains::benchmarking::{ + Config as BridgeParachainsConfig, + Pallet as BridgeParachainsBench, + }; + use pallet_bridge_relayers::benchmarking::{ + Pallet as BridgeRelayersBench, + Config as BridgeRelayersConfig, + }; + impl BridgeParachainsConfig for Runtime { + fn parachains() -> Vec { + use bp_runtime::Parachain; + vec![bp_polkadot_core::parachains::ParaId(bp_bridge_hub_polkadot::BridgeHubPolkadot::PARACHAIN_ID)] + } + fn prepare_parachain_heads_proof( + parachains: &[bp_polkadot_core::parachains::ParaId], + parachain_head_size: u32, + proof_size: bp_runtime::StorageProofSize, + ) -> ( + pallet_bridge_parachains::RelayBlockNumber, + pallet_bridge_parachains::RelayBlockHash, + bp_polkadot_core::parachains::ParaHeadsProof, + Vec<(bp_polkadot_core::parachains::ParaId, bp_polkadot_core::parachains::ParaHash)>, + ) { + prepare_parachain_heads_proof::( + parachains, + parachain_head_size, + proof_size, + ) + } + } + + impl BridgeRelayersConfig for Runtime { + fn prepare_rewards_account( + account_params: bp_relayers::RewardsAccountParams, + reward: Balance, + ) { + let rewards_account = bp_relayers::PayRewardFromAccount::< + Balances, + AccountId + >::rewards_account(account_params); + Self::deposit_account(rewards_account, reward); + } + fn deposit_account(account: AccountId, balance: Balance) { + use frame_support::traits::fungible::Mutate; + Balances::mint_into(&account, balance.saturating_add(ExistentialDeposit::get())).unwrap(); + } + } + let whitelist: Vec = vec![ // Block Number hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), @@ -785,3 +1074,49 @@ cumulus_pallet_parachain_system::register_validate_block! { Runtime = Runtime, BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, } + +#[cfg(test)] +mod tests { + use super::*; + use codec::Encode; + use sp_runtime::{ + generic::Era, + traits::{SignedExtension, Zero}, + }; + + #[test] + fn ensure_signed_extension_definition_is_compatible_with_relay() { + use bp_polkadot_core::SuffixedCommonSignedExtensionExt; + + sp_io::TestExternalities::default().execute_with(|| { + frame_system::BlockHash::::insert(BlockNumber::zero(), Hash::default()); + let payload: SignedExtra = ( + frame_system::CheckNonZeroSender::new(), + frame_system::CheckSpecVersion::new(), + frame_system::CheckTxVersion::new(), + frame_system::CheckGenesis::new(), + frame_system::CheckEra::from(Era::Immortal), + frame_system::CheckNonce::from(10), + frame_system::CheckWeight::new(), + pallet_transaction_payment::ChargeTransactionPayment::from(10), + BridgeRejectObsoleteHeadersAndMessages, + BridgeRefundBridgeHubPolkadotMessages::default(), + ); + + let bh_indirect_payload = bp_bridge_hub_polkadot::SignedExtension::from_params( + VERSION.spec_version, + VERSION.transaction_version, + bp_runtime::TransactionEra::Immortal, + System::block_hash(BlockNumber::zero()), + 10, + 10, + (((), ()), ((), ())), + ); + assert_eq!(payload.encode(), bh_indirect_payload.encode()); + assert_eq!( + payload.additional_signed().unwrap().encode(), + bh_indirect_payload.additional_signed().unwrap().encode() + ); + }) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/mod.rs index e226021e77ab..759aa1eac63c 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/mod.rs @@ -22,6 +22,10 @@ pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; pub mod pallet_balances; +pub mod pallet_bridge_grandpa; +pub mod pallet_bridge_messages; +pub mod pallet_bridge_parachains; +pub mod pallet_bridge_relayers; pub mod pallet_collator_selection; pub mod pallet_multisig; pub mod pallet_session; @@ -36,3 +40,32 @@ pub use block_weights::constants::BlockExecutionWeight; pub use extrinsic_weights::constants::ExtrinsicBaseWeight; pub use paritydb_weights::constants::ParityDbWeight; pub use rocksdb_weights::constants::RocksDbWeight; + +use frame_support::weights::Weight; + +// import trait from dependency module +use ::pallet_bridge_relayers::WeightInfoExt as _; + +impl ::pallet_bridge_messages::WeightInfoExt + for pallet_bridge_messages::WeightInfo +{ + fn expected_extra_storage_proof_size() -> u32 { + bp_bridge_hub_polkadot::EXTRA_STORAGE_PROOF_SIZE + } + + fn receive_messages_proof_overhead_from_runtime() -> Weight { + pallet_bridge_relayers::WeightInfo::::receive_messages_proof_overhead_from_runtime() + } + + fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight { + pallet_bridge_relayers::WeightInfo::::receive_messages_delivery_proof_overhead_from_runtime() + } +} + +impl ::pallet_bridge_parachains::WeightInfoExt + for pallet_bridge_parachains::WeightInfo +{ + fn expected_extra_storage_proof_size() -> u32 { + bp_bridge_hub_polkadot::EXTRA_STORAGE_PROOF_SIZE + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_grandpa.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_grandpa.rs new file mode 100644 index 000000000000..b9d4f0a17e0a --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_grandpa.rs @@ -0,0 +1,80 @@ +// 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 . + +//! Autogenerated weights for `pallet_bridge_grandpa` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `bm3`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-kusama-dev"), DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot-parachain +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/var/lib/gitlab-runner/builds/zyw4fam_/0/parity/mirrors/cumulus/.git/.artifacts/bench.json +// --pallet=pallet_bridge_grandpa +// --chain=bridge-hub-kusama-dev +// --header=./file_header.txt +// --output=./parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_bridge_grandpa`. +pub struct WeightInfo(PhantomData); +impl pallet_bridge_grandpa::WeightInfo for WeightInfo { + /// Storage: BridgePolkadotGrandpa PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotGrandpa PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: BridgePolkadotGrandpa BestFinalized (r:1 w:1) + /// Proof: BridgePolkadotGrandpa BestFinalized (max_values: Some(1), max_size: Some(36), added: 531, mode: MaxEncodedLen) + /// Storage: BridgePolkadotGrandpa CurrentAuthoritySet (r:1 w:0) + /// Proof: BridgePolkadotGrandpa CurrentAuthoritySet (max_values: Some(1), max_size: Some(50250), added: 50745, mode: MaxEncodedLen) + /// Storage: BridgePolkadotGrandpa ImportedHashesPointer (r:1 w:1) + /// Proof: BridgePolkadotGrandpa ImportedHashesPointer (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: BridgePolkadotGrandpa ImportedHashes (r:1 w:1) + /// Proof: BridgePolkadotGrandpa ImportedHashes (max_values: Some(1024), max_size: Some(36), added: 1521, mode: MaxEncodedLen) + /// Storage: BridgePolkadotGrandpa ImportedHeaders (r:0 w:2) + /// Proof: BridgePolkadotGrandpa ImportedHeaders (max_values: Some(1024), max_size: Some(68), added: 1553, mode: MaxEncodedLen) + /// The range of component `p` is `[1, 838]`. + /// The range of component `v` is `[50, 100]`. + fn submit_finality_proof(p: u32, v: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `231 + p * (60 ±0)` + // Estimated: `51735` + // Minimum execution time: 229_674_000 picoseconds. + Weight::from_parts(110_662_672, 0) + .saturating_add(Weight::from_parts(0, 51735)) + // Standard Error: 16_268 + .saturating_add(Weight::from_parts(47_526_047, 0).saturating_mul(p.into())) + // Standard Error: 271_338 + .saturating_add(Weight::from_parts(743_913, 0).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_messages.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_messages.rs new file mode 100644 index 000000000000..f083169f513a --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_messages.rs @@ -0,0 +1,231 @@ +// 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 . + +//! Autogenerated weights for `pallet_bridge_messages` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `bm3`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-kusama-dev"), DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot-parachain +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/var/lib/gitlab-runner/builds/zyw4fam_/0/parity/mirrors/cumulus/.git/.artifacts/bench.json +// --pallet=pallet_bridge_messages +// --chain=bridge-hub-kusama-dev +// --header=./file_header.txt +// --output=./parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_bridge_messages`. +pub struct WeightInfo(PhantomData); +impl pallet_bridge_messages::WeightInfo for WeightInfo { + /// Storage: BridgePolkadotMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgePolkadotMessages InboundLanes (r:1 w:1) + /// Proof: BridgePolkadotMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn receive_single_message_proof() -> Weight { + // Proof Size summary in bytes: + // Measured: `403` + // Estimated: `52645` + // Minimum execution time: 44_142_000 picoseconds. + Weight::from_parts(44_925_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgePolkadotMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgePolkadotMessages InboundLanes (r:1 w:1) + /// Proof: BridgePolkadotMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn receive_two_messages_proof() -> Weight { + // Proof Size summary in bytes: + // Measured: `403` + // Estimated: `52645` + // Minimum execution time: 54_901_000 picoseconds. + Weight::from_parts(55_357_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgePolkadotMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgePolkadotMessages InboundLanes (r:1 w:1) + /// Proof: BridgePolkadotMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn receive_single_message_proof_with_outbound_lane_state() -> Weight { + // Proof Size summary in bytes: + // Measured: `403` + // Estimated: `52645` + // Minimum execution time: 49_037_000 picoseconds. + Weight::from_parts(49_616_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgePolkadotMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgePolkadotMessages InboundLanes (r:1 w:1) + /// Proof: BridgePolkadotMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + fn receive_single_message_proof_1_kb() -> Weight { + // Proof Size summary in bytes: + // Measured: `372` + // Estimated: `52645` + // Minimum execution time: 42_180_000 picoseconds. + Weight::from_parts(42_666_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgePolkadotMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgePolkadotMessages InboundLanes (r:1 w:1) + /// Proof: BridgePolkadotMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + fn receive_single_message_proof_16_kb() -> Weight { + // Proof Size summary in bytes: + // Measured: `372` + // Estimated: `52645` + // Minimum execution time: 69_307_000 picoseconds. + Weight::from_parts(69_871_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgePolkadotMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgePolkadotMessages OutboundLanes (r:1 w:1) + /// Proof: BridgePolkadotMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) + /// Storage: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Proof Skipped: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + fn receive_delivery_proof_for_single_message() -> Weight { + // Proof Size summary in bytes: + // Measured: `376` + // Estimated: `3841` + // Minimum execution time: 33_354_000 picoseconds. + Weight::from_parts(34_244_000, 0) + .saturating_add(Weight::from_parts(0, 3841)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgePolkadotMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgePolkadotMessages OutboundLanes (r:1 w:1) + /// Proof: BridgePolkadotMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) + /// Storage: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Proof Skipped: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { + // Proof Size summary in bytes: + // Measured: `376` + // Estimated: `3841` + // Minimum execution time: 33_264_000 picoseconds. + Weight::from_parts(33_675_000, 0) + .saturating_add(Weight::from_parts(0, 3841)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgePolkadotMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgePolkadotMessages OutboundLanes (r:1 w:1) + /// Proof: BridgePolkadotMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) + /// Storage: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Proof Skipped: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Storage: BridgeRelayers RelayerRewards (r:2 w:2) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { + // Proof Size summary in bytes: + // Measured: `376` + // Estimated: `6086` + // Minimum execution time: 35_608_000 picoseconds. + Weight::from_parts(36_142_000, 0) + .saturating_add(Weight::from_parts(0, 6086)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: BridgePolkadotMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgePolkadotMessages InboundLanes (r:1 w:1) + /// Proof: BridgePolkadotMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem RelevantMessagingState (r:1 w:0) + /// Proof Skipped: ParachainSystem RelevantMessagingState (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: XcmpQueue OutboundXcmpStatus (r:1 w:1) + /// Proof Skipped: XcmpQueue OutboundXcmpStatus (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: XcmpQueue OutboundXcmpMessages (r:0 w:1) + /// Proof Skipped: XcmpQueue OutboundXcmpMessages (max_values: None, max_size: None, mode: Measured) + /// The range of component `i` is `[128, 2048]`. + fn receive_single_message_proof_with_dispatch(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `634` + // Estimated: `52645` + // Minimum execution time: 130_265_000 picoseconds. + Weight::from_parts(100_110_870, 0) + .saturating_add(Weight::from_parts(0, 52645)) + // Standard Error: 3_659 + .saturating_add(Weight::from_parts(547_474, 0).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(4)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_parachains.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_parachains.rs new file mode 100644 index 000000000000..82a19eccba46 --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_parachains.rs @@ -0,0 +1,113 @@ +// 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 . + +//! Autogenerated weights for `pallet_bridge_parachains` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-06, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `bm3`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-kusama-dev"), DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot-parachain +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/var/lib/gitlab-runner/builds/zyw4fam_/0/parity/mirrors/cumulus/.git/.artifacts/bench.json +// --pallet=pallet_bridge_parachains +// --chain=bridge-hub-kusama-dev +// --header=./file_header.txt +// --output=./parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_bridge_parachains`. +pub struct WeightInfo(PhantomData); +impl pallet_bridge_parachains::WeightInfo for WeightInfo { + /// Storage: BridgePolkadotParachain PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotParachain PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: BridgePolkadotGrandpa ImportedHeaders (r:1 w:0) + /// Proof: BridgePolkadotGrandpa ImportedHeaders (max_values: Some(1024), max_size: Some(68), added: 1553, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ParasInfo (r:1 w:1) + /// Proof: BridgePolkadotParachain ParasInfo (max_values: Some(1), max_size: Some(60), added: 555, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHashes (r:1 w:1) + /// Proof: BridgePolkadotParachain ImportedParaHashes (max_values: Some(64), max_size: Some(64), added: 1054, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:0 w:1) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// The range of component `p` is `[1, 2]`. + fn submit_parachain_heads_with_n_parachains(_p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `330` + // Estimated: `2543` + // Minimum execution time: 33_988_000 picoseconds. + Weight::from_parts(35_239_510, 0) + .saturating_add(Weight::from_parts(0, 2543)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: BridgePolkadotParachain PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotParachain PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: BridgePolkadotGrandpa ImportedHeaders (r:1 w:0) + /// Proof: BridgePolkadotGrandpa ImportedHeaders (max_values: Some(1024), max_size: Some(68), added: 1553, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ParasInfo (r:1 w:1) + /// Proof: BridgePolkadotParachain ParasInfo (max_values: Some(1), max_size: Some(60), added: 555, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHashes (r:1 w:1) + /// Proof: BridgePolkadotParachain ImportedParaHashes (max_values: Some(64), max_size: Some(64), added: 1054, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:0 w:1) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + fn submit_parachain_heads_with_1kb_proof() -> Weight { + // Proof Size summary in bytes: + // Measured: `330` + // Estimated: `2543` + // Minimum execution time: 35_298_000 picoseconds. + Weight::from_parts(36_119_000, 0) + .saturating_add(Weight::from_parts(0, 2543)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: BridgePolkadotParachain PalletOperatingMode (r:1 w:0) + /// Proof: BridgePolkadotParachain PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: BridgePolkadotGrandpa ImportedHeaders (r:1 w:0) + /// Proof: BridgePolkadotGrandpa ImportedHeaders (max_values: Some(1024), max_size: Some(68), added: 1553, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ParasInfo (r:1 w:1) + /// Proof: BridgePolkadotParachain ParasInfo (max_values: Some(1), max_size: Some(60), added: 555, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHashes (r:1 w:1) + /// Proof: BridgePolkadotParachain ImportedParaHashes (max_values: Some(64), max_size: Some(64), added: 1054, mode: MaxEncodedLen) + /// Storage: BridgePolkadotParachain ImportedParaHeads (r:0 w:1) + /// Proof: BridgePolkadotParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + fn submit_parachain_heads_with_16kb_proof() -> Weight { + // Proof Size summary in bytes: + // Measured: `330` + // Estimated: `2543` + // Minimum execution time: 61_503_000 picoseconds. + Weight::from_parts(61_999_000, 0) + .saturating_add(Weight::from_parts(0, 2543)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_relayers.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_relayers.rs new file mode 100644 index 000000000000..d51f44aee56b --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/pallet_bridge_relayers.rs @@ -0,0 +1,124 @@ +// 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 . + +//! Autogenerated weights for `pallet_bridge_relayers` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-05, STEPS: `2`, REPEAT: `2`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `bkontur-ThinkPad-P14s-Gen-2i`, CPU: `11th Gen Intel(R) Core(TM) i7-1185G7 @ 3.00GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-kusama-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/production/polkadot-parachain +// benchmark +// pallet +// --steps=2 +// --repeat=2 +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=./bench.json +// --header=./file_header.txt +// --chain=bridge-hub-kusama-dev +// --pallet=pallet_bridge_relayers +// --output=./parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_bridge_relayers`. +pub struct WeightInfo(PhantomData); +impl pallet_bridge_relayers::WeightInfo for WeightInfo { + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + fn claim_rewards() -> Weight { + // Proof Size summary in bytes: + // Measured: `207` + // Estimated: `3593` + // Minimum execution time: 52_874_000 picoseconds. + Weight::from_parts(72_930_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgeRelayers RegisteredRelayers (r:1 w:1) + /// Proof: BridgeRelayers RegisteredRelayers (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: unknown `0x1e8445dc201eeb8560e5579a5dd54655` (r:1 w:0) + /// Proof Skipped: unknown `0x1e8445dc201eeb8560e5579a5dd54655` (r:1 w:0) + /// Storage: Balances Reserves (r:1 w:1) + /// Proof: Balances Reserves (max_values: None, max_size: Some(1249), added: 3724, mode: MaxEncodedLen) + fn register() -> Weight { + // Proof Size summary in bytes: + // Measured: `61` + // Estimated: `4714` + // Minimum execution time: 28_476_000 picoseconds. + Weight::from_parts(32_338_000, 0) + .saturating_add(Weight::from_parts(0, 4714)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgeRelayers RegisteredRelayers (r:1 w:1) + /// Proof: BridgeRelayers RegisteredRelayers (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: Balances Reserves (r:1 w:1) + /// Proof: Balances Reserves (max_values: None, max_size: Some(1249), added: 3724, mode: MaxEncodedLen) + fn deregister() -> Weight { + // Proof Size summary in bytes: + // Measured: `160` + // Estimated: `4714` + // Minimum execution time: 28_815_000 picoseconds. + Weight::from_parts(30_180_000, 0) + .saturating_add(Weight::from_parts(0, 4714)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgeRelayers RegisteredRelayers (r:1 w:1) + /// Proof: BridgeRelayers RegisteredRelayers (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: Balances Reserves (r:1 w:1) + /// Proof: Balances Reserves (max_values: None, max_size: Some(1249), added: 3724, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + fn slash_and_deregister() -> Weight { + // Proof Size summary in bytes: + // Measured: `263` + // Estimated: `4714` + // Minimum execution time: 29_426_000 picoseconds. + Weight::from_parts(31_393_000, 0) + .saturating_add(Weight::from_parts(0, 4714)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + fn register_relayer_reward() -> Weight { + // Proof Size summary in bytes: + // Measured: `6` + // Estimated: `3538` + // Minimum execution time: 3_035_000 picoseconds. + Weight::from_parts(3_572_000, 0) + .saturating_add(Weight::from_parts(0, 3538)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/xcm/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/xcm/mod.rs index 0e740922f339..8d65067d95d1 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/xcm/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/xcm/mod.rs @@ -18,6 +18,7 @@ mod pallet_xcm_benchmarks_fungible; mod pallet_xcm_benchmarks_generic; use crate::{xcm_config::MaxAssetsIntoHolding, Runtime}; +use codec::Encode; use frame_support::weights::Weight; use pallet_xcm_benchmarks_fungible::WeightInfo as XcmFungibleWeight; use pallet_xcm_benchmarks_generic::WeightInfo as XcmGeneric; @@ -222,8 +223,9 @@ impl XcmWeightInfo for BridgeHubKusamaXcmWeight { fn universal_origin(_: &Junction) -> Weight { Weight::MAX } - fn export_message(_: &NetworkId, _: &Junctions, _: &Xcm<()>) -> Weight { - Weight::MAX + fn export_message(_: &NetworkId, _: &Junctions, inner: &Xcm<()>) -> Weight { + let inner_encoded_len = inner.encode().len() as u32; + XcmGeneric::::export_message(inner_encoded_len) } fn lock_asset(_: &MultiAsset, _: &MultiLocation) -> Weight { Weight::MAX diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/xcm/pallet_xcm_benchmarks_generic.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/xcm/pallet_xcm_benchmarks_generic.rs index b1e8107b30bb..5b88094a867c 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/xcm/pallet_xcm_benchmarks_generic.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/weights/xcm/pallet_xcm_benchmarks_generic.rs @@ -312,6 +312,26 @@ impl WeightInfo { // Minimum execution time: 2_576_000 picoseconds. Weight::from_parts(2_701_000, 0) } + // Storage: ParachainInfo ParachainId (r:1 w:0) + // Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + // Storage: BridgePolkadotMessages PalletOperatingMode (r:1 w:0) + // Proof: BridgePolkadotMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + // Storage: BridgePolkadotMessages OutboundLanes (r:1 w:1) + // Proof: BridgePolkadotMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) + // Storage: BridgePolkadotMessages OutboundMessages (r:0 w:1) + // Proof: BridgePolkadotMessages OutboundMessages (max_values: None, max_size: Some(2621472), added: 2623947, mode: MaxEncodedLen) + /// The range of component `x` is `[1, 1000]`. + pub fn export_message(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `132` + // Estimated: `1529` + // Minimum execution time: 29_796_000 picoseconds. + Weight::from_parts(32_947_104, 1529) + // Standard Error: 930 + .saturating_add(Weight::from_parts(177_649, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) + } pub fn set_fees_mode() -> Weight { // Proof Size summary in bytes: // Measured: `0` diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/xcm_config.rs index 696462be9c45..75e7454b727d 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/src/xcm_config.rs @@ -18,6 +18,10 @@ use super::{ AccountId, AllPalletsWithSystem, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, }; +use crate::{ + bridge_hub_config::ToBridgeHubPolkadotHaulBlobExporter, BridgeGrandpaPolkadotInstance, + DeliveryRewardInBalance, RequiredStakeForStakeAndSlash, +}; use frame_support::{ match_types, parameter_types, traits::{ConstU32, Contains, Everything, Nothing}, @@ -83,7 +87,7 @@ pub type XcmOriginToTransactDispatchOrigin = ( // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for // foreign chains who want to have a local sovereign account on this chain which they control. SovereignSignedViaLocation, - // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when + // Native converter for Relay-chain (Parent) location; will convert to a `Relay` origin when // recognized. RelayChainAsNative, // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when @@ -109,6 +113,7 @@ match_types! { MultiLocation { parents: 1, interior: X1(_) } }; } + /// A call filter for the XCM Transact instruction. This is a temporary measure until we properly /// account for proof size weights. /// @@ -126,6 +131,17 @@ impl Contains for SafeCallFilter { } } + // Allow to change dedicated storage items (called by governance-like) + match call { + RuntimeCall::System(frame_system::Call::set_storage { items }) + if items.iter().all(|(k, _)| { + k.eq(&DeliveryRewardInBalance::key()) | + k.eq(&RequiredStakeForStakeAndSlash::key()) + }) => + return true, + _ => (), + }; + matches!( call, RuntimeCall::PolkadotXcm(pallet_xcm::Call::force_xcm_version { .. }) | @@ -147,7 +163,11 @@ impl Contains for SafeCallFilter { pallet_collator_selection::Call::remove_invulnerable { .. }, ) | RuntimeCall::Session(pallet_session::Call::purge_keys { .. }) | RuntimeCall::XcmpQueue(..) | - RuntimeCall::DmpQueue(..) + RuntimeCall::DmpQueue(..) | + RuntimeCall::BridgePolkadotGrandpa(pallet_bridge_grandpa::Call::< + Runtime, + BridgeGrandpaPolkadotInstance, + >::initialize { .. }) ) } } @@ -166,7 +186,7 @@ pub type Barrier = TrailingSetTopicAsId< // allow it. AllowTopLevelPaidExecutionFrom, // Parent and its pluralities (i.e. governance bodies) get free execution. - AllowExplicitUnpaidExecutionFrom, + AllowExplicitUnpaidExecutionFrom<(ParentOrParentsPlurality,)>, // Subscriptions for version tracking are OK. AllowSubscriptionsFrom, ), @@ -199,14 +219,14 @@ impl xcm_executor::Config for XcmConfig { UsingComponents>; type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; + type AssetLocker = (); + type AssetExchanger = (); type AssetClaims = PolkadotXcm; type SubscriptionService = PolkadotXcm; type PalletInstancesInfo = AllPalletsWithSystem; type MaxAssetsIntoHolding = MaxAssetsIntoHolding; - type AssetLocker = (); - type AssetExchanger = (); type FeeManager = (); - type MessageExporter = (); + type MessageExporter = ToBridgeHubPolkadotHaulBlobExporter; type UniversalAliases = Nothing; type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/tests/tests.rs index 893524e12f66..a16a57a8c758 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-kusama/tests/tests.rs @@ -14,18 +14,84 @@ // You should have received a copy of the GNU General Public License // along with Cumulus. If not, see . +use bp_polkadot_core::Signature; pub use bridge_hub_kusama_runtime::{ - xcm_config::XcmConfig, AllPalletsWithoutSystem, Balances, ExistentialDeposit, ParachainSystem, - PolkadotXcm, Runtime, RuntimeEvent, SessionKeys, + bridge_hub_config, + xcm_config::{KsmRelayLocation, RelayNetwork, XcmConfig}, + AllPalletsWithoutSystem, Balances, BridgeGrandpaPolkadotInstance, + BridgeRejectObsoleteHeadersAndMessages, ExistentialDeposit, ParachainSystem, PolkadotXcm, + Runtime, RuntimeCall, RuntimeEvent, SessionKeys, WithBridgeHubPolkadotMessagesInstance, }; -use codec::Decode; +use bridge_hub_kusama_runtime::{ + bridge_hub_config::WithBridgeHubPolkadotMessageBridge, BridgeParachainPolkadotInstance, + DeliveryRewardInBalance, Executive, RequiredStakeForStakeAndSlash, SignedExtra, + UncheckedExtrinsic, +}; +use codec::{Decode, Encode}; use frame_support::parameter_types; -use parachains_common::{kusama::fee::WeightToFee, AccountId, AuraId}; +use parachains_common::{kusama::fee::WeightToFee, AccountId, AuraId, Balance}; +use sp_keyring::AccountKeyring::Alice; +use sp_runtime::{ + generic::{Era, SignedPayload}, + traits::Block as BlockT, + AccountId32, +}; +use xcm::latest::prelude::*; -const ALICE: [u8; 32] = [1u8; 32]; +// Para id of sibling chain (e.g. Statemine) used in tests. +pub const SIBLING_PARACHAIN_ID: u32 = 1000; parameter_types! { pub CheckingAccount: AccountId = PolkadotXcm::check_account(); + pub RuntimeNetwork: NetworkId = RelayNetwork::get().unwrap(); +} + +fn construct_extrinsic( + sender: sp_keyring::AccountKeyring, + call: RuntimeCall, +) -> UncheckedExtrinsic { + let extra: SignedExtra = ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(Era::immortal()), + frame_system::CheckNonce::::from(0), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(0), + BridgeRejectObsoleteHeadersAndMessages::default(), + bridge_hub_config::BridgeRefundBridgeHubPolkadotMessages::default(), + ); + let payload = SignedPayload::new(call.clone(), extra.clone()).unwrap(); + let signature = payload.using_encoded(|e| sender.sign(e)); + UncheckedExtrinsic::new_signed( + call, + AccountId32::from(sender.public()).into(), + Signature::Sr25519(signature.clone()), + extra, + ) +} + +fn construct_and_apply_extrinsic( + relayer_at_target: sp_keyring::AccountKeyring, + batch: pallet_utility::Call, +) -> sp_runtime::DispatchOutcome { + let batch_call = RuntimeCall::Utility(batch); + let xt = construct_extrinsic(relayer_at_target, batch_call); + let r = Executive::apply_extrinsic(xt); + r.unwrap() +} + +fn executive_init_block(header: &<::Block as BlockT>::Header) { + Executive::initialize_block(header) +} + +fn collator_session_keys() -> bridge_hub_test_utils::CollatorSessionKeys { + bridge_hub_test_utils::CollatorSessionKeys::new( + AccountId::from(Alice), + AccountId::from(Alice), + SessionKeys { aura: AuraId::from(Alice.public()) }, + ) } bridge_hub_test_utils::test_cases::include_teleports_for_native_asset_works!( @@ -35,11 +101,7 @@ bridge_hub_test_utils::test_cases::include_teleports_for_native_asset_works!( CheckingAccount, WeightToFee, ParachainSystem, - bridge_hub_test_utils::CollatorSessionKeys::new( - AccountId::from(ALICE), - AccountId::from(ALICE), - SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) } - ), + collator_session_keys(), ExistentialDeposit::get(), Box::new(|runtime_event_encoded: Vec| { match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { @@ -55,3 +117,169 @@ bridge_hub_test_utils::test_cases::include_teleports_for_native_asset_works!( }), 1002 ); + +#[test] +fn initialize_bridge_by_governance_works() { + bridge_hub_test_utils::test_cases::initialize_bridge_by_governance_works::< + Runtime, + BridgeGrandpaPolkadotInstance, + >( + collator_session_keys(), + bp_bridge_hub_kusama::BRIDGE_HUB_KUSAMA_PARACHAIN_ID, + Box::new(|call| RuntimeCall::BridgePolkadotGrandpa(call).encode()), + ) +} + +#[test] +fn change_delivery_reward_by_governance_works() { + bridge_hub_test_utils::test_cases::change_storage_constant_by_governance_works::< + Runtime, + DeliveryRewardInBalance, + u64, + >( + collator_session_keys(), + bp_bridge_hub_kusama::BRIDGE_HUB_KUSAMA_PARACHAIN_ID, + Box::new(|call| RuntimeCall::System(call).encode()), + || (DeliveryRewardInBalance::key().to_vec(), DeliveryRewardInBalance::get()), + |old_value| old_value.checked_mul(2).unwrap(), + ) +} + +#[test] +fn change_required_stake_by_governance_works() { + bridge_hub_test_utils::test_cases::change_storage_constant_by_governance_works::< + Runtime, + RequiredStakeForStakeAndSlash, + Balance, + >( + collator_session_keys(), + bp_bridge_hub_kusama::BRIDGE_HUB_KUSAMA_PARACHAIN_ID, + Box::new(|call| RuntimeCall::System(call).encode()), + || (RequiredStakeForStakeAndSlash::key().to_vec(), RequiredStakeForStakeAndSlash::get()), + |old_value| { + if let Some(new_value) = old_value.checked_add(1) { + new_value + } else { + old_value.checked_sub(1).unwrap() + } + }, + ) +} + +#[test] +fn handle_export_message_from_system_parachain_add_to_outbound_queue_works() { + bridge_hub_test_utils::test_cases::handle_export_message_from_system_parachain_to_outbound_queue_works::< + Runtime, + XcmConfig, + WithBridgeHubPolkadotMessagesInstance, + >( + collator_session_keys(), + bp_bridge_hub_kusama::BRIDGE_HUB_KUSAMA_PARACHAIN_ID, + SIBLING_PARACHAIN_ID, + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::BridgePolkadotMessages(event)) => Some(event), + _ => None, + } + }), + || ExportMessage { network: Polkadot, destination: X1(Parachain(1234)), xcm: Xcm(vec![]) }, + bridge_hub_config::ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID, + Some((KsmRelayLocation::get(), ExistentialDeposit::get()).into()), + // value should be >= than value generated by `can_calculate_weight_for_paid_export_message_with_reserve_transfer` + Some((KsmRelayLocation::get(), bp_asset_hub_kusama::BridgeHubKusamaBaseFeeInDots::get()).into()), + ) +} + +#[test] +fn message_dispatch_routing_works() { + bridge_hub_test_utils::test_cases::message_dispatch_routing_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + WithBridgeHubPolkadotMessagesInstance, + RuntimeNetwork, + bridge_hub_config::PolkadotGlobalConsensusNetwork, + >( + collator_session_keys(), + bp_bridge_hub_kusama::BRIDGE_HUB_KUSAMA_PARACHAIN_ID, + SIBLING_PARACHAIN_ID, + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::ParachainSystem(event)) => Some(event), + _ => None, + } + }), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), + _ => None, + } + }), + bridge_hub_config::ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID, + ) +} + +#[test] +fn relayed_incoming_message_works() { + bridge_hub_test_utils::test_cases::relayed_incoming_message_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + BridgeGrandpaPolkadotInstance, + BridgeParachainPolkadotInstance, + WithBridgeHubPolkadotMessagesInstance, + WithBridgeHubPolkadotMessageBridge, + >( + collator_session_keys(), + bp_bridge_hub_kusama::BRIDGE_HUB_KUSAMA_PARACHAIN_ID, + bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, + SIBLING_PARACHAIN_ID, + RuntimeNetwork::get(), + bridge_hub_config::ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID, + ) +} + +#[test] +pub fn complex_relay_extrinsic_works() { + bridge_hub_test_utils::test_cases::complex_relay_extrinsic_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + BridgeGrandpaPolkadotInstance, + BridgeParachainPolkadotInstance, + WithBridgeHubPolkadotMessagesInstance, + WithBridgeHubPolkadotMessageBridge, + >( + collator_session_keys(), + bp_bridge_hub_kusama::BRIDGE_HUB_KUSAMA_PARACHAIN_ID, + bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, + SIBLING_PARACHAIN_ID, + bridge_hub_config::BridgeHubPolkadotChainId::get(), + RuntimeNetwork::get(), + bridge_hub_config::ASSET_HUB_KUSAMA_TO_ASSET_HUB_POLKADOT_LANE_ID, + ExistentialDeposit::get(), + executive_init_block, + construct_and_apply_extrinsic, + ); +} + +#[test] +pub fn can_calculate_weight_for_paid_export_message_with_reserve_transfer() { + let estimated = bridge_hub_test_utils::test_cases::can_calculate_weight_for_paid_export_message_with_reserve_transfer::< + Runtime, + XcmConfig, + WeightToFee, + >(); + + // check if estimated value is sane + let max_expected = bp_asset_hub_kusama::BridgeHubKusamaBaseFeeInDots::get(); + assert!( + estimated <= max_expected, + "calculated: {:?}, max_expected: {:?}, please adjust `bp_asset_hub_kusama::BridgeHubKusamaBaseFeeInDots` value", + estimated, + max_expected + ); +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/Cargo.toml index 77923ee74f89..6c6611205c3a 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/Cargo.toml @@ -64,19 +64,51 @@ cumulus-pallet-dmp-queue = { path = "../../../../pallets/dmp-queue", default-fea cumulus-pallet-parachain-system = { path = "../../../../pallets/parachain-system", default-features = false, features = ["parameterized-consensus-hook",] } cumulus-pallet-session-benchmarking = { path = "../../../../pallets/session-benchmarking", default-features = false} cumulus-pallet-xcm = { path = "../../../../pallets/xcm", default-features = false } -cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false } +cumulus-pallet-xcmp-queue = { path = "../../../../pallets/xcmp-queue", default-features = false, features = ["bridging"] } cumulus-primitives-core = { path = "../../../../primitives/core", default-features = false } cumulus-primitives-utility = { path = "../../../../primitives/utility", default-features = false } pallet-collator-selection = { path = "../../../../pallets/collator-selection", default-features = false } parachain-info = { path = "../../../pallets/parachain-info", default-features = false } parachains-common = { path = "../../../common", default-features = false } +# Bridges +bp-asset-hub-polkadot = { path = "../../../../../bridges/primitives/chain-asset-hub-polkadot", default-features = false } +bp-bridge-hub-kusama = { path = "../../../../../bridges/primitives/chain-bridge-hub-kusama", default-features = false } +bp-bridge-hub-polkadot = { path = "../../../../../bridges/primitives/chain-bridge-hub-polkadot", default-features = false } +bp-header-chain = { path = "../../../../../bridges/primitives/header-chain", default-features = false } +bp-messages = { path = "../../../../../bridges/primitives/messages", default-features = false } +bp-parachains = { path = "../../../../../bridges/primitives/parachains", default-features = false } +bp-polkadot-core = { path = "../../../../../bridges/primitives/polkadot-core", default-features = false } +bp-relayers = { path = "../../../../../bridges/primitives/relayers", default-features = false } +bp-runtime = { path = "../../../../../bridges/primitives/runtime", default-features = false } +bp-kusama = { path = "../../../../../bridges/primitives/chain-kusama", default-features = false } +bridge-runtime-common = { path = "../../../../../bridges/bin/runtime-common", default-features = false } +pallet-bridge-grandpa = { path = "../../../../../bridges/modules/grandpa", default-features = false } +pallet-bridge-messages = { path = "../../../../../bridges/modules/messages", default-features = false } +pallet-bridge-parachains = { path = "../../../../../bridges/modules/parachains", default-features = false } +pallet-bridge-relayers = { path = "../../../../../bridges/modules/relayers", default-features = false } + [dev-dependencies] +static_assertions = "1.1" bridge-hub-test-utils = { path = "../test-utils" } +bridge-runtime-common = { path = "../../../../../bridges/bin/runtime-common", features = ["integrity-test"] } +bp-polkadot = { path = "../../../../../bridges/primitives/chain-polkadot" } +sp-keyring = { path = "../../../../../substrate/primitives/keyring" } [features] default = [ "std" ] std = [ + "bp-asset-hub-polkadot/std", + "bp-bridge-hub-kusama/std", + "bp-bridge-hub-polkadot/std", + "bp-header-chain/std", + "bp-kusama/std", + "bp-messages/std", + "bp-parachains/std", + "bp-polkadot-core/std", + "bp-relayers/std", + "bp-runtime/std", + "bridge-runtime-common/std", "codec/std", "cumulus-pallet-aura-ext/std", "cumulus-pallet-dmp-queue/std", @@ -97,6 +129,10 @@ std = [ "pallet-aura/std", "pallet-authorship/std", "pallet-balances/std", + "pallet-bridge-grandpa/std", + "pallet-bridge-messages/std", + "pallet-bridge-parachains/std", + "pallet-bridge-relayers/std", "pallet-collator-selection/std", "pallet-multisig/std", "pallet-session/std", @@ -134,6 +170,7 @@ std = [ ] runtime-benchmarks = [ + "bridge-runtime-common/runtime-benchmarks", "cumulus-pallet-parachain-system/runtime-benchmarks", "cumulus-pallet-session-benchmarking/runtime-benchmarks", "cumulus-pallet-xcmp-queue/runtime-benchmarks", @@ -143,6 +180,10 @@ runtime-benchmarks = [ "frame-system-benchmarking/runtime-benchmarks", "frame-system/runtime-benchmarks", "pallet-balances/runtime-benchmarks", + "pallet-bridge-grandpa/runtime-benchmarks", + "pallet-bridge-messages/runtime-benchmarks", + "pallet-bridge-parachains/runtime-benchmarks", + "pallet-bridge-relayers/runtime-benchmarks", "pallet-collator-selection/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", @@ -170,6 +211,10 @@ try-runtime = [ "pallet-aura/try-runtime", "pallet-authorship/try-runtime", "pallet-balances/try-runtime", + "pallet-bridge-grandpa/try-runtime", + "pallet-bridge-messages/try-runtime", + "pallet-bridge-parachains/try-runtime", + "pallet-bridge-relayers/try-runtime", "pallet-collator-selection/try-runtime", "pallet-multisig/try-runtime", "pallet-session/try-runtime", diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/bridge_hub_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/bridge_hub_config.rs new file mode 100644 index 000000000000..bc9547e1601e --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/bridge_hub_config.rs @@ -0,0 +1,268 @@ +// 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 . + +//! Polkadot BridgeHub definitions. + +use crate::{ + BridgeKusamaMessages, BridgeParachainKusamaInstance, Runtime, + WithBridgeHubKusamaMessagesInstance, XcmRouter, +}; +use bp_messages::LaneId; +use bridge_runtime_common::{ + messages, + messages::{ + source::FromBridgedChainMessagesDeliveryProof, target::FromBridgedChainMessagesProof, + MessageBridge, ThisChainWithMessages, UnderlyingChainProvider, + }, + messages_xcm_extension::{SenderAndLane, XcmBlobHauler, XcmBlobHaulerAdapter}, + refund_relayer_extension::{ + ActualFeeRefund, RefundBridgedParachainMessages, RefundableMessagesLane, + RefundableParachain, + }, +}; +use codec::Encode; +use frame_support::{parameter_types, traits::PalletInfoAccess}; +use sp_runtime::RuntimeDebug; +use xcm::{latest::prelude::*, prelude::NetworkId}; +use xcm_builder::{BridgeBlobDispatcher, HaulBlobExporter}; + +parameter_types! { + pub const MaxUnrewardedRelayerEntriesAtInboundLane: bp_messages::MessageNonce = + bp_bridge_hub_polkadot::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX; + pub const MaxUnconfirmedMessagesAtInboundLane: bp_messages::MessageNonce = + bp_bridge_hub_polkadot::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX; + pub const BridgeHubKusamaChainId: bp_runtime::ChainId = bp_runtime::BRIDGE_HUB_KUSAMA_CHAIN_ID; + pub BridgeKusamaMessagesPalletInstance: InteriorMultiLocation = X1(PalletInstance(::index() as u8)); + pub KusamaGlobalConsensusNetwork: NetworkId = NetworkId::Kusama; + // see the `FEE_BOOST_PER_MESSAGE` constant to get the meaning of this value + pub PriorityBoostPerMessage: u64 = 4_551_111_111_111; + + pub AssetHubPolkadotParaId: cumulus_primitives_core::ParaId = bp_asset_hub_polkadot::ASSET_HUB_POLKADOT_PARACHAIN_ID.into(); + + pub FromAssetHubPolkadotToAssetHubKusamaRoute: SenderAndLane = SenderAndLane::new( + ParentThen(X1(Parachain(AssetHubPolkadotParaId::get().into()))).into(), + ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID, + ); + + pub CongestedMessage: Xcm<()> = sp_std::vec![Transact { + origin_kind: OriginKind::Xcm, + require_weight_at_most: bp_asset_hub_polkadot::XcmBridgeHubRouterTransactCallMaxWeight::get(), + call: bp_asset_hub_polkadot::Call::ToKusamaXcmRouter( + bp_asset_hub_polkadot::XcmBridgeHubRouterCall::report_bridge_status { + bridge_id: Default::default(), + is_congested: true, + } + ).encode().into(), + }].into(); + + pub UncongestedMessage: Xcm<()> = sp_std::vec![Transact { + origin_kind: OriginKind::Xcm, + require_weight_at_most: bp_asset_hub_polkadot::XcmBridgeHubRouterTransactCallMaxWeight::get(), + call: bp_asset_hub_polkadot::Call::ToKusamaXcmRouter( + bp_asset_hub_polkadot::XcmBridgeHubRouterCall::report_bridge_status { + bridge_id: Default::default(), + is_congested: false, + } + ).encode().into(), + }].into(); +} + +/// Proof of messages, coming from BridgeHubKusama. +pub type FromBridgeHubKusamaMessagesProof = + FromBridgedChainMessagesProof; +/// Message delivery proof for `BridgeHubKusama` messages. +pub type ToBridgeHubKusamaMessagesDeliveryProof = + FromBridgedChainMessagesDeliveryProof; + +/// Dispatches received XCM messages from other bridge +pub type OnThisChainBlobDispatcher = + BridgeBlobDispatcher; + +/// Export XCM messages to be relayed to the other side. +pub type ToBridgeHubKusamaHaulBlobExporter = HaulBlobExporter< + XcmBlobHaulerAdapter, + KusamaGlobalConsensusNetwork, + (), +>; +pub struct ToBridgeHubKusamaXcmBlobHauler; +impl XcmBlobHauler for ToBridgeHubKusamaXcmBlobHauler { + type Runtime = Runtime; + type MessagesInstance = WithBridgeHubKusamaMessagesInstance; + type SenderAndLane = FromAssetHubPolkadotToAssetHubKusamaRoute; + + type ToSourceChainSender = crate::XcmRouter; + type CongestedMessage = CongestedMessage; + type UncongestedMessage = UncongestedMessage; +} + +/// On messages delivered callback. +pub type OnMessagesDelivered = XcmBlobHaulerAdapter; + +/// Messaging Bridge configuration for ThisChain -> BridgeHubKusama +pub struct WithBridgeHubKusamaMessageBridge; +impl MessageBridge for WithBridgeHubKusamaMessageBridge { + const BRIDGED_MESSAGES_PALLET_NAME: &'static str = + bp_bridge_hub_polkadot::WITH_BRIDGE_HUB_POLKADOT_MESSAGES_PALLET_NAME; + type ThisChain = ThisChain; + type BridgedChain = BridgeHubKusama; + type BridgedHeaderChain = pallet_bridge_parachains::ParachainHeaders< + Runtime, + BridgeParachainKusamaInstance, + bp_bridge_hub_kusama::BridgeHubKusama, + >; +} + +/// Message verifier for BridgeHubKusama messages sent from ThisChain +pub type ToBridgeHubKusamaMessageVerifier = + messages::source::FromThisChainMessageVerifier; + +/// Maximal outbound payload size of ThisChain -> BridgeHubKusama messages. +pub type ToBridgeHubKusamaMaximalOutboundPayloadSize = + messages::source::FromThisChainMaximalOutboundPayloadSize; + +/// BridgeHubKusama chain from message lane point of view. +#[derive(RuntimeDebug, Clone, Copy)] +pub struct BridgeHubKusama; + +impl UnderlyingChainProvider for BridgeHubKusama { + type Chain = bp_bridge_hub_kusama::BridgeHubKusama; +} + +impl messages::BridgedChainWithMessages for BridgeHubKusama {} + +/// ThisChain chain from message lane point of view. +#[derive(RuntimeDebug, Clone, Copy)] +pub struct ThisChain; + +impl UnderlyingChainProvider for ThisChain { + type Chain = bp_bridge_hub_polkadot::BridgeHubPolkadot; +} + +impl ThisChainWithMessages for ThisChain { + type RuntimeOrigin = crate::RuntimeOrigin; +} + +// TODO: rework once dynamic lanes are supported (https://github.com/paritytech/parity-bridges-common/issues/1760) +/// Signed extension that refunds relayers that are delivering messages from the kusama BridgeHub. +pub type BridgeRefundBridgeHubKusamaMessages = RefundBridgedParachainMessages< + Runtime, + RefundableParachain, + RefundableMessagesLane< + WithBridgeHubKusamaMessagesInstance, + AssetHubPolkadotToAssetHubKusamaMessageLane, + >, + ActualFeeRefund, + PriorityBoostPerMessage, + StrBridgeRefundBridgeHubKusamaMessages, +>; +bp_runtime::generate_static_str_provider!(BridgeRefundBridgeHubKusamaMessages); + +// TODO: rework once dynamic lanes are supported (https://github.com/paritytech/parity-bridges-common/issues/1760) +// now we support only AHP<>AHK Lanes setup +pub const ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID: LaneId = LaneId([0, 0, 0, 0]); +parameter_types! { + pub ActiveOutboundLanesToBridgeHubKusama: &'static [bp_messages::LaneId] = &[ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID]; + pub const AssetHubPolkadotToAssetHubKusamaMessageLane: bp_messages::LaneId = ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID; +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::BridgeGrandpaKusamaInstance; + use bridge_runtime_common::{ + assert_complete_bridge_types, + integrity::{ + assert_complete_bridge_constants, check_message_lane_weights, + AssertBridgeMessagesPalletConstants, AssertBridgePalletNames, AssertChainConstants, + AssertCompleteBridgeConstants, + }, + }; + use parachains_common::{polkadot, Balance}; + + /// Every additional message in the message delivery transaction boosts its priority. + /// So the priority of transaction with `N+1` messages is larger than priority of + /// transaction with `N` messages by the `PriorityBoostPerMessage`. + /// + /// Economically, it is an equivalent of adding tip to the transaction with `N` messages. + /// The `FEE_BOOST_PER_MESSAGE` constant is the value of this tip. + /// + /// We want this tip to be large enough (delivery transactions with more messages = less + /// operational costs and a faster bridge), so this value should be significant. + const FEE_BOOST_PER_MESSAGE: Balance = 5 * polkadot::currency::UNITS; + + #[test] + fn ensure_lane_weights_are_correct() { + check_message_lane_weights::< + bp_bridge_hub_polkadot::BridgeHubPolkadot, + Runtime, + WithBridgeHubKusamaMessagesInstance, + >( + bp_bridge_hub_kusama::EXTRA_STORAGE_PROOF_SIZE, + bp_bridge_hub_polkadot::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + bp_bridge_hub_polkadot::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + true, + ); + } + + #[test] + fn ensure_bridge_integrity() { + assert_complete_bridge_types!( + runtime: Runtime, + with_bridged_chain_grandpa_instance: BridgeGrandpaKusamaInstance, + with_bridged_chain_messages_instance: WithBridgeHubKusamaMessagesInstance, + bridge: WithBridgeHubKusamaMessageBridge, + this_chain: bp_polkadot::Polkadot, + bridged_chain: bp_kusama::Kusama, + ); + + assert_complete_bridge_constants::< + Runtime, + BridgeGrandpaKusamaInstance, + WithBridgeHubKusamaMessagesInstance, + WithBridgeHubKusamaMessageBridge, + >(AssertCompleteBridgeConstants { + this_chain_constants: AssertChainConstants { + block_length: bp_bridge_hub_polkadot::BlockLength::get(), + block_weights: bp_bridge_hub_polkadot::BlockWeights::get(), + }, + messages_pallet_constants: AssertBridgeMessagesPalletConstants { + max_unrewarded_relayers_in_bridged_confirmation_tx: + bp_bridge_hub_kusama::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + max_unconfirmed_messages_in_bridged_confirmation_tx: + bp_bridge_hub_kusama::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + bridged_chain_id: bp_runtime::BRIDGE_HUB_KUSAMA_CHAIN_ID, + }, + pallet_names: AssertBridgePalletNames { + with_this_chain_messages_pallet_name: + bp_bridge_hub_polkadot::WITH_BRIDGE_HUB_POLKADOT_MESSAGES_PALLET_NAME, + with_bridged_chain_grandpa_pallet_name: bp_kusama::WITH_KUSAMA_GRANDPA_PALLET_NAME, + with_bridged_chain_messages_pallet_name: + bp_bridge_hub_kusama::WITH_BRIDGE_HUB_KUSAMA_MESSAGES_PALLET_NAME, + }, + }); + + bridge_runtime_common::priority_calculator::ensure_priority_boost_is_sane::< + Runtime, + WithBridgeHubKusamaMessagesInstance, + PriorityBoostPerMessage, + >(FEE_BOOST_PER_MESSAGE); + + assert_eq!( + BridgeKusamaMessagesPalletInstance::get(), + X1(PalletInstance(bp_bridge_hub_polkadot::WITH_BRIDGE_KUSAMA_MESSAGES_PALLET_INDEX)) + ); + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/lib.rs index dbfdc249a3cd..a2f59931af0c 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/lib.rs @@ -22,6 +22,7 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +pub mod bridge_hub_config; mod weights; pub mod xcm_config; @@ -59,6 +60,9 @@ use xcm_config::{ FellowshipLocation, GovernanceLocation, XcmConfig, XcmOriginToTransactDispatchOrigin, }; +use bp_parachains::SingleParaStoredHeaderDataBuilder; +use bp_runtime::HeaderId; + #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; @@ -73,7 +77,20 @@ use parachains_common::{ AccountId, Balance, BlockNumber, Hash, Header, Nonce, Signature, AVERAGE_ON_INITIALIZE_RATIO, HOURS, MAXIMUM_BLOCK_WEIGHT, NORMAL_DISPATCH_RATIO, SLOT_DURATION, }; -// XCM Imports + +use crate::{ + bridge_hub_config::{ + BridgeRefundBridgeHubKusamaMessages, OnThisChainBlobDispatcher, + WithBridgeHubKusamaMessageBridge, + }, + xcm_config::{UniversalLocation, XcmRouter}, +}; + +use bridge_runtime_common::{ + messages::{source::TargetHeaderChainAdapter, target::SourceHeaderChainAdapter}, + messages_xcm_extension::{XcmAsPlainPayload, XcmBlobMessageDispatch}, +}; + use xcm::latest::prelude::BodyId; use xcm_executor::XcmExecutor; @@ -99,6 +116,8 @@ pub type SignedExtra = ( frame_system::CheckNonce, frame_system::CheckWeight, pallet_transaction_payment::ChargeTransactionPayment, + BridgeRejectObsoleteHeadersAndMessages, + BridgeRefundBridgeHubKusamaMessages, ); /// Unchecked extrinsic type as expected by this runtime. @@ -401,6 +420,108 @@ impl pallet_utility::Config for Runtime { type WeightInfo = weights::pallet_utility::WeightInfo; } +// Add bridge pallets (GPA) +/// Add GRANDPA bridge pallet to track Kusama relay chain on Polkadot BridgeHub +pub type BridgeGrandpaKusamaInstance = pallet_bridge_grandpa::Instance1; +impl pallet_bridge_grandpa::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type BridgedChain = bp_kusama::Kusama; + type MaxFreeMandatoryHeadersPerBlock = ConstU32<4>; + type HeadersToKeep = RelayChainHeadersToKeep; + type WeightInfo = weights::pallet_bridge_grandpa::WeightInfo; +} + +parameter_types! { + pub const RelayChainHeadersToKeep: u32 = 600; + pub const ParachainHeadsToKeep: u32 = 300; + /// Delay (in blocks) before registered relayer could get its stake back. It guarantees + /// that all pending delivery transactions are either dropped or mined and relayer is + /// slashed in case of misbehavior. So this value should be large enough (e.g. 24 hours). + pub const RelayerStakeLease: u32 = parachains_common::DAYS; + pub const KusamaBridgeParachainPalletName: &'static str = bp_kusama::PARAS_PALLET_NAME; + pub const MaxKusamaParaHeadDataSize: u32 = bp_kusama::MAX_NESTED_PARACHAIN_HEAD_DATA_SIZE; + + pub const RelayerStakeReserveId: [u8; 8] = *b"brdgrlrs"; + // Just initial value, and concrete values will be set up by governance call (`set_storage`) with `initialize` bridge call as a part of cutover plan (https://github.com/paritytech/parity-bridges-common/issues/1730) + pub storage DeliveryRewardInBalance: u64 = 1_000_000; +} + +#[cfg(feature = "runtime-benchmarks")] +parameter_types! { + pub storage RequiredStakeForStakeAndSlash: Balance = 1; +} +#[cfg(not(feature = "runtime-benchmarks"))] +parameter_types! { + // Just initial value, and concrete values will be set up by governance call (`set_storage`) with `initialize` bridge call as a part of cutover plan (https://github.com/paritytech/parity-bridges-common/issues/1730) + pub storage RequiredStakeForStakeAndSlash: Balance = Balance::MAX; +} + +/// Add parachain bridge pallet to track Kusama BridgeHub parachain +pub type BridgeParachainKusamaInstance = pallet_bridge_parachains::Instance1; +impl pallet_bridge_parachains::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = weights::pallet_bridge_parachains::WeightInfo; + type BridgesGrandpaPalletInstance = BridgeGrandpaKusamaInstance; + type ParasPalletName = KusamaBridgeParachainPalletName; + type ParaStoredHeaderDataBuilder = + SingleParaStoredHeaderDataBuilder; + type HeadsToKeep = ParachainHeadsToKeep; + type MaxParaHeadDataSize = MaxKusamaParaHeadDataSize; +} + +/// Add XCM messages support for Polkadot<->Kusama XCM messages +pub type WithBridgeHubKusamaMessagesInstance = pallet_bridge_messages::Instance1; +impl pallet_bridge_messages::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = weights::pallet_bridge_messages::WeightInfo; + type BridgedChainId = bridge_hub_config::BridgeHubKusamaChainId; + type ActiveOutboundLanes = bridge_hub_config::ActiveOutboundLanesToBridgeHubKusama; + type MaxUnrewardedRelayerEntriesAtInboundLane = + bridge_hub_config::MaxUnrewardedRelayerEntriesAtInboundLane; + type MaxUnconfirmedMessagesAtInboundLane = + bridge_hub_config::MaxUnconfirmedMessagesAtInboundLane; + type MaximalOutboundPayloadSize = + bridge_hub_config::ToBridgeHubKusamaMaximalOutboundPayloadSize; + type OutboundPayload = XcmAsPlainPayload; + type InboundPayload = XcmAsPlainPayload; + type InboundRelayer = AccountId; + type DeliveryPayments = (); + type TargetHeaderChain = TargetHeaderChainAdapter; + type LaneMessageVerifier = bridge_hub_config::ToBridgeHubKusamaMessageVerifier; + type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< + Runtime, + WithBridgeHubKusamaMessagesInstance, + DeliveryRewardInBalance, + >; + type SourceHeaderChain = SourceHeaderChainAdapter; + type MessageDispatch = XcmBlobMessageDispatch< + OnThisChainBlobDispatcher, + Self::WeightInfo, + cumulus_pallet_xcmp_queue::bridging::OutXcmpChannelStatusProvider< + bridge_hub_config::AssetHubPolkadotParaId, + Runtime, + >, + >; + type OnMessagesDelivered = bridge_hub_config::OnMessagesDelivered; +} + +/// Allows collect and claim rewards for relayers +impl pallet_bridge_relayers::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type Reward = Balance; + type PaymentProcedure = + bp_relayers::PayRewardFromAccount, AccountId>; + type StakeAndSlash = pallet_bridge_relayers::StakeAndSlashNamed< + AccountId, + BlockNumber, + Balances, + RelayerStakeReserveId, + RequiredStakeForStakeAndSlash, + RelayerStakeLease, + >; + type WeightInfo = weights::pallet_bridge_relayers::WeightInfo; +} + // Create the runtime by composing the FRAME pallets that were previously configured. construct_runtime!( pub enum Runtime @@ -433,9 +554,25 @@ construct_runtime!( // Handy utilities. Utility: pallet_utility::{Pallet, Call, Event} = 40, Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 41, + + // Polkadot<>Kusama bridge pallets + BridgeKusamaGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Storage, Event, Config} = 51, + BridgeKusamaParachain: pallet_bridge_parachains::::{Pallet, Call, Storage, Event} = 52, + BridgeKusamaMessages: pallet_bridge_messages::::{Pallet, Call, Storage, Event, Config} = 53, + BridgeRelayers: pallet_bridge_relayers::{Pallet, Call, Storage, Event} = 54, } ); +bridge_runtime_common::generate_bridge_reject_obsolete_headers_and_messages! { + RuntimeCall, AccountId, + // Grandpa + BridgeKusamaGrandpa, + // Parachains + BridgeKusamaParachain, + // Messages + BridgeKusamaMessages +} + #[cfg(feature = "runtime-benchmarks")] #[macro_use] extern crate frame_benchmarking; @@ -456,6 +593,12 @@ mod benches { // NOTE: Make sure you point to the individual modules below. [pallet_xcm_benchmarks::fungible, XcmBalances] [pallet_xcm_benchmarks::generic, XcmGeneric] + // Bridge pallets for Polkadot + [pallet_bridge_grandpa, BridgeKusamaGrandpa] + [pallet_bridge_parachains, BridgeParachainsBench::] + [pallet_bridge_messages, BridgeMessagesBench::] + // Bridge relayer pallets + [pallet_bridge_relayers, BridgeRelayersBench::] ); } @@ -603,6 +746,49 @@ impl_runtime_apis! { } } + impl bp_kusama::KusamaFinalityApi for Runtime { + fn best_finalized() -> Option> { + BridgeKusamaGrandpa::best_finalized() + } + fn synced_headers_grandpa_info( + ) -> Vec> { + BridgeKusamaGrandpa::synced_headers_grandpa_info() + } + } + + impl bp_bridge_hub_kusama::BridgeHubKusamaFinalityApi for Runtime { + fn best_finalized() -> Option> { + BridgeKusamaParachain::best_parachain_head_id::< + bp_bridge_hub_kusama::BridgeHubKusama + >().unwrap_or(None) + } + } + + impl bp_bridge_hub_kusama::FromBridgeHubKusamaInboundLaneApi for Runtime { + fn message_details( + lane: bp_messages::LaneId, + messages: Vec<(bp_messages::MessagePayload, bp_messages::OutboundMessageDetails)>, + ) -> Vec { + bridge_runtime_common::messages_api::inbound_message_details::< + Runtime, + WithBridgeHubKusamaMessagesInstance, + >(lane, messages) + } + } + + impl bp_bridge_hub_kusama::ToBridgeHubKusamaOutboundLaneApi for Runtime { + fn message_details( + lane: bp_messages::LaneId, + begin: bp_messages::MessageNonce, + end: bp_messages::MessageNonce, + ) -> Vec { + bridge_runtime_common::messages_api::outbound_message_details::< + Runtime, + WithBridgeHubKusamaMessagesInstance, + >(lane, begin, end) + } + } + #[cfg(feature = "try-runtime")] impl frame_try_runtime::TryRuntime for Runtime { fn on_runtime_upgrade(checks: frame_try_runtime::UpgradeCheckSelect) -> (Weight, Weight) { @@ -639,6 +825,10 @@ impl_runtime_apis! { type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::; type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::; + use pallet_bridge_parachains::benchmarking::Pallet as BridgeParachainsBench; + use pallet_bridge_messages::benchmarking::Pallet as BridgeMessagesBench; + use pallet_bridge_relayers::benchmarking::Pallet as BridgeRelayersBench; + let mut list = Vec::::new(); list_benchmarks!(list, extra); @@ -748,7 +938,7 @@ impl_runtime_apis! { fn export_message_origin_and_destination( ) -> Result<(MultiLocation, NetworkId, InteriorMultiLocation), BenchmarkError> { - Err(BenchmarkError::Skip) + Ok((DotRelayLocation::get(), bridge_hub_config::KusamaGlobalConsensusNetwork::get(), X1(Parachain(100)))) } fn alias_origin() -> Result<(MultiLocation, MultiLocation), BenchmarkError> { @@ -759,6 +949,106 @@ impl_runtime_apis! { type XcmBalances = pallet_xcm_benchmarks::fungible::Pallet::; type XcmGeneric = pallet_xcm_benchmarks::generic::Pallet::; + use bridge_runtime_common::messages_benchmarking::{ + generate_xcm_builder_bridge_message_sample, + prepare_message_delivery_proof_from_parachain, + prepare_message_proof_from_parachain + }; + use pallet_bridge_messages::benchmarking::{ + Config as BridgeMessagesConfig, + Pallet as BridgeMessagesBench, + MessageDeliveryProofParams, + MessageProofParams, + }; + impl BridgeMessagesConfig for Runtime { + fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool { + let bench_lane_id = >::bench_lane_id(); + let bridged_chain_id = bp_runtime::BRIDGE_HUB_KUSAMA_CHAIN_ID; + pallet_bridge_relayers::Pallet::::relayer_reward( + relayer, + bp_relayers::RewardsAccountParams::new( + bench_lane_id, + bridged_chain_id, + bp_relayers::RewardsAccountOwner::BridgedChain + ) + ).is_some() + } + fn prepare_message_proof( + params: MessageProofParams, + ) -> (bridge_hub_config::FromBridgeHubKusamaMessagesProof, Weight) { + use cumulus_primitives_core::XcmpMessageSource; + assert!(XcmpQueue::take_outbound_messages(usize::MAX).is_empty()); + ParachainSystem::open_outbound_hrmp_channel_for_benchmarks_or_tests(42.into()); + prepare_message_proof_from_parachain::< + Runtime, + BridgeGrandpaKusamaInstance, + bridge_hub_config::WithBridgeHubKusamaMessageBridge, + >(params, generate_xcm_builder_bridge_message_sample(X2(GlobalConsensus(xcm_config::RelayNetwork::get().unwrap()), Parachain(42)))) + } + fn prepare_message_delivery_proof( + params: MessageDeliveryProofParams, + ) -> bridge_hub_config::ToBridgeHubKusamaMessagesDeliveryProof { + prepare_message_delivery_proof_from_parachain::< + Runtime, + BridgeGrandpaKusamaInstance, + bridge_hub_config::WithBridgeHubKusamaMessageBridge, + >(params) + } + fn is_message_successfully_dispatched(_nonce: bp_messages::MessageNonce) -> bool { + use cumulus_primitives_core::XcmpMessageSource; + !XcmpQueue::take_outbound_messages(usize::MAX).is_empty() + } + } + + use bridge_runtime_common::parachains_benchmarking::prepare_parachain_heads_proof; + use pallet_bridge_parachains::benchmarking::{ + Config as BridgeParachainsConfig, + Pallet as BridgeParachainsBench, + }; + use pallet_bridge_relayers::benchmarking::{ + Pallet as BridgeRelayersBench, + Config as BridgeRelayersConfig, + }; + impl BridgeParachainsConfig for Runtime { + fn parachains() -> Vec { + use bp_runtime::Parachain; + vec![bp_polkadot_core::parachains::ParaId(bp_bridge_hub_kusama::BridgeHubKusama::PARACHAIN_ID)] + } + fn prepare_parachain_heads_proof( + parachains: &[bp_polkadot_core::parachains::ParaId], + parachain_head_size: u32, + proof_size: bp_runtime::StorageProofSize, + ) -> ( + pallet_bridge_parachains::RelayBlockNumber, + pallet_bridge_parachains::RelayBlockHash, + bp_polkadot_core::parachains::ParaHeadsProof, + Vec<(bp_polkadot_core::parachains::ParaId, bp_polkadot_core::parachains::ParaHash)>, + ) { + prepare_parachain_heads_proof::( + parachains, + parachain_head_size, + proof_size, + ) + } + } + + impl BridgeRelayersConfig for Runtime { + fn prepare_rewards_account( + account_params: bp_relayers::RewardsAccountParams, + reward: Balance, + ) { + let rewards_account = bp_relayers::PayRewardFromAccount::< + Balances, + AccountId + >::rewards_account(account_params); + Self::deposit_account(rewards_account, reward); + } + fn deposit_account(account: AccountId, balance: Balance) { + use frame_support::traits::fungible::Mutate; + Balances::mint_into(&account, balance.saturating_add(ExistentialDeposit::get())).unwrap(); + } + } + let whitelist: Vec = vec![ // Block Number hex_literal::hex!("26aa394eea5630e07c48ae0c9558cef702a5c1b19ab7a04f536c519aca4983ac").to_vec().into(), @@ -785,3 +1075,49 @@ cumulus_pallet_parachain_system::register_validate_block! { Runtime = Runtime, BlockExecutor = cumulus_pallet_aura_ext::BlockExecutor::, } + +#[cfg(test)] +mod tests { + use super::*; + use codec::Encode; + use sp_runtime::{ + generic::Era, + traits::{SignedExtension, Zero}, + }; + + #[test] + fn ensure_signed_extension_definition_is_compatible_with_relay() { + use bp_polkadot_core::SuffixedCommonSignedExtensionExt; + + sp_io::TestExternalities::default().execute_with(|| { + frame_system::BlockHash::::insert(BlockNumber::zero(), Hash::default()); + let payload: SignedExtra = ( + frame_system::CheckNonZeroSender::new(), + frame_system::CheckSpecVersion::new(), + frame_system::CheckTxVersion::new(), + frame_system::CheckGenesis::new(), + frame_system::CheckEra::from(Era::Immortal), + frame_system::CheckNonce::from(10), + frame_system::CheckWeight::new(), + pallet_transaction_payment::ChargeTransactionPayment::from(10), + BridgeRejectObsoleteHeadersAndMessages, + BridgeRefundBridgeHubKusamaMessages::default(), + ); + + let bh_indirect_payload = bp_bridge_hub_polkadot::SignedExtension::from_params( + VERSION.spec_version, + VERSION.transaction_version, + bp_runtime::TransactionEra::Immortal, + System::block_hash(BlockNumber::zero()), + 10, + 10, + (((), ()), ((), ())), + ); + assert_eq!(payload.encode(), bh_indirect_payload.encode()); + assert_eq!( + payload.additional_signed().unwrap().encode(), + bh_indirect_payload.additional_signed().unwrap().encode() + ); + }) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/mod.rs index e226021e77ab..75f7c2376741 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/mod.rs @@ -22,6 +22,10 @@ pub mod cumulus_pallet_xcmp_queue; pub mod extrinsic_weights; pub mod frame_system; pub mod pallet_balances; +pub mod pallet_bridge_grandpa; +pub mod pallet_bridge_messages; +pub mod pallet_bridge_parachains; +pub mod pallet_bridge_relayers; pub mod pallet_collator_selection; pub mod pallet_multisig; pub mod pallet_session; @@ -36,3 +40,32 @@ pub use block_weights::constants::BlockExecutionWeight; pub use extrinsic_weights::constants::ExtrinsicBaseWeight; pub use paritydb_weights::constants::ParityDbWeight; pub use rocksdb_weights::constants::RocksDbWeight; + +use frame_support::weights::Weight; + +// import trait from dependency module +use ::pallet_bridge_relayers::WeightInfoExt as _; + +impl ::pallet_bridge_messages::WeightInfoExt + for pallet_bridge_messages::WeightInfo +{ + fn expected_extra_storage_proof_size() -> u32 { + bp_bridge_hub_kusama::EXTRA_STORAGE_PROOF_SIZE + } + + fn receive_messages_proof_overhead_from_runtime() -> Weight { + pallet_bridge_relayers::WeightInfo::::receive_messages_proof_overhead_from_runtime() + } + + fn receive_messages_delivery_proof_overhead_from_runtime() -> Weight { + pallet_bridge_relayers::WeightInfo::::receive_messages_delivery_proof_overhead_from_runtime() + } +} + +impl ::pallet_bridge_parachains::WeightInfoExt + for pallet_bridge_parachains::WeightInfo +{ + fn expected_extra_storage_proof_size() -> u32 { + bp_bridge_hub_kusama::EXTRA_STORAGE_PROOF_SIZE + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_grandpa.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_grandpa.rs new file mode 100644 index 000000000000..3df4f7673ddd --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_grandpa.rs @@ -0,0 +1,80 @@ +// 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 . + +//! Autogenerated weights for `pallet_bridge_grandpa` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `bm3`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-polkadot-dev"), DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot-parachain +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/var/lib/gitlab-runner/builds/zyw4fam_/0/parity/mirrors/cumulus/.git/.artifacts/bench.json +// --pallet=pallet_bridge_grandpa +// --chain=bridge-hub-polkadot-dev +// --header=./file_header.txt +// --output=./parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_bridge_grandpa`. +pub struct WeightInfo(PhantomData); +impl pallet_bridge_grandpa::WeightInfo for WeightInfo { + /// Storage: BridgeKusamaGrandpa PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaGrandpa PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: BridgeKusamaGrandpa BestFinalized (r:1 w:1) + /// Proof: BridgeKusamaGrandpa BestFinalized (max_values: Some(1), max_size: Some(36), added: 531, mode: MaxEncodedLen) + /// Storage: BridgeKusamaGrandpa CurrentAuthoritySet (r:1 w:0) + /// Proof: BridgeKusamaGrandpa CurrentAuthoritySet (max_values: Some(1), max_size: Some(50250), added: 50745, mode: MaxEncodedLen) + /// Storage: BridgeKusamaGrandpa ImportedHashesPointer (r:1 w:1) + /// Proof: BridgeKusamaGrandpa ImportedHashesPointer (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: BridgeKusamaGrandpa ImportedHashes (r:1 w:1) + /// Proof: BridgeKusamaGrandpa ImportedHashes (max_values: Some(1024), max_size: Some(36), added: 1521, mode: MaxEncodedLen) + /// Storage: BridgeKusamaGrandpa ImportedHeaders (r:0 w:2) + /// Proof: BridgeKusamaGrandpa ImportedHeaders (max_values: Some(1024), max_size: Some(68), added: 1553, mode: MaxEncodedLen) + /// The range of component `p` is `[1, 838]`. + /// The range of component `v` is `[50, 100]`. + fn submit_finality_proof(p: u32, v: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `302 + p * (60 ±0)` + // Estimated: `51735` + // Minimum execution time: 233_697_000 picoseconds. + Weight::from_parts(112_259_940, 0) + .saturating_add(Weight::from_parts(0, 51735)) + // Standard Error: 15_026 + .saturating_add(Weight::from_parts(47_393_046, 0).saturating_mul(p.into())) + // Standard Error: 250_621 + .saturating_add(Weight::from_parts(755_255, 0).saturating_mul(v.into())) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(5)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_messages.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_messages.rs new file mode 100644 index 000000000000..4679e9da87fe --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_messages.rs @@ -0,0 +1,231 @@ +// 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 . + +//! Autogenerated weights for `pallet_bridge_messages` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `bm3`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-polkadot-dev"), DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot-parachain +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/var/lib/gitlab-runner/builds/zyw4fam_/0/parity/mirrors/cumulus/.git/.artifacts/bench.json +// --pallet=pallet_bridge_messages +// --chain=bridge-hub-polkadot-dev +// --header=./file_header.txt +// --output=./parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_bridge_messages`. +pub struct WeightInfo(PhantomData); +impl pallet_bridge_messages::WeightInfo for WeightInfo { + /// Storage: BridgeKusamaMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgeKusamaMessages InboundLanes (r:1 w:1) + /// Proof: BridgeKusamaMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn receive_single_message_proof() -> Weight { + // Proof Size summary in bytes: + // Measured: `548` + // Estimated: `52645` + // Minimum execution time: 45_129_000 picoseconds. + Weight::from_parts(66_835_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgeKusamaMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgeKusamaMessages InboundLanes (r:1 w:1) + /// Proof: BridgeKusamaMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn receive_two_messages_proof() -> Weight { + // Proof Size summary in bytes: + // Measured: `548` + // Estimated: `52645` + // Minimum execution time: 56_593_000 picoseconds. + Weight::from_parts(76_972_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgeKusamaMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgeKusamaMessages InboundLanes (r:1 w:1) + /// Proof: BridgeKusamaMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + fn receive_single_message_proof_with_outbound_lane_state() -> Weight { + // Proof Size summary in bytes: + // Measured: `548` + // Estimated: `52645` + // Minimum execution time: 51_050_000 picoseconds. + Weight::from_parts(75_275_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgeKusamaMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgeKusamaMessages InboundLanes (r:1 w:1) + /// Proof: BridgeKusamaMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + fn receive_single_message_proof_1_kb() -> Weight { + // Proof Size summary in bytes: + // Measured: `516` + // Estimated: `52645` + // Minimum execution time: 43_320_000 picoseconds. + Weight::from_parts(51_994_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgeKusamaMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgeKusamaMessages InboundLanes (r:1 w:1) + /// Proof: BridgeKusamaMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + fn receive_single_message_proof_16_kb() -> Weight { + // Proof Size summary in bytes: + // Measured: `516` + // Estimated: `52645` + // Minimum execution time: 69_124_000 picoseconds. + Weight::from_parts(81_677_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: BridgeKusamaMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgeKusamaMessages OutboundLanes (r:1 w:1) + /// Proof: BridgeKusamaMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) + /// Storage: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Proof Skipped: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + fn receive_delivery_proof_for_single_message() -> Weight { + // Proof Size summary in bytes: + // Measured: `517` + // Estimated: `3982` + // Minimum execution time: 33_813_000 picoseconds. + Weight::from_parts(34_488_000, 0) + .saturating_add(Weight::from_parts(0, 3982)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgeKusamaMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgeKusamaMessages OutboundLanes (r:1 w:1) + /// Proof: BridgeKusamaMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) + /// Storage: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Proof Skipped: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { + // Proof Size summary in bytes: + // Measured: `517` + // Estimated: `3982` + // Minimum execution time: 34_317_000 picoseconds. + Weight::from_parts(34_792_000, 0) + .saturating_add(Weight::from_parts(0, 3982)) + .saturating_add(T::DbWeight::get().reads(5)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgeKusamaMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgeKusamaMessages OutboundLanes (r:1 w:1) + /// Proof: BridgeKusamaMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) + /// Storage: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Proof Skipped: unknown `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Storage: BridgeRelayers RelayerRewards (r:2 w:2) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { + // Proof Size summary in bytes: + // Measured: `517` + // Estimated: `6086` + // Minimum execution time: 36_468_000 picoseconds. + Weight::from_parts(36_905_000, 0) + .saturating_add(Weight::from_parts(0, 6086)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: BridgeKusamaMessages PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:1 w:0) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// Storage: BridgeKusamaMessages InboundLanes (r:1 w:1) + /// Proof: BridgeKusamaMessages InboundLanes (max_values: None, max_size: Some(49180), added: 51655, mode: MaxEncodedLen) + /// Storage: ParachainInfo ParachainId (r:1 w:0) + /// Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + /// Storage: PolkadotXcm SupportedVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SupportedVersion (max_values: None, max_size: None, mode: Measured) + /// Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + /// Proof Skipped: PolkadotXcm VersionDiscoveryQueue (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + /// Proof Skipped: PolkadotXcm SafeXcmVersion (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: ParachainSystem RelevantMessagingState (r:1 w:0) + /// Proof Skipped: ParachainSystem RelevantMessagingState (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: XcmpQueue OutboundXcmpStatus (r:1 w:1) + /// Proof Skipped: XcmpQueue OutboundXcmpStatus (max_values: Some(1), max_size: None, mode: Measured) + /// Storage: XcmpQueue OutboundXcmpMessages (r:0 w:1) + /// Proof Skipped: XcmpQueue OutboundXcmpMessages (max_values: None, max_size: None, mode: Measured) + /// The range of component `i` is `[128, 2048]`. + fn receive_single_message_proof_with_dispatch(i: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `706` + // Estimated: `52645` + // Minimum execution time: 130_562_000 picoseconds. + Weight::from_parts(100_661_765, 0) + .saturating_add(Weight::from_parts(0, 52645)) + // Standard Error: 3_792 + .saturating_add(Weight::from_parts(545_755, 0).saturating_mul(i.into())) + .saturating_add(T::DbWeight::get().reads(9)) + .saturating_add(T::DbWeight::get().writes(4)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_parachains.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_parachains.rs new file mode 100644 index 000000000000..ecc884bcc0fc --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_parachains.rs @@ -0,0 +1,115 @@ +// 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 . + +//! Autogenerated weights for `pallet_bridge_parachains` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `bm3`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-polkadot-dev"), DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot-parachain +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/var/lib/gitlab-runner/builds/zyw4fam_/0/parity/mirrors/cumulus/.git/.artifacts/bench.json +// --pallet=pallet_bridge_parachains +// --chain=bridge-hub-polkadot-dev +// --header=./file_header.txt +// --output=./parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_bridge_parachains`. +pub struct WeightInfo(PhantomData); +impl pallet_bridge_parachains::WeightInfo for WeightInfo { + /// Storage: BridgeKusamaParachain PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaParachain PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: BridgeKusamaGrandpa ImportedHeaders (r:1 w:0) + /// Proof: BridgeKusamaGrandpa ImportedHeaders (max_values: Some(1024), max_size: Some(68), added: 1553, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ParasInfo (r:1 w:1) + /// Proof: BridgeKusamaParachain ParasInfo (max_values: Some(1), max_size: Some(60), added: 555, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHashes (r:1 w:1) + /// Proof: BridgeKusamaParachain ImportedParaHashes (max_values: Some(64), max_size: Some(64), added: 1054, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:0 w:1) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + /// The range of component `p` is `[1, 2]`. + fn submit_parachain_heads_with_n_parachains(p: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `473` + // Estimated: `2543` + // Minimum execution time: 35_849_000 picoseconds. + Weight::from_parts(36_706_800, 0) + .saturating_add(Weight::from_parts(0, 2543)) + // Standard Error: 54_685 + .saturating_add(Weight::from_parts(1_700, 0).saturating_mul(p.into())) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: BridgeKusamaParachain PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaParachain PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: BridgeKusamaGrandpa ImportedHeaders (r:1 w:0) + /// Proof: BridgeKusamaGrandpa ImportedHeaders (max_values: Some(1024), max_size: Some(68), added: 1553, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ParasInfo (r:1 w:1) + /// Proof: BridgeKusamaParachain ParasInfo (max_values: Some(1), max_size: Some(60), added: 555, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHashes (r:1 w:1) + /// Proof: BridgeKusamaParachain ImportedParaHashes (max_values: Some(64), max_size: Some(64), added: 1054, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:0 w:1) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + fn submit_parachain_heads_with_1kb_proof() -> Weight { + // Proof Size summary in bytes: + // Measured: `473` + // Estimated: `2543` + // Minimum execution time: 37_271_000 picoseconds. + Weight::from_parts(37_692_000, 0) + .saturating_add(Weight::from_parts(0, 2543)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: BridgeKusamaParachain PalletOperatingMode (r:1 w:0) + /// Proof: BridgeKusamaParachain PalletOperatingMode (max_values: Some(1), max_size: Some(1), added: 496, mode: MaxEncodedLen) + /// Storage: BridgeKusamaGrandpa ImportedHeaders (r:1 w:0) + /// Proof: BridgeKusamaGrandpa ImportedHeaders (max_values: Some(1024), max_size: Some(68), added: 1553, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ParasInfo (r:1 w:1) + /// Proof: BridgeKusamaParachain ParasInfo (max_values: Some(1), max_size: Some(60), added: 555, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHashes (r:1 w:1) + /// Proof: BridgeKusamaParachain ImportedParaHashes (max_values: Some(64), max_size: Some(64), added: 1054, mode: MaxEncodedLen) + /// Storage: BridgeKusamaParachain ImportedParaHeads (r:0 w:1) + /// Proof: BridgeKusamaParachain ImportedParaHeads (max_values: Some(64), max_size: Some(196), added: 1186, mode: MaxEncodedLen) + fn submit_parachain_heads_with_16kb_proof() -> Weight { + // Proof Size summary in bytes: + // Measured: `473` + // Estimated: `2543` + // Minimum execution time: 63_033_000 picoseconds. + Weight::from_parts(63_704_000, 0) + .saturating_add(Weight::from_parts(0, 2543)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(3)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_relayers.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_relayers.rs new file mode 100644 index 000000000000..f2cc9490ee34 --- /dev/null +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/pallet_bridge_relayers.rs @@ -0,0 +1,124 @@ +// 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 . + +//! Autogenerated weights for `pallet_bridge_relayers` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2023-05-10, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `bm3`, CPU: `Intel(R) Core(TM) i7-7700K CPU @ 4.20GHz` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("bridge-hub-polkadot-dev"), DB CACHE: 1024 + +// Executed Command: +// target/production/polkadot-parachain +// benchmark +// pallet +// --steps=50 +// --repeat=20 +// --extrinsic=* +// --execution=wasm +// --wasm-execution=compiled +// --heap-pages=4096 +// --json-file=/var/lib/gitlab-runner/builds/zyw4fam_/0/parity/mirrors/cumulus/.git/.artifacts/bench.json +// --pallet=pallet_bridge_relayers +// --chain=bridge-hub-polkadot-dev +// --header=./file_header.txt +// --output=./parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/ + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] +#![allow(missing_docs)] + +use frame_support::{traits::Get, weights::Weight}; +use core::marker::PhantomData; + +/// Weight functions for `pallet_bridge_relayers`. +pub struct WeightInfo(PhantomData); +impl pallet_bridge_relayers::WeightInfo for WeightInfo { + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + fn claim_rewards() -> Weight { + // Proof Size summary in bytes: + // Measured: `278` + // Estimated: `3593` + // Minimum execution time: 52_513_000 picoseconds. + Weight::from_parts(53_314_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgeRelayers RegisteredRelayers (r:1 w:1) + /// Proof: BridgeRelayers RegisteredRelayers (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: unknown `0x1e8445dc201eeb8560e5579a5dd54655` (r:1 w:0) + /// Proof Skipped: unknown `0x1e8445dc201eeb8560e5579a5dd54655` (r:1 w:0) + /// Storage: Balances Reserves (r:1 w:1) + /// Proof: Balances Reserves (max_values: None, max_size: Some(1249), added: 3724, mode: MaxEncodedLen) + fn register() -> Weight { + // Proof Size summary in bytes: + // Measured: `131` + // Estimated: `4714` + // Minimum execution time: 29_576_000 picoseconds. + Weight::from_parts(30_157_000, 0) + .saturating_add(Weight::from_parts(0, 4714)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgeRelayers RegisteredRelayers (r:1 w:1) + /// Proof: BridgeRelayers RegisteredRelayers (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: Balances Reserves (r:1 w:1) + /// Proof: Balances Reserves (max_values: None, max_size: Some(1249), added: 3724, mode: MaxEncodedLen) + fn deregister() -> Weight { + // Proof Size summary in bytes: + // Measured: `231` + // Estimated: `4714` + // Minimum execution time: 31_146_000 picoseconds. + Weight::from_parts(31_774_000, 0) + .saturating_add(Weight::from_parts(0, 4714)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: BridgeRelayers RegisteredRelayers (r:1 w:1) + /// Proof: BridgeRelayers RegisteredRelayers (max_values: None, max_size: Some(68), added: 2543, mode: MaxEncodedLen) + /// Storage: Balances Reserves (r:1 w:1) + /// Proof: Balances Reserves (max_values: None, max_size: Some(1249), added: 3724, mode: MaxEncodedLen) + /// Storage: System Account (r:1 w:1) + /// Proof: System Account (max_values: None, max_size: Some(128), added: 2603, mode: MaxEncodedLen) + fn slash_and_deregister() -> Weight { + // Proof Size summary in bytes: + // Measured: `334` + // Estimated: `4714` + // Minimum execution time: 30_665_000 picoseconds. + Weight::from_parts(31_435_000, 0) + .saturating_add(Weight::from_parts(0, 4714)) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: BridgeRelayers RelayerRewards (r:1 w:1) + /// Proof: BridgeRelayers RelayerRewards (max_values: None, max_size: Some(73), added: 2548, mode: MaxEncodedLen) + fn register_relayer_reward() -> Weight { + // Proof Size summary in bytes: + // Measured: `76` + // Estimated: `3538` + // Minimum execution time: 3_524_000 picoseconds. + Weight::from_parts(3_723_000, 0) + .saturating_add(Weight::from_parts(0, 3538)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/xcm/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/xcm/mod.rs index 4f8c2dec7a8c..24f28fbbd3a3 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/xcm/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/xcm/mod.rs @@ -18,6 +18,7 @@ mod pallet_xcm_benchmarks_fungible; mod pallet_xcm_benchmarks_generic; use crate::{xcm_config::MaxAssetsIntoHolding, Runtime}; +use codec::Encode; use frame_support::weights::Weight; use pallet_xcm_benchmarks_fungible::WeightInfo as XcmFungibleWeight; use pallet_xcm_benchmarks_generic::WeightInfo as XcmGeneric; @@ -225,8 +226,9 @@ impl XcmWeightInfo for BridgeHubPolkadotXcmWeight { fn universal_origin(_: &Junction) -> Weight { Weight::MAX } - fn export_message(_: &NetworkId, _: &Junctions, _: &Xcm<()>) -> Weight { - Weight::MAX + fn export_message(_: &NetworkId, _: &Junctions, inner: &Xcm<()>) -> Weight { + let inner_encoded_len = inner.encode().len() as u32; + XcmGeneric::::export_message(inner_encoded_len) } fn lock_asset(_: &MultiAsset, _: &MultiLocation) -> Weight { Weight::MAX diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/xcm/pallet_xcm_benchmarks_generic.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/xcm/pallet_xcm_benchmarks_generic.rs index 7968649d143c..7752a0533625 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/xcm/pallet_xcm_benchmarks_generic.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/weights/xcm/pallet_xcm_benchmarks_generic.rs @@ -312,6 +312,26 @@ impl WeightInfo { // Minimum execution time: 2_611_000 picoseconds. Weight::from_parts(2_707_000, 0) } + // Storage: ParachainInfo ParachainId (r:1 w:0) + // Proof: ParachainInfo ParachainId (max_values: Some(1), max_size: Some(4), added: 499, mode: MaxEncodedLen) + // Storage: BridgeKusamaMessages PalletOperatingMode (r:1 w:0) + // Proof: BridgeKusamaMessages PalletOperatingMode (max_values: Some(1), max_size: Some(2), added: 497, mode: MaxEncodedLen) + // Storage: BridgeKusamaMessages OutboundLanes (r:1 w:1) + // Proof: BridgeKusamaMessages OutboundLanes (max_values: Some(1), max_size: Some(44), added: 539, mode: MaxEncodedLen) + // Storage: BridgeKusamaMessages OutboundMessages (r:0 w:1) + // Proof: BridgeKusamaMessages OutboundMessages (max_values: None, max_size: Some(2621472), added: 2623947, mode: MaxEncodedLen) + /// The range of component `x` is `[1, 1000]`. + pub fn export_message(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `167` + // Estimated: `1529` + // Minimum execution time: 30_323_000 picoseconds. + Weight::from_parts(32_469_359, 1529) + // Standard Error: 208 + .saturating_add(Weight::from_parts(176_327, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(3)) + .saturating_add(T::DbWeight::get().writes(2)) + } pub fn set_fees_mode() -> Weight { // Proof Size summary in bytes: // Measured: `0` diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs index 0965600c2468..5154a28a1dcd 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/src/xcm_config.rs @@ -18,6 +18,10 @@ use super::{ AccountId, AllPalletsWithSystem, Balances, ParachainInfo, ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, WeightToFee, XcmpQueue, }; +use crate::{ + bridge_hub_config::ToBridgeHubKusamaHaulBlobExporter, BridgeGrandpaKusamaInstance, + DeliveryRewardInBalance, RequiredStakeForStakeAndSlash, +}; use frame_support::{ match_types, parameter_types, traits::{ConstU32, Contains, Everything, Nothing}, @@ -83,7 +87,7 @@ pub type XcmOriginToTransactDispatchOrigin = ( // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for // foreign chains who want to have a local sovereign account on this chain which they control. SovereignSignedViaLocation, - // Native converter for Relay-chain (Parent) location; will converts to a `Relay` origin when + // Native converter for Relay-chain (Parent) location; will convert to a `Relay` origin when // recognized. RelayChainAsNative, // Native converter for sibling Parachains; will convert to a `SiblingPara` origin when @@ -112,6 +116,7 @@ match_types! { MultiLocation { parents: 1, interior: X2(Parachain(1001), Plurality { id: BodyId::Technical, ..}) } }; } + /// A call filter for the XCM Transact instruction. This is a temporary measure until we properly /// account for proof size weights. /// @@ -129,6 +134,17 @@ impl Contains for SafeCallFilter { } } + // Allow to change dedicated storage items (called by governance-like) + match call { + RuntimeCall::System(frame_system::Call::set_storage { items }) + if items.iter().all(|(k, _)| { + k.eq(&DeliveryRewardInBalance::key()) | + k.eq(&RequiredStakeForStakeAndSlash::key()) + }) => + return true, + _ => (), + }; + matches!( call, RuntimeCall::PolkadotXcm(pallet_xcm::Call::force_xcm_version { .. }) | @@ -150,7 +166,11 @@ impl Contains for SafeCallFilter { pallet_collator_selection::Call::remove_invulnerable { .. }, ) | RuntimeCall::Session(pallet_session::Call::purge_keys { .. }) | RuntimeCall::XcmpQueue(..) | - RuntimeCall::DmpQueue(..) + RuntimeCall::DmpQueue(..) | + RuntimeCall::BridgeKusamaGrandpa(pallet_bridge_grandpa::Call::< + Runtime, + BridgeGrandpaKusamaInstance, + >::initialize { .. }) ) } } @@ -168,7 +188,7 @@ pub type Barrier = TrailingSetTopicAsId< // If the message is one that immediately attemps to pay for execution, then // allow it. AllowTopLevelPaidExecutionFrom, - // Parent, its pluralities (i.e. governance bodies), and the Fellows plurality + // Parent, its pluralities (i.e. governance bodies) and the Fellows plurality // get free execution. AllowExplicitUnpaidExecutionFrom<(ParentOrParentsPlurality, FellowsPlurality)>, // Subscriptions for version tracking are OK. @@ -203,14 +223,14 @@ impl xcm_executor::Config for XcmConfig { UsingComponents>; type ResponseHandler = PolkadotXcm; type AssetTrap = PolkadotXcm; + type AssetLocker = (); + type AssetExchanger = (); type AssetClaims = PolkadotXcm; type SubscriptionService = PolkadotXcm; type PalletInstancesInfo = AllPalletsWithSystem; type MaxAssetsIntoHolding = MaxAssetsIntoHolding; - type AssetLocker = (); - type AssetExchanger = (); type FeeManager = (); - type MessageExporter = (); + type MessageExporter = ToBridgeHubKusamaHaulBlobExporter; type UniversalAliases = Nothing; type CallDispatcher = WithOriginFilter; type SafeCallFilter = SafeCallFilter; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/tests/tests.rs index 0be87bd46fac..38f6462579f4 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-polkadot/tests/tests.rs @@ -14,18 +14,84 @@ // You should have received a copy of the GNU General Public License // along with Cumulus. If not, see . +use bp_polkadot_core::Signature; pub use bridge_hub_polkadot_runtime::{ - xcm_config::XcmConfig, AllPalletsWithoutSystem, Balances, ExistentialDeposit, ParachainSystem, - PolkadotXcm, Runtime, RuntimeEvent, SessionKeys, + bridge_hub_config, + xcm_config::{DotRelayLocation, RelayNetwork, XcmConfig}, + AllPalletsWithoutSystem, Balances, BridgeGrandpaKusamaInstance, + BridgeRejectObsoleteHeadersAndMessages, ExistentialDeposit, ParachainSystem, PolkadotXcm, + Runtime, RuntimeCall, RuntimeEvent, SessionKeys, WithBridgeHubKusamaMessagesInstance, }; -use codec::Decode; +use bridge_hub_polkadot_runtime::{ + bridge_hub_config::WithBridgeHubKusamaMessageBridge, BridgeParachainKusamaInstance, + DeliveryRewardInBalance, Executive, RequiredStakeForStakeAndSlash, SignedExtra, + UncheckedExtrinsic, +}; +use codec::{Decode, Encode}; use frame_support::parameter_types; -use parachains_common::{polkadot::fee::WeightToFee, AccountId, AuraId}; +use parachains_common::{polkadot::fee::WeightToFee, AccountId, AuraId, Balance}; +use sp_keyring::AccountKeyring::Alice; +use sp_runtime::{ + generic::{Era, SignedPayload}, + traits::Block as BlockT, + AccountId32, +}; +use xcm::latest::prelude::*; -const ALICE: [u8; 32] = [1u8; 32]; +// Para id of sibling chain (e.g. Statemint) used in tests. +pub const SIBLING_PARACHAIN_ID: u32 = 1000; parameter_types! { pub CheckingAccount: AccountId = PolkadotXcm::check_account(); + pub RuntimeNetwork: NetworkId = RelayNetwork::get().unwrap(); +} + +fn construct_extrinsic( + sender: sp_keyring::AccountKeyring, + call: RuntimeCall, +) -> UncheckedExtrinsic { + let extra: SignedExtra = ( + frame_system::CheckNonZeroSender::::new(), + frame_system::CheckSpecVersion::::new(), + frame_system::CheckTxVersion::::new(), + frame_system::CheckGenesis::::new(), + frame_system::CheckEra::::from(Era::immortal()), + frame_system::CheckNonce::::from(0), + frame_system::CheckWeight::::new(), + pallet_transaction_payment::ChargeTransactionPayment::::from(0), + BridgeRejectObsoleteHeadersAndMessages::default(), + bridge_hub_config::BridgeRefundBridgeHubKusamaMessages::default(), + ); + let payload = SignedPayload::new(call.clone(), extra.clone()).unwrap(); + let signature = payload.using_encoded(|e| sender.sign(e)); + UncheckedExtrinsic::new_signed( + call, + AccountId32::from(sender.public()).into(), + Signature::Sr25519(signature.clone()), + extra, + ) +} + +fn construct_and_apply_extrinsic( + relayer_at_target: sp_keyring::AccountKeyring, + batch: pallet_utility::Call, +) -> sp_runtime::DispatchOutcome { + let batch_call = RuntimeCall::Utility(batch); + let xt = construct_extrinsic(relayer_at_target, batch_call); + let r = Executive::apply_extrinsic(xt); + r.unwrap() +} + +fn executive_init_block(header: &<::Block as BlockT>::Header) { + Executive::initialize_block(header) +} + +fn collator_session_keys() -> bridge_hub_test_utils::CollatorSessionKeys { + bridge_hub_test_utils::CollatorSessionKeys::new( + AccountId::from(Alice), + AccountId::from(Alice), + SessionKeys { aura: AuraId::from(Alice.public()) }, + ) } bridge_hub_test_utils::test_cases::include_teleports_for_native_asset_works!( @@ -35,11 +101,7 @@ bridge_hub_test_utils::test_cases::include_teleports_for_native_asset_works!( CheckingAccount, WeightToFee, ParachainSystem, - bridge_hub_test_utils::CollatorSessionKeys::new( - AccountId::from(ALICE), - AccountId::from(ALICE), - SessionKeys { aura: AuraId::from(sp_core::sr25519::Public::from_raw(ALICE)) } - ), + collator_session_keys(), ExistentialDeposit::get(), Box::new(|runtime_event_encoded: Vec| { match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { @@ -55,3 +117,169 @@ bridge_hub_test_utils::test_cases::include_teleports_for_native_asset_works!( }), 1002 ); + +#[test] +fn initialize_bridge_by_governance_works() { + bridge_hub_test_utils::test_cases::initialize_bridge_by_governance_works::< + Runtime, + BridgeGrandpaKusamaInstance, + >( + collator_session_keys(), + bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, + Box::new(|call| RuntimeCall::BridgeKusamaGrandpa(call).encode()), + ) +} + +#[test] +fn change_delivery_reward_by_governance_works() { + bridge_hub_test_utils::test_cases::change_storage_constant_by_governance_works::< + Runtime, + DeliveryRewardInBalance, + u64, + >( + collator_session_keys(), + bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, + Box::new(|call| RuntimeCall::System(call).encode()), + || (DeliveryRewardInBalance::key().to_vec(), DeliveryRewardInBalance::get()), + |old_value| old_value.checked_mul(2).unwrap(), + ) +} + +#[test] +fn change_required_stake_by_governance_works() { + bridge_hub_test_utils::test_cases::change_storage_constant_by_governance_works::< + Runtime, + RequiredStakeForStakeAndSlash, + Balance, + >( + collator_session_keys(), + bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, + Box::new(|call| RuntimeCall::System(call).encode()), + || (RequiredStakeForStakeAndSlash::key().to_vec(), RequiredStakeForStakeAndSlash::get()), + |old_value| { + if let Some(new_value) = old_value.checked_add(1) { + new_value + } else { + old_value.checked_sub(1).unwrap() + } + }, + ) +} + +#[test] +fn handle_export_message_from_system_parachain_add_to_outbound_queue_works() { + bridge_hub_test_utils::test_cases::handle_export_message_from_system_parachain_to_outbound_queue_works::< + Runtime, + XcmConfig, + WithBridgeHubKusamaMessagesInstance, + >( + collator_session_keys(), + bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, + SIBLING_PARACHAIN_ID, + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::BridgeKusamaMessages(event)) => Some(event), + _ => None, + } + }), + || ExportMessage { network: Kusama, destination: X1(Parachain(1234)), xcm: Xcm(vec![]) }, + bridge_hub_config::ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID, + Some((DotRelayLocation::get(), ExistentialDeposit::get()).into()), + // value should be >= than value generated by `can_calculate_weight_for_paid_export_message_with_reserve_transfer` + Some((DotRelayLocation::get(), bp_asset_hub_polkadot::BridgeHubPolkadotBaseFeeInDots::get()).into()), + ) +} + +#[test] +fn message_dispatch_routing_works() { + bridge_hub_test_utils::test_cases::message_dispatch_routing_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + WithBridgeHubKusamaMessagesInstance, + RuntimeNetwork, + bridge_hub_config::KusamaGlobalConsensusNetwork, + >( + collator_session_keys(), + bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, + SIBLING_PARACHAIN_ID, + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::ParachainSystem(event)) => Some(event), + _ => None, + } + }), + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::XcmpQueue(event)) => Some(event), + _ => None, + } + }), + bridge_hub_config::ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID, + ) +} + +#[test] +fn relayed_incoming_message_works() { + bridge_hub_test_utils::test_cases::relayed_incoming_message_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + BridgeGrandpaKusamaInstance, + BridgeParachainKusamaInstance, + WithBridgeHubKusamaMessagesInstance, + WithBridgeHubKusamaMessageBridge, + >( + collator_session_keys(), + bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, + bp_bridge_hub_kusama::BRIDGE_HUB_KUSAMA_PARACHAIN_ID, + SIBLING_PARACHAIN_ID, + RuntimeNetwork::get(), + bridge_hub_config::ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID, + ) +} + +#[test] +pub fn complex_relay_extrinsic_works() { + bridge_hub_test_utils::test_cases::complex_relay_extrinsic_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + BridgeGrandpaKusamaInstance, + BridgeParachainKusamaInstance, + WithBridgeHubKusamaMessagesInstance, + WithBridgeHubKusamaMessageBridge, + >( + collator_session_keys(), + bp_bridge_hub_polkadot::BRIDGE_HUB_POLKADOT_PARACHAIN_ID, + bp_bridge_hub_kusama::BRIDGE_HUB_KUSAMA_PARACHAIN_ID, + SIBLING_PARACHAIN_ID, + bridge_hub_config::BridgeHubKusamaChainId::get(), + RuntimeNetwork::get(), + bridge_hub_config::ASSET_HUB_POLKADOT_TO_ASSET_HUB_KUSAMA_LANE_ID, + ExistentialDeposit::get(), + executive_init_block, + construct_and_apply_extrinsic, + ); +} + +#[test] +pub fn can_calculate_weight_for_paid_export_message_with_reserve_transfer() { + let estimated = bridge_hub_test_utils::test_cases::can_calculate_weight_for_paid_export_message_with_reserve_transfer::< + Runtime, + XcmConfig, + WeightToFee, + >(); + + // check if estimated value is sane + let max_expected = bp_asset_hub_polkadot::BridgeHubPolkadotBaseFeeInDots::get(); + assert!( + estimated <= max_expected, + "calculated: {:?}, max_expected: {:?}, please adjust `bp_asset_hub_polkadot::BridgeHubPolkadotBaseFeeInDots` value", + estimated, + max_expected + ); +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_hub_rococo_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_hub_rococo_config.rs index bc8f97ad97c1..8ef6d9fca85d 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_hub_rococo_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_hub_rococo_config.rs @@ -62,7 +62,7 @@ parameter_types! { /// Proof of messages, coming from Wococo. pub type FromWococoBridgeHubMessagesProof = FromBridgedChainMessagesProof; -/// Messages delivery proof for Rococo Bridge Hub -> Wococo Bridge Hub messages. +/// Messages delivery proof for Rococo BridgeHub -> Wococo BridgeHub messages. pub type ToWococoBridgeHubMessagesDeliveryProof = FromBridgedChainMessagesDeliveryProof; @@ -73,7 +73,7 @@ pub type OnBridgeHubRococoBlobDispatcher = BridgeBlobDispatcher< BridgeWococoMessagesPalletInstance, >; -/// Export XCM messages to be relayed to the otherside +/// Export XCM messages to be relayed to the other side. pub type ToBridgeHubWococoHaulBlobExporter = HaulBlobExporter< XcmBlobHaulerAdapter, WococoGlobalConsensusNetwork, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_hub_wococo_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_hub_wococo_config.rs index 5178b75c3039..a11f80f2a9cb 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_hub_wococo_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_hub_wococo_config.rs @@ -62,7 +62,7 @@ parameter_types! { /// Proof of messages, coming from Rococo. pub type FromRococoBridgeHubMessagesProof = FromBridgedChainMessagesProof; -/// Messages delivery proof for Rococo Bridge Hub -> Wococo Bridge Hub messages. +/// Messages delivery proof for Rococo BridgeHub -> Wococo BridgeHub messages. pub type ToRococoBridgeHubMessagesDeliveryProof = FromBridgedChainMessagesDeliveryProof; @@ -73,7 +73,7 @@ pub type OnBridgeHubWococoBlobDispatcher = BridgeBlobDispatcher< BridgeRococoMessagesPalletInstance, >; -/// Export XCM messages to be relayed to the otherside +/// Export XCM messages to be relayed to the other side. pub type ToBridgeHubRococoHaulBlobExporter = HaulBlobExporter< XcmBlobHaulerAdapter, RococoGlobalConsensusNetwork, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs index dbdc2133ec88..29274f8b7f87 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/lib.rs @@ -439,7 +439,7 @@ parameter_types! { pub const RelayerStakeReserveId: [u8; 8] = *b"brdgrlrs"; } -/// Add parachain bridge pallet to track Wococo bridge hub parachain +/// Add parachain bridge pallet to track Wococo BridgeHub parachain pub type BridgeParachainWococoInstance = pallet_bridge_parachains::Instance1; impl pallet_bridge_parachains::Config for Runtime { type RuntimeEvent = RuntimeEvent; @@ -452,7 +452,7 @@ impl pallet_bridge_parachains::Config for Runtime type MaxParaHeadDataSize = MaxWococoParaHeadDataSize; } -/// Add parachain bridge pallet to track Rococo bridge hub parachain +/// Add parachain bridge pallet to track Rococo BridgeHub parachain pub type BridgeParachainRococoInstance = pallet_bridge_parachains::Instance2; impl pallet_bridge_parachains::Config for Runtime { type RuntimeEvent = RuntimeEvent; @@ -583,16 +583,16 @@ construct_runtime!( Utility: pallet_utility::{Pallet, Call, Event} = 40, Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 36, - // Rococo and Wococo Bridge Hubs are sharing the runtime, so this runtime has two sets of + // Rococo and Wococo BridgeHubs are sharing the runtime, so this runtime has two sets of // bridge pallets. Both are deployed at both runtimes, but only one set is actually used // at particular runtime. - // With-Wococo bridge modules that are active (used) at Rococo Bridge Hub runtime. + // With-Wococo bridge modules that are active (used) at Rococo BridgeHub runtime. BridgeWococoGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Storage, Event, Config} = 41, BridgeWococoParachain: pallet_bridge_parachains::::{Pallet, Call, Storage, Event} = 42, BridgeWococoMessages: pallet_bridge_messages::::{Pallet, Call, Storage, Event, Config} = 46, - // With-Rococo bridge modules that are active (used) at Wococo Bridge Hub runtime. + // With-Rococo bridge modules that are active (used) at Wococo BridgeHub runtime. BridgeRococoGrandpa: pallet_bridge_grandpa::::{Pallet, Call, Storage, Event, Config} = 43, BridgeRococoParachain: pallet_bridge_parachains::::{Pallet, Call, Storage, Event} = 44, BridgeRococoMessages: pallet_bridge_messages::::{Pallet, Call, Storage, Event, Config} = 45, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs index e3d8645d49e7..55064af74a8e 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/xcm_config.rs @@ -154,7 +154,7 @@ impl Contains for SafeCallFilter { // Allow to change dedicated storage items (called by governance-like) match call { RuntimeCall::System(frame_system::Call::set_storage { items }) - if items.iter().any(|(k, _)| { + if items.iter().all(|(k, _)| { k.eq(&DeliveryRewardInBalance::key()) | k.eq(&RequiredStakeForStakeAndSlash::key()) }) => diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs index e5fe67f2a8e5..f128d9fc48db 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/tests/tests.rs @@ -55,7 +55,7 @@ fn construct_extrinsic( frame_system::CheckNonce::::from(0), frame_system::CheckWeight::::new(), pallet_transaction_payment::ChargeTransactionPayment::::from(0), - BridgeRejectObsoleteHeadersAndMessages {}, + BridgeRejectObsoleteHeadersAndMessages::default(), ( bridge_hub_wococo_config::BridgeRefundBridgeHubRococoMessages::default(), bridge_hub_rococo_config::BridgeRefundBridgeHubWococoMessages::default(), @@ -191,7 +191,9 @@ mod bridge_hub_rococo_tests { } }), || ExportMessage { network: Wococo, destination: X1(Parachain(1234)), xcm: Xcm(vec![]) }, - bridge_hub_rococo_config::DEFAULT_XCM_LANE_TO_BRIDGE_HUB_WOCOCO + bridge_hub_rococo_config::DEFAULT_XCM_LANE_TO_BRIDGE_HUB_WOCOCO, + None, + None, ) } @@ -370,7 +372,9 @@ mod bridge_hub_wococo_tests { } }), || ExportMessage { network: Rococo, destination: X1(Parachain(4321)), xcm: Xcm(vec![]) }, - bridge_hub_wococo_config::DEFAULT_XCM_LANE_TO_BRIDGE_HUB_ROCOCO + bridge_hub_wococo_config::DEFAULT_XCM_LANE_TO_BRIDGE_HUB_ROCOCO, + None, + None, ) } diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml b/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml index d56c32d8afab..2ad79bb24886 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/Cargo.toml @@ -8,7 +8,6 @@ description = "Utils for BridgeHub testing" [dependencies] codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive", "max-encoded-len"] } log = { version = "0.4.20", default-features = false } -assert_matches = "1.4.0" # Substrate frame-benchmarking = { path = "../../../../../substrate/frame/benchmarking", default-features = false, optional = true } @@ -19,6 +18,7 @@ sp-core = { path = "../../../../../substrate/primitives/core", default-features sp-io = { path = "../../../../../substrate/primitives/io", default-features = false} sp-keyring = { path = "../../../../../substrate/primitives/keyring" } sp-runtime = { path = "../../../../../substrate/primitives/runtime", default-features = false} +sp-tracing = { path = "../../../../../substrate/primitives/tracing" } pallet-balances = { path = "../../../../../substrate/frame/balances", default-features = false} pallet-utility = { path = "../../../../../substrate/frame/utility", default-features = false} pallet-session = { path = "../../../../../substrate/frame/session", default-features = false} diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases.rs index aa7fa16a9791..125a4bd460ed 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases.rs @@ -16,7 +16,6 @@ //! Module contains predefined test-case scenarios for `Runtime` with bridging capabilities. -use assert_matches::assert_matches; use bp_messages::{ target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch, SourceHeaderChain}, LaneId, MessageKey, OutboundLaneData, Weight, @@ -47,10 +46,16 @@ use parachains_runtimes_test_utils::{ }; use sp_core::H256; use sp_keyring::AccountKeyring::*; -use sp_runtime::{traits::Header as HeaderT, AccountId32}; +use sp_runtime::{ + traits::{Header as HeaderT, Zero}, + AccountId32, +}; use xcm::latest::prelude::*; use xcm_builder::DispatchBlobError; -use xcm_executor::XcmExecutor; +use xcm_executor::{ + traits::{TransactAsset, WeightBounds}, + XcmExecutor, +}; // Re-export test_case from assets pub use asset_test_utils::include_teleports_for_native_asset_works; @@ -137,6 +142,8 @@ pub fn handle_export_message_from_system_parachain_to_outbound_queue_works< >, export_message_instruction: fn() -> Instruction, expected_lane_id: LaneId, + existential_deposit: Option, + maybe_paid_export_message: Option, ) where Runtime: frame_system::Config + pallet_balances::Config @@ -170,10 +177,35 @@ pub fn handle_export_message_from_system_parachain_to_outbound_queue_works< ); // prepare `ExportMessage` - let xcm = Xcm(vec![ - UnpaidExecution { weight_limit: Unlimited, check_origin: None }, - export_message_instruction(), - ]); + let xcm = if let Some(fee) = maybe_paid_export_message { + // deposit ED to origin (if needed) + if let Some(ed) = existential_deposit { + XcmConfig::AssetTransactor::deposit_asset( + &ed, + &sibling_parachain_location, + &XcmContext::with_message_id([0; 32]), + ) + .expect("deposited ed"); + } + // deposit fee to origin + XcmConfig::AssetTransactor::deposit_asset( + &fee, + &sibling_parachain_location, + &XcmContext::with_message_id([0; 32]), + ) + .expect("deposited fee"); + + Xcm(vec![ + WithdrawAsset(MultiAssets::from(vec![fee.clone()])), + BuyExecution { fees: fee, weight_limit: Unlimited }, + export_message_instruction(), + ]) + } else { + Xcm(vec![ + UnpaidExecution { weight_limit: Unlimited, check_origin: None }, + export_message_instruction(), + ]) + }; // execute XCM let hash = xcm.using_encoded(sp_io::hashing::blake2_256); @@ -249,6 +281,7 @@ pub fn message_dispatch_routing_works< XcmConfig: xcm_executor::Config, MessagesPalletInstance: 'static, ValidatorIdOf: From>, + ::AccountId: From, HrmpChannelOpener: frame_support::inherent::ProvideInherent< Call = cumulus_pallet_parachain_system::Call, >, @@ -272,7 +305,7 @@ pub fn message_dispatch_routing_works< let included_head = RuntimeHelper::::run_to_block( 2, - AccountId::from(alice), + AccountId::from(alice).into(), ); // 1. this message is sent from other global consensus with destination of this Runtime relay chain (UMP) let bridging_message = @@ -374,11 +407,11 @@ pub fn relayed_incoming_message_works>::BridgedChain as bp_runtime::Chain>::Hash>, ::AccountId: Into<<::RuntimeOrigin as OriginTrait>::AccountId>, + ::AccountId: From, AccountIdOf: From, >::InboundRelayer: From, { assert_ne!(runtime_para_id, sibling_parachain_id); - assert_ne!(runtime_para_id, bridged_para_id); ExtBuilder::::default() .with_collators(collator_session_key.collators()) @@ -393,7 +426,7 @@ pub fn relayed_incoming_message_works::run_to_block( 2, - AccountId::from(alice), + AccountId::from(alice).into(), ); mock_open_hrmp_channel::( runtime_para_id.into(), @@ -528,15 +561,24 @@ pub fn relayed_incoming_message_works>::take_xcm( sibling_parachain_id.into(), ) .unwrap(); - let mut dispatched = xcm::latest::Xcm::<()>::try_from(dispatched).unwrap(); - // We use `WithUniqueTopic`, so expect a trailing `SetTopic`. - assert_matches!(dispatched.0.pop(), Some(SetTopic(..))); - assert_eq!(dispatched, expected_dispatch); + // verify contains original message + let dispatched = xcm::latest::Xcm::<()>::try_from(dispatched).unwrap(); + let mut dispatched_clone = dispatched.clone(); + for (idx, expected_instr) in expected_dispatch.0.iter().enumerate() { + assert_eq!(expected_instr, &dispatched.0[idx]); + assert_eq!(expected_instr, &dispatched_clone.0.remove(0)); + } + match dispatched_clone.0.len() { + 0 => (), + 1 => assert!(matches!(dispatched_clone.0[0], SetTopic(_))), + count => assert!(false, "Unexpected messages count: {:?}", count), + } }) } @@ -591,6 +633,7 @@ pub fn complex_relay_extrinsic_works::AccountId: Into<<::RuntimeOrigin as OriginTrait>::AccountId>, AccountIdOf: From, + ::AccountId: From, >::InboundRelayer: From, ::RuntimeCall: From> @@ -598,7 +641,6 @@ pub fn complex_relay_extrinsic_works> { assert_ne!(runtime_para_id, sibling_parachain_id); - assert_ne!(runtime_para_id, bridged_para_id); // Relayer account at local/this BH. let relayer_at_target = Bob; @@ -622,7 +664,7 @@ pub fn complex_relay_extrinsic_works::run_to_block( 2, - AccountId::from(alice), + AccountId::from(alice).into(), ); let zero: BlockNumberFor = 0u32.into(); let genesis_hash = frame_system::Pallet::::block_hash(zero); @@ -678,7 +720,7 @@ pub fn complex_relay_extrinsic_works, MB, ()>( lane_id, - xcm.into(), + xcm.clone().into(), message_nonce, message_destination, para_header_number, @@ -769,18 +811,133 @@ pub fn complex_relay_extrinsic_works>::take_xcm( sibling_parachain_id.into(), ) .unwrap(); - let mut dispatched = xcm::latest::Xcm::<()>::try_from(dispatched).unwrap(); - // We use `WithUniqueTopic`, so expect a trailing `SetTopic`. - assert_matches!(dispatched.0.pop(), Some(SetTopic(..))); - assert_eq!(dispatched, expected_dispatch); + // verify contains original message + let dispatched = xcm::latest::Xcm::<()>::try_from(dispatched).unwrap(); + let mut dispatched_clone = dispatched.clone(); + for (idx, expected_instr) in expected_dispatch.0.iter().enumerate() { + assert_eq!(expected_instr, &dispatched.0[idx]); + assert_eq!(expected_instr, &dispatched_clone.0.remove(0)); + } + match dispatched_clone.0.len() { + 0 => (), + 1 => assert!(matches!(dispatched_clone.0[0], SetTopic(_))), + count => assert!(false, "Unexpected messages count: {:?}", count), + } }) } +/// Estimates fee for paid `ExportMessage` processing. +pub fn can_calculate_weight_for_paid_export_message_with_reserve_transfer< + Runtime, + XcmConfig, + WeightToFee, +>() -> u128 +where + Runtime: frame_system::Config + pallet_balances::Config, + XcmConfig: xcm_executor::Config, + WeightToFee: frame_support::weights::WeightToFee>, + ::Balance: From + Into, +{ + // data here are not relevant for weighing + let mut xcm = Xcm(vec![ + WithdrawAsset(MultiAssets::from(vec![MultiAsset { + id: Concrete(MultiLocation { parents: 1, interior: Here }), + fun: Fungible(34333299), + }])), + BuyExecution { + fees: MultiAsset { + id: Concrete(MultiLocation { parents: 1, interior: Here }), + fun: Fungible(34333299), + }, + weight_limit: Unlimited, + }, + ExportMessage { + network: Polkadot, + destination: X1(Parachain(1000)), + xcm: Xcm(vec![ + ReserveAssetDeposited(MultiAssets::from(vec![MultiAsset { + id: Concrete(MultiLocation { + parents: 2, + interior: X1(GlobalConsensus(Kusama)), + }), + fun: Fungible(1000000000000), + }])), + ClearOrigin, + BuyExecution { + fees: MultiAsset { + id: Concrete(MultiLocation { + parents: 2, + interior: X1(GlobalConsensus(Kusama)), + }), + fun: Fungible(1000000000000), + }, + weight_limit: Unlimited, + }, + DepositAsset { + assets: Wild(AllCounted(1)), + beneficiary: MultiLocation { + parents: 0, + interior: X1(xcm::latest::prelude::AccountId32 { + network: None, + id: [ + 212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, + 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, + 109, 162, 125, + ], + }), + }, + }, + SetTopic([ + 116, 82, 194, 132, 171, 114, 217, 165, 23, 37, 161, 177, 165, 179, 247, 114, + 137, 101, 147, 70, 28, 157, 168, 32, 154, 63, 74, 228, 152, 180, 5, 63, + ]), + ]), + }, + RefundSurplus, + DepositAsset { + assets: Wild(All), + beneficiary: MultiLocation { parents: 1, interior: X1(Parachain(1000)) }, + }, + SetTopic([ + 36, 224, 250, 165, 82, 195, 67, 110, 160, 170, 140, 87, 217, 62, 201, 164, 42, 98, 219, + 157, 124, 105, 248, 25, 131, 218, 199, 36, 109, 173, 100, 122, + ]), + ]); + + // get weight + let weight = XcmConfig::Weigher::weight(&mut xcm); + assert_ok!(weight); + let weight = weight.unwrap(); + // check if sane + let max_expected = Runtime::BlockWeights::get().max_block / 10; + assert!( + weight.all_lte(max_expected), + "calculated weight: {:?}, max_expected: {:?}", + weight, + max_expected + ); + + // check fee, should not be 0 + let estimated_fee = WeightToFee::weight_to_fee(&weight); + assert!(estimated_fee > BalanceOf::::zero()); + + sp_tracing::try_init_simple(); + log::error!( + target: "bridges::estimate", + "Estimate fee: {:?} for `ExportMessage` for runtime: {:?}", + estimated_fee, + Runtime::Version::get(), + ); + + estimated_fee.into() +} + pub mod test_data { use super::*; use bp_header_chain::justification::GrandpaJustification; @@ -928,7 +1085,7 @@ pub mod test_data { ); /// Simulates `HaulBlobExporter` and all its wrapping and captures generated plain bytes, - /// which are transfered over bridge. + /// which are transferred over bridge. pub(crate) fn simulate_message_exporter_on_bridged_chain< SourceNetwork: Get, DestinationNetwork: Get, diff --git a/cumulus/parachains/runtimes/test-utils/Cargo.toml b/cumulus/parachains/runtimes/test-utils/Cargo.toml index 378d9ea4c42c..1ecbb212a0e6 100644 --- a/cumulus/parachains/runtimes/test-utils/Cargo.toml +++ b/cumulus/parachains/runtimes/test-utils/Cargo.toml @@ -27,11 +27,11 @@ cumulus-pallet-xcmp-queue = { path = "../../../pallets/xcmp-queue", default-feat cumulus-pallet-dmp-queue = { path = "../../../pallets/dmp-queue", default-features = false } pallet-collator-selection = { path = "../../../pallets/collator-selection", default-features = false } parachains-common = { path = "../../common", default-features = false } +parachain-info = { path = "../../pallets/parachain-info", default-features = false } assets-common = { path = "../assets/common", default-features = false } cumulus-primitives-core = { path = "../../../primitives/core", default-features = false } cumulus-primitives-parachain-inherent = { path = "../../../primitives/parachain-inherent", default-features = false } cumulus-test-relay-sproof-builder = { path = "../../../test/relay-sproof-builder", default-features = false } -parachain-info = { path = "../../pallets/parachain-info", default-features = false } # Polkadot xcm = { package = "staging-xcm", path = "../../../../polkadot/xcm", default-features = false} diff --git a/cumulus/parachains/runtimes/test-utils/src/lib.rs b/cumulus/parachains/runtimes/test-utils/src/lib.rs index 8289a80baa11..1e73de9f53d3 100644 --- a/cumulus/parachains/runtimes/test-utils/src/lib.rs +++ b/cumulus/parachains/runtimes/test-utils/src/lib.rs @@ -24,11 +24,12 @@ use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder; use frame_support::{ dispatch::{DispatchResult, RawOrigin}, inherent::{InherentData, ProvideInherent}, + pallet_prelude::Get, traits::{OnFinalize, OnInitialize, OriginTrait, UnfilteredDispatchable}, weights::Weight, }; use frame_system::pallet_prelude::{BlockNumberFor, HeaderFor}; -use parachains_common::{AccountId, SLOT_DURATION}; +use parachains_common::SLOT_DURATION; use polkadot_parachain_primitives::primitives::{ HeadData, HrmpChannelId, RelayChainBlockNumber, XcmpMessageFormat, }; @@ -49,7 +50,7 @@ pub type AccountIdOf = ::AccountId; pub type ValidatorIdOf = ::ValidatorId; pub type SessionKeysOf = ::Keys; -pub struct CollatorSessionKeys< +pub struct CollatorSessionKey< Runtime: frame_system::Config + pallet_balances::Config + pallet_session::Config, > { collator: AccountIdOf, @@ -57,8 +58,14 @@ pub struct CollatorSessionKeys< key: SessionKeysOf, } +pub struct CollatorSessionKeys< + Runtime: frame_system::Config + pallet_balances::Config + pallet_session::Config, +> { + items: Vec>, +} + impl - CollatorSessionKeys + CollatorSessionKey { pub fn new( collator: AccountIdOf, @@ -67,14 +74,43 @@ impl Self { Self { collator, validator, key } } +} + +impl Default + for CollatorSessionKeys +{ + fn default() -> Self { + Self { items: vec![] } + } +} + +impl + CollatorSessionKeys +{ + pub fn new( + collator: AccountIdOf, + validator: ValidatorIdOf, + key: SessionKeysOf, + ) -> Self { + Self { items: vec![CollatorSessionKey::new(collator, validator, key)] } + } + + pub fn add(mut self, item: CollatorSessionKey) -> Self { + self.items.push(item); + self + } + pub fn collators(&self) -> Vec> { - vec![self.collator.clone()] + self.items.iter().map(|item| item.collator.clone()).collect::>() } pub fn session_keys( &self, ) -> Vec<(AccountIdOf, ValidatorIdOf, SessionKeysOf)> { - vec![(self.collator.clone(), self.validator.clone(), self.key.clone())] + self.items + .iter() + .map(|item| (item.collator.clone(), item.validator.clone(), item.key.clone())) + .collect::>() } } @@ -225,7 +261,7 @@ where AllPalletsWithoutSystem: OnInitialize> + OnFinalize>, { - pub fn run_to_block(n: u32, author: AccountId) -> HeaderFor { + pub fn run_to_block(n: u32, author: AccountIdOf) -> HeaderFor { let mut last_header = None; loop { let block_number = frame_system::Pallet::::block_number(); @@ -360,7 +396,6 @@ impl { pub fn xcm_max_weight(from: XcmReceivedFrom) -> Weight { - use frame_support::traits::Get; match from { XcmReceivedFrom::Parent => ParachainSystem::ReservedDmpWeight::get(), XcmReceivedFrom::Sibling => ParachainSystem::ReservedXcmpWeight::get(), @@ -375,16 +410,20 @@ impl) -> Option>>, assert_outcome: fn(Outcome), ) { - let outcome = >::events() + assert_outcome(Self::get_pallet_xcm_event_outcome(unwrap_pallet_xcm_event)); + } + + pub fn get_pallet_xcm_event_outcome( + unwrap_pallet_xcm_event: &Box) -> Option>>, + ) -> Outcome { + >::events() .into_iter() .filter_map(|e| unwrap_pallet_xcm_event(e.event.encode())) .find_map(|e| match e { pallet_xcm::Event::Attempted { outcome } => Some(outcome), _ => None, }) - .expect("No `pallet_xcm::Event::Attempted(outcome)` event found!"); - - assert_outcome(outcome); + .expect("No `pallet_xcm::Event::Attempted(outcome)` event found!") } } diff --git a/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs b/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs index 5de4a49f8275..b3ae5bec6222 100644 --- a/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs +++ b/cumulus/polkadot-parachain/src/chain_spec/bridge_hubs.rs @@ -104,12 +104,14 @@ impl BridgeHubRuntimeType { "Polkadot BridgeHub Local", "polkadot-local", ParaId::new(1002), + Some("Bob".to_string()), ))), BridgeHubRuntimeType::PolkadotDevelopment => Ok(Box::new(polkadot::local_config( polkadot::BRIDGE_HUB_POLKADOT_DEVELOPMENT, "Polkadot BridgeHub Development", "polkadot-dev", ParaId::new(1002), + Some("Bob".to_string()), ))), BridgeHubRuntimeType::Kusama => Ok(Box::new(kusama::BridgeHubChainSpec::from_json_bytes( @@ -119,13 +121,15 @@ impl BridgeHubRuntimeType { kusama::BRIDGE_HUB_KUSAMA_LOCAL, "Kusama BridgeHub Local", "kusama-local", - ParaId::new(1003), + ParaId::new(1002), + Some("Bob".to_string()), ))), BridgeHubRuntimeType::KusamaDevelopment => Ok(Box::new(kusama::local_config( kusama::BRIDGE_HUB_KUSAMA_DEVELOPMENT, "Kusama BridgeHub Development", "kusama-dev", - ParaId::new(1003), + ParaId::new(1002), + Some("Bob".to_string()), ))), BridgeHubRuntimeType::Westend => Ok(Box::new(westend::BridgeHubChainSpec::from_json_bytes( @@ -384,6 +388,7 @@ pub mod kusama { chain_name: &str, relay_chain: &str, para_id: ParaId, + bridges_pallet_owner_seed: Option, ) -> BridgeHubChainSpec { let mut properties = sc_chain_spec::Properties::new(); properties.insert("ss58Format".into(), 2.into()); @@ -424,6 +429,9 @@ pub mod kusama { get_account_id_from_seed::("Ferdie//stash"), ], para_id, + bridges_pallet_owner_seed + .as_ref() + .map(|seed| get_account_id_from_seed::(&seed)), ) }, Vec::new(), @@ -439,6 +447,7 @@ pub mod kusama { invulnerables: Vec<(AccountId, AuraId)>, endowed_accounts: Vec, id: ParaId, + bridges_pallet_owner: Option, ) -> bridge_hub_kusama_runtime::RuntimeGenesisConfig { bridge_hub_kusama_runtime::RuntimeGenesisConfig { system: bridge_hub_kusama_runtime::SystemConfig { @@ -482,6 +491,14 @@ pub mod kusama { safe_xcm_version: Some(SAFE_XCM_VERSION), ..Default::default() }, + bridge_polkadot_grandpa: bridge_hub_kusama_runtime::BridgePolkadotGrandpaConfig { + owner: bridges_pallet_owner.clone(), + ..Default::default() + }, + bridge_polkadot_messages: bridge_hub_kusama_runtime::BridgePolkadotMessagesConfig { + owner: bridges_pallet_owner, + ..Default::default() + }, } } } @@ -521,6 +538,7 @@ pub mod polkadot { chain_name: &str, relay_chain: &str, para_id: ParaId, + bridges_pallet_owner_seed: Option, ) -> BridgeHubChainSpec { let mut properties = sc_chain_spec::Properties::new(); properties.insert("ss58Format".into(), 0.into()); @@ -561,6 +579,9 @@ pub mod polkadot { get_account_id_from_seed::("Ferdie//stash"), ], para_id, + bridges_pallet_owner_seed + .as_ref() + .map(|seed| get_account_id_from_seed::(&seed)), ) }, Vec::new(), @@ -576,6 +597,7 @@ pub mod polkadot { invulnerables: Vec<(AccountId, AuraId)>, endowed_accounts: Vec, id: ParaId, + bridges_pallet_owner: Option, ) -> bridge_hub_polkadot_runtime::RuntimeGenesisConfig { bridge_hub_polkadot_runtime::RuntimeGenesisConfig { system: bridge_hub_polkadot_runtime::SystemConfig { @@ -619,6 +641,14 @@ pub mod polkadot { safe_xcm_version: Some(SAFE_XCM_VERSION), ..Default::default() }, + bridge_kusama_grandpa: bridge_hub_polkadot_runtime::BridgeKusamaGrandpaConfig { + owner: bridges_pallet_owner.clone(), + ..Default::default() + }, + bridge_kusama_messages: bridge_hub_polkadot_runtime::BridgeKusamaMessagesConfig { + owner: bridges_pallet_owner, + ..Default::default() + }, } } } diff --git a/cumulus/scripts/bridges_kusama_polkadot.sh b/cumulus/scripts/bridges_kusama_polkadot.sh new file mode 100755 index 000000000000..a189ef3bbcf1 --- /dev/null +++ b/cumulus/scripts/bridges_kusama_polkadot.sh @@ -0,0 +1,249 @@ +#!/bin/bash + +# import common functions +source "$(dirname "$0")"/bridges_rococo_wococo.sh "import" + +# Address: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY +# AccountId: [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] +ASSET_HUB_KUSAMA_ACCOUNT_SEED_FOR_LOCAL="//Alice" +# Address: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY +# AccountId: [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] +ASSET_HUB_POLKADOT_ACCOUNT_ADDRESS_FOR_LOCAL="5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" + +# Expected sovereign accounts. +# +# Generated by: +# +# #[test] +# fn generate_sovereign_accounts() { +# use sp_core::crypto::Ss58Codec; +# use polkadot_parachain_primitives::primitives::Sibling; +# +# parameter_types! { +# pub UniversalLocationAHK: InteriorMultiLocation = X2(GlobalConsensus(Kusama), Parachain(1000)); +# pub UniversalLocationAHP: InteriorMultiLocation = X2(GlobalConsensus(Polkadot), Parachain(1000)); +# } +# +# // SS58=0 +# println!("GLOBAL_CONSENSUS_KUSAMA_SOVEREIGN_ACCOUNT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# GlobalConsensusConvertsFor::::convert_location( +# &MultiLocation { parents: 2, interior: X1(GlobalConsensus(Kusama)) }).unwrap() +# ).to_ss58check_with_version(0_u16.into()) +# ); +# println!("GLOBAL_CONSENSUS_KUSAMA_ASSET_HUB_KUSAMA_1000_SOVEREIGN_ACCOUNT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# GlobalConsensusParachainConvertsFor::::convert_location( +# &MultiLocation { parents: 2, interior: X2(GlobalConsensus(Kusama), Parachain(1000)) }).unwrap() +# ).to_ss58check_with_version(0_u16.into()) +# ); +# println!("ASSET_HUB_POLKADOT_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_POLKADOT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# SiblingParachainConvertsVia::::convert_location( +# &MultiLocation { parents: 1, interior: X1(Parachain(1000)) }).unwrap() +# ).to_ss58check_with_version(0_u16.into()) +# ); +# +# // SS58=2 +# println!("GLOBAL_CONSENSUS_POLKADOT_SOVEREIGN_ACCOUNT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# GlobalConsensusConvertsFor::::convert_location( +# &MultiLocation { parents: 2, interior: X1(GlobalConsensus(Polkadot)) }).unwrap() +# ).to_ss58check_with_version(2_u16.into()) +# ); +# println!("GLOBAL_CONSENSUS_POLKADOT_ASSET_HUB_POLKADOT_1000_SOVEREIGN_ACCOUNT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# GlobalConsensusParachainConvertsFor::::convert_location( +# &MultiLocation { parents: 2, interior: X2(GlobalConsensus(Polkadot), Parachain(1000)) }).unwrap() +# ).to_ss58check_with_version(2_u16.into()) +# ); +# println!("ASSET_HUB_KUSAMA_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_KUSAMA=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# SiblingParachainConvertsVia::::convert_location( +# &MultiLocation { parents: 1, interior: X1(Parachain(1000)) }).unwrap() +# ).to_ss58check_with_version(2_u16.into()) +# ); +# } +GLOBAL_CONSENSUS_KUSAMA_SOVEREIGN_ACCOUNT="14zcUAhP5XypiFQWA3b1AnGKrhZqR4XWUo4deWkwuN5y983G" +GLOBAL_CONSENSUS_KUSAMA_ASSET_HUB_KUSAMA_1000_SOVEREIGN_ACCOUNT="12GvRkNCmXFuaaziTJ2ZKAfa7MArKfLT2HYvLjQuepP3JuHf" +ASSET_HUB_POLKADOT_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_POLKADOT="13cKp89SgdtqUngo2WiEijPrQWdHFhzYZLf2TJePKRvExk7o" +GLOBAL_CONSENSUS_POLKADOT_SOVEREIGN_ACCOUNT="FxqimVubBRPqJ8kTwb3wL7G4q645hEkBEnXPyttLsTrFc5Q" +GLOBAL_CONSENSUS_POLKADOT_ASSET_HUB_POLKADOT_1000_SOVEREIGN_ACCOUNT="FwGjEp7GXJXT9NjH8r4sqdyd8XZVogbxSs3iFakx4wFwJ5Y" +ASSET_HUB_KUSAMA_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_KUSAMA="FBeL7EFTDeHnuViqaUHUXvhhUusN5FawDmHgfvzF97DXFr3" + +function init_ksm_dot() { + ensure_relayer + + RUST_LOG=runtime=trace,rpc=trace,bridge=trace \ + ~/local_bridge_testing/bin/substrate-relay init-bridge kusama-to-bridge-hub-polkadot \ + --source-host localhost \ + --source-port 9942 \ + --source-version-mode Auto \ + --target-host localhost \ + --target-port 8945 \ + --target-version-mode Auto \ + --target-signer //Bob +} + +function init_dot_ksm() { + ensure_relayer + + RUST_LOG=runtime=trace,rpc=trace,bridge=trace \ + ~/local_bridge_testing/bin/substrate-relay init-bridge polkadot-to-bridge-hub-kusama \ + --source-host localhost \ + --source-port 9945 \ + --source-version-mode Auto \ + --target-host localhost \ + --target-port 8943 \ + --target-version-mode Auto \ + --target-signer //Bob +} + +function run_relay() { + ensure_relayer + +RUST_LOG=runtime=trace,rpc=trace,bridge=trace \ + ~/local_bridge_testing/bin/substrate-relay relay-headers-and-messages bridge-hub-kusama-bridge-hub-polkadot \ + --kusama-host localhost \ + --kusama-port 9942 \ + --kusama-version-mode Auto \ + --bridge-hub-kusama-host localhost \ + --bridge-hub-kusama-port 8943 \ + --bridge-hub-kusama-version-mode Auto \ + --bridge-hub-kusama-signer //Charlie \ + --polkadot-headers-to-bridge-hub-kusama-signer //Bob \ + --polkadot-parachains-to-bridge-hub-kusama-signer //Bob \ + --bridge-hub-kusama-transactions-mortality 4 \ + --polkadot-host localhost \ + --polkadot-port 9945 \ + --polkadot-version-mode Auto \ + --bridge-hub-polkadot-host localhost \ + --bridge-hub-polkadot-port 8945 \ + --bridge-hub-polkadot-version-mode Auto \ + --bridge-hub-polkadot-signer //Charlie \ + --kusama-headers-to-bridge-hub-polkadot-signer //Bob \ + --kusama-parachains-to-bridge-hub-polkadot-signer //Bob \ + --bridge-hub-polkadot-transactions-mortality 4 \ + --lane 00000000 +} + +case "$1" in + run-relay) + init_ksm_dot + init_dot_ksm + run_relay + ;; + init-asset-hub-kusama-local) + ensure_polkadot_js_api + # create foreign assets for native Polkadot token (governance call on Kusama) + force_create_foreign_asset \ + "ws://127.0.0.1:9942" \ + "//Alice" \ + 1000 \ + "ws://127.0.0.1:9910" \ + "$(jq --null-input '{ "parents": 2, "interior": { "X1": { "GlobalConsensus": "Polkadot" } } }')" \ + "$GLOBAL_CONSENSUS_POLKADOT_SOVEREIGN_ACCOUNT" \ + 100000000 \ + true + # drip SA which holds reserves + transfer_balance \ + "ws://127.0.0.1:9910" \ + "//Alice" \ + "$GLOBAL_CONSENSUS_POLKADOT_ASSET_HUB_POLKADOT_1000_SOVEREIGN_ACCOUNT" \ + $((1000000000 + 50000000000 * 20)) + # HRMP + open_hrmp_channels \ + "ws://127.0.0.1:9942" \ + "//Alice" \ + 1000 1002 4 524288 + open_hrmp_channels \ + "ws://127.0.0.1:9942" \ + "//Alice" \ + 1002 1000 4 524288 + ;; + init-bridge-hub-kusama-local) + ensure_polkadot_js_api + # SA of sibling asset hub pays for the execution + transfer_balance \ + "ws://127.0.0.1:8943" \ + "//Alice" \ + "$ASSET_HUB_KUSAMA_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_KUSAMA" \ + $((1000000000 + 50000000000 * 20)) + ;; + init-asset-hub-polkadot-local) + ensure_polkadot_js_api + # create foreign assets for native Polkadot token (governance call on Kusama) + force_create_foreign_asset \ + "ws://127.0.0.1:9945" \ + "//Alice" \ + 1000 \ + "ws://127.0.0.1:9010" \ + "$(jq --null-input '{ "parents": 2, "interior": { "X1": { "GlobalConsensus": "Kusama" } } }')" \ + "$GLOBAL_CONSENSUS_KUSAMA_SOVEREIGN_ACCOUNT" \ + 10000000000 \ + true + # drip SA which holds reserves + transfer_balance \ + "ws://127.0.0.1:9010" \ + "//Alice" \ + "$GLOBAL_CONSENSUS_KUSAMA_ASSET_HUB_KUSAMA_1000_SOVEREIGN_ACCOUNT" \ + $((1000000000 + 50000000000 * 20)) + # HRMP + open_hrmp_channels \ + "ws://127.0.0.1:9945" \ + "//Alice" \ + 1000 1002 4 524288 + open_hrmp_channels \ + "ws://127.0.0.1:9945" \ + "//Alice" \ + 1002 1000 4 524288 + ;; + init-bridge-hub-polkadot-local) + # SA of sibling asset hub pays for the execution + transfer_balance \ + "ws://127.0.0.1:8945" \ + "//Alice" \ + "$ASSET_HUB_POLKADOT_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_POLKADOT" \ + $((1000000000 + 50000000000 * 20)) + ;; + reserve-transfer-assets-from-asset-hub-kusama-local) + ensure_polkadot_js_api + # send KSMs to Alice account on AHP + limited_reserve_transfer_assets \ + "ws://127.0.0.1:9910" \ + "//Alice" \ + "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Polkadot" }, { "Parachain": 1000 } ] } } }')" \ + "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": 2500000000000 } } ] }')" \ + 0 \ + "Unlimited" + ;; + reserve-transfer-assets-from-asset-hub-polkadot-local) + ensure_polkadot_js_api + # send DOTs to Alice account on AHH + limited_reserve_transfer_assets \ + "ws://127.0.0.1:9010" \ + "//Alice" \ + "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Kusama" }, { "Parachain": 1000 } ] } } }')" \ + "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": 300000000000 } } ] }')" \ + 0 \ + "Unlimited" + ;; + stop) + pkill -f polkadot + pkill -f parachain + ;; + *) + echo "A command is require. Supported commands for: + Local (zombienet) run: + - run-relay + - init-asset-hub-kusama-local + - init-bridge-hub-kusama-local + - init-asset-hub-polkadot-local + - init-bridge-hub-polkadot-local + - reserve-transfer-assets-from-asset-hub-kusama-local + - reserve-transfer-assets-from-asset-hub-polkadot-local"; + exit 1 + ;; +esac diff --git a/cumulus/scripts/bridges_rococo_wococo.sh b/cumulus/scripts/bridges_rococo_wococo.sh index 1117ed681092..d1675b2c9688 100755 --- a/cumulus/scripts/bridges_rococo_wococo.sh +++ b/cumulus/scripts/bridges_rococo_wococo.sh @@ -1,44 +1,65 @@ #!/bin/bash -# Address: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY -# AccountId: [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] -ASSET_HUB_KUSAMA_ACCOUNT_SEED_FOR_LOCAL="//Alice" -# Address: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY -# AccountId: [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] -ASSET_HUB_WOCOCO_ACCOUNT_SEED_FOR_LOCAL="5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY" - -# SovereignAccount for `MultiLocation { parents: 2, interior: X2(GlobalConsensus(Rococo), Parachain(1000)) }` => 5CfNu7eH3SJvqqPt3aJh38T8dcFvhGzEohp9tsd41ANhXDnQ +# Expected sovereign accounts. # -# use sp_core::crypto::Ss58Codec; -# println!("{}", -# frame_support::sp_runtime::AccountId32::new( -# GlobalConsensusParachainConvertsFor::::convert_ref( -# MultiLocation { parents: 2, interior: X2(GlobalConsensus(Kusama), Parachain(1000)) }).unwrap() -# ).to_ss58check_with_version(42_u16.into()) -# ); -ASSET_HUB_ROCOCO_1000_SOVEREIGN_ACCOUNT="5CfNu7eH3SJvqqPt3aJh38T8dcFvhGzEohp9tsd41ANhXDnQ" - -# Address: GegTpZJMyzkntLN7NJhRfHDk4GWukLbGSsag6PHrLSrCK4h -ASSET_HUB2_ROCOCO_1000_SOVEREIGN_ACCOUNT="scatter feed race company oxygen trip extra elbow slot bundle auto canoe" - -# Adress: 5Ge7YcbctWCP1CccugzxWDn9hFnTxvTh3bL6PNy4ubNJmp7Y / H9jCvwVWsDJkrS4gPp1QB99qr4hmbGsVyAqn3F2PPaoWyU3 -# AccountId: [202, 107, 198, 135, 15, 25, 193, 165, 172, 73, 137, 218, 115, 177, 204, 0, 5, 155, 215, 86, 208, 51, 50, 130, 190, 110, 184, 143, 124, 50, 160, 20] -ASSET_HUB_WOCOCO_ACCOUNT_ADDRESS_FOR_ROCOCO="5Ge7YcbctWCP1CccugzxWDn9hFnTxvTh3bL6PNy4ubNJmp7Y" -ASSET_HUB_WOCOCO_ACCOUNT_SEED_FOR_WOCOCO="tone spirit magnet sunset cannon poverty forget lock river east blouse random" - -function address_to_account_id_bytes() { - local address=$1 - local output=$2 - echo "address_to_account_id_bytes - address: $address, output: $output" - if [ $address == "$ASSET_HUB_WOCOCO_ACCOUNT_SEED_FOR_LOCAL" ]; then - jq --null-input '[212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125]' > $output - elif [ $address == "$ASSET_HUB_WOCOCO_ACCOUNT_ADDRESS_FOR_ROCOCO" ]; then - jq --null-input '[202, 107, 198, 135, 15, 25, 193, 165, 172, 73, 137, 218, 115, 177, 204, 0, 5, 155, 215, 86, 208, 51, 50, 130, 190, 110, 184, 143, 124, 50, 160, 20]' > $output - else - echo -n "Sorry, unknown address: $address - please, add bytes here or function for that!" - exit 1 - fi -} +# Generated by: +# +# #[test] +# fn generate_sovereign_accounts() { +# use sp_core::crypto::Ss58Codec; +# use polkadot_parachain_primitives::primitives::Sibling; +# +# parameter_types! { +# pub UniversalLocationAHR: InteriorMultiLocation = X2(GlobalConsensus(Rococo), Parachain(1000)); +# pub UniversalLocationAHW: InteriorMultiLocation = X2(GlobalConsensus(Wococo), Parachain(1000)); +# } +# +# // SS58=42 +# println!("GLOBAL_CONSENSUS_ROCOCO_SOVEREIGN_ACCOUNT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# GlobalConsensusConvertsFor::::convert_location( +# &MultiLocation { parents: 2, interior: X1(GlobalConsensus(Rococo)) }).unwrap() +# ).to_ss58check_with_version(42_u16.into()) +# ); +# println!("GLOBAL_CONSENSUS_ROCOCO_ASSET_HUB_ROCOCO_1000_SOVEREIGN_ACCOUNT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# GlobalConsensusParachainConvertsFor::::convert_location( +# &MultiLocation { parents: 2, interior: X2(GlobalConsensus(Rococo), Parachain(1000)) }).unwrap() +# ).to_ss58check_with_version(42_u16.into()) +# ); +# println!("ASSET_HUB_WOCOCO_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_WOCOCO=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# SiblingParachainConvertsVia::::convert_location( +# &MultiLocation { parents: 1, interior: X1(Parachain(1000)) }).unwrap() +# ).to_ss58check_with_version(42_u16.into()) +# ); +# +# // SS58=42 +# println!("GLOBAL_CONSENSUS_WOCOCO_SOVEREIGN_ACCOUNT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# GlobalConsensusConvertsFor::::convert_location( +# &MultiLocation { parents: 2, interior: X1(GlobalConsensus(Wococo)) }).unwrap() +# ).to_ss58check_with_version(42_u16.into()) +# ); +# println!("GLOBAL_CONSENSUS_WOCOCO_ASSET_HUB_WOCOCO_1000_SOVEREIGN_ACCOUNT=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# GlobalConsensusParachainConvertsFor::::convert_location( +# &MultiLocation { parents: 2, interior: X2(GlobalConsensus(Wococo), Parachain(1000)) }).unwrap() +# ).to_ss58check_with_version(42_u16.into()) +# ); +# println!("ASSET_HUB_ROCOCO_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_ROCOCO=\"{}\"", +# frame_support::sp_runtime::AccountId32::new( +# SiblingParachainConvertsVia::::convert_location( +# &MultiLocation { parents: 1, interior: X1(Parachain(1000)) }).unwrap() +# ).to_ss58check_with_version(42_u16.into()) +# ); +# } +GLOBAL_CONSENSUS_ROCOCO_SOVEREIGN_ACCOUNT="5GxRGwT8bU1JeBPTUXc7LEjZMxNrK8MyL2NJnkWFQJTQ4sii" +GLOBAL_CONSENSUS_ROCOCO_ASSET_HUB_ROCOCO_1000_SOVEREIGN_ACCOUNT="5CfNu7eH3SJvqqPt3aJh38T8dcFvhGzEohp9tsd41ANhXDnQ" +ASSET_HUB_WOCOCO_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_WOCOCO="5Eg2fntNprdN3FgH4sfEaaZhYtddZQSQUqvYJ1f2mLtinVhV" +GLOBAL_CONSENSUS_WOCOCO_SOVEREIGN_ACCOUNT="5EWw2NzfPr2DCahourp33cya6bGWEJViTnJN6Z2ruFevpJML" +GLOBAL_CONSENSUS_WOCOCO_ASSET_HUB_WOCOCO_1000_SOVEREIGN_ACCOUNT="5EJX8L4dwGyYnCsjZ91LfWAsm3rCN8vY2AYvT4mauMEjsrQz" +ASSET_HUB_ROCOCO_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_ROCOCO="5Eg2fntNprdN3FgH4sfEaaZhYtddZQSQUqvYJ1f2mLtinVhV" function ensure_binaries() { if [[ ! -f ~/local_bridge_testing/bin/polkadot ]]; then @@ -87,8 +108,8 @@ function ensure_polkadot_js_api() { echo "" echo "" echo "-------------------" - echo "Installing (nodejs) sub module: ./scripts/generate_hex_encoded_call" - pushd ./scripts/generate_hex_encoded_call + echo "Installing (nodejs) sub module: $(dirname "$0")/generate_hex_encoded_call" + pushd $(dirname "$0")/generate_hex_encoded_call npm install popd fi @@ -103,7 +124,7 @@ function generate_hex_encoded_call_data() { shift echo "Input params: $@" - node ./scripts/generate_hex_encoded_call "$type" "$endpoint" "$output" "$@" + node $(dirname "$0")/generate_hex_encoded_call "$type" "$endpoint" "$output" "$@" local retVal=$? if [ $type != "check" ]; then @@ -129,7 +150,7 @@ function transfer_balance() { polkadot-js-api \ --ws "${runtime_para_endpoint}" \ --seed "${seed?}" \ - tx.balances.transfer \ + tx.balances.transferAllowDeath \ "${target_account}" \ "${amount}" } @@ -200,324 +221,113 @@ function send_governance_transact() { "${message}" } -function allow_assets_transfer_send() { +function open_hrmp_channels() { local relay_url=$1 local relay_chain_seed=$2 - local runtime_para_id=$3 - local runtime_para_endpoint=$4 - local bridge_hub_para_id=$5 - local bridged_para_network=$6 - local bridged_para_para_id=$7 - echo " calling allow_assets_transfer_send:" + local sender_para_id=$3 + local recipient_para_id=$4 + local max_capacity=$5 + local max_message_size=$6 + echo " calling open_hrmp_channels:" echo " relay_url: ${relay_url}" echo " relay_chain_seed: ${relay_chain_seed}" - echo " runtime_para_id: ${runtime_para_id}" - echo " runtime_para_endpoint: ${runtime_para_endpoint}" - echo " bridge_hub_para_id: ${bridge_hub_para_id}" - echo " bridged_para_network: ${bridged_para_network}" - echo " bridged_para_para_id: ${bridged_para_para_id}" - echo " params:" - - # 1. generate data for Transact (add_exporter_config) - local bridge_config=$(jq --null-input \ - --arg bridge_hub_para_id "$bridge_hub_para_id" \ - --arg bridged_para_network "$bridged_para_network" \ - --arg bridged_para_para_id "$bridged_para_para_id" \ - ' - { - "bridgeLocation": { - "parents": 1, - "interior": { - "X1": { "Parachain": $bridge_hub_para_id } - } - }, - "allowedTargetLocation": { - "parents": 2, - "interior": { - "X2": [ - { - "GlobalConsensus": $bridged_para_network, - }, - { - "Parachain": $bridged_para_para_id - } - ] - } - }, - "maxTargetLocationFee": { - "id": { - "Concrete": { - "parents": 1, - "interior": "Here" - } - }, - "fun": { - "Fungible": 50000000000 - } - } - } - ' - ) - local tmp_output_file=$(mktemp) - generate_hex_encoded_call_data "add-exporter-config" "${runtime_para_endpoint}" "${tmp_output_file}" $bridged_para_network "$bridge_config" - local hex_encoded_data=$(cat $tmp_output_file) - - send_governance_transact "${relay_url}" "${relay_chain_seed}" "${runtime_para_id}" "${hex_encoded_data}" 200000000 12000 -} - -function force_create_foreign_asset() { - local relay_url=$1 - local relay_chain_seed=$2 - local runtime_para_id=$3 - local runtime_para_endpoint=$4 - local global_consensus=$5 - local asset_owner_account_id=$6 - echo " calling force_create_foreign_asset:" - echo " relay_url: ${relay_url}" - echo " relay_chain_seed: ${relay_chain_seed}" - echo " runtime_para_id: ${runtime_para_id}" - echo " runtime_para_endpoint: ${runtime_para_endpoint}" - echo " global_consensus: ${global_consensus}" - echo " asset_owner_account_id: ${asset_owner_account_id}" + echo " sender_para_id: ${sender_para_id}" + echo " recipient_para_id: ${recipient_para_id}" + echo " max_capacity: ${max_capacity}" + echo " max_message_size: ${max_message_size}" echo " params:" - - # 1. generate data for Transact (ForeignAssets::force_create) - local asset_id=$(jq --null-input \ - --arg global_consensus "$global_consensus" \ - ' - { - "parents": 2, - "interior": { - "X1": { - "GlobalConsensus": $global_consensus, - } - } - } - ' - ) - local tmp_output_file=$(mktemp) - generate_hex_encoded_call_data "force-create-asset" "${runtime_para_endpoint}" "${tmp_output_file}" "$asset_id" "$asset_owner_account_id" false "1000" - local hex_encoded_data=$(cat $tmp_output_file) - - send_governance_transact "${relay_url}" "${relay_chain_seed}" "${runtime_para_id}" "${hex_encoded_data}" 200000000 12000 + echo "--------------------------------------------------" + polkadot-js-api \ + --ws "${relay_url?}" \ + --seed "${relay_chain_seed?}" \ + --sudo \ + tx.hrmp.forceOpenHrmpChannel \ + ${sender_para_id} \ + ${recipient_para_id} \ + ${max_capacity} \ + ${max_message_size} } -function allow_assets_transfer_receive() { +function set_storage() { local relay_url=$1 local relay_chain_seed=$2 local runtime_para_id=$3 local runtime_para_endpoint=$4 - local bridge_hub_para_id=$5 - local bridged_network=$6 - local bridged_para_id=$7 - echo " calling allow_assets_transfer_receive:" + local items=$5 + echo " calling set_storage:" echo " relay_url: ${relay_url}" echo " relay_chain_seed: ${relay_chain_seed}" echo " runtime_para_id: ${runtime_para_id}" echo " runtime_para_endpoint: ${runtime_para_endpoint}" - echo " bridge_hub_para_id: ${bridge_hub_para_id}" - echo " bridged_network: ${bridged_network}" - echo " bridged_para_id: ${bridged_para_id}" + echo " items: ${items}" echo " params:" - # 1. generate data for Transact (add_universal_alias) - local location=$(jq --null-input \ - --arg bridge_hub_para_id "$bridge_hub_para_id" \ - '{ "V3": { "parents": 1, "interior": { "X1": { "Parachain": $bridge_hub_para_id } } } }') - - local junction=$(jq --null-input \ - --arg bridged_network "$bridged_network" \ - '{ "GlobalConsensus": $bridged_network } ') - + # 1. generate data for Transact (System::set_storage) local tmp_output_file=$(mktemp) - generate_hex_encoded_call_data "add-universal-alias" "${runtime_para_endpoint}" "${tmp_output_file}" "$location" "$junction" - local hex_encoded_data=$(cat $tmp_output_file) - - send_governance_transact "${relay_url}" "${relay_chain_seed}" "${runtime_para_id}" "${hex_encoded_data}" 200000000 12000 - - # 2. generate data for Transact (add_reserve_location) - local reserve_location=$(jq --null-input \ - --arg bridged_network "$bridged_network" \ - --arg bridged_para_id "$bridged_para_id" \ - '{ "V3": { - "parents": 2, - "interior": { - "X2": [ - { - "GlobalConsensus": $bridged_network, - }, - { - "Parachain": $bridged_para_id - } - ] - } - } }') - - local tmp_output_file=$(mktemp) - generate_hex_encoded_call_data "add-reserve-location" "${runtime_para_endpoint}" "${tmp_output_file}" "$reserve_location" + generate_hex_encoded_call_data "set-storage" "${runtime_para_endpoint}" "${tmp_output_file}" "$items" local hex_encoded_data=$(cat $tmp_output_file) + # 2. trigger governance call send_governance_transact "${relay_url}" "${relay_chain_seed}" "${runtime_para_id}" "${hex_encoded_data}" 200000000 12000 } -function remove_assets_transfer_send() { +function force_create_foreign_asset() { local relay_url=$1 local relay_chain_seed=$2 local runtime_para_id=$3 local runtime_para_endpoint=$4 - local bridged_network=$5 - echo " calling remove_assets_transfer_send:" + local asset_multilocation=$5 + local asset_owner_account_id=$6 + local min_balance=$7 + local is_sufficient=$8 + echo " calling force_create_foreign_asset:" echo " relay_url: ${relay_url}" echo " relay_chain_seed: ${relay_chain_seed}" echo " runtime_para_id: ${runtime_para_id}" echo " runtime_para_endpoint: ${runtime_para_endpoint}" - echo " bridged_network: ${bridged_network}" + echo " asset_multilocation: ${asset_multilocation}" + echo " asset_owner_account_id: ${asset_owner_account_id}" + echo " min_balance: ${min_balance}" + echo " is_sufficient: ${is_sufficient}" echo " params:" + # 1. generate data for Transact (ForeignAssets::force_create) local tmp_output_file=$(mktemp) - generate_hex_encoded_call_data "remove-exporter-config" "${runtime_para_endpoint}" "${tmp_output_file}" $bridged_network + generate_hex_encoded_call_data "force-create-asset" "${runtime_para_endpoint}" "${tmp_output_file}" "$asset_multilocation" "$asset_owner_account_id" $is_sufficient $min_balance local hex_encoded_data=$(cat $tmp_output_file) + # 2. trigger governance call send_governance_transact "${relay_url}" "${relay_chain_seed}" "${runtime_para_id}" "${hex_encoded_data}" 200000000 12000 } -# TODO: we need to fill sovereign account for bridge-hub, because, small ammouts does not match ExistentialDeposit, so no reserve pass -# SA for BH: MultiLocation { parents: 1, interior: X1(Parachain(1013)) } - 5Eg2fntRRwLinojmk3sh5xscp7F3S6Zzm5oDVtoLTALKiypR on Kusama Asset Hub - -function transfer_asset_via_bridge() { +function limited_reserve_transfer_assets() { local url=$1 local seed=$2 - local target_account=$3 - local target_global_consensus=$4 - echo " calling transfer_asset_via_bridge:" + local destination=$3 + local beneficiary=$4 + local assets=$5 + local fee_asset_item=$6 + local weight_limit=$7 + echo " calling limited_reserve_transfer_assets:" echo " url: ${url}" echo " seed: ${seed}" - echo " target_account: ${target_account}" - echo " target_global_consensus: ${target_global_consensus}" - echo " params:" - - local assets=$(jq --null-input \ - ' - { - "V3": [ - { - "id": { - "Concrete": { - "parents": 1, - "interior": "Here" - } - }, - "fun": { - "Fungible": 100000000 - } - } - ] - } - ' - ) - - local tmp_output_file=$(mktemp) - address_to_account_id_bytes "$target_account" "${tmp_output_file}" - local hex_encoded_data=$(cat $tmp_output_file) - - local destination=$(jq --null-input \ - --arg target_global_consensus "$target_global_consensus" \ - --argjson hex_encoded_data "$hex_encoded_data" \ - ' - { - "V3": { - "parents": 2, - "interior": { - "X3": [ - { - "GlobalConsensus": $target_global_consensus - }, - { - "Parachain": 1000 - }, - { - "AccountId32": { - "id": $hex_encoded_data - } - } - ] - } - } - } - ' - ) - - echo "" - echo " assets:" - echo "${assets}" - echo "" - echo " destination:" - echo "${destination}" + echo " destination: ${destination}" + echo " beneficiary: ${beneficiary}" + echo " assets: ${assets}" + echo " fee_asset_item: ${fee_asset_item}" + echo " weight_limit: ${weight_limit}" echo "" echo "--------------------------------------------------" polkadot-js-api \ --ws "${url?}" \ --seed "${seed?}" \ - tx.bridgeTransfer.transferAssetViaBridge \ + tx.polkadotXcm.limitedReserveTransferAssets \ + "${destination}" \ + "${beneficiary}" \ "${assets}" \ - "${destination}" -} - -function ping_via_bridge() { - local url=$1 - local seed=$2 - local target_account=$3 - local target_global_consensus=$4 - echo " calling ping_via_bridge:" - echo " url: ${url}" - echo " seed: ${seed}" - echo " target_account: ${target_account}" - echo " target_global_consensus: ${target_global_consensus}" - echo " params:" - - local tmp_output_file=$(mktemp) - address_to_account_id_bytes "$target_account" "${tmp_output_file}" - local hex_encoded_data=$(cat $tmp_output_file) - - local destination=$(jq --null-input \ - --arg target_global_consensus "$target_global_consensus" \ - --argjson hex_encoded_data "$hex_encoded_data" \ - ' - { - "V3": { - "parents": 2, - "interior": { - "X3": [ - { - "GlobalConsensus": $target_global_consensus - }, - { - "Parachain": 1000 - }, - { - "AccountId32": { - "id": $hex_encoded_data - } - } - ] - } - } - } - ' - ) - - echo "" - echo " destination:" - echo "${destination}" - echo "" - echo "--------------------------------------------------" - - polkadot-js-api \ - --ws "${url?}" \ - --seed "${seed?}" \ - tx.bridgeTransfer.pingViaBridge \ - "${destination}" + "${fee_asset_item}" \ + "${weight_limit}" } function init_ro_wo() { @@ -582,93 +392,120 @@ case "$1" in init_wo_ro run_relay ;; - allow-transfers-local) - # this allows send transfers on asset hub kusama local (by governance-like) - ./$0 "allow-transfer-on-asset-hub-kusama-local" - # this allows receive transfers on asset hub westend local (by governance-like) - ./$0 "allow-transfer-on-asset-hub-westend-local" - ;; - allow-transfer-on-asset-hub-kusama-local) + init-asset-hub-rococo-local) ensure_polkadot_js_api - allow_assets_transfer_send \ + # create foreign assets for native Wococo token (governance call on Rococo) + force_create_foreign_asset \ "ws://127.0.0.1:9942" \ "//Alice" \ 1000 \ "ws://127.0.0.1:9910" \ - 1013 \ - "Wococo" 1000 + "$(jq --null-input '{ "parents": 2, "interior": { "X1": { "GlobalConsensus": "Wococo" } } }')" \ + "$GLOBAL_CONSENSUS_WOCOCO_SOVEREIGN_ACCOUNT" \ + 10000000000 \ + true + # drip SA which holds reserves + transfer_balance \ + "ws://127.0.0.1:9910" \ + "//Alice" \ + "$GLOBAL_CONSENSUS_WOCOCO_ASSET_HUB_WOCOCO_1000_SOVEREIGN_ACCOUNT" \ + $((1000000000 + 50000000000 * 20)) + # HRMP + open_hrmp_channels \ + "ws://127.0.0.1:9942" \ + "//Alice" \ + 1000 1013 4 524288 + open_hrmp_channels \ + "ws://127.0.0.1:9942" \ + "//Alice" \ + 1013 1000 4 524288 ;; - allow-transfer-on-asset-hub-westend-local) + init-bridge-hub-rococo-local) ensure_polkadot_js_api - allow_assets_transfer_receive \ + # SA of sibling asset hub pays for the execution + transfer_balance \ + "ws://127.0.0.1:8943" \ + "//Alice" \ + "$ASSET_HUB_ROCOCO_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_ROCOCO" \ + $((1000000000 + 50000000000 * 20)) + ;; + init-asset-hub-wococo-local) + ensure_polkadot_js_api + # set Wococo flavor - set_storage with: + # - `key` is `HexDisplay::from(&asset_hub_rococo_runtime::xcm_config::Flavor::key())` + # - `value` is `HexDisplay::from(&asset_hub_rococo_runtime::RuntimeFlavor::Wococo.encode())` + set_storage \ "ws://127.0.0.1:9945" \ "//Alice" \ 1000 \ "ws://127.0.0.1:9010" \ - 1014 \ - "Rococo" \ - 1000 - transfer_balance \ - "ws://127.0.0.1:9010" \ - "//Alice" \ - "$ASSET_HUB_ROCOCO_1000_SOVEREIGN_ACCOUNT" \ - $((1000000000 + 50000000000 * 20)) # ExistentialDeposit + maxTargetLocationFee * 20 - # create foreign assets for native Kusama token (yes, Kusama, because we are using Kusama Asset Hub runtime on rococo) + "$(jq --null-input '[["0x48297505634037ef48c848c99c0b1f1b", "0x01"]]')" + # create foreign assets for native Rococo token (governance call on Wococo) force_create_foreign_asset \ "ws://127.0.0.1:9945" \ "//Alice" \ 1000 \ "ws://127.0.0.1:9010" \ - "Kusama" \ - "$ASSET_HUB_ROCOCO_1000_SOVEREIGN_ACCOUNT" - ;; - remove-assets-transfer-from-asset-hub-kusama-local) - ensure_polkadot_js_api - remove_assets_transfer_send \ - "ws://127.0.0.1:9942" \ + "$(jq --null-input '{ "parents": 2, "interior": { "X1": { "GlobalConsensus": "Rococo" } } }')" \ + "$GLOBAL_CONSENSUS_ROCOCO_SOVEREIGN_ACCOUNT" \ + 10000000000 \ + true + # drip SA which holds reserves + transfer_balance \ + "ws://127.0.0.1:9010" \ "//Alice" \ - 1000 \ - "ws://127.0.0.1:9910" \ - "Wococo" + "$GLOBAL_CONSENSUS_ROCOCO_ASSET_HUB_ROCOCO_1000_SOVEREIGN_ACCOUNT" \ + $((1000000000 + 50000000000 * 20)) + # HRMP + open_hrmp_channels \ + "ws://127.0.0.1:9945" \ + "//Alice" \ + 1000 1014 4 524288 + open_hrmp_channels \ + "ws://127.0.0.1:9945" \ + "//Alice" \ + 1014 1000 4 524288 ;; - transfer-asset-from-asset-hub-kusama-local) - ensure_polkadot_js_api - transfer_asset_via_bridge \ - "ws://127.0.0.1:9910" \ - "$ASSET_HUB_KUSAMA_ACCOUNT_SEED_FOR_LOCAL" \ - "$ASSET_HUB_WOCOCO_ACCOUNT_SEED_FOR_LOCAL" \ - "Wococo" + init-bridge-hub-wococo-local) + # set Wococo flavor - set_storage with: + # - `key` is `HexDisplay::from(&bridge_hub_rococo_runtime::xcm_config::Flavor::key())` + # - `value` is `HexDisplay::from(&bridge_hub_rococo_runtime::RuntimeFlavor::Wococo.encode())` + set_storage \ + "ws://127.0.0.1:9945" \ + "//Alice" \ + 1014 \ + "ws://127.0.0.1:8945" \ + "$(jq --null-input '[["0x48297505634037ef48c848c99c0b1f1b", "0x01"]]')" + # SA of sibling asset hub pays for the execution + transfer_balance \ + "ws://127.0.0.1:8945" \ + "//Alice" \ + "$ASSET_HUB_WOCOCO_SOVEREIGN_ACCOUNT_AT_BRIDGE_HUB_WOCOCO" \ + $((1000000000 + 50000000000 * 20)) ;; - ping-via-bridge-from-asset-hub-kusama-local) + reserve-transfer-assets-from-asset-hub-rococo-local) ensure_polkadot_js_api - ping_via_bridge \ + # send ROCs to Alice account on AHW + limited_reserve_transfer_assets \ "ws://127.0.0.1:9910" \ - "$ASSET_HUB_KUSAMA_ACCOUNT_SEED_FOR_LOCAL" \ - "$ASSET_HUB_WOCOCO_ACCOUNT_SEED_FOR_LOCAL" \ - "Wococo" - ;; - transfer-asset-from-asset-hub-rococo) - ensure_polkadot_js_api - transfer_asset_via_bridge \ - "wss://ws-rococo-rockmine2-collator-node-0.parity-testnet.parity.io" \ - "$ASSET_HUB2_ROCOCO_1000_SOVEREIGN_ACCOUNT" \ - "$ASSET_HUB_WOCOCO_ACCOUNT_ADDRESS_FOR_ROCOCO" \ - "Wococo" + "//Alice" \ + "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Wococo" }, { "Parachain": 1000 } ] } } }')" \ + "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": 200000000000 } } ] }')" \ + 0 \ + "Unlimited" ;; - ping-via-bridge-from-asset-hub-rococo) + reserve-transfer-assets-from-asset-hub-wococo-local) ensure_polkadot_js_api - ping_via_bridge \ - "wss://ws-rococo-rockmine2-collator-node-0.parity-testnet.parity.io" \ - "${ASSET_HUB2_ROCOCO_1000_SOVEREIGN_ACCOUNT}" \ - "$ASSET_HUB_WOCOCO_ACCOUNT_ADDRESS_FOR_ROCOCO" \ - "Wococo" - ;; - drip) - transfer_balance \ + # send WOCs to Alice account on AHR + limited_reserve_transfer_assets \ "ws://127.0.0.1:9010" \ "//Alice" \ - "$ASSET_HUB_ROCOCO_1000_SOVEREIGN_ACCOUNT" \ - $((1000000000 + 50000000000 * 20)) + "$(jq --null-input '{ "V3": { "parents": 2, "interior": { "X2": [ { "GlobalConsensus": "Rococo" }, { "Parachain": 1000 } ] } } }')" \ + "$(jq --null-input '{ "V3": { "parents": 0, "interior": { "X1": { "AccountId32": { "id": [212, 53, 147, 199, 21, 253, 211, 28, 97, 20, 26, 189, 4, 169, 159, 214, 130, 44, 133, 88, 133, 76, 205, 227, 154, 86, 132, 231, 165, 109, 162, 125] } } } } }')" \ + "$(jq --null-input '{ "V3": [ { "id": { "Concrete": { "parents": 1, "interior": "Here" } }, "fun": { "Fungible": 150000000000 } } ] }')" \ + 0 \ + "Unlimited" ;; stop) pkill -f polkadot @@ -681,15 +518,12 @@ case "$1" in echo "A command is require. Supported commands for: Local (zombienet) run: - run-relay - - allow-transfers-local - - allow-transfer-on-asset-hub-kusama-local - - allow-transfer-on-asset-hub-westend-local - - remove-assets-transfer-from-asset-hub-kusama-local - - transfer-asset-from-asset-hub-kusama-local - - ping-via-bridge-from-asset-hub-kusama-local - Live Rococo/Wococo run: - - transfer-asset-from-asset-hub-rococo - - ping-via-bridge-from-asset-hub-rococo"; + - init-asset-hub-rococo-local + - init-bridge-hub-rococo-local + - init-asset-hub-wococo-local + - init-bridge-hub-wococo-local + - reserve-transfer-assets-from-asset-hub-rococo-local + - reserve-transfer-assets-from-asset-hub-wococo-local"; exit 1 ;; esac diff --git a/cumulus/zombienet/bridge-hubs/bridge_hub_kusama_local_network.toml b/cumulus/zombienet/bridge-hubs/bridge_hub_kusama_local_network.toml new file mode 100644 index 000000000000..378e636cc115 --- /dev/null +++ b/cumulus/zombienet/bridge-hubs/bridge_hub_kusama_local_network.toml @@ -0,0 +1,97 @@ +[settings] +node_spawn_timeout = 240 + +[relaychain] +default_command = "{{POLKADOT_BINARY_PATH}}" +default_args = [ "-lparachain=debug,xcm=trace" ] +chain = "kusama-local" + + [[relaychain.nodes]] + name = "alice-kusama-validator" + validator = true + rpc_port = 9932 + ws_port = 9942 + balance = 200000000000000 + + [[relaychain.nodes]] + name = "bob-kusama-validator" + validator = true + rpc_port = 9933 + ws_port = 9943 + balance = 200000000000000 + + [[relaychain.nodes]] + name = "charlie-kusama-validator" + validator = true + rpc_port = 9934 + ws_port = 9944 + balance = 200000000000000 + +[[parachains]] +id = 1002 +chain = "bridge-hub-kusama-local" +cumulus_based = true + + # run alice as parachain collator + [[parachains.collators]] + name = "bridge-hub-kusama-collator1" + validator = true + command = "{{POLKADOT_PARACHAIN_BINARY_PATH}}" + rpc_port = 8933 + ws_port = 8943 + args = [ + "-lparachain=debug,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace", + "--force-authoring", + "--", "--port 41333", "--rpc-port 48933", "--ws-port 48943" + ] + + # run bob as parachain collator + [[parachains.collators]] + name = "bridge-hub-kusama-collator2" + validator = true + command = "{{POLKADOT_PARACHAIN_BINARY_PATH}}" + rpc_port = 8934 + ws_port = 8944 + args = [ + "-lparachain=trace,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace", + "--force-authoring", + "--", "--port 41334", "--rpc-port 48934", "--ws-port 48944" + ] + +[[parachains]] +id = 1000 +chain = "asset-hub-kusama-local" +cumulus_based = true + + [[parachains.collators]] + name = "asset-hub-kusama-collator1" + rpc_port = 9911 + ws_port = 9910 + command = "{{POLKADOT_PARACHAIN_BINARY_PATH_FOR_ASSET_HUB_KUSAMA}}" + args = [ + "-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace", + "--", "--port 51333", "--rpc-port 58933", "--ws-port 58943" + ] + + [[parachains.collators]] + name = "asset-hub-kusama-collator2" + command = "{{POLKADOT_PARACHAIN_BINARY_PATH_FOR_ASSET_HUB_KUSAMA}}" + args = [ + "-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace", + ] + extra_args = [ + "--no-mdns", "--bootnodes {{'asset-hub-kusama-collator1'|zombie('multiAddress')}}", + "--", "--port 51433", "--rpc-port 58833", "--ws-port 58843" + ] + +#[[hrmp_channels]] +#sender = 1000 +#recipient = 1002 +#max_capacity = 4 +#max_message_size = 524288 +# +#[[hrmp_channels]] +#sender = 1002 +#recipient = 1000 +#max_capacity = 4 +#max_message_size = 524288 diff --git a/cumulus/zombienet/bridge-hubs/bridge_hub_polkadot_local_network.toml b/cumulus/zombienet/bridge-hubs/bridge_hub_polkadot_local_network.toml new file mode 100644 index 000000000000..51e654f95c92 --- /dev/null +++ b/cumulus/zombienet/bridge-hubs/bridge_hub_polkadot_local_network.toml @@ -0,0 +1,94 @@ +[settings] +node_spawn_timeout = 240 + +[relaychain] +default_command = "{{POLKADOT_BINARY_PATH}}" +default_args = [ "-lparachain=debug,xcm=trace" ] +chain = "polkadot-local" + + [[relaychain.nodes]] + name = "alice-polkadot-validator" + validator = true + rpc_port = 9935 + ws_port = 9945 + balance = 20000000000000 + + [[relaychain.nodes]] + name = "bob-polkadot-validator" + validator = true + rpc_port = 9936 + ws_port = 9946 + balance = 20000000000000 + + [[relaychain.nodes]] + name = "charlie-polkadot-validator" + validator = true + rpc_port = 9937 + ws_port = 9947 + balance = 20000000000000 + +[[parachains]] +id = 1002 +chain = "bridge-hub-polkadot-local" +cumulus_based = true + + # run alice as parachain collator + [[parachains.collators]] + name = "bridge-hub-polkadot-collator1" + validator = true + command = "{{POLKADOT_PARACHAIN_BINARY_PATH}}" + rpc_port = 8935 + ws_port = 8945 + args = [ + "-lparachain=debug,runtime::mmr=info,substrate=info,runtime=info,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace", + "--force-authoring", + "--", "--port 41335", "--rpc-port 48935", "--ws-port 48945" + ] + + # run bob as parachain collator + [[parachains.collators]] + name = "bridge-hub-polkadot-collator2" + validator = true + command = "{{POLKADOT_PARACHAIN_BINARY_PATH}}" + rpc_port = 8936 + ws_port = 8946 + args = [ + "-lparachain=trace,runtime::mmr=info,substrate=info,runtime=info,runtime::bridge-hub=trace,runtime::bridge=trace,runtime::bridge-dispatch=trace,bridge=trace,runtime::bridge-messages=trace,xcm=trace", + "--force-authoring", + "--", "--port 41336", "--rpc-port 48936", "--ws-port 48946" + ] + +[[parachains]] +id = 1000 +chain = "asset-hub-polkadot-local" +cumulus_based = true + + [[parachains.collators]] + name = "asset-hub-polkadot-collator1" + rpc_port = 9011 + ws_port = 9010 + command = "{{POLKADOT_PARACHAIN_BINARY_PATH_FOR_ASSET_HUB_POLKADOT}}" + args = [ + "-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace", + "--", "--port 31333", "--rpc-port 38933", "--ws-port 38943" + ] + + [[parachains.collators]] + name = "asset-hub-polkadot-collator2" + command = "{{POLKADOT_PARACHAIN_BINARY_PATH_FOR_ASSET_HUB_POLKADOT}}" + args = [ + "-lparachain=debug,xcm=trace,runtime::bridge-transfer=trace", + "--", "--port 31433", "--rpc-port 38833", "--ws-port 38843" + ] + +#[[hrmp_channels]] +#sender = 1000 +#recipient = 1002 +#max_capacity = 4 +#max_message_size = 524288 +# +#[[hrmp_channels]] +#sender = 1002 +#recipient = 1000 +#max_capacity = 4 +#max_message_size = 524288 diff --git a/cumulus/zombienet/examples/statemine_kusama_local_network.toml b/cumulus/zombienet/examples/statemine_kusama_local_network.toml index 1f3debfb9d29..f7de44a1fb63 100644 --- a/cumulus/zombienet/examples/statemine_kusama_local_network.toml +++ b/cumulus/zombienet/examples/statemine_kusama_local_network.toml @@ -1,5 +1,5 @@ [relaychain] -default_command = "../polkadot/target/release/polkadot" +default_command = "./target/release/polkadot" default_args = [ "-lparachain=debug" ] chain = "kusama-local"