diff --git a/Cargo.lock b/Cargo.lock index a3aa1c4fc9e8a..c4e7979317871 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1055,7 +1055,14 @@ dependencies = [ "bp-asset-hub-westend", "bp-bridge-hub-rococo", "bp-bridge-hub-westend", + "bp-header-chain", + "bp-messages", + "bp-relayers", + "bp-runtime", "bp-xcm-bridge", + "bridge-hub-common", + "bridge-hub-test-utils", + "bridge-runtime-common", "cumulus-pallet-aura-ext", "cumulus-pallet-parachain-system", "cumulus-pallet-session-benchmarking", @@ -1083,6 +1090,8 @@ dependencies = [ "pallet-aura", "pallet-authorship", "pallet-balances", + "pallet-bridge-messages", + "pallet-bridge-relayers", "pallet-collator-selection", "pallet-message-queue", "pallet-multisig", @@ -1097,6 +1106,7 @@ dependencies = [ "pallet-utility", "pallet-xcm", "pallet-xcm-benchmarks", + "pallet-xcm-bridge", "pallet-xcm-bridge-router", "parachains-common", "parachains-runtimes-test-utils", @@ -1155,6 +1165,9 @@ version = "1.0.0" dependencies = [ "assert_matches", "asset-test-utils", + "bp-asset-hub-rococo", + "bp-asset-hub-westend", + "bp-xcm-bridge", "cumulus-pallet-parachain-system", "cumulus-pallet-xcmp-queue", "emulated-integration-tests-common", @@ -1167,9 +1180,12 @@ dependencies = [ "pallet-message-queue", "pallet-treasury", "pallet-xcm", + "pallet-xcm-bridge", "parachains-common", "parity-scale-codec", "polkadot-runtime-common", + "rococo-system-emulated-network", + "rococo-westend-system-emulated-network", "sp-core 28.0.0", "sp-runtime", "sp-tracing 16.0.0", @@ -1191,7 +1207,14 @@ dependencies = [ "bp-asset-hub-westend", "bp-bridge-hub-rococo", "bp-bridge-hub-westend", + "bp-header-chain", + "bp-messages", + "bp-relayers", + "bp-runtime", "bp-xcm-bridge", + "bridge-hub-common", + "bridge-hub-test-utils", + "bridge-runtime-common", "cumulus-pallet-aura-ext", "cumulus-pallet-parachain-system", "cumulus-pallet-session-benchmarking", @@ -1223,6 +1246,8 @@ dependencies = [ "pallet-authorship", "pallet-bags-list", "pallet-balances", + "pallet-bridge-messages", + "pallet-bridge-relayers", "pallet-collator-selection", "pallet-conviction-voting", "pallet-delegated-staking", @@ -1260,6 +1285,7 @@ dependencies = [ "pallet-whitelist", "pallet-xcm", "pallet-xcm-benchmarks", + "pallet-xcm-bridge", "pallet-xcm-bridge-router", "parachains-common", "parachains-runtimes-test-utils", @@ -2098,12 +2124,15 @@ dependencies = [ "bp-bridge-hub-cumulus", "bp-messages", "bp-runtime", + "bp-xcm-bridge", "bp-xcm-bridge-router", "frame-support", "parity-scale-codec", "scale-info", "sp-api", "sp-core 28.0.0", + "sp-runtime 31.0.1", + "sp-std 14.0.0", "staging-xcm", "testnet-parachains-constants", ] @@ -2115,12 +2144,15 @@ dependencies = [ "bp-bridge-hub-cumulus", "bp-messages", "bp-runtime", + "bp-xcm-bridge", "bp-xcm-bridge-router", "frame-support", "parity-scale-codec", "scale-info", "sp-api", "sp-core 28.0.0", + "sp-runtime 31.0.1", + "sp-std 14.0.0", "staging-xcm", "testnet-parachains-constants", ] @@ -2452,6 +2484,14 @@ version = "1.0.0" dependencies = [ "asset-hub-rococo-runtime", "bp-asset-hub-rococo", + "bp-asset-hub-westend", + "bp-bridge-hub-westend", + "bp-header-chain", + "bp-parachains", + "bp-polkadot-core", + "bp-runtime", + "bp-test-utils", + "bp-westend", "cumulus-pallet-xcmp-queue", "emulated-integration-tests-common", "frame-support", @@ -2645,7 +2685,15 @@ name = "bridge-hub-westend-integration-tests" version = "1.0.0" dependencies = [ "asset-hub-westend-runtime", + "bp-asset-hub-rococo", "bp-asset-hub-westend", + "bp-bridge-hub-rococo", + "bp-header-chain", + "bp-parachains", + "bp-polkadot-core", + "bp-rococo", + "bp-runtime", + "bp-test-utils", "bridge-hub-common", "bridge-hub-westend-runtime", "cumulus-pallet-parachain-system", diff --git a/bridges/modules/xcm-bridge/src/lib.rs b/bridges/modules/xcm-bridge/src/lib.rs index 6720a845cc8bd..2feeab91f6ac7 100644 --- a/bridges/modules/xcm-bridge/src/lib.rs +++ b/bridges/modules/xcm-bridge/src/lib.rs @@ -667,6 +667,11 @@ pub mod pallet { .into()), } } + + /// Get the bridge deposit amount required to open a new bridge. + pub fn bridge_deposit() -> BalanceOf> { + T::BridgeDeposit::get() + } } #[cfg(feature = "runtime-benchmarks")] diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/src/lib.rs index d8564d7676d37..4a9ab6b770c86 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-rococo/src/lib.rs @@ -13,7 +13,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -pub use asset_hub_rococo_runtime; +pub use asset_hub_rococo_runtime::{ + self as asset_hub_rococo_runtime, xcm_config::XcmConfig as AssetHubRococoXcmConfig, + ExistentialDeposit as AssetHubRococoExistentialDeposit, + RuntimeOrigin as AssetHubRococoRuntimeOrigin, +}; pub mod genesis; @@ -52,6 +56,7 @@ decl_test_parachains! { PoolAssets: asset_hub_rococo_runtime::PoolAssets, AssetConversion: asset_hub_rococo_runtime::AssetConversion, Balances: asset_hub_rococo_runtime::Balances, + XcmOverAssetHubWestend: asset_hub_rococo_runtime::XcmOverAssetHubWestend, } }, } diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/src/lib.rs index 40da6f2f9fc6b..57a03c944a792 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/assets/asset-hub-westend/src/lib.rs @@ -13,7 +13,11 @@ // See the License for the specific language governing permissions and // limitations under the License. -pub use asset_hub_westend_runtime; +pub use asset_hub_westend_runtime::{ + self as asset_hub_westend_runtime, xcm_config::XcmConfig as AssetHubWestendXcmConfig, + ExistentialDeposit as AssetHubWestendExistentialDeposit, + RuntimeOrigin as AssetHubWestendRuntimeOrigin, +}; pub mod genesis; @@ -54,6 +58,7 @@ decl_test_parachains! { AssetConversion: asset_hub_westend_runtime::AssetConversion, SnowbridgeSystemFrontend: asset_hub_westend_runtime::SnowbridgeSystemFrontend, Revive: asset_hub_westend_runtime::Revive, + XcmOverAssetHubRococo: asset_hub_westend_runtime::XcmOverAssetHubRococo, } }, } diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/bridges/bridge-hub-rococo/src/lib.rs b/cumulus/parachains/integration-tests/emulated/chains/parachains/bridges/bridge-hub-rococo/src/lib.rs index 43398eb8bd480..38851e6cdfa8c 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/bridges/bridge-hub-rococo/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/bridges/bridge-hub-rococo/src/lib.rs @@ -51,6 +51,8 @@ decl_test_parachains! { EthereumSystem: bridge_hub_rococo_runtime::EthereumSystem, EthereumInboundQueue: bridge_hub_rococo_runtime::EthereumInboundQueue, EthereumOutboundQueue: bridge_hub_rococo_runtime::EthereumOutboundQueue, + BridgeWestendGrandpa: bridge_hub_rococo_runtime::BridgeWestendGrandpa, + BridgeWestendParachains: bridge_hub_rococo_runtime::BridgeWestendParachains, } }, } diff --git a/cumulus/parachains/integration-tests/emulated/chains/parachains/bridges/bridge-hub-westend/src/lib.rs b/cumulus/parachains/integration-tests/emulated/chains/parachains/bridges/bridge-hub-westend/src/lib.rs index 5eada9569d5d3..47e279345772a 100644 --- a/cumulus/parachains/integration-tests/emulated/chains/parachains/bridges/bridge-hub-westend/src/lib.rs +++ b/cumulus/parachains/integration-tests/emulated/chains/parachains/bridges/bridge-hub-westend/src/lib.rs @@ -52,6 +52,8 @@ decl_test_parachains! { EthereumOutboundQueue: bridge_hub_westend_runtime::EthereumOutboundQueue, EthereumSystemV2: bridge_hub_westend_runtime::EthereumSystemV2, BridgeRelayers: bridge_hub_westend_runtime::BridgeRelayers, + BridgeRococoGrandpa: bridge_hub_westend_runtime::BridgeRococoGrandpa, + BridgeRococoParachains: bridge_hub_westend_runtime::BridgeRococoParachains, } }, } diff --git a/cumulus/parachains/integration-tests/emulated/common/src/impls.rs b/cumulus/parachains/integration-tests/emulated/common/src/impls.rs index 168ac7cf4ea24..4ef50fa03e437 100644 --- a/cumulus/parachains/integration-tests/emulated/common/src/impls.rs +++ b/cumulus/parachains/integration-tests/emulated/common/src/impls.rs @@ -106,6 +106,11 @@ where // collect messages from `OutboundMessages` for each active outbound lane in the source for lane in active_outbound_lanes { + if OutboundLanes::::get(lane).is_none() { + // TODO: FAIL - investigate how was this created + continue; + } + let latest_generated_nonce = OutboundLanes::::get(lane).unwrap().latest_generated_nonce; let latest_received_nonce = @@ -192,6 +197,11 @@ where // collect messages from `OutboundMessages` for each active outbound lane in the source for lane in active_outbound_lanes { + if OutboundLanes::::get(lane).is_none() { + // TODO: FAIL - investigate how was this created + continue; + } + let latest_generated_nonce = OutboundLanes::::get(lane).unwrap().latest_generated_nonce; let latest_received_nonce = diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/Cargo.toml index af7a593b25ede..3ee1a1877af29 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/Cargo.toml @@ -40,7 +40,15 @@ cumulus-pallet-parachain-system = { workspace = true } cumulus-pallet-xcmp-queue = { workspace = true } emulated-integration-tests-common = { workspace = true } parachains-common = { workspace = true, default-features = true } +rococo-system-emulated-network = { workspace = true } westend-system-emulated-network = { workspace = true } +rococo-westend-system-emulated-network = { workspace = true } + +# Bridge +bp-asset-hub-westend = { workspace = true } +bp-asset-hub-rococo = { workspace = true } +bp-xcm-bridge = { workspace = true } +pallet-xcm-bridge = { workspace = true } [dev-dependencies] sp-tracing = { workspace = true, default-features = true } diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/bridging.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/bridging.rs new file mode 100644 index 0000000000000..4ea9aa80a6788 --- /dev/null +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/bridging.rs @@ -0,0 +1,271 @@ +// 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::imports::assert_ok; +pub use codec::Encode; +use emulated_integration_tests_common::{ + xcm_emulator::{bx, Chain, Parachain as Para, TestExt}, + xcm_helpers::xcm_transact_paid_execution, +}; +use xcm::{ + latest::{ROCOCO_GENESIS_HASH, WESTEND_GENESIS_HASH}, + prelude::*, +}; + +// For a bridging we need rococo_westend system and not separated ones (because different Penpal setups). +use rococo_westend_system_emulated_network::{ + asset_hub_rococo_emulated_chain::{ + asset_hub_rococo_runtime::ExistentialDeposit as AssetHubRococoExistentialDeposit, + genesis::AssetHubRococoUniversalLocation, AssetHubRococoParaPallet as AssetHubRococoPallet, + AssetHubRococoRuntimeOrigin, + }, + asset_hub_westend_emulated_chain::{ + asset_hub_westend_runtime::ExistentialDeposit as AssetHubWestendExistentialDeposit, + genesis::AssetHubWestendUniversalLocation, + AssetHubWestendParaPallet as AssetHubWestendPallet, AssetHubWestendRuntimeOrigin, + }, + penpal_emulated_chain::{ + PenpalAParaPallet as PenpalAPallet, PenpalBParaPallet as PenpalBPallet, + }, + AssetHubRococoPara as AssetHubRococo, AssetHubWestendPara as AssetHubWestend, + PenpalAPara as PenpalA, PenpalBPara as PenpalB, +}; + +#[test] +fn ah_to_ah_open_close_bridge_works() { + // open bridges + let westend_bridge_opened_lane_id = AssetHubWestend::execute_with(|| { + assert_ok!(::XcmOverAssetHubRococo::open_bridge( + AssetHubWestendRuntimeOrigin::root(), + Box::new(AssetHubRococoUniversalLocation::get().into()), + None, + )); + let events = AssetHubWestend::events(); + type RuntimeEventWestend = ::RuntimeEvent; + events.iter().find_map(|event| { + if let RuntimeEventWestend::XcmOverAssetHubRococo( + pallet_xcm_bridge::Event::BridgeOpened { lane_id, .. }, + ) = event + { + Some(*lane_id) + } else { + None + } + }) + }); + assert!(westend_bridge_opened_lane_id.is_some(), "Westend BridgeOpened event not found"); + + let rococo_bridge_opened_lane_id = AssetHubRococo::execute_with(|| { + assert_ok!(::XcmOverAssetHubWestend::open_bridge( + AssetHubRococoRuntimeOrigin::root(), + Box::new(AssetHubWestendUniversalLocation::get().into()), + None, + )); + let events = AssetHubRococo::events(); + type RuntimeEventRococo = ::RuntimeEvent; + events.iter().find_map(|event| { + if let RuntimeEventRococo::XcmOverAssetHubWestend( + pallet_xcm_bridge::Event::BridgeOpened { lane_id, .. }, + ) = event + { + Some(*lane_id) + } else { + None + } + }) + }); + assert!(rococo_bridge_opened_lane_id.is_some(), "Rococo BridgeOpened event not found"); + + // check the same lane ID is generated + assert_eq!(westend_bridge_opened_lane_id, rococo_bridge_opened_lane_id); + + // close bridges + let westend_bridge_pruned_lane_id = AssetHubWestend::execute_with(|| { + assert_ok!( + ::XcmOverAssetHubRococo::close_bridge( + AssetHubWestendRuntimeOrigin::root(), + Box::new(AssetHubRococoUniversalLocation::get().into()), + 1, + ) + ); + let events = AssetHubWestend::events(); + type RuntimeEventWestend = ::RuntimeEvent; + events.iter().find_map(|event| { + if let RuntimeEventWestend::XcmOverAssetHubRococo( + pallet_xcm_bridge::Event::BridgePruned { lane_id, .. }, + ) = event + { + Some(*lane_id) + } else { + None + } + }) + }); + assert!(westend_bridge_pruned_lane_id.is_some(), "Westend BridgePruned event not found"); + + let rococo_bridge_pruned_lane_id = AssetHubRococo::execute_with(|| { + assert_ok!(::XcmOverAssetHubWestend::close_bridge( + AssetHubRococoRuntimeOrigin::root(), + Box::new(AssetHubWestendUniversalLocation::get().into()), + 1, + )); + let events = AssetHubRococo::events(); + type RuntimeEventRococo = ::RuntimeEvent; + events.iter().find_map(|event| { + if let RuntimeEventRococo::XcmOverAssetHubWestend( + pallet_xcm_bridge::Event::BridgePruned { lane_id, .. }, + ) = event + { + Some(*lane_id) + } else { + None + } + }) + }); + assert!(rococo_bridge_pruned_lane_id.is_some(), "Rococo BridgePruned event not found"); +} + +#[test] +fn para_to_para_open_close_bridge_works() { + // Ensure Penpal A/B locations (set `on_init` with `set_storage`). + let penpal_a_on_rococo_universal_location = PenpalA::execute_with(|| { + let loc = <::Runtime as pallet_xcm::Config>::UniversalLocation::get(); + assert_eq!(loc.global_consensus(), Ok(ByGenesis(ROCOCO_GENESIS_HASH))); + loc + }); + let penpal_b_on_westend_universal_location = PenpalB::execute_with(|| { + let loc = <::Runtime as pallet_xcm::Config>::UniversalLocation::get(); + assert_eq!(loc.global_consensus(), Ok(ByGenesis(WESTEND_GENESIS_HASH))); + loc + }); + + // 1. Open bridge from PenpalA(Rococo) to PenpalB(Westend) + let penpal_a_para_sovereign_account = AssetHubRococo::sovereign_account_id_of( + AssetHubRococo::sibling_location_of(PenpalA::para_id()), + ); + let fee_amount = AssetHubRococoExistentialDeposit::get() * 1000; + let bridge_deposit = AssetHubRococo::ext_wrapper(|| { + ::XcmOverAssetHubWestend::bridge_deposit() + }); + AssetHubRococo::fund_accounts(vec![( + penpal_a_para_sovereign_account.clone().into(), + AssetHubRococoExistentialDeposit::get() + fee_amount + bridge_deposit, + )]); + + // send paid XCM with `open_bridge` from PenpalA to the AssetHubRococo + PenpalA::execute_with(|| { + assert_ok!(::PolkadotXcm::send( + ::RuntimeOrigin::root(), + bx!(PenpalA::sibling_location_of(AssetHubRococo::para_id()).into()), + bx!(xcm_transact_paid_execution( + bp_asset_hub_rococo::Call::XcmOverAssetHubWestend( + bp_xcm_bridge::XcmBridgeCall::open_bridge { + bridge_destination_universal_location: Box::new( + penpal_b_on_westend_universal_location.into() + ), + maybe_notify: None, + }, + ) + .encode() + .into(), + OriginKind::Xcm, + (Parent, fee_amount).into(), + penpal_a_para_sovereign_account, + )), + )); + + PenpalA::assert_xcm_pallet_sent(); + }); + + // check BridgeOpened event on AssetHubRococo + let penpal_a_bridge_opened_lane_id = AssetHubRococo::execute_with(|| { + let events = AssetHubRococo::events(); + type RuntimeEvent = ::RuntimeEvent; + AssetHubRococo::assert_xcmp_queue_success(None); + let e = events.iter().find_map(|event| { + if let RuntimeEvent::XcmOverAssetHubWestend(pallet_xcm_bridge::Event::BridgeOpened { + lane_id, + .. + }) = event + { + Some(*lane_id) + } else { + None + } + }); + e + }); + assert!(penpal_a_bridge_opened_lane_id.is_some(), "PenpalA BridgeOpened event not found"); + + // 2. Open bridge from PenpalB(Westend) to PenpalA(Rococo) + let penpal_b_para_sovereign_account = AssetHubWestend::sovereign_account_id_of( + AssetHubWestend::sibling_location_of(PenpalB::para_id()), + ); + let fee_amount = AssetHubWestendExistentialDeposit::get() * 1000; + let bridge_deposit = AssetHubWestend::ext_wrapper(|| { + ::XcmOverAssetHubRococo::bridge_deposit() + }); + AssetHubWestend::fund_accounts(vec![( + penpal_b_para_sovereign_account.clone().into(), + AssetHubWestendExistentialDeposit::get() + fee_amount + bridge_deposit, + )]); + + // send paid XCM with `open_bridge` from PenpalB to the AssetHubWestend + PenpalB::execute_with(|| { + assert_ok!(::PolkadotXcm::send( + ::RuntimeOrigin::root(), + bx!(PenpalB::sibling_location_of(AssetHubWestend::para_id()).into()), + bx!(xcm_transact_paid_execution( + bp_asset_hub_westend::Call::XcmOverAssetHubRococo( + bp_xcm_bridge::XcmBridgeCall::open_bridge { + bridge_destination_universal_location: Box::new( + penpal_a_on_rococo_universal_location.into() + ), + maybe_notify: None, + }, + ) + .encode() + .into(), + OriginKind::Xcm, + (Parent, fee_amount).into(), + penpal_b_para_sovereign_account, + )), + )); + + PenpalB::assert_xcm_pallet_sent(); + }); + + // check BridgeOpened event on AssetHubWestend + let penpal_b_bridge_opened_lane_id = AssetHubWestend::execute_with(|| { + let events = AssetHubWestend::events(); + type RuntimeEvent = ::RuntimeEvent; + AssetHubWestend::assert_xcmp_queue_success(None); + events.iter().find_map(|event| { + if let RuntimeEvent::XcmOverAssetHubRococo(pallet_xcm_bridge::Event::BridgeOpened { + lane_id, + .. + }) = event + { + Some(*lane_id) + } else { + None + } + }) + }); + assert!(penpal_b_bridge_opened_lane_id.is_some(), "PenpalB BridgeOpened event not found"); + + // check the same lane ID is generated + assert_eq!(penpal_a_bridge_opened_lane_id, penpal_b_bridge_opened_lane_id); +} diff --git a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs index 22bfebddefee2..1a17db5334a4d 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/assets/asset-hub-westend/src/tests/mod.rs @@ -14,6 +14,7 @@ // limitations under the License. mod aliases; +mod bridging; mod claim_assets; mod exchange_asset; mod fellowship_treasury; diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml index c44e9c5c91791..1f3b03a01f349 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/Cargo.toml @@ -32,6 +32,14 @@ xcm-executor = { workspace = true } # Bridges bp-asset-hub-rococo = { workspace = true } +bp-asset-hub-westend = { workspace = true } +bp-bridge-hub-westend = { workspace = true } +bp-header-chain = { workspace = true } +bp-parachains = { workspace = true } +bp-polkadot-core = { workspace = true } +bp-runtime = { workspace = true } +bp-test-utils = { workspace = true } +bp-westend = { workspace = true } pallet-bridge-messages = { workspace = true } # Cumulus diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/bridging.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/bridging.rs new file mode 100644 index 0000000000000..ec11ea8d8c61d --- /dev/null +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/bridging.rs @@ -0,0 +1,143 @@ +// 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. + +//! Tests related to bridging itself. + +use crate::tests::*; +use bp_header_chain::HeaderChain; +use bp_parachains::RelayBlockHash; +use bp_polkadot_core::parachains::{ParaHash, ParaHead}; +use bp_runtime::{BasicOperatingMode, Chain as BpChain, HashOf, HeaderOf, Parachain}; +use bp_test_utils::{ + make_default_justification, prepare_parachain_heads_proof, test_header_with_root, +}; + +/// Submits to BH's `pallet-bridge-parachains` some header and return (bridged_block_hash, +/// bridged_state_root) +fn submit_fake_parachain_heads< + BridgedRelay: BpChain, + BridgedPara: Parachain, +>( + para_header_number: u32, + relay_chain_header_number: u32, +) -> (HashOf, HashOf) { + // prepare parachain proofs + let para_state_root = ParaHash::from([para_header_number as u8; 32]); + let bridged_para_head = ParaHead( + test_header_with_root::>(para_header_number.into(), para_state_root) + .encode(), + ); + let (relay_chain_state_root, para_heads_proof, parachain_heads) = + prepare_parachain_heads_proof::>(vec![( + BridgedPara::PARACHAIN_ID, + bridged_para_head.clone(), + )]); + + // prepare Rococo grandpa proof + let relay_chain_header = test_header_with_root::>( + relay_chain_header_number.into(), + relay_chain_state_root.into(), + ); + let relay_chain_header_hash = relay_chain_header.hash(); + let justification = make_default_justification(&relay_chain_header); + + // prepare init bridge data + let init_bridge_data = bp_header_chain::InitializationData { + header: Box::new(bp_test_utils::test_header(0_u32)), + authority_list: bp_test_utils::authority_list(), + set_id: 1, + operating_mode: BasicOperatingMode::Normal, + }; + + // submit head proofs as the relayer would do + BridgeHubRococo::execute_with(|| { + let relayer = ::RuntimeOrigin::signed( + BridgeHubRococo::account_id_of(ALICE), + ); + + // initialize bridge (if not) + if ::BridgeWestendGrandpa::best_finalized() + .is_none() + { + assert_ok!( + ::BridgeWestendGrandpa::initialize( + ::RuntimeOrigin::root(), + init_bridge_data + ) + ); + } + + // grandpa (if needed) + if ::BridgeWestendGrandpa::finalized_header_state_root(relay_chain_header_hash.into()).is_none() + { + assert_ok!( + ::BridgeWestendGrandpa::submit_finality_proof_ex( + relayer.clone(), + relay_chain_header.into(), + justification, + 1, + true + ) + ); + } + + // parachains + assert_ok!( + ::BridgeWestendParachains::submit_parachain_heads_ex( + relayer, + ( + relay_chain_header_number, + relay_chain_header_hash.into(), + ), + parachain_heads, + para_heads_proof, + true, + ) + ); + }); + + (bridged_para_head.hash(), para_state_root) +} + +fn is_parachain_header_submitted(block_hash: ParaHash) -> bool { + BridgeHubRococo::ext_wrapper(|| { + ::BridgeWestendParachains::parachain_head( + BridgedPara::PARACHAIN_ID.into(), + block_hash, + ) + .is_some() + }) +} + +#[test] +fn can_submit_ahw_and_bhw_parachain_proofs_works() { + // Submit BridgeHubWestend + let (bhr_para_head_hash, _) = submit_fake_parachain_heads::< + bp_westend::Westend, + bp_bridge_hub_westend::BridgeHubWestend, + >(1, 1); + assert!(is_parachain_header_submitted::( + bhr_para_head_hash + )); + + let (ahr_para_head_hash, _) = submit_fake_parachain_heads::< + bp_westend::Westend, + bp_asset_hub_westend::AssetHubWestend, + >(1, 2); + // Submit AssetHubWestend header + assert!(is_parachain_header_submitted::( + ahr_para_head_hash + )); +} diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/mod.rs index 890a0d4b0b97c..81d6379d08714 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-rococo/src/tests/mod.rs @@ -20,6 +20,7 @@ use xcm::opaque::v5; use xcm_executor::traits::ConvertLocation; mod asset_transfers; +mod bridging; mod claim_assets; mod register_bridged_assets; mod send_xcm; diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml index dcfef7a077dd6..130a1deac9ac4 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/Cargo.toml @@ -37,7 +37,15 @@ pallet-bridge-relayers = { workspace = true } # Cumulus asset-hub-westend-runtime = { workspace = true } +bp-asset-hub-rococo = { workspace = true } bp-asset-hub-westend = { workspace = true } +bp-bridge-hub-rococo = { workspace = true } +bp-header-chain = { workspace = true } +bp-parachains = { workspace = true } +bp-polkadot-core = { workspace = true } +bp-rococo = { workspace = true } +bp-runtime = { workspace = true } +bp-test-utils = { workspace = true } bridge-hub-common = { workspace = true } bridge-hub-westend-runtime = { workspace = true } cumulus-pallet-parachain-system = { workspace = true } diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/bridging.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/bridging.rs new file mode 100644 index 0000000000000..b66ab316331b6 --- /dev/null +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/bridging.rs @@ -0,0 +1,141 @@ +// 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. + +//! Tests related to bridging itself. + +use crate::tests::*; +use bp_header_chain::HeaderChain; +use bp_parachains::RelayBlockHash; +use bp_polkadot_core::parachains::{ParaHash, ParaHead}; +use bp_runtime::{BasicOperatingMode, Chain as BpChain, HashOf, HeaderOf, Parachain}; +use bp_test_utils::{ + make_default_justification, prepare_parachain_heads_proof, test_header_with_root, +}; + +/// Submits to BH's `pallet-bridge-parachains` some header and return (bridged_block_hash, +/// bridged_state_root) +fn submit_fake_parachain_heads< + BridgedRelay: BpChain, + BridgedPara: Parachain, +>( + para_header_number: u32, + relay_chain_header_number: u32, +) -> (HashOf, HashOf) { + // prepare parachain proofs + let para_state_root = ParaHash::from([para_header_number as u8; 32]); + let bridged_para_head = ParaHead( + test_header_with_root::>(para_header_number.into(), para_state_root) + .encode(), + ); + let (relay_chain_state_root, para_heads_proof, parachain_heads) = + prepare_parachain_heads_proof::>(vec![( + BridgedPara::PARACHAIN_ID, + bridged_para_head.clone(), + )]); + + // prepare Rococo grandpa proof + let relay_chain_header = test_header_with_root::>( + relay_chain_header_number.into(), + relay_chain_state_root.into(), + ); + let relay_chain_header_hash = relay_chain_header.hash(); + let justification = make_default_justification(&relay_chain_header); + + // prepare init bridge data + let init_bridge_data = bp_header_chain::InitializationData { + header: Box::new(bp_test_utils::test_header(0_u32)), + authority_list: bp_test_utils::authority_list(), + set_id: 1, + operating_mode: BasicOperatingMode::Normal, + }; + + // submit head proofs as the relayer would do + BridgeHubWestend::execute_with(|| { + let relayer = ::RuntimeOrigin::signed( + BridgeHubWestend::account_id_of(ALICE), + ); + + // initialize bridge (if not) + if ::BridgeRococoGrandpa::best_finalized() + .is_none() + { + assert_ok!( + ::BridgeRococoGrandpa::initialize( + ::RuntimeOrigin::root(), + init_bridge_data + ) + ); + } + + // grandpa (if needed) + if ::BridgeRococoGrandpa::finalized_header_state_root(relay_chain_header_hash).is_none() + { + assert_ok!( + ::BridgeRococoGrandpa::submit_finality_proof_ex( + relayer.clone(), + relay_chain_header.into(), + justification, + 1, + true + ) + ); + } + + // parachains + assert_ok!( + ::BridgeRococoParachains::submit_parachain_heads_ex( + relayer, + ( + relay_chain_header_number, + relay_chain_header_hash.into(), + ), + parachain_heads, + para_heads_proof, + true, + ) + ); + }); + + (bridged_para_head.hash(), para_state_root) +} + +fn is_parachain_header_submitted(block_hash: ParaHash) -> bool { + BridgeHubWestend::ext_wrapper(|| { + ::BridgeRococoParachains::parachain_head( + BridgedPara::PARACHAIN_ID.into(), + block_hash, + ) + .is_some() + }) +} + +#[test] +fn can_submit_ahr_and_bhr_parachain_proofs_works() { + // Submit BridgeHubRococo + let (bhr_para_head_hash, _) = submit_fake_parachain_heads::< + bp_rococo::Rococo, + bp_bridge_hub_rococo::BridgeHubRococo, + >(1, 1); + assert!(is_parachain_header_submitted::( + bhr_para_head_hash + )); + + // Submit AssetHubRococo header + let (ahr_para_head_hash, _) = + submit_fake_parachain_heads::(1, 2); + assert!(is_parachain_header_submitted::( + ahr_para_head_hash + )); +} diff --git a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/mod.rs b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/mod.rs index 8545984038182..45d926721e1f1 100644 --- a/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/mod.rs +++ b/cumulus/parachains/integration-tests/emulated/tests/bridges/bridge-hub-westend/src/tests/mod.rs @@ -18,6 +18,7 @@ use emulated_integration_tests_common::snowbridge::{SEPOLIA_ID, WETH}; mod aliases; mod asset_transfers; +mod bridging; mod claim_assets; mod register_bridged_assets; mod send_xcm; diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml index f1b1425457c4a..ab5d2ccd858f3 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/Cargo.toml @@ -97,11 +97,23 @@ bp-asset-hub-rococo = { workspace = true } bp-asset-hub-westend = { workspace = true } bp-bridge-hub-rococo = { workspace = true } bp-bridge-hub-westend = { workspace = true } +bp-header-chain = { workspace = true } +bp-messages = { workspace = true } +bp-relayers = { workspace = true } +bp-runtime = { workspace = true } +bridge-hub-common = { workspace = true } +bridge-runtime-common = { workspace = true } +pallet-bridge-messages = { workspace = true } +pallet-bridge-relayers = { workspace = true } +pallet-xcm-bridge = { workspace = true } pallet-xcm-bridge-router = { workspace = true } [dev-dependencies] asset-test-utils = { workspace = true, default-features = true } bp-xcm-bridge = { workspace = true } +bridge-hub-test-utils = { workspace = true, default-features = true } +bridge-runtime-common = { features = ["integrity-test"], workspace = true } +pallet-bridge-relayers = { features = ["integrity-test"], workspace = true } parachains-runtimes-test-utils = { workspace = true, default-features = true } [build-dependencies] @@ -111,6 +123,8 @@ substrate-wasm-builder = { optional = true, workspace = true, default-features = default = ["std"] runtime-benchmarks = [ "assets-common/runtime-benchmarks", + "bridge-hub-common/runtime-benchmarks", + "bridge-runtime-common/runtime-benchmarks", "cumulus-pallet-parachain-system/runtime-benchmarks", "cumulus-pallet-session-benchmarking/runtime-benchmarks", "cumulus-pallet-weight-reclaim/runtime-benchmarks", @@ -128,6 +142,8 @@ runtime-benchmarks = [ "pallet-assets-freezer/runtime-benchmarks", "pallet-assets/runtime-benchmarks", "pallet-balances/runtime-benchmarks", + "pallet-bridge-messages/runtime-benchmarks", + "pallet-bridge-relayers/runtime-benchmarks", "pallet-collator-selection/runtime-benchmarks", "pallet-message-queue/runtime-benchmarks", "pallet-multisig/runtime-benchmarks", @@ -140,6 +156,7 @@ runtime-benchmarks = [ "pallet-utility/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", "pallet-xcm-bridge-router/runtime-benchmarks", + "pallet-xcm-bridge/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "parachains-common/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", @@ -170,6 +187,8 @@ try-runtime = [ "pallet-aura/try-runtime", "pallet-authorship/try-runtime", "pallet-balances/try-runtime", + "pallet-bridge-messages/try-runtime", + "pallet-bridge-relayers/try-runtime", "pallet-collator-selection/try-runtime", "pallet-message-queue/try-runtime", "pallet-multisig/try-runtime", @@ -182,6 +201,7 @@ try-runtime = [ "pallet-uniques/try-runtime", "pallet-utility/try-runtime", "pallet-xcm-bridge-router/try-runtime", + "pallet-xcm-bridge/try-runtime", "pallet-xcm/try-runtime", "parachain-info/try-runtime", "parachains-common/try-runtime", @@ -194,7 +214,13 @@ std = [ "bp-asset-hub-westend/std", "bp-bridge-hub-rococo/std", "bp-bridge-hub-westend/std", + "bp-header-chain/std", + "bp-messages/std", + "bp-relayers/std", + "bp-runtime/std", "bp-xcm-bridge/std", + "bridge-hub-common/std", + "bridge-runtime-common/std", "codec/std", "cumulus-pallet-aura-ext/std", "cumulus-pallet-parachain-system/std", @@ -222,6 +248,8 @@ std = [ "pallet-aura/std", "pallet-authorship/std", "pallet-balances/std", + "pallet-bridge-messages/std", + "pallet-bridge-relayers/std", "pallet-collator-selection/std", "pallet-message-queue/std", "pallet-multisig/std", @@ -236,6 +264,7 @@ std = [ "pallet-utility/std", "pallet-xcm-benchmarks?/std", "pallet-xcm-bridge-router/std", + "pallet-xcm-bridge/std", "pallet-xcm/std", "parachain-info/std", "parachains-common/std", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/bridge-primitives/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-rococo/bridge-primitives/Cargo.toml index fd7c3e97b56f4..7921406d7972d 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/bridge-primitives/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/bridge-primitives/Cargo.toml @@ -21,11 +21,14 @@ scale-info = { features = ["derive"], workspace = true } frame-support = { workspace = true } sp-api = { workspace = true } sp-core = { workspace = true } +sp-runtime = { workspace = true } +sp-std = { workspace = true } # Bridge Dependencies bp-bridge-hub-cumulus = { workspace = true } bp-messages = { workspace = true } bp-runtime = { workspace = true } +bp-xcm-bridge = { workspace = true } bp-xcm-bridge-router = { workspace = true } testnet-parachains-constants = { features = ["rococo"], workspace = true } @@ -39,11 +42,16 @@ std = [ "bp-messages/std", "bp-runtime/std", "bp-xcm-bridge-router/std", + "bp-xcm-bridge/std", "codec/std", + "codec/std", + "frame-support/std", "frame-support/std", "scale-info/std", "sp-api/std", "sp-core/std", + "sp-runtime/std", + "sp-std/std", "testnet-parachains-constants/std", "xcm/std", ] diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/bridge-primitives/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/bridge-primitives/src/lib.rs index 52ccc8bb1881c..6ffb01df265e8 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/bridge-primitives/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/bridge-primitives/src/lib.rs @@ -13,7 +13,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Module with configuration which reflects AssetHubRococo runtime setup. +//! Module with configuration which reflects AssetHubRococo runtime setup (AccountId, Headers, +//! Hashes...) #![cfg_attr(not(feature = "std"), no_std)] @@ -49,6 +50,9 @@ pub enum Call { /// `ToWestendXcmRouter` bridge pallet. #[codec(index = 45)] ToWestendXcmRouter(XcmBridgeHubCall), + /// Points to the `pallet_xcm_bridge` pallet instance for `AssetHubWestend`. + #[codec(index = 61)] + XcmOverAssetHubWestend(bp_xcm_bridge::XcmBridgeCall), } frame_support::parameter_types! { @@ -85,7 +89,6 @@ pub const ASSET_HUB_ROCOCO_PARACHAIN_ID: u32 = 1000; /// AssetHubRococo parachain. #[derive(RuntimeDebug)] - pub struct AssetHubRococo; impl Chain for AssetHubRococo { @@ -149,3 +152,18 @@ pub const WITH_BRIDGE_ROCOCO_TO_WESTEND_MESSAGES_PALLET_INDEX: u8 = 62; decl_bridge_finality_runtime_apis!(asset_hub_rococo); decl_bridge_messages_runtime_apis!(asset_hub_rococo, HashedLaneId); + +frame_support::parameter_types! { + /// The XCM fee that is paid for executing a XCM program (with `ExportMessage` instruction) at the Rococo + /// BridgeHub. + /// (initially was calculated by test `AssetHubRococo::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`) + pub const AssetHubRococoBaseXcmFeeInRocs: u128 = 18_451_090_000; + + /// Transaction fee that is paid at the Rococo BridgeHub for delivering a single inbound message. + /// (initially was calculated by test `AssetHubRococo::can_calculate_fee_for_standalone_message_delivery_transaction` + `33%`) + pub const AssetHubRococoBaseDeliveryFeeInRocs: u128 = 298_893_456; + + /// Transaction fee that is paid at the Rococo BridgeHub for delivering single outbound message confirmation. + /// (initially was calculated by test `AssetHubRococo::can_calculate_fee_for_standalone_message_confirmation_transaction` + `33%`) + pub const AssetHubRococoBaseConfirmationFeeInRocs: u128 = 56_535_560; +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/bridge_common_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/bridge_common_config.rs new file mode 100644 index 0000000000000..f9ffa83860ae6 --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/bridge_common_config.rs @@ -0,0 +1,53 @@ +// Copyright (C) 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 . + +//! Bridge definitions that can be used by multiple bridges. + +use super::{weights, AccountId, Balance, Balances, BlockNumber, Runtime, RuntimeEvent}; +use bp_relayers::RewardsAccountParams; + +frame_support::parameter_types! { + pub storage RequiredStakeForStakeAndSlash: Balance = 1_000_000; + pub const RelayerStakeLease: u32 = 8; + pub const RelayerStakeReserveId: [u8; 8] = *b"brdgrlrs"; + pub storage DeliveryRewardInBalance: u64 = 1_000_000; +} + +/// Allows collect and claim rewards for the relayers +pub type BridgeRelayersInstance = pallet_bridge_relayers::Instance1; +impl pallet_bridge_relayers::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + + type RewardBalance = Balance; + type Reward = RewardsAccountParams; + type PaymentProcedure = bp_relayers::PayRewardFromAccount< + pallet_balances::Pallet, + AccountId, + bp_messages::HashedLaneId, + Self::RewardBalance, + >; + + type StakeAndSlash = pallet_bridge_relayers::StakeAndSlashNamed< + AccountId, + BlockNumber, + Balances, + RelayerStakeReserveId, + RequiredStakeForStakeAndSlash, + RelayerStakeLease, + >; + type Balance = Balance; + type WeightInfo = weights::pallet_bridge_relayers::WeightInfo; +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/bridge_to_westend_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/bridge_to_westend_config.rs new file mode 100644 index 0000000000000..ccfbf6189370e --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/bridge_to_westend_config.rs @@ -0,0 +1,325 @@ +// Copyright (C) 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 . + +//! Bridge definitions used on BridgeHubRococo for bridging to BridgeHubWestend. + +use crate::{ + bridge_common_config::{BridgeRelayersInstance, DeliveryRewardInBalance}, + weights, xcm_config, + xcm_config::UniversalLocation, + AccountId, Balance, Balances, BridgeWestendMessages, PolkadotXcm, Runtime, RuntimeEvent, + RuntimeHoldReason, ToWestendOverAssetHubWestendXcmRouter, XcmOverAssetHubWestend, +}; +use alloc::{vec, vec::Vec}; +use bp_messages::HashedLaneId; +use bp_runtime::HashOf; +use bridge_hub_common::xcm_version::XcmVersionOfDestAndRemoteBridge; +use pallet_xcm_bridge::XcmAsPlainPayload; + +use frame_support::{ + parameter_types, + traits::{EitherOf, Equals, PalletInfoAccess}, +}; +use frame_system::{EnsureRoot, EnsureRootWithSuccess}; +use pallet_bridge_relayers::extension::{ + BridgeRelayersTransactionExtension, WithMessagesExtensionConfig, +}; +use pallet_xcm::EnsureXcm; +use pallet_xcm_bridge::congestion::{ + BlobDispatcherWithChannelStatus, HereOrLocalConsensusXcmChannelManager, + UpdateBridgeStatusXcmChannelManager, +}; +use pallet_xcm_bridge_router::impls::GetPriceForBridge; +use parachains_common::xcm_config::{ + AllSiblingSystemParachains, ParentRelayOrSiblingParachains, RelayOrOtherSystemParachains, +}; +use polkadot_parachain_primitives::primitives::Sibling; +use sp_runtime::traits::Convert; +use testnet_parachains_constants::rococo::currency::UNITS as ROC; +use xcm::{ + latest::{prelude::*, WESTEND_GENESIS_HASH}, + prelude::NetworkId, +}; +use xcm_builder::{ + BridgeBlobDispatcher, LocalExporter, ParentIsPreset, SiblingParachainConvertsVia, +}; + +parameter_types! { + pub BridgeRococoToWestendMessagesPalletInstance: InteriorLocation = [PalletInstance(::index() as u8)].into(); + pub const HereLocation: Location = Location::here(); + pub WestendGlobalConsensusNetwork: NetworkId = NetworkId::ByGenesis(WESTEND_GENESIS_HASH); + pub WestendGlobalConsensusNetworkLocation: Location = Location::new( + 2, + [GlobalConsensus(WestendGlobalConsensusNetwork::get())] + ); + // see the `FEE_BOOST_PER_MESSAGE` constant to get the meaning of this value + pub PriorityBoostPerMessage: u64 = 364_088_888_888_888; + + // The other side of the bridge + pub AssetHubWestendLocation: Location = Location::new( + 2, + [ + GlobalConsensus(WestendGlobalConsensusNetwork::get()), + Parachain(::PARACHAIN_ID) + ] + ); + + pub storage BridgeDeposit: Balance = 5 * ROC; + + // The fee for exporting/delivery. + pub BaseMessageExportPrice: Assets = ( + xcm_config::bridging::XcmBridgeHubRouterFeeAssetId::get(), + xcm_config::bridging::ToWestendOverAssetHubWestendXcmRouterBaseFee::get(), + ).into(); +} + +/// Transaction extension that refunds relayers that are delivering messages from the Westend +/// parachain. +pub type OnAssetHubRococoRefundAssetHubWestendMessages = BridgeRelayersTransactionExtension< + Runtime, + WithMessagesExtensionConfig< + StrOnAssetHubRococoRefundAssetHubWestendMessages, + Runtime, + WithAssetHubWestendMessagesInstance, + BridgeRelayersInstance, + PriorityBoostPerMessage, + >, +>; +bp_runtime::generate_static_str_provider!(OnAssetHubRococoRefundAssetHubWestendMessages); + +/// Add XCM messages support for AssetHubRococo to support Rococo->Westend XCM messages +pub type WithAssetHubWestendMessagesInstance = pallet_bridge_messages::Instance1; +impl pallet_bridge_messages::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = weights::pallet_bridge_messages::WeightInfo; + + type ThisChain = bp_asset_hub_rococo::AssetHubRococo; + type BridgedChain = bp_asset_hub_westend::AssetHubWestend; + type BridgedHeaderChain = ParachainHeaderProofs; + + type OutboundPayload = XcmAsPlainPayload; + type InboundPayload = XcmAsPlainPayload; + type LaneId = HashedLaneId; + + type DeliveryPayments = (); + type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< + Runtime, + WithAssetHubWestendMessagesInstance, + BridgeRelayersInstance, + DeliveryRewardInBalance, + >; + + type MessageDispatch = XcmOverAssetHubWestend; + type OnMessagesDelivered = XcmOverAssetHubWestend; +} + +/// TODO: doc + FAIL-CI - implement storage for synced proofs from BridgeHub +pub struct ParachainHeaderProofs(core::marker::PhantomData); +impl bp_header_chain::HeaderChain for ParachainHeaderProofs { + fn finalized_header_state_root(_header_hash: HashOf) -> Option> { + todo!("TODO: FAIL-CI - implement storage for synced proofs from BridgeHub") + } +} + +/// Converts encoded call to the unpaid XCM `Transact`. +pub struct UpdateBridgeStatusXcmProvider; +impl Convert, Xcm<()>> for UpdateBridgeStatusXcmProvider { + fn convert(encoded_call: Vec) -> Xcm<()> { + Xcm(vec![ + UnpaidExecution { weight_limit: Unlimited, check_origin: None }, + Transact { + origin_kind: OriginKind::Xcm, + call: encoded_call.into(), + fallback_max_weight: None, + }, + ExpectTransactStatus(MaybeErrorCode::Success), + ]) + } +} + +/// Add support for the export and dispatch of XCM programs withing +/// `WithAssetHubWestendMessagesInstance`. +pub type XcmOverAssetHubWestendInstance = pallet_xcm_bridge::Instance1; +impl pallet_xcm_bridge::Config for Runtime { + type WeightInfo = weights::pallet_xcm_bridge::WeightInfo; + + type UniversalLocation = UniversalLocation; + type BridgedNetwork = WestendGlobalConsensusNetworkLocation; + type BridgeMessagesPalletInstance = WithAssetHubWestendMessagesInstance; + + /// This price covers: + /// - `BaseMessageExportPrice` (for message proof delivery/confirmation) + /// - Message size fee (if configured) + /// - Dynamic fee factor (if congested) + /// + /// This price is calculated either for local routing with `ToWestendOverAssetHubWestendXcmRouter` + /// or executing `ExportMessage` from a sibling chain. + type MessageExportPrice = GetPriceForBridge< + Runtime, + ToWestendOverAssetHubWestendXcmRouterInstance, + BaseMessageExportPrice, + >; + type DestinationVersion = XcmVersionOfDestAndRemoteBridge; + + type ForceOrigin = EnsureRoot; + // We allow creating bridges for the runtime itself and for other local consensus chains (relay, + // paras). + type OpenBridgeOrigin = EitherOf< + // We want to translate `RuntimeOrigin::root()` to the `Location::here()`, e.g. for + // governance calls. + EnsureRootWithSuccess, + // For relay or sibling chains + EnsureXcm, + >; + // Converter aligned with `OpenBridgeOrigin`. + type BridgeOriginAccountIdConverter = + (ParentIsPreset, SiblingParachainConvertsVia); + + type BridgeDeposit = BridgeDeposit; + type Currency = Balances; + type RuntimeHoldReason = RuntimeHoldReason; + // Do not require deposit from system parachains (including itself) or relay chain + type AllowWithoutBridgeDeposit = + (RelayOrOtherSystemParachains, Equals); + + // This pallet is deployed on AH, so we expect a remote router with `ExportMessage`. We handle + // congestion with XCM using `udpate_bridge_status` sent to the sending chain. (congestion with + // local sending chain) + type LocalXcmChannelManager = HereOrLocalConsensusXcmChannelManager< + pallet_xcm_bridge::BridgeId, + // handles congestion for local chain router for local AH's bridges + ToWestendOverAssetHubWestendXcmRouter, + // handles congestion for other local chains with XCM using `update_bridge_status` sent to + // the sending chain. + UpdateBridgeStatusXcmChannelManager< + Runtime, + XcmOverAssetHubWestendInstance, + UpdateBridgeStatusXcmProvider, + xcm_config::LocalXcmRouter, + >, + >; + // Dispatching inbound messages from the bridge and managing congestion with the local + // receiving/destination chain + type BlobDispatcher = BlobDispatcherWithChannelStatus< + // Dispatches received XCM messages from other bridge + BridgeBlobDispatcher< + xcm_config::LocalXcmRouter, + UniversalLocation, + // TODO: FAIL-CI wait for https://github.com/paritytech/polkadot-sdk/pull/6002#issuecomment-2469892343 + BridgeRococoToWestendMessagesPalletInstance, + >, + // Provides the status of the XCMP queue's outbound queue, indicating whether messages can + // be dispatched to the sibling. + cumulus_pallet_xcmp_queue::bridging::OutXcmpChannelStatusProvider, + >; + type CongestionLimits = (); +} + +/// XCM router instance to the local `pallet_xcm_bridge::` with +/// direct bridging capabilities for `Westend` global consensus with dynamic fees and back-pressure. +pub type ToWestendOverAssetHubWestendXcmRouterInstance = pallet_xcm_bridge_router::Instance4; +impl pallet_xcm_bridge_router::Config for Runtime { + type WeightInfo = + weights::pallet_xcm_bridge_router_to_westend_over_asset_hub_westend::WeightInfo; + + type DestinationVersion = PolkadotXcm; + + // We use `LocalExporter` to ensure that `pallet_xcm_bridge_router` can directly trigger + // `pallet_xcm_bridge` as an exporter. + type MessageExporter = LocalExporter; + + // For congestion - resolves `BridgeId` using the same algorithm as `pallet_xcm_bridge` on + // the BH. + type BridgeIdResolver = + pallet_xcm_bridge_router::impls::EnsureIsRemoteBridgeIdResolver; + // We don't expect here `update_bridge_status` calls, but let's allow just for root (governance, + // ...). + type UpdateBridgeStatusOrigin = EnsureRoot; + + // For adding message size fees + type ByteFee = xcm_config::bridging::XcmBridgeHubRouterByteFee; + // For adding message size fees + type FeeAsset = xcm_config::bridging::XcmBridgeHubRouterFeeAssetId; +} + +#[cfg(test)] +mod tests { + use super::*; + use bridge_runtime_common::{ + assert_complete_bridge_types, + integrity::{ + assert_standalone_messages_bridge_constants, check_message_lane_weights, + AssertChainConstants, AssertCompleteBridgeConstants, + }, + }; + + /// 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 = 2 * ROC; + + #[test] + fn ensure_bridge_hub_rococo_message_lane_weights_are_correct() { + check_message_lane_weights::< + bp_asset_hub_rococo::AssetHubRococo, + Runtime, + WithAssetHubWestendMessagesInstance, + >( + bp_asset_hub_westend::EXTRA_STORAGE_PROOF_SIZE, + bp_asset_hub_rococo::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + bp_asset_hub_rococo::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + true, + ); + } + + #[test] + fn ensure_bridge_integrity() { + assert_complete_bridge_types!( + runtime: Runtime, + with_bridged_chain_messages_instance: WithAssetHubWestendMessagesInstance, + this_chain: bp_asset_hub_rococo::AssetHubRococo, + bridged_chain: bp_asset_hub_westend::AssetHubWestend, + expected_payload_type: XcmAsPlainPayload, + ); + + assert_standalone_messages_bridge_constants::( + AssertCompleteBridgeConstants { + this_chain_constants: AssertChainConstants { + block_length: bp_bridge_hub_rococo::BlockLength::get(), + block_weights: bp_bridge_hub_rococo::BlockWeightsForAsyncBacking::get(), + }, + }, + ); + + pallet_bridge_relayers::extension::per_message::ensure_priority_boost_is_sane::< + Runtime, + WithAssetHubWestendMessagesInstance, + PriorityBoostPerMessage, + >(FEE_BOOST_PER_MESSAGE); + + let expected: InteriorLocation = [PalletInstance( + bp_asset_hub_rococo::WITH_BRIDGE_ROCOCO_TO_WESTEND_MESSAGES_PALLET_INDEX, + )] + .into(); + assert_eq!(BridgeRococoToWestendMessagesPalletInstance::get(), expected); + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs index da93f839b322c..dc2594d22b26e 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/lib.rs @@ -24,6 +24,8 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +pub mod bridge_common_config; +pub mod bridge_to_westend_config; mod genesis_config_presets; mod weights; pub mod xcm_config; @@ -101,7 +103,7 @@ use polkadot_runtime_common::{BlockHashCount, SlowAdjustingFeeUpdate}; #[cfg(feature = "runtime-benchmarks")] use xcm::latest::prelude::{ Asset, Assets as XcmAssets, Fungible, Here, InteriorLocation, Junction, Junction::*, Location, - NetworkId, NonFungible, Parent, ParentThen, Response, WeightLimit, + NetworkId, NonFungible, Parent, ParentThen, Response, WeightLimit, XCM_VERSION, }; use xcm::{ latest::prelude::{AssetId, BodyId}, @@ -994,10 +996,12 @@ impl pallet_nfts::Config for Runtime { } /// XCM router instance to BridgeHub with bridging capabilities for `Westend` global -/// consensus with dynamic fees and back-pressure. +/// consensus with dynamic fees and back-pressure +/// (legacy routing with `ExportMessage` over BridgeHub). pub type ToWestendXcmRouterInstance = pallet_xcm_bridge_router::Instance3; impl pallet_xcm_bridge_router::Config for Runtime { - type WeightInfo = weights::pallet_xcm_bridge_router::WeightInfo; + type WeightInfo = + weights::pallet_xcm_bridge_router_to_westend_over_bridge_hub::WeightInfo; type DestinationVersion = PolkadotXcm; @@ -1132,12 +1136,24 @@ construct_runtime!( AssetRewards: pallet_asset_rewards = 60, + // Bridges permissionless lanes. + XcmOverAssetHubWestend: pallet_xcm_bridge:: = 61, + BridgeWestendMessages: pallet_bridge_messages:: = 62, + BridgeRelayers: pallet_bridge_relayers:: = 63, + ToWestendOverAssetHubWestendXcmRouter: pallet_xcm_bridge_router:: = 64, + // TODO: the pallet instance should be removed once all pools have migrated // to the new account IDs. AssetConversionMigration: pallet_asset_conversion_ops = 200, } ); +bridge_runtime_common::generate_bridge_reject_obsolete_headers_and_messages! { + RuntimeCall, AccountId, + // Messages + BridgeWestendMessages +} + /// The address format for describing accounts. pub type Address = sp_runtime::MultiAddress; /// Block type as expected by this runtime. @@ -1160,6 +1176,8 @@ pub type TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim< frame_system::CheckWeight, pallet_asset_conversion_tx_payment::ChargeAssetTxPayment, frame_metadata_hash_extension::CheckMetadataHash, + BridgeRejectObsoleteHeadersAndMessages, + (bridge_to_westend_config::OnAssetHubRococoRefundAssetHubWestendMessages,), ), >; /// Unchecked extrinsic type as expected by this runtime. @@ -1344,8 +1362,13 @@ mod benches { [pallet_collator_selection, CollatorSelection] [cumulus_pallet_parachain_system, ParachainSystem] [cumulus_pallet_xcmp_queue, XcmpQueue] - [pallet_xcm_bridge_router, ToWestend] [pallet_asset_conversion_ops, AssetConversionMigration] + // Bridge pallets + [pallet_xcm_bridge_router, ToWestendOverBridgeHub] + [pallet_xcm_bridge_router, ToWestendOverAssetHubWestend] + [pallet_bridge_messages, RococoToWestend] + [pallet_bridge_relayers, BridgeRelayersBench::] + [pallet_xcm_bridge, OverWestend] // XCM [pallet_xcm, PalletXcmExtrinsicsBenchmark::] // NOTE: Make sure you point to the individual modules below. @@ -1666,7 +1689,8 @@ impl_runtime_apis! { use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; - use pallet_xcm_bridge_router::benchmarking::Pallet as XcmBridgeHubRouterBench; + use pallet_xcm_bridge_router::benchmarking::Pallet as XcmBridgeRouterBench; + use pallet_bridge_relayers::benchmarking::Pallet as BridgeRelayersBench; // This is defined once again in dispatch_benchmark, because list_benchmarks! // and add_benchmarks! are macros exported by define_benchmarks! macros and those types @@ -1682,7 +1706,10 @@ impl_runtime_apis! { type Foreign = pallet_assets::Pallet::; type Pool = pallet_assets::Pallet::; - type ToWestend = XcmBridgeHubRouterBench; + type ToWestendOverBridgeHub = XcmBridgeRouterBench; + type ToWestendOverAssetHubWestend = XcmBridgeRouterBench; + type OverWestend = pallet_xcm_bridge::benchmarking::Pallet::; + type RococoToWestend = pallet_bridge_messages::benchmarking::Pallet::; let mut list = Vec::::new(); list_benchmarks!(list, extra); @@ -1716,8 +1743,8 @@ impl_runtime_apis! { impl cumulus_pallet_session_benchmarking::Config for Runtime {} use pallet_xcm_bridge_router::benchmarking::{ - Pallet as XcmBridgeHubRouterBench, - Config as XcmBridgeHubRouterConfig, + Pallet as XcmBridgeRouterBench, + Config as XcmBridgeRouterConfig, }; parameter_types! { @@ -1846,7 +1873,7 @@ impl_runtime_apis! { } } - impl XcmBridgeHubRouterConfig for Runtime { + impl XcmBridgeRouterConfig for Runtime { fn ensure_bridged_target_destination() -> Result { Ok(xcm_config::bridging::to_westend::AssetHubWestend::get()) } @@ -1854,6 +1881,14 @@ impl_runtime_apis! { Some(pallet_xcm::Origin::Xcm(xcm_config::bridging::SiblingBridgeHub::get()).into()) } } + impl XcmBridgeRouterConfig for Runtime { + fn ensure_bridged_target_destination() -> Result { + Ok(xcm_config::bridging::to_westend::AssetHubWestend::get()) + } + fn update_bridge_status_origin() -> Option { + None + } + } use xcm_config::{TokenLocation, MaxAssetsIntoHolding}; use pallet_xcm_benchmarks::asset_instance_from; @@ -1984,7 +2019,50 @@ impl_runtime_apis! { fn export_message_origin_and_destination( ) -> Result<(Location, NetworkId, InteriorLocation), BenchmarkError> { - Err(BenchmarkError::Skip) + // save XCM version for remote permissionless lanes on bridged asset hub + let _ = PolkadotXcm::force_xcm_version( + RuntimeOrigin::root(), + alloc::boxed::Box::new(bridge_to_westend_config::AssetHubWestendLocation::get()), + XCM_VERSION, + ).map_err(|e| { + log::error!( + "Failed to dispatch `force_xcm_version({:?}, {:?}, {:?})`, error: {:?}", + RuntimeOrigin::root(), + bridge_to_westend_config::AssetHubWestendLocation::get(), + XCM_VERSION, + e + ); + BenchmarkError::Stop("XcmVersion was not stored!") + })?; + + // open bridge + let westend = bridge_to_westend_config::WestendGlobalConsensusNetwork::get(); + let sibling_parachain_location = Location::new(1, [Parachain(5678)]); + let bridge_destination_universal_location: InteriorLocation = [GlobalConsensus(westend), Parachain(8765)].into(); + let _ = XcmOverAssetHubWestend::open_bridge_for_benchmarks( + ::try_new(1, 2).unwrap(), + sibling_parachain_location.clone(), + bridge_destination_universal_location.clone(), + true, + None, + || ExistentialDeposit::get(), + ).map_err(|e| { + log::error!( + "Failed to `XcmOverAssetHubWestend::open_bridge`({:?}, {:?})`, error: {:?}", + sibling_parachain_location, + bridge_destination_universal_location, + e + ); + BenchmarkError::Stop("Bridge was not opened!") + })?; + + Ok( + ( + sibling_parachain_location, + westend, + [Parachain(8765)].into() + ) + ) } fn alias_origin() -> Result<(Location, Location), BenchmarkError> { @@ -2004,7 +2082,135 @@ impl_runtime_apis! { type Foreign = pallet_assets::Pallet::; type Pool = pallet_assets::Pallet::; - type ToWestend = XcmBridgeHubRouterBench; + type ToWestendOverBridgeHub = XcmBridgeRouterBench; + type ToWestendOverAssetHubWestend = XcmBridgeRouterBench; + type OverWestend = pallet_xcm_bridge::benchmarking::Pallet::; + type RococoToWestend = pallet_bridge_messages::benchmarking::Pallet::; + + use pallet_bridge_relayers::benchmarking::{ + Config as BridgeRelayersConfig, + Pallet as BridgeRelayersBench + }; + + impl BridgeRelayersConfig for Runtime { + fn bench_reward() -> Self::Reward { + bp_relayers::RewardsAccountParams::new( + bp_messages::HashedLaneId::default(), + *b"test", + bp_relayers::RewardsAccountOwner::ThisChain + ) + } + + fn prepare_rewards_account( + reward_kind: Self::Reward, + reward: Balance, + ) -> Option { + let rewards_account = bp_relayers::PayRewardFromAccount::< + Balances, + AccountId, + bp_messages::HashedLaneId, + Balance, + >::rewards_account(reward_kind); + >::deposit_account(rewards_account, reward); + + None + } + + fn deposit_account(account: AccountId, balance: Balance) { + use frame_support::traits::fungible::Mutate; + Balances::mint_into(&account, balance.saturating_add(ExistentialDeposit::get())).unwrap(); + } + } + + impl pallet_xcm_bridge::benchmarking::Config for Runtime { + fn open_bridge_origin() -> Option<(RuntimeOrigin, Balance)> { + // We allow bridges to be opened for sibling parachains. + Some(( + pallet_xcm::Origin::Xcm(Location::new(1, [Parachain(42)])).into(), + ExistentialDeposit::get(), + )) + } + } + + use pallet_bridge_messages::{BridgedChainOf, LaneIdOf}; + use pallet_bridge_messages::benchmarking::{ + Config as BridgeMessagesConfig, + MessageDeliveryProofParams, + MessageProofParams, + }; + + impl BridgeMessagesConfig for Runtime { + fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool { + let bench_lane_id = >::bench_lane_id(); + use bp_runtime::Chain; + let bridged_chain_id =>::BridgedChain::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>, + ) -> ( + bp_messages::target_chain::FromBridgedChainMessagesProof< + bp_runtime::HashOf>, + LaneIdOf + >, + 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()); + let _bridge_locations = XcmOverAssetHubWestend::open_bridge_for_benchmarks( + params.lane, + Location::new(1, [Parachain(42)]), + [GlobalConsensus(bridge_to_westend_config::WestendGlobalConsensusNetwork::get()), Parachain(2075)].into(), + // do not create lanes, because they are already created `params.lane` + false, + None, + || ExistentialDeposit::get(), + ).expect("valid bridge opened"); + todo!("TODO: FAIL-CI - prepare storage proof for synced proof") + // prepare_message_proof_from_parachain::< + // Runtime, + // bridge_common_config::BridgeGrandpaWestendInstance, + // bridge_to_westend_config::WithAssetHubWestendMessagesInstance, + // >(params, generate_xcm_builder_bridge_message_sample(bridge_locations.bridge_origin_universal_location().clone())) + } + + fn prepare_message_delivery_proof( + params: MessageDeliveryProofParams>, + ) -> bp_messages::source_chain::FromBridgedChainMessagesDeliveryProof< + bp_runtime::HashOf>, + LaneIdOf + > { + let _ = XcmOverAssetHubWestend::open_bridge_for_benchmarks( + params.lane, + Location::new(1, [Parachain(42)]), + [GlobalConsensus(bridge_to_westend_config::WestendGlobalConsensusNetwork::get()), Parachain(2075)].into(), + // do not create lanes, because they are already created `params.lane` + false, + None, + || ExistentialDeposit::get(), + ); + todo!("TODO: FAIL-CI - prepare storage proof for synced proof") + // prepare_message_delivery_proof_from_parachain::< + // Runtime, + // bridge_common_config::BridgeGrandpaWestendInstance, + // bridge_to_westend_config::WithAssetHubWestendMessagesInstance, + // >(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 frame_support::traits::WhitelistedStorageKeys; let whitelist: Vec = AllPalletsWithSystem::whitelisted_storage_keys(); diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs index f7ca4c9e0df95..c181afd05aebd 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/mod.rs @@ -29,6 +29,8 @@ pub mod pallet_assets_foreign; pub mod pallet_assets_local; pub mod pallet_assets_pool; pub mod pallet_balances; +pub mod pallet_bridge_messages; +pub mod pallet_bridge_relayers; pub mod pallet_collator_selection; pub mod pallet_message_queue; pub mod pallet_multisig; @@ -41,7 +43,9 @@ pub mod pallet_transaction_payment; pub mod pallet_uniques; pub mod pallet_utility; pub mod pallet_xcm; -pub mod pallet_xcm_bridge_router; +pub mod pallet_xcm_bridge; +pub mod pallet_xcm_bridge_router_to_westend_over_asset_hub_westend; +pub mod pallet_xcm_bridge_router_to_westend_over_bridge_hub; pub mod paritydb_weights; pub mod rocksdb_weights; pub mod xcm; @@ -49,3 +53,23 @@ pub mod xcm; pub use block_weights::constants::BlockExecutionWeight; pub use extrinsic_weights::constants::ExtrinsicBaseWeight; pub use rocksdb_weights::constants::RocksDbWeight; + +use ::pallet_bridge_messages::WeightInfoExt as MessagesWeightInfoExt; +use ::pallet_bridge_relayers::WeightInfoExt as _; + +use crate::{Runtime, Weight}; + +impl MessagesWeightInfoExt for pallet_bridge_messages::WeightInfo { + fn expected_extra_storage_proof_size() -> u32 { + bp_bridge_hub_westend::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() + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_bridge_messages.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_bridge_messages.rs new file mode 100644 index 0000000000000..dbe2465342379 --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_bridge_messages.rs @@ -0,0 +1,273 @@ +// Copyright (C) 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 32.0.0 +//! DATE: 2024-11-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-wiukf8gn-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-rococo-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/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_bridge_messages +// --chain=bridge-hub-rococo-dev TODO: FAIL-CI regenerate +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/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: `BridgeWestendMessages::PalletOperatingMode` (r:1 w:0) + /// Proof: `BridgeWestendMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendParachains::ImportedParaHeads` (r:1 w:0) + /// Proof: `BridgeWestendParachains::ImportedParaHeads` (`max_values`: Some(64), `max_size`: Some(196), added: 1186, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::InboundLanes` (r:1 w:1) + /// Proof: `BridgeWestendMessages::InboundLanes` (`max_values`: None, `max_size`: Some(49180), added: 51655, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::LaneToBridge` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::LaneToBridge` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::Bridges` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::Bridges` (`max_values`: None, `max_size`: Some(1893), added: 4368, mode: `MaxEncodedLen`) + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: Some(1282), added: 1777, 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: `940` + // Estimated: `52645` + // Minimum execution time: 62_868_000 picoseconds. + Weight::from_parts(65_210_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `BridgeWestendMessages::PalletOperatingMode` (r:1 w:0) + /// Proof: `BridgeWestendMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendParachains::ImportedParaHeads` (r:1 w:0) + /// Proof: `BridgeWestendParachains::ImportedParaHeads` (`max_values`: Some(64), `max_size`: Some(196), added: 1186, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::InboundLanes` (r:1 w:1) + /// Proof: `BridgeWestendMessages::InboundLanes` (`max_values`: None, `max_size`: Some(49180), added: 51655, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::LaneToBridge` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::LaneToBridge` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::Bridges` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::Bridges` (`max_values`: None, `max_size`: Some(1893), added: 4368, mode: `MaxEncodedLen`) + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: Some(1282), added: 1777, mode: `MaxEncodedLen`) + /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) + /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 4076]`. + /// The range of component `n` is `[1, 4076]`. + fn receive_n_messages_proof(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `940` + // Estimated: `52645` + // Minimum execution time: 62_893_000 picoseconds. + Weight::from_parts(63_992_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + // Standard Error: 13_856 + .saturating_add(Weight::from_parts(12_332_627, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `BridgeWestendMessages::PalletOperatingMode` (r:1 w:0) + /// Proof: `BridgeWestendMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendParachains::ImportedParaHeads` (r:1 w:0) + /// Proof: `BridgeWestendParachains::ImportedParaHeads` (`max_values`: Some(64), `max_size`: Some(196), added: 1186, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::InboundLanes` (r:1 w:1) + /// Proof: `BridgeWestendMessages::InboundLanes` (`max_values`: None, `max_size`: Some(49180), added: 51655, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::LaneToBridge` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::LaneToBridge` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::Bridges` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::Bridges` (`max_values`: None, `max_size`: Some(1893), added: 4368, mode: `MaxEncodedLen`) + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: Some(1282), added: 1777, 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: `940` + // Estimated: `52645` + // Minimum execution time: 68_193_000 picoseconds. + Weight::from_parts(70_799_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `BridgeWestendMessages::PalletOperatingMode` (r:1 w:0) + /// Proof: `BridgeWestendMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendParachains::ImportedParaHeads` (r:1 w:0) + /// Proof: `BridgeWestendParachains::ImportedParaHeads` (`max_values`: Some(64), `max_size`: Some(196), added: 1186, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::InboundLanes` (r:1 w:1) + /// Proof: `BridgeWestendMessages::InboundLanes` (`max_values`: None, `max_size`: Some(49180), added: 51655, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::LaneToBridge` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::LaneToBridge` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::Bridges` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::Bridges` (`max_values`: None, `max_size`: Some(1893), added: 4368, mode: `MaxEncodedLen`) + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: Some(1282), added: 1777, mode: `MaxEncodedLen`) + /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) + /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 16384]`. + /// The range of component `n` is `[1, 16384]`. + fn receive_single_n_bytes_message_proof(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `940` + // Estimated: `52645` + // Minimum execution time: 61_230_000 picoseconds. + Weight::from_parts(65_437_770, 0) + .saturating_add(Weight::from_parts(0, 52645)) + // Standard Error: 9 + .saturating_add(Weight::from_parts(2_168, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `BridgeWestendMessages::PalletOperatingMode` (r:1 w:0) + /// Proof: `BridgeWestendMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendParachains::ImportedParaHeads` (r:1 w:0) + /// Proof: `BridgeWestendParachains::ImportedParaHeads` (`max_values`: Some(64), `max_size`: Some(196), added: 1186, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::OutboundLanes` (r:1 w:1) + /// Proof: `BridgeWestendMessages::OutboundLanes` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Proof: UNKNOWN KEY `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`) + /// Storage: `XcmOverBridgeHubWestend::LaneToBridge` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::LaneToBridge` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::Bridges` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::Bridges` (`max_values`: None, `max_size`: Some(1893), added: 4368, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::OutboundMessages` (r:0 w:1) + /// Proof: `BridgeWestendMessages::OutboundMessages` (`max_values`: None, `max_size`: Some(65568), added: 68043, mode: `MaxEncodedLen`) + fn receive_delivery_proof_for_single_message() -> Weight { + // Proof Size summary in bytes: + // Measured: `711` + // Estimated: `5358` + // Minimum execution time: 51_650_000 picoseconds. + Weight::from_parts(53_190_000, 0) + .saturating_add(Weight::from_parts(0, 5358)) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: `BridgeWestendMessages::PalletOperatingMode` (r:1 w:0) + /// Proof: `BridgeWestendMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendParachains::ImportedParaHeads` (r:1 w:0) + /// Proof: `BridgeWestendParachains::ImportedParaHeads` (`max_values`: Some(64), `max_size`: Some(196), added: 1186, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::OutboundLanes` (r:1 w:1) + /// Proof: `BridgeWestendMessages::OutboundLanes` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Proof: UNKNOWN KEY `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`) + /// Storage: `XcmOverBridgeHubWestend::LaneToBridge` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::LaneToBridge` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::Bridges` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::Bridges` (`max_values`: None, `max_size`: Some(1893), added: 4368, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::OutboundMessages` (r:0 w:2) + /// Proof: `BridgeWestendMessages::OutboundMessages` (`max_values`: None, `max_size`: Some(65568), added: 68043, mode: `MaxEncodedLen`) + fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { + // Proof Size summary in bytes: + // Measured: `711` + // Estimated: `5358` + // Minimum execution time: 51_836_000 picoseconds. + Weight::from_parts(53_960_000, 0) + .saturating_add(Weight::from_parts(0, 5358)) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: `BridgeWestendMessages::PalletOperatingMode` (r:1 w:0) + /// Proof: `BridgeWestendMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendParachains::ImportedParaHeads` (r:1 w:0) + /// Proof: `BridgeWestendParachains::ImportedParaHeads` (`max_values`: Some(64), `max_size`: Some(196), added: 1186, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::OutboundLanes` (r:1 w:1) + /// Proof: `BridgeWestendMessages::OutboundLanes` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Proof: UNKNOWN KEY `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`) + /// Storage: `XcmOverBridgeHubWestend::LaneToBridge` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::LaneToBridge` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::Bridges` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::Bridges` (`max_values`: None, `max_size`: Some(1893), added: 4368, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::OutboundMessages` (r:0 w:2) + /// Proof: `BridgeWestendMessages::OutboundMessages` (`max_values`: None, `max_size`: Some(65568), added: 68043, mode: `MaxEncodedLen`) + fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { + // Proof Size summary in bytes: + // Measured: `711` + // Estimated: `6086` + // Minimum execution time: 56_606_000 picoseconds. + Weight::from_parts(58_528_000, 0) + .saturating_add(Weight::from_parts(0, 6086)) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(5)) + } + /// Storage: `BridgeWestendMessages::PalletOperatingMode` (r:1 w:0) + /// Proof: `BridgeWestendMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendParachains::ImportedParaHeads` (r:1 w:0) + /// Proof: `BridgeWestendParachains::ImportedParaHeads` (`max_values`: Some(64), `max_size`: Some(196), added: 1186, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::InboundLanes` (r:1 w:1) + /// Proof: `BridgeWestendMessages::InboundLanes` (`max_values`: None, `max_size`: Some(49180), added: 51655, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::LaneToBridge` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::LaneToBridge` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::Bridges` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::Bridges` (`max_values`: None, `max_size`: Some(1893), added: 4368, mode: `MaxEncodedLen`) + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:1) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: Some(1282), added: 1777, 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: `XcmpQueue::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `XcmpQueue::DeliveryFeeFactor` (`max_values`: None, `max_size`: Some(28), added: 2503, 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::OutboundXcmpMessages` (r:0 w:1) + /// Proof: `XcmpQueue::OutboundXcmpMessages` (`max_values`: None, `max_size`: Some(105506), added: 107981, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 16384]`. + /// The range of component `n` is `[1, 16384]`. + fn receive_single_n_bytes_message_proof_with_dispatch(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1071` + // Estimated: `52645` + // Minimum execution time: 85_179_000 picoseconds. + Weight::from_parts(91_600_892, 0) + .saturating_add(Weight::from_parts(0, 52645)) + // Standard Error: 11 + .saturating_add(Weight::from_parts(7_210, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(12)) + .saturating_add(T::DbWeight::get().writes(4)) + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_bridge_relayers.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_bridge_relayers.rs new file mode 100644 index 0000000000000..34a9f7fce0a2b --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_bridge_relayers.rs @@ -0,0 +1,133 @@ +// Copyright (C) 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 32.0.0 +//! DATE: 2024-08-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-696hpswk-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-rococo-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/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_bridge_relayers +// --chain=bridge-hub-rococo-dev TODO: FAIL-CI regenerate +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/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(102), added: 2577, 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: `306` + // Estimated: `3593` + // Minimum execution time: 53_924_000 picoseconds. + Weight::from_parts(54_736_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn claim_rewards_to() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. + Weight::from_parts(18_446_744_073_709_551_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `BridgeRelayers::RegisteredRelayers` (r:1 w:1) + /// Proof: `BridgeRelayers::RegisteredRelayers` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x1e8445dc201eeb8560e5579a5dd54655` (r:1 w:0) + /// Proof: UNKNOWN KEY `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: 28_608_000 picoseconds. + Weight::from_parts(29_081_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: 29_738_000 picoseconds. + Weight::from_parts(30_242_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: 33_174_000 picoseconds. + Weight::from_parts(33_992_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(102), added: 2577, mode: `MaxEncodedLen`) + fn register_relayer_reward() -> Weight { + // Proof Size summary in bytes: + // Measured: `76` + // Estimated: `3567` + // Minimum execution time: 7_950_000 picoseconds. + Weight::from_parts(8_123_000, 0) + .saturating_add(Weight::from_parts(0, 3567)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm_bridge.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm_bridge.rs new file mode 100644 index 0000000000000..76ebd021ce2df --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm_bridge.rs @@ -0,0 +1,110 @@ +// Copyright (C) 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` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-11-18, STEPS: `2`, REPEAT: `1`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `toaster1`, CPU: `AMD Ryzen Threadripper 7980X 64-Cores` +//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024 + +// Executed Command: +// ./target/release/frame-omni-bencher +// v1 +// benchmark +// pallet +// --runtime +// ./target/debug/wbuild/asset-hub-rococo-runtime/asset_hub_rococo_runtime.wasm +// --pallet +// pallet_xcm_bridge_hub +// --extrinsic +// * +// --steps +// 2 +// --repeat +// 1 +// --output +// ./remote-builds -- TODO: FAIL-CI new 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`. +pub struct WeightInfo(PhantomData); +impl pallet_xcm_bridge::WeightInfo for WeightInfo { + /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) + /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `XcmOverAssetHubWestend::Bridges` (r:1 w:1) + /// Proof: `XcmOverAssetHubWestend::Bridges` (`max_values`: None, `max_size`: Some(1922), added: 4397, mode: `MaxEncodedLen`) + /// Storage: `XcmOverAssetHubWestend::LaneToBridge` (r:1 w:1) + /// Proof: `XcmOverAssetHubWestend::LaneToBridge` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::InboundLanes` (r:1 w:1) + /// Proof: `BridgeWestendMessages::InboundLanes` (`max_values`: None, `max_size`: Some(49208), added: 51683, mode: `MaxEncodedLen`) + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: Some(1282), added: 1777, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::OutboundLanes` (r:1 w:1) + /// Proof: `BridgeWestendMessages::OutboundLanes` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + fn open_bridge() -> Weight { + // Proof Size summary in bytes: + // Measured: `214` + // Estimated: `52673` + // Minimum execution time: 40_171_000 picoseconds. + Weight::from_parts(40_171_000, 0) + .saturating_add(Weight::from_parts(0, 52673)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) + /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `XcmOverAssetHubWestend::Bridges` (r:1 w:1) + /// Proof: `XcmOverAssetHubWestend::Bridges` (`max_values`: None, `max_size`: Some(1922), added: 4397, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::InboundLanes` (r:1 w:1) + /// Proof: `BridgeWestendMessages::InboundLanes` (`max_values`: None, `max_size`: Some(49208), added: 51683, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::OutboundLanes` (r:1 w:1) + /// Proof: `BridgeWestendMessages::OutboundLanes` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `XcmOverAssetHubWestend::LaneToBridge` (r:0 w:1) + /// Proof: `XcmOverAssetHubWestend::LaneToBridge` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + fn close_bridge() -> Weight { + // Proof Size summary in bytes: + // Measured: `488` + // Estimated: `52673` + // Minimum execution time: 30_096_000 picoseconds. + Weight::from_parts(30_096_000, 0) + .saturating_add(Weight::from_parts(0, 52673)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) + /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `XcmOverAssetHubWestend::Bridges` (r:1 w:1) + /// Proof: `XcmOverAssetHubWestend::Bridges` (`max_values`: None, `max_size`: Some(1922), added: 4397, mode: `MaxEncodedLen`) + fn update_notification_receiver() -> Weight { + // Proof Size summary in bytes: + // Measured: `212` + // Estimated: `5387` + // Minimum execution time: 15_994_000 picoseconds. + Weight::from_parts(15_994_000, 0) + .saturating_add(Weight::from_parts(0, 5387)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm_bridge_router.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm_bridge_router_to_westend_over_asset_hub_westend.rs similarity index 98% rename from cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm_bridge_router.rs rename to cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm_bridge_router_to_westend_over_asset_hub_westend.rs index e025b3139323e..21d0e295602e0 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm_bridge_router.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm_bridge_router_to_westend_over_asset_hub_westend.rs @@ -50,6 +50,7 @@ impl pallet_xcm_bridge_router::WeightInfo for WeightInf /// Storage: `ToWestendXcmRouter::Bridges` (r:1 w:1) /// Proof: `ToWestendXcmRouter::Bridges` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) fn update_bridge_status() -> Weight { + // TODO: FAIL-CI new weights // Proof Size summary in bytes: // Measured: `109` // Estimated: `3530` diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm_bridge_router_to_westend_over_bridge_hub.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm_bridge_router_to_westend_over_bridge_hub.rs new file mode 100644 index 0000000000000..bf1a6fcd4eb70 --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/pallet_xcm_bridge_router_to_westend_over_bridge_hub.rs @@ -0,0 +1,64 @@ +// Copyright (C) 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 32.0.0 +//! DATE: 2024-11-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-wiukf8gn-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-rococo-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/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_xcm_bridge_hub_router +// --chain=asset-hub-rococo-dev +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/assets/asset-hub-rococo/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_router::WeightInfo for WeightInfo { + /// Storage: `ToWestendXcmRouter::Bridges` (r:1 w:1) + /// Proof: `ToWestendXcmRouter::Bridges` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + fn update_bridge_status() -> Weight { + // TODO: FAIL-CI fresh weights + // Proof Size summary in bytes: + // Measured: `109` + // Estimated: `3530` + // Minimum execution time: 12_193_000 picoseconds. + Weight::from_parts(12_658_000, 0) + .saturating_add(Weight::from_parts(0, 3530)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/xcm/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/xcm/mod.rs index 3dc3e82a62ff9..e55ccdd6844e6 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/xcm/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/xcm/mod.rs @@ -19,6 +19,7 @@ mod pallet_xcm_benchmarks_generic; use crate::{xcm_config::MaxAssetsIntoHolding, Runtime}; use alloc::vec::Vec; +use codec::Encode; use frame_support::weights::Weight; use pallet_xcm_benchmarks_fungible::WeightInfo as XcmFungibleWeight; use pallet_xcm_benchmarks_generic::WeightInfo as XcmGeneric; @@ -238,8 +239,9 @@ impl XcmWeightInfo for AssetHubRococoXcmWeight { fn universal_origin(_: &Junction) -> Weight { XcmGeneric::::universal_origin() } - 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(_: &Asset, _: &Location) -> Weight { Weight::MAX diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/xcm/pallet_xcm_benchmarks_generic.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/xcm/pallet_xcm_benchmarks_generic.rs index 2b881606fe306..c19c86f18a3fb 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/xcm/pallet_xcm_benchmarks_generic.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/weights/xcm/pallet_xcm_benchmarks_generic.rs @@ -345,6 +345,30 @@ impl WeightInfo { Weight::from_parts(4_981_000, 1489) .saturating_add(T::DbWeight::get().reads(1)) } + /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) + /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `XcmOverAssetHubWestend::Bridges` (r:1 w:0) + /// Proof: `XcmOverAssetHubWestend::Bridges` (`max_values`: None, `max_size`: Some(1922), added: 4397, mode: `MaxEncodedLen`) + /// Storage: `PolkadotXcm::SupportedVersion` (r:2 w:0) + /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `BridgeWestendMessages::PalletOperatingMode` (r:1 w:0) + /// Proof: `BridgeWestendMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::OutboundLanes` (r:1 w:1) + /// Proof: `BridgeWestendMessages::OutboundLanes` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::OutboundMessages` (r:0 w:1) + /// Proof: `BridgeWestendMessages::OutboundMessages` (`max_values`: None, `max_size`: Some(65596), added: 68071, mode: `MaxEncodedLen`) + /// The range of component `x` is `[1, 1000]`. + pub fn export_message(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `583` + // Estimated: `6523` + // Minimum execution time: 54_537_000 picoseconds. + Weight::from_parts(56_626_935, 6523) + // Standard Error: 172 + .saturating_add(Weight::from_parts(54_409, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(6)) + .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/assets/asset-hub-rococo/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs index 6f4b834e3529e..12d1b48d71e93 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/src/xcm_config.rs @@ -16,8 +16,9 @@ use super::{ AccountId, AllPalletsWithSystem, Assets, Balance, Balances, BaseDeliveryFee, CollatorSelection, FeeAssetId, ForeignAssets, ParachainInfo, ParachainSystem, PolkadotXcm, PoolAssets, Runtime, - RuntimeCall, RuntimeEvent, RuntimeHoldReason, RuntimeOrigin, ToWestendXcmRouter, - TransactionByteFee, Uniques, WeightToFee, XcmpQueue, + RuntimeCall, RuntimeEvent, RuntimeHoldReason, RuntimeOrigin, + ToWestendOverAssetHubWestendXcmRouter, ToWestendXcmRouter, TransactionByteFee, Uniques, + WeightToFee, XcmOverAssetHubWestend, XcmpQueue, }; use assets_common::{ matching::{FromNetwork, FromSiblingParachain, IsForeignConcreteAsset, ParentLocation}, @@ -399,7 +400,10 @@ impl xcm_executor::Config for XcmConfig { WaivedLocations, SendXcmFeeToAccount, >; - type MessageExporter = (); + type MessageExporter = ( + // AH's permissionless lanes support exporting to Westend. + XcmOverAssetHubWestend, + ); type UniversalAliases = (bridging::to_westend::UniversalAliases, bridging::to_ethereum::UniversalAliases); type CallDispatcher = RuntimeCall; @@ -421,7 +425,7 @@ pub type PriceForParentDelivery = ExponentialPrice; /// For routing XCM messages which do not cross local consensus boundary. -type LocalXcmRouter = ( +pub(crate) type LocalXcmRouter = ( // Two routers - use UMP to communicate with the relay chain: cumulus_primitives_utility::ParentAsUmp, // ..and XCMP to communicate with the sibling chains. @@ -432,8 +436,15 @@ type LocalXcmRouter = ( /// queues. pub type XcmRouter = WithUniqueTopic<( LocalXcmRouter, - // Router which wraps and sends xcm to BridgeHub to be delivered to the Westend - // GlobalConsensus + // Router that exports messages to be delivered to the Westend GlobalConsensus, + // when a permissionless lane is created between the origin and destination. + // + // Note: `ToWestendOverAssetHubWestendXcmRouter` must come before `ToWestendXcmRouter` + // because it checks if the lane is created dynamically, whereas `ToWestendXcmRouter` has a + // static configuration. + ToWestendOverAssetHubWestendXcmRouter, + // Router which wraps (`ExportMessage`) and sends xcm to BridgeHub to be delivered to the + // Westend GlobalConsensus ToWestendXcmRouter, // Router which wraps and sends xcm to BridgeHub to be delivered to the Ethereum // GlobalConsensus @@ -507,10 +518,12 @@ pub mod bridging { // common/shared parameters parameter_types! { + /// (for AH -> -> BH -> BH -> AH route) + /// /// Base price of every byte of the Rococo -> Westend message. Can be adjusted via /// governance `set_storage` call. /// - /// Default value is our estimation of the: + /// The default value is our estimation of the: /// /// 1) an approximate cost of XCM execution (`ExportMessage` and surroundings) at Rococo bridge hub; /// @@ -522,6 +535,26 @@ pub mod bridging { bp_bridge_hub_rococo::BridgeHubRococoBaseXcmFeeInRocs::get() .saturating_add(bp_bridge_hub_westend::BridgeHubWestendBaseDeliveryFeeInWnds::get()) .saturating_add(bp_bridge_hub_rococo::BridgeHubRococoBaseConfirmationFeeInRocs::get()); + + /// (for direct AH -> AH route) + /// + /// Base price of every byte of the Rococo -> Westend message. Can be adjusted via + /// governance `set_storage` call. + /// + /// The default value is our estimation of the: + /// + /// 1) the approximate cost of Rococo -> Westend message delivery transaction on Westend Asset Hub, + /// converted into WNDs using 1:1 conversion rate; + /// + /// 2) the approximate cost of Rococo -> Westend message confirmation transaction on Rococo Asset Hub. + /// + /// Note: We do not account for `ExportMessage`, because we are doing direct `ExportXcm`, + /// which should be already accounted for benchmarked extrinsic cost. + pub storage ToWestendOverAssetHubWestendXcmRouterBaseFee: Balance = DefaultToWestendOverAssetHubWestendXcmRouterBaseFee::get(); + pub const DefaultToWestendOverAssetHubWestendXcmRouterBaseFee: Balance = + bp_asset_hub_westend::AssetHubWestendBaseDeliveryFeeInWnds::get() + .saturating_add(bp_asset_hub_rococo::AssetHubRococoBaseConfirmationFeeInRocs::get()); + /// Price of every byte of the Rococo -> Westend message. Can be adjusted via /// governance `set_storage` call. pub storage XcmBridgeHubRouterByteFee: Balance = TransactionByteFee::get(); @@ -551,6 +584,12 @@ pub mod bridging { PalletInstance(bp_bridge_hub_rococo::WITH_BRIDGE_ROCOCO_TO_WESTEND_MESSAGES_PALLET_INDEX) ] ); + pub LocalBridge: Location = Location::new( + 0, + [ + PalletInstance(bp_asset_hub_rococo::WITH_BRIDGE_ROCOCO_TO_WESTEND_MESSAGES_PALLET_INDEX) + ] + ); pub const WestendNetwork: NetworkId = NetworkId::ByGenesis(WESTEND_GENESIS_HASH); pub const EthereumNetwork: NetworkId = NetworkId::Ethereum { chain_id: 11155111 }; @@ -582,7 +621,10 @@ pub mod bridging { /// Universal aliases pub UniversalAliases: BTreeSet<(Location, Junction)> = BTreeSet::from_iter( alloc::vec![ - (SiblingBridgeHubWithBridgeHubWestendInstance::get(), GlobalConsensus(WestendNetwork::get())) + // The bridge over BridgeHubs (legacy). + (SiblingBridgeHubWithBridgeHubWestendInstance::get(), GlobalConsensus(WestendNetwork::get())), + // The direct bridge over AssetHubs. + (LocalBridge::get(), GlobalConsensus(WestendNetwork::get())) ] ); } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs index 9598fbe6ddb2e..7fd3a6d49e2ce 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-rococo/tests/tests.rs @@ -18,24 +18,27 @@ //! Tests for the Rococo Assets Hub chain. use asset_hub_rococo_runtime::{ - xcm_config, + bridge_to_westend_config, xcm_config::{ - bridging, CheckingAccount, GovernanceLocation, LocationToAccountId, StakingPot, + self, bridging, CheckingAccount, GovernanceLocation, LocationToAccountId, StakingPot, TokenLocation, TrustBackedAssetsPalletLocation, XcmConfig, }, AllPalletsWithoutSystem, AssetConversion, AssetDeposit, Assets, Balances, Block, - CollatorSelection, ExistentialDeposit, ForeignAssets, ForeignAssetsInstance, - MetadataDepositBase, MetadataDepositPerByte, ParachainSystem, Runtime, RuntimeCall, - RuntimeEvent, RuntimeOrigin, SessionKeys, ToWestendXcmRouterInstance, - TrustBackedAssetsInstance, XcmpQueue, + BridgeRejectObsoleteHeadersAndMessages, CollatorSelection, ExistentialDeposit, ForeignAssets, + ForeignAssetsInstance, MetadataDepositBase, MetadataDepositPerByte, ParachainSystem, Runtime, + RuntimeCall, RuntimeEvent, RuntimeOrigin, SessionKeys, TransactionPayment, + TrustBackedAssetsInstance, TxExtension, UncheckedExtrinsic, XcmpQueue, }; use asset_test_utils::{ test_cases_over_bridge::TestBridgingConfig, CollatorSessionKey, CollatorSessionKeys, ExtBuilder, GovernanceOrigin, SlotDurations, }; +use bp_asset_hub_rococo::Signature; use codec::{Decode, Encode}; use frame_support::{ - assert_noop, assert_ok, parameter_types, + assert_noop, assert_ok, + dispatch::GetDispatchInfo, + parameter_types, traits::{ fungible::{Inspect, Mutate}, fungibles::{ @@ -48,7 +51,11 @@ use hex_literal::hex; use parachains_common::{AccountId, AssetIdForTrustBackedAssets, AuraId, Balance}; use sp_consensus_aura::SlotDuration; use sp_core::crypto::Ss58Codec; -use sp_runtime::traits::MaybeEquivalence; +use sp_keyring::Sr25519Keyring::Alice; +use sp_runtime::{ + generic::{Era, SignedPayload}, + traits::MaybeEquivalence, +}; use std::convert::Into; use testnet_parachains_constants::rococo::{consensus::*, currency::UNITS, fee::WeightToFee}; use xcm::latest::{ @@ -83,6 +90,42 @@ fn collator_session_keys() -> CollatorSessionKeys { CollatorSessionKeys::default().add(collator_session_key(ALICE)) } +fn construct_extrinsic( + sender: sp_keyring::Sr25519Keyring, + call: RuntimeCall, +) -> UncheckedExtrinsic { + let account_id = sp_runtime::AccountId32::from(sender.public()); + let tx_ext: TxExtension = ( + frame_system::AuthorizeCall::::new(), + 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( + frame_system::Pallet::::account(&account_id).nonce, + ), + frame_system::CheckWeight::::new(), + pallet_asset_conversion_tx_payment::ChargeAssetTxPayment::::from( + Balance::MIN, + None, + ), + frame_metadata_hash_extension::CheckMetadataHash::new(false), + BridgeRejectObsoleteHeadersAndMessages::default(), + (bridge_to_westend_config::OnAssetHubRococoRefundAssetHubWestendMessages::default(),), + ) + .into(); + let payload = SignedPayload::new(call.clone(), tx_ext.clone()).unwrap(); + let signature = payload.using_encoded(|e| sender.sign(e)); + UncheckedExtrinsic::new_signed(call, account_id.into(), Signature::Sr25519(signature), tx_ext) +} + +fn construct_and_estimate_extrinsic_fee(call: RuntimeCall) -> Balance { + let info = call.get_dispatch_info(); + let xt = construct_extrinsic(Alice, call); + TransactionPayment::compute_fee(xt.encoded_size() as _, &info, 0) +} + fn slot_durations() -> SlotDurations { SlotDurations { relay: SlotDuration::from_millis(RELAY_CHAIN_SLOT_DURATION_MILLIS.into()), @@ -737,10 +780,13 @@ fn limited_reserve_transfer_assets_for_native_asset_over_bridge_works( mod asset_hub_rococo_tests { use super::*; - use asset_hub_rococo_runtime::PolkadotXcm; - use xcm::latest::WESTEND_GENESIS_HASH; + use asset_hub_rococo_runtime::{ + bridge_to_westend_config::WestendGlobalConsensusNetwork, PolkadotXcm, + ToWestendXcmRouterInstance, + }; use xcm_executor::traits::ConvertLocation; + /// The bridge over BridgeHubs: AHW <-> BHW <-> BHR <-> AHR fn bridging_to_asset_hub_westend() -> TestBridgingConfig { let _ = PolkadotXcm::force_xcm_version( RuntimeOrigin::root(), @@ -756,6 +802,24 @@ mod asset_hub_rococo_tests { } } + /// The direct bridge over AssetHubs: AHW <-> AHR + fn direct_bridging_to_asset_hub_westend() -> TestBridgingConfig { + let _ = PolkadotXcm::force_xcm_version( + RuntimeOrigin::root(), + Box::new(bridging::to_westend::AssetHubWestend::get()), + XCM_VERSION, + ) + .expect("version saved!"); + TestBridgingConfig { + bridged_network: bridging::to_westend::WestendNetwork::get(), + // Local AH para_id. + local_bridge_hub_para_id: bp_asset_hub_rococo::ASSET_HUB_ROCOCO_PARACHAIN_ID, + // The bridge is deployed `Here` on the AH chain. + local_bridge_hub_location: Location::here(), + bridged_target_location: bridging::to_westend::AssetHubWestend::get(), + } + } + #[test] fn limited_reserve_transfer_assets_for_native_asset_to_asset_hub_westend_works() { limited_reserve_transfer_assets_for_native_asset_over_bridge_works( @@ -765,77 +829,97 @@ mod asset_hub_rococo_tests { #[test] fn receive_reserve_asset_deposited_wnd_from_asset_hub_westend_fees_paid_by_pool_swap_works() { - const BLOCK_AUTHOR_ACCOUNT: [u8; 32] = [13; 32]; - let block_author_account = AccountId::from(BLOCK_AUTHOR_ACCOUNT); - let staking_pot = StakingPot::get(); + fn test_with( + bridging_cfg: impl Fn() -> TestBridgingConfig, + bridge_instance: InteriorLocation, + ) { + const BLOCK_AUTHOR_ACCOUNT: [u8; 32] = [13; 32]; + let block_author_account = AccountId::from(BLOCK_AUTHOR_ACCOUNT); + let staking_pot = StakingPot::get(); + + let foreign_asset_id_location = + Location::new(2, [GlobalConsensus(WestendGlobalConsensusNetwork::get())]); + let foreign_asset_id_minimum_balance = 1_000_000_000; + // sovereign account as foreign asset owner (can be whoever for this scenario) + let foreign_asset_owner = + LocationToAccountId::convert_location(&Location::parent()).unwrap(); + let foreign_asset_create_params = ( + foreign_asset_owner, + foreign_asset_id_location.clone(), + foreign_asset_id_minimum_balance, + ); - let foreign_asset_id_location = Location::new( - 2, - [Junction::GlobalConsensus(NetworkId::ByGenesis(WESTEND_GENESIS_HASH))], + asset_test_utils::test_cases_over_bridge::receive_reserve_asset_deposited_from_different_consensus_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ForeignAssetsInstance, + >( + collator_session_keys().add(collator_session_key(BLOCK_AUTHOR_ACCOUNT)), + ExistentialDeposit::get(), + AccountId::from([73; 32]), + block_author_account, + // receiving WNDs + foreign_asset_create_params.clone(), + 1000000000000, + || { + // setup pool for paying fees to touch `SwapFirstAssetTrader` + asset_test_utils::test_cases::setup_pool_for_paying_fees_with_foreign_assets::(ExistentialDeposit::get(), foreign_asset_create_params); + // staking pot account for collecting local native fees from `BuyExecution` + let _ = Balances::force_set_balance(RuntimeOrigin::root(), StakingPot::get().into(), ExistentialDeposit::get()); + // prepare bridge configuration + bridging_cfg() + }, + ( + bridge_instance, + GlobalConsensus(WestendGlobalConsensusNetwork::get()), + [Parachain(1000)].into() + ), + || { + // check staking pot for ED + assert_eq!(Balances::free_balance(&staking_pot), ExistentialDeposit::get()); + // check now foreign asset for staking pot + assert_eq!( + ForeignAssets::balance( + foreign_asset_id_location.clone().into(), + &staking_pot + ), + 0 + ); + }, + || { + // `SwapFirstAssetTrader` - staking pot receives xcm fees in ROCs + assert!( + Balances::free_balance(&staking_pot) > ExistentialDeposit::get() + ); + // staking pot receives no foreign assets + assert_eq!( + ForeignAssets::balance( + foreign_asset_id_location.clone().into(), + &staking_pot + ), + 0 + ); + } + ) + } + + // The bridge with BHs is working. + test_with( + bridging_to_asset_hub_westend, + [PalletInstance( + bp_bridge_hub_rococo::WITH_BRIDGE_ROCOCO_TO_WESTEND_MESSAGES_PALLET_INDEX, + )] + .into(), ); - let foreign_asset_id_minimum_balance = 1_000_000_000; - // sovereign account as foreign asset owner (can be whoever for this scenario) - let foreign_asset_owner = - LocationToAccountId::convert_location(&Location::parent()).unwrap(); - let foreign_asset_create_params = ( - foreign_asset_owner, - foreign_asset_id_location.clone(), - foreign_asset_id_minimum_balance, + // The bridge with direct AHs is working. + test_with( + direct_bridging_to_asset_hub_westend, + [PalletInstance( + bp_asset_hub_rococo::WITH_BRIDGE_ROCOCO_TO_WESTEND_MESSAGES_PALLET_INDEX, + )] + .into(), ); - - asset_test_utils::test_cases_over_bridge::receive_reserve_asset_deposited_from_different_consensus_works::< - Runtime, - AllPalletsWithoutSystem, - XcmConfig, - ForeignAssetsInstance, - >( - collator_session_keys().add(collator_session_key(BLOCK_AUTHOR_ACCOUNT)), - ExistentialDeposit::get(), - AccountId::from([73; 32]), - block_author_account, - // receiving WNDs - foreign_asset_create_params.clone(), - 1000000000000, - || { - // setup pool for paying fees to touch `SwapFirstAssetTrader` - asset_test_utils::test_cases::setup_pool_for_paying_fees_with_foreign_assets::(ExistentialDeposit::get(), foreign_asset_create_params); - // staking pot account for collecting local native fees from `BuyExecution` - let _ = Balances::force_set_balance(RuntimeOrigin::root(), StakingPot::get().into(), ExistentialDeposit::get()); - // prepare bridge configuration - bridging_to_asset_hub_westend() - }, - ( - [PalletInstance(bp_bridge_hub_rococo::WITH_BRIDGE_ROCOCO_TO_WESTEND_MESSAGES_PALLET_INDEX)].into(), - GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)), - [Parachain(1000)].into() - ), - || { - // check staking pot for ED - assert_eq!(Balances::free_balance(&staking_pot), ExistentialDeposit::get()); - // check now foreign asset for staking pot - assert_eq!( - ForeignAssets::balance( - foreign_asset_id_location.clone().into(), - &staking_pot - ), - 0 - ); - }, - || { - // `SwapFirstAssetTrader` - staking pot receives xcm fees in ROCs - assert!( - Balances::free_balance(&staking_pot) > ExistentialDeposit::get() - ); - // staking pot receives no foreign assets - assert_eq!( - ForeignAssets::balance( - foreign_asset_id_location.clone().into(), - &staking_pot - ), - 0 - ); - } - ) } #[test] @@ -845,10 +929,8 @@ mod asset_hub_rococo_tests { let block_author_account = AccountId::from(BLOCK_AUTHOR_ACCOUNT); let staking_pot = StakingPot::get(); - let foreign_asset_id_location = Location::new( - 2, - [Junction::GlobalConsensus(NetworkId::ByGenesis(WESTEND_GENESIS_HASH))], - ); + let foreign_asset_id_location = + Location::new(2, [Junction::GlobalConsensus(WestendGlobalConsensusNetwork::get())]); let foreign_asset_id_minimum_balance = 1_000_000_000; // sovereign account as foreign asset owner (can be whoever for this scenario) let foreign_asset_owner = @@ -878,7 +960,7 @@ mod asset_hub_rococo_tests { }, ( [PalletInstance(bp_bridge_hub_rococo::WITH_BRIDGE_ROCOCO_TO_WESTEND_MESSAGES_PALLET_INDEX)].into(), - GlobalConsensus(ByGenesis(WESTEND_GENESIS_HASH)), + GlobalConsensus(WestendGlobalConsensusNetwork::get()), [Parachain(1000)].into() ), || { @@ -1337,3 +1419,404 @@ fn xcm_payment_api_works() { WeightToFee, >(ExistentialDeposit::get(), WESTEND_GENESIS_HASH); } + +mod bridge_to_westend_tests { + use super::{ + collator_session_keys, construct_and_estimate_extrinsic_fee, slot_durations, AccountId, + ExtBuilder, Governance, RuntimeHelper, + }; + use asset_hub_rococo_runtime::{ + bridge_common_config::DeliveryRewardInBalance, + bridge_to_westend_config::{ + AssetHubWestendLocation, WestendGlobalConsensusNetwork, + WithAssetHubWestendMessagesInstance, XcmOverAssetHubWestendInstance, + }, + xcm_config::{bridging, LocationToAccountId, RelayNetwork, TokenLocation, XcmConfig}, + AllPalletsWithoutSystem, ExistentialDeposit, ParachainSystem, PolkadotXcm, Runtime, + RuntimeEvent, RuntimeOrigin, + }; + use bp_runtime::RangeInclusiveExt; + use bridge_hub_test_utils::{mock_open_hrmp_channel, test_cases}; + use codec::Decode; + use cumulus_primitives_core::UpwardMessageSender; + use frame_support::traits::{ConstU8, ProcessMessageError}; + use sp_runtime::Perbill; + use testnet_parachains_constants::westend::fee::WeightToFee; + use xcm::latest::prelude::*; + use xcm_builder::{CreateMatcher, MatchXcm}; + + // Random para id of sibling chain used in tests. + pub const SIBLING_PARACHAIN_ID: u32 = 2053; + // Random para id of bridged chain from different global consensus used in tests. + pub const BRIDGED_LOCATION_PARACHAIN_ID: u32 = 1075; + const RUNTIME_PARA_ID: u32 = bp_asset_hub_rococo::ASSET_HUB_ROCOCO_PARACHAIN_ID; + + frame_support::parameter_types! { + pub SiblingParachainLocation: Location = Location::new(1, [Parachain(SIBLING_PARACHAIN_ID)]); + pub BridgedUniversalLocation: InteriorLocation = [GlobalConsensus(WestendGlobalConsensusNetwork::get()), Parachain(BRIDGED_LOCATION_PARACHAIN_ID)].into(); + } + + #[test] + fn change_bridge_messages_pallet_mode_by_governance_works() { + bridge_hub_test_utils::test_cases::change_bridge_messages_pallet_mode_by_governance_works::< + Runtime, + WithAssetHubWestendMessagesInstance, + >(collator_session_keys(), RUNTIME_PARA_ID, Governance::get()) + } + + #[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(), + RUNTIME_PARA_ID, + Governance::get(), + || (DeliveryRewardInBalance::key().to_vec(), DeliveryRewardInBalance::get()), + |old_value| old_value.checked_mul(2).unwrap(), + ) + } + + #[test] + fn handle_export_message_from_sibling_parachain_and_add_to_outbound_queue_works() { + // for Westend + bridge_hub_test_utils::test_cases::handle_export_message_from_system_parachain_to_outbound_queue_works::< + Runtime, + XcmConfig, + WithAssetHubWestendMessagesInstance, + >( + collator_session_keys(), + RUNTIME_PARA_ID, + SIBLING_PARACHAIN_ID, + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::BridgeWestendMessages(event)) => Some(event), + _ => None, + } + }), + || ExportMessage { network: WestendGlobalConsensusNetwork::get(), destination: [Parachain(BRIDGED_LOCATION_PARACHAIN_ID)].into(), xcm: Xcm(vec![]) }, + Some((TokenLocation::get(), ExistentialDeposit::get()).into()), + // value should be >= than value generated by `can_calculate_weight_for_paid_export_message_with_reserve_transfer` + Some(( + TokenLocation::get(), + bp_asset_hub_rococo::AssetHubRococoBaseXcmFeeInRocs::get() + + bridging::DefaultToWestendOverAssetHubWestendXcmRouterBaseFee::get() + ).into()), + || { + PolkadotXcm::force_xcm_version(RuntimeOrigin::root(), Box::new(AssetHubWestendLocation::get()), XCM_VERSION).expect("version saved!"); + + // we need to create lane between sibling parachain and remote destination + bridge_hub_test_utils::ensure_opened_xcm_bridge::< + Runtime, + XcmOverAssetHubWestendInstance, + LocationToAccountId, + TokenLocation, + >( + SiblingParachainLocation::get(), + BridgedUniversalLocation::get(), + true, + |locations, fee| { + bridge_hub_test_utils::open_xcm_bridge_with_extrinsic::< + Runtime, + XcmOverAssetHubWestendInstance + >((locations.bridge_origin_relative_location().clone(), OriginKind::Xcm), locations.bridge_destination_universal_location().clone(), fee) + } + ).1 + }, + ) + } + + #[test] + fn message_dispatch_routing_works() { + // from Westend + bridge_hub_test_utils::test_cases::message_dispatch_routing_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + WithAssetHubWestendMessagesInstance, + RelayNetwork, + WestendGlobalConsensusNetwork, + ConstU8<2>, + >( + collator_session_keys(), + slot_durations(), + RUNTIME_PARA_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, + } + }), + || ::ensure_successful_delivery(), + ) + } + + #[test] + fn open_and_close_bridge_for_sibling_parachain_works() { + bridge_hub_test_utils::test_cases::open_and_close_xcm_bridge_works::< + Runtime, + XcmOverAssetHubWestendInstance, + LocationToAccountId, + TokenLocation, + >( + collator_session_keys(), + RUNTIME_PARA_ID, + SiblingParachainLocation::get(), + BridgedUniversalLocation::get(), + (SiblingParachainLocation::get(), OriginKind::Xcm), + true, + ) + } + + #[test] + fn open_and_close_bridge_for_relay_works() { + bridge_hub_test_utils::test_cases::open_and_close_xcm_bridge_works::< + Runtime, + XcmOverAssetHubWestendInstance, + LocationToAccountId, + TokenLocation, + >( + collator_session_keys(), + RUNTIME_PARA_ID, + Location::parent(), + BridgedUniversalLocation::get(), + (Location::parent(), OriginKind::Xcm), + false, + ) + } + + #[test] + fn open_and_close_bridge_for_local_works() { + bridge_hub_test_utils::test_cases::open_and_close_xcm_bridge_works::< + Runtime, + XcmOverAssetHubWestendInstance, + LocationToAccountId, + TokenLocation, + >( + collator_session_keys(), + RUNTIME_PARA_ID, + // The source is `here` as the local chain, e.g., AssetHub itself can open its lanes. + Location::here(), + BridgedUniversalLocation::get(), + // This should represent `RuntimeOrigin::root()` which represents `Location::here()` + // for `OpenBridgeOrigin` + (Location::parent(), OriginKind::Superuser), + false, + ) + } + + #[test] + fn westend_xcm_routing_works() { + let runtime_para_id = 1000; + ExtBuilder::::default() + .with_collators(collator_session_keys().collators()) + .with_session_keys(collator_session_keys().session_keys()) + .with_para_id(runtime_para_id.into()) + .build() + .execute_with(|| { + frame_support::__private::sp_tracing::try_init_simple(); + let sibling_bridge_hub_para_id = bridging::SiblingBridgeHubParaId::get(); + let bridged_destination = bridging::to_westend::AssetHubWestend::get(); + let bridged_universal_destination = bridged_destination.interior().clone(); + + // Common setup + frame_support::assert_ok!(PolkadotXcm::force_xcm_version( + RuntimeOrigin::root(), + Box::new(bridging::to_westend::AssetHubWestend::get()), + XCM_VERSION, + )); + + // Setup for `ExportMessage` to the `BridgeHub` + let mut alice = [0u8; 32]; + alice[0] = 1; + let included_head = RuntimeHelper::run_to_block(2, AccountId::from(alice)); + mock_open_hrmp_channel::( + runtime_para_id.into(), + sibling_bridge_hub_para_id.into(), + included_head, + &alice, + &slot_durations(), + ); + frame_support::assert_ok!(PolkadotXcm::force_xcm_version( + RuntimeOrigin::root(), + Box::new(bridging::SiblingBridgeHub::get()), + XCM_VERSION, + )); + + // check no bridge/lane exists + assert_eq!( + 0, + pallet_bridge_messages::OutboundLanes::< + Runtime, + WithAssetHubWestendMessagesInstance, + >::iter() + .count() + ); + + // send to the `bridged_destination` + frame_support::assert_ok!(PolkadotXcm::send_xcm( + Here, + bridged_destination.clone(), + Xcm::<()>::default() + )); + + // check HRMP message contains `ExportMessage`. + assert!(asset_test_utils::RuntimeHelper::< + cumulus_pallet_xcmp_queue::Pallet, + AllPalletsWithoutSystem, + >::take_xcm(sibling_bridge_hub_para_id.into()) + .map(|m| { + let mut m: Xcm<()> = m.try_into().expect("valid XCM version"); + m.0.matcher() + .skip_inst_while(|inst| !matches!(inst, ExportMessage { .. })) + .expect("no instruction ExportMessage?") + .match_next_inst(|instr| match instr { + ExportMessage { ref network, .. } => { + assert_eq!( + network, + &bridged_destination + .interior + .global_consensus() + .expect("valid NetworkId") + ); + Ok(()) + }, + _ => Err(ProcessMessageError::BadFormat), + }) + .is_ok() + }) + .unwrap_or(false)); + + // open permissionless lane between this AH and bridged AH + let (_, lane_id) = bridge_hub_test_utils::ensure_opened_xcm_bridge::< + Runtime, + XcmOverAssetHubWestendInstance, + LocationToAccountId, + TokenLocation, + >( + Here.into(), + bridged_universal_destination, + false, + |locations, maybe_paid_execution| { + bridge_hub_test_utils::open_xcm_bridge_with_extrinsic::< + Runtime, + XcmOverAssetHubWestendInstance, + >( + // This should represent `RuntimeOrigin::root()` which represents + // `Location::here()` for `OpenBridgeOrigin` + (Location::parent(), OriginKind::Superuser), + locations.bridge_destination_universal_location().clone(), + maybe_paid_execution, + ) + }, + ); + // lane created + assert_eq!( + 1, + pallet_bridge_messages::OutboundLanes::< + Runtime, + WithAssetHubWestendMessagesInstance, + >::iter() + .count() + ); + + // send to the `bridged_destination` again + frame_support::assert_ok!(PolkadotXcm::send_xcm( + Here, + bridged_destination.clone(), + Xcm::<()>::default() + )); + + // messages pallet holds outbound message for expected lane_id + assert_eq!( + 1, + pallet_bridge_messages::OutboundLanes::< + Runtime, + WithAssetHubWestendMessagesInstance, + >::get(lane_id) + .map(|d| d.queued_messages().saturating_len()) + .unwrap_or(0) + ); + + // no hrmp message was fired + assert!(asset_test_utils::RuntimeHelper::< + cumulus_pallet_xcmp_queue::Pallet, + AllPalletsWithoutSystem, + >::take_xcm(sibling_bridge_hub_para_id.into()) + .is_none()); + }); + } + + #[test] + pub fn can_calculate_weight_for_paid_export_message_with_reserve_transfer() { + bridge_hub_test_utils::check_sane_fees_values( + "bp_asset_hub_rococo::AssetHubRococoBaseXcmFeeInRocs", + bp_asset_hub_rococo::AssetHubRococoBaseXcmFeeInRocs::get(), + || { + test_cases::can_calculate_weight_for_paid_export_message_with_reserve_transfer::< + Runtime, + XcmConfig, + WeightToFee, + >() + }, + Perbill::from_percent(33), + Some(-33), + &format!( + "Estimate fee for `ExportMessage` for runtime: {:?}", + ::Version::get() + ), + ) + } + + #[test] + fn can_calculate_fee_for_standalone_message_delivery_transaction() { + bridge_hub_test_utils::check_sane_fees_values( + "bp_asset_hub_rococo::AssetHubRococoBaseDeliveryFeeInRocs", + bp_asset_hub_rococo::AssetHubRococoBaseDeliveryFeeInRocs::get(), + || { + test_cases::can_calculate_fee_for_standalone_message_delivery_transaction( + collator_session_keys(), + 1000, + construct_and_estimate_extrinsic_fee, + ) + }, + Perbill::from_percent(25), + Some(-25), + &format!( + "Estimate fee for `single message delivery` for runtime: {:?}", + ::Version::get() + ), + ) + } + + #[test] + fn can_calculate_fee_for_standalone_message_confirmation_transaction() { + bridge_hub_test_utils::check_sane_fees_values( + "bp_asset_hub_rococo::AssetHubRococoBaseConfirmationFeeInRocs", + bp_asset_hub_rococo::AssetHubRococoBaseConfirmationFeeInRocs::get(), + || { + test_cases::can_calculate_fee_for_standalone_message_confirmation_transaction( + collator_session_keys(), + 1000, + construct_and_estimate_extrinsic_fee, + ) + }, + Perbill::from_percent(25), + Some(-25), + &format!( + "Estimate fee for `single message confirmation` for runtime: {:?}", + ::Version::get() + ), + ) + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml index 8cc0fb46f371c..4d27d4672d1d9 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/Cargo.toml @@ -127,6 +127,15 @@ bp-asset-hub-rococo = { workspace = true } bp-asset-hub-westend = { workspace = true } bp-bridge-hub-rococo = { workspace = true } bp-bridge-hub-westend = { workspace = true } +bp-header-chain = { workspace = true } +bp-messages = { workspace = true } +bp-relayers = { workspace = true } +bp-runtime = { workspace = true } +bridge-hub-common = { workspace = true } +bridge-runtime-common = { workspace = true } +pallet-bridge-messages = { workspace = true } +pallet-bridge-relayers = { workspace = true } +pallet-xcm-bridge = { workspace = true } pallet-xcm-bridge-router = { workspace = true } snowbridge-outbound-queue-primitives = { workspace = true } snowbridge-pallet-system-frontend = { workspace = true } @@ -136,6 +145,9 @@ snowbridge-runtime-common = { workspace = true } alloy-core = { workspace = true, features = ["sol-types"] } asset-test-utils = { workspace = true, default-features = true } bp-xcm-bridge = { workspace = true } +bridge-hub-test-utils = { workspace = true, default-features = true } +bridge-runtime-common = { features = ["integrity-test"], workspace = true } +pallet-bridge-relayers = { features = ["integrity-test"], workspace = true } pallet-revive-fixtures = { workspace = true, default-features = true } parachains-runtimes-test-utils = { workspace = true, default-features = true } @@ -146,6 +158,8 @@ substrate-wasm-builder = { optional = true, workspace = true, default-features = default = ["std"] runtime-benchmarks = [ "assets-common/runtime-benchmarks", + "bridge-hub-common/runtime-benchmarks", + "bridge-runtime-common/runtime-benchmarks", "cumulus-pallet-parachain-system/runtime-benchmarks", "cumulus-pallet-session-benchmarking/runtime-benchmarks", "cumulus-pallet-weight-reclaim/runtime-benchmarks", @@ -167,6 +181,8 @@ runtime-benchmarks = [ "pallet-assets/runtime-benchmarks", "pallet-bags-list/runtime-benchmarks", "pallet-balances/runtime-benchmarks", + "pallet-bridge-messages/runtime-benchmarks", + "pallet-bridge-relayers/runtime-benchmarks", "pallet-collator-selection/runtime-benchmarks", "pallet-conviction-voting/runtime-benchmarks", "pallet-delegated-staking/runtime-benchmarks", @@ -198,6 +214,7 @@ runtime-benchmarks = [ "pallet-whitelist/runtime-benchmarks", "pallet-xcm-benchmarks/runtime-benchmarks", "pallet-xcm-bridge-router/runtime-benchmarks", + "pallet-xcm-bridge/runtime-benchmarks", "pallet-xcm/runtime-benchmarks", "parachains-common/runtime-benchmarks", "polkadot-parachain-primitives/runtime-benchmarks", @@ -236,6 +253,8 @@ try-runtime = [ "pallet-authorship/try-runtime", "pallet-bags-list/try-runtime", "pallet-balances/try-runtime", + "pallet-bridge-messages/try-runtime", + "pallet-bridge-relayers/try-runtime", "pallet-collator-selection/try-runtime", "pallet-conviction-voting/try-runtime", "pallet-delegated-staking/try-runtime", @@ -267,6 +286,7 @@ try-runtime = [ "pallet-vesting/try-runtime", "pallet-whitelist/try-runtime", "pallet-xcm-bridge-router/try-runtime", + "pallet-xcm-bridge/try-runtime", "pallet-xcm/try-runtime", "parachain-info/try-runtime", "parachains-common/try-runtime", @@ -282,7 +302,13 @@ std = [ "bp-asset-hub-westend/std", "bp-bridge-hub-rococo/std", "bp-bridge-hub-westend/std", + "bp-header-chain/std", + "bp-messages/std", + "bp-relayers/std", + "bp-runtime/std", "bp-xcm-bridge/std", + "bridge-hub-common/std", + "bridge-runtime-common/std", "codec/std", "cumulus-pallet-aura-ext/std", "cumulus-pallet-parachain-system/std", @@ -314,6 +340,8 @@ std = [ "pallet-authorship/std", "pallet-bags-list/std", "pallet-balances/std", + "pallet-bridge-messages/std", + "pallet-bridge-relayers/std", "pallet-collator-selection/std", "pallet-conviction-voting/std", "pallet-delegated-staking/std", @@ -350,6 +378,7 @@ std = [ "pallet-whitelist/std", "pallet-xcm-benchmarks?/std", "pallet-xcm-bridge-router/std", + "pallet-xcm-bridge/std", "pallet-xcm/std", "parachain-info/std", "parachains-common/std", diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/bridge-primitives/Cargo.toml b/cumulus/parachains/runtimes/assets/asset-hub-westend/bridge-primitives/Cargo.toml index 5c654f52b471b..615b2afce5ef2 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/bridge-primitives/Cargo.toml +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/bridge-primitives/Cargo.toml @@ -21,11 +21,14 @@ scale-info = { features = ["derive"], workspace = true } frame-support = { workspace = true } sp-api = { workspace = true } sp-core = { workspace = true } +sp-runtime = { workspace = true } +sp-std = { workspace = true } # Bridge Dependencies bp-bridge-hub-cumulus = { workspace = true } bp-messages = { workspace = true } bp-runtime = { workspace = true } +bp-xcm-bridge = { workspace = true } bp-xcm-bridge-router = { workspace = true } testnet-parachains-constants = { features = ["westend"], workspace = true } @@ -39,11 +42,16 @@ std = [ "bp-messages/std", "bp-runtime/std", "bp-xcm-bridge-router/std", + "bp-xcm-bridge/std", "codec/std", + "codec/std", + "frame-support/std", "frame-support/std", "scale-info/std", "sp-api/std", "sp-core/std", + "sp-runtime/std", + "sp-std/std", "testnet-parachains-constants/std", "xcm/std", ] diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/bridge-primitives/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/bridge-primitives/src/lib.rs index c96f1c95905f2..0dda8b626fb0b 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/bridge-primitives/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/bridge-primitives/src/lib.rs @@ -13,7 +13,8 @@ // See the License for the specific language governing permissions and // limitations under the License. -//! Module with configuration which reflects AssetHubWestend runtime setup. +//! Module with configuration which reflects AssetHubWestend runtime setup (AccountId, Headers, +//! Hashes...) #![cfg_attr(not(feature = "std"), no_std)] @@ -25,11 +26,12 @@ use bp_runtime::{ decl_bridge_finality_runtime_apis, decl_bridge_messages_runtime_apis, Chain, ChainId, Parachain, }; pub use bp_xcm_bridge_router::XcmBridgeHubCall; -use codec::{Decode, Encode}; use frame_support::{ dispatch::DispatchClass, sp_runtime::{MultiAddress, MultiSigner, RuntimeDebug, StateVersion}, }; + +use codec::{Decode, Encode}; use scale_info::TypeInfo; use testnet_parachains_constants::westend::currency::UNITS; use xcm::latest::prelude::*; @@ -48,6 +50,9 @@ pub enum Call { /// `ToRococoXcmRouter` bridge pallet. #[codec(index = 34)] ToRococoXcmRouter(XcmBridgeHubCall), + /// Points to the `pallet_xcm_bridge_hub` pallet instance for `AssetHubRococo`. + #[codec(index = 62)] + XcmOverAssetHubRococo(bp_xcm_bridge::XcmBridgeCall), } frame_support::parameter_types! { @@ -148,3 +153,18 @@ pub const WITH_BRIDGE_WESTEND_TO_ROCOCO_MESSAGES_PALLET_INDEX: u8 = 63; decl_bridge_finality_runtime_apis!(asset_hub_westend); decl_bridge_messages_runtime_apis!(asset_hub_westend, HashedLaneId); + +frame_support::parameter_types! { + /// The XCM fee that is paid for executing XCM program (with `ExportMessage` instruction) at the Westend + /// AssetHub. + /// (initially was calculated by test `AssetHubWestend::can_calculate_weight_for_paid_export_message_with_reserve_transfer` + `33%`) + pub const AssetHubWestendBaseXcmFeeInWnds: u128 = 23_180_570_000; + + /// Transaction fee that is paid at the Westend AssetHub for delivering a single inbound message. + /// (initially was calculated by test `AssetHubWestend::can_calculate_fee_for_standalone_message_delivery_transaction` + `33%`) + pub const AssetHubWestendBaseDeliveryFeeInWnds: u128 = 89_668_215_915; + + /// Transaction fee that is paid at the Westend AssetHub for delivering single outbound message confirmation. + /// (initially was calculated by test `AssetHubWestend::can_calculate_fee_for_standalone_message_confirmation_transaction` + `33%`) + pub const AssetHubWestendBaseConfirmationFeeInWnds: u128 = 16_960_715_915; +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/bridge_common_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/bridge_common_config.rs new file mode 100644 index 0000000000000..96c3e171c84b6 --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/bridge_common_config.rs @@ -0,0 +1,125 @@ +// Copyright (C) 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 . + +//! Bridge definitions that can be used by multiple bridges. + +use super::{weights, AccountId, Balance, Balances, BlockNumber, Runtime, RuntimeEvent}; +use bp_messages::HashedLaneId; +use bp_relayers::RewardsAccountParams; +use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen}; +use scale_info::TypeInfo; +use xcm::VersionedLocation; + +frame_support::parameter_types! { + pub storage RequiredStakeForStakeAndSlash: Balance = 1_000_000; + pub const RelayerStakeLease: u32 = 8; + pub const RelayerStakeReserveId: [u8; 8] = *b"brdgrlrs"; + pub storage DeliveryRewardInBalance: u64 = 1_000_000; +} + +/// Showcasing that we can handle multiple different rewards with the same pallet. +#[derive( + Clone, + Copy, + Debug, + Decode, + DecodeWithMemTracking, + Encode, + Eq, + MaxEncodedLen, + PartialEq, + TypeInfo, +)] +pub enum BridgeReward { + /// Rewards for the R/W bridge—distinguished by the `RewardsAccountParams` key. + RococoWestend(RewardsAccountParams), +} + +impl From> for BridgeReward { + fn from(value: RewardsAccountParams) -> Self { + Self::RococoWestend(value) + } +} + +/// An enum representing the different types of supported beneficiaries. +#[derive( + Clone, Debug, Decode, DecodeWithMemTracking, Encode, Eq, MaxEncodedLen, PartialEq, TypeInfo, +)] +pub enum BridgeRewardBeneficiaries { + /// A local chain account. + LocalAccount(AccountId), + /// A beneficiary specified by a VersionedLocation. + AssetHubLocation(VersionedLocation), +} + +impl From for BridgeRewardBeneficiaries { + fn from(value: sp_runtime::AccountId32) -> Self { + BridgeRewardBeneficiaries::LocalAccount(value) + } +} + +/// Implementation of `bp_relayers::PaymentProcedure` as a pay/claim rewards scheme. +pub struct BridgeRewardPayer; +impl bp_relayers::PaymentProcedure for BridgeRewardPayer { + type Error = sp_runtime::DispatchError; + type Beneficiary = BridgeRewardBeneficiaries; + + fn pay_reward( + relayer: &AccountId, + reward_kind: BridgeReward, + reward: u128, + beneficiary: BridgeRewardBeneficiaries, + ) -> Result<(), Self::Error> { + match reward_kind { + BridgeReward::RococoWestend(lane_params) => { + match beneficiary { + BridgeRewardBeneficiaries::LocalAccount(account) => { + bp_relayers::PayRewardFromAccount::< + Balances, + AccountId, + HashedLaneId, + u128, + >::pay_reward( + &relayer, lane_params, reward, account, + ) + }, + BridgeRewardBeneficiaries::AssetHubLocation(_) => Err(Self::Error::Other("`AssetHubLocation` beneficiary is not supported for `RococoWestend` rewards!")), + } + } + } + } +} + +/// Allows collect and claim rewards for the relayers +pub type BridgeRelayersInstance = pallet_bridge_relayers::Instance1; +impl pallet_bridge_relayers::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + + type RewardBalance = u128; + type Reward = BridgeReward; + type PaymentProcedure = BridgeRewardPayer; + + type StakeAndSlash = pallet_bridge_relayers::StakeAndSlashNamed< + AccountId, + BlockNumber, + Balances, + RelayerStakeReserveId, + RequiredStakeForStakeAndSlash, + RelayerStakeLease, + >; + type Balance = Balance; + type WeightInfo = weights::pallet_bridge_relayers::WeightInfo; +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/bridge_to_rococo_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/bridge_to_rococo_config.rs new file mode 100644 index 0000000000000..285310a2dc79c --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/bridge_to_rococo_config.rs @@ -0,0 +1,325 @@ +// Copyright (C) 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 . + +//! Bridge definitions used on BridgeHubWestend for bridging to BridgeHubRococo. + +use crate::{ + bridge_common_config::{BridgeRelayersInstance, DeliveryRewardInBalance}, + weights, xcm_config, + xcm_config::UniversalLocation, + AccountId, Balance, Balances, BridgeRococoMessages, PolkadotXcm, Runtime, RuntimeEvent, + RuntimeHoldReason, ToRococoOverAssetHubRococoXcmRouter, XcmOverAssetHubRococo, +}; +use alloc::{vec, vec::Vec}; +use bp_messages::HashedLaneId; +use bp_runtime::HashOf; +use bridge_hub_common::xcm_version::XcmVersionOfDestAndRemoteBridge; +use pallet_xcm_bridge::XcmAsPlainPayload; + +use frame_support::{ + parameter_types, + traits::{EitherOf, Equals, PalletInfoAccess}, +}; +use frame_system::{EnsureRoot, EnsureRootWithSuccess}; +use pallet_bridge_relayers::extension::{ + BridgeRelayersTransactionExtension, WithMessagesExtensionConfig, +}; +use pallet_xcm::EnsureXcm; +use pallet_xcm_bridge::congestion::{ + BlobDispatcherWithChannelStatus, HereOrLocalConsensusXcmChannelManager, + UpdateBridgeStatusXcmChannelManager, +}; +use pallet_xcm_bridge_router::impls::GetPriceForBridge; +use parachains_common::xcm_config::{ + AllSiblingSystemParachains, ParentRelayOrSiblingParachains, RelayOrOtherSystemParachains, +}; +use polkadot_parachain_primitives::primitives::Sibling; +use sp_runtime::traits::Convert; +use testnet_parachains_constants::westend::currency::UNITS as WND; +use xcm::{ + latest::{prelude::*, ROCOCO_GENESIS_HASH}, + prelude::NetworkId, +}; +use xcm_builder::{ + BridgeBlobDispatcher, LocalExporter, ParentIsPreset, SiblingParachainConvertsVia, +}; + +parameter_types! { + pub BridgeWestendToRococoMessagesPalletInstance: InteriorLocation = [PalletInstance(::index() as u8)].into(); + pub const HereLocation: Location = Location::here(); + pub RococoGlobalConsensusNetwork: NetworkId = NetworkId::ByGenesis(ROCOCO_GENESIS_HASH); + pub RococoGlobalConsensusNetworkLocation: Location = Location::new( + 2, + [GlobalConsensus(RococoGlobalConsensusNetwork::get())] + ); + // see the `FEE_BOOST_PER_MESSAGE` constant to get the meaning of this value + pub PriorityBoostPerMessage: u64 = 364_088_888_888_888; + + // The other side of the bridge + pub AssetHubRococoLocation: Location = Location::new( + 2, + [ + GlobalConsensus(RococoGlobalConsensusNetwork::get()), + Parachain(::PARACHAIN_ID) + ] + ); + + pub storage BridgeDeposit: Balance = 5 * WND; + + // The fee for exporting/delivery. + pub BaseMessageExportPrice: Assets = ( + xcm_config::bridging::XcmBridgeHubRouterFeeAssetId::get(), + xcm_config::bridging::ToRococoOverAssetHubRococoXcmRouterBaseFee::get(), + ).into(); +} + +/// Transaction extension that refunds relayers that are delivering messages from the Rococo +/// parachain. +pub type OnAssetHubWestendRefundAssetHubRococoMessages = BridgeRelayersTransactionExtension< + Runtime, + WithMessagesExtensionConfig< + StrOnAssetHubWestendRefundAssetHubRococoMessages, + Runtime, + WithAssetHubRococoMessagesInstance, + BridgeRelayersInstance, + PriorityBoostPerMessage, + >, +>; +bp_runtime::generate_static_str_provider!(OnAssetHubWestendRefundAssetHubRococoMessages); + +/// Add XCM messages support for AssetHubWestend to support Westend->Rococo XCM messages +pub type WithAssetHubRococoMessagesInstance = pallet_bridge_messages::Instance1; +impl pallet_bridge_messages::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type WeightInfo = weights::pallet_bridge_messages::WeightInfo; + + type ThisChain = bp_asset_hub_westend::AssetHubWestend; + type BridgedChain = bp_asset_hub_rococo::AssetHubRococo; + type BridgedHeaderChain = ParachainHeaderProofs; + + type OutboundPayload = XcmAsPlainPayload; + type InboundPayload = XcmAsPlainPayload; + type LaneId = HashedLaneId; + + type DeliveryPayments = (); + type DeliveryConfirmationPayments = pallet_bridge_relayers::DeliveryConfirmationPaymentsAdapter< + Runtime, + WithAssetHubRococoMessagesInstance, + BridgeRelayersInstance, + DeliveryRewardInBalance, + >; + + type MessageDispatch = XcmOverAssetHubRococo; + type OnMessagesDelivered = XcmOverAssetHubRococo; +} + +/// TODO: doc + FAIL-CI - implement storage for synced proofs from BridgeHub +pub struct ParachainHeaderProofs(core::marker::PhantomData); +impl bp_header_chain::HeaderChain for ParachainHeaderProofs { + fn finalized_header_state_root(_header_hash: HashOf) -> Option> { + todo!("TODO: FAIL-CI - implement storage for synced proofs from BridgeHub") + } +} + +/// Converts encoded call to the unpaid XCM `Transact`. +pub struct UpdateBridgeStatusXcmProvider; +impl Convert, Xcm<()>> for UpdateBridgeStatusXcmProvider { + fn convert(encoded_call: Vec) -> Xcm<()> { + Xcm(vec![ + UnpaidExecution { weight_limit: Unlimited, check_origin: None }, + Transact { + origin_kind: OriginKind::Xcm, + call: encoded_call.into(), + fallback_max_weight: None, + }, + ExpectTransactStatus(MaybeErrorCode::Success), + ]) + } +} + +/// Add support for the export and dispatch of XCM programs withing +/// `WithAssetHubRococoMessagesInstance`. +pub type XcmOverAssetHubRococoInstance = pallet_xcm_bridge::Instance1; +impl pallet_xcm_bridge::Config for Runtime { + type WeightInfo = weights::pallet_xcm_bridge::WeightInfo; + + type UniversalLocation = UniversalLocation; + type BridgedNetwork = RococoGlobalConsensusNetworkLocation; + type BridgeMessagesPalletInstance = WithAssetHubRococoMessagesInstance; + + /// This price covers: + /// - `BaseMessageExportPrice` (for message proof delivery/confirmation) + /// - Message size fee (if configured) + /// - Dynamic fee factor (if congested) + /// + /// This price is calculated either for local routing with `ToRococoOverAssetHubRococoXcmRouter` + /// or executing `ExportMessage` from a sibling chain. + type MessageExportPrice = GetPriceForBridge< + Runtime, + ToRococoOverAssetHubRococoXcmRouterInstance, + BaseMessageExportPrice, + >; + type DestinationVersion = XcmVersionOfDestAndRemoteBridge; + + type ForceOrigin = EnsureRoot; + // We allow creating bridges for the runtime itself and for other local consensus chains (relay, + // paras). + type OpenBridgeOrigin = EitherOf< + // We want to translate `RuntimeOrigin::root()` to the `Location::here()`, e.g. for + // governance calls. + EnsureRootWithSuccess, + // For relay or sibling chains + EnsureXcm, + >; + // Converter aligned with `OpenBridgeOrigin`. + type BridgeOriginAccountIdConverter = + (ParentIsPreset, SiblingParachainConvertsVia); + + type BridgeDeposit = BridgeDeposit; + type Currency = Balances; + type RuntimeHoldReason = RuntimeHoldReason; + // Do not require deposit from system parachains (including itself) or relay chain + type AllowWithoutBridgeDeposit = + (RelayOrOtherSystemParachains, Equals); + + // This pallet is deployed on AH, so we expect a remote router with `ExportMessage`. We handle + // congestion with XCM using `udpate_bridge_status` sent to the sending chain. (congestion with + // local sending chain) + type LocalXcmChannelManager = HereOrLocalConsensusXcmChannelManager< + pallet_xcm_bridge::BridgeId, + // handles congestion for local chain router for local AH's bridges + ToRococoOverAssetHubRococoXcmRouter, + // handles congestion for other local chains with XCM using `update_bridge_status` sent to + // the sending chain. + UpdateBridgeStatusXcmChannelManager< + Runtime, + XcmOverAssetHubRococoInstance, + UpdateBridgeStatusXcmProvider, + xcm_config::LocalXcmRouter, + >, + >; + // Dispatching inbound messages from the bridge and managing congestion with the local + // receiving/destination chain + type BlobDispatcher = BlobDispatcherWithChannelStatus< + // Dispatches received XCM messages from other bridge + BridgeBlobDispatcher< + xcm_config::LocalXcmRouter, + UniversalLocation, + // TODO: FAIL-CI wait for https://github.com/paritytech/polkadot-sdk/pull/6002#issuecomment-2469892343 + BridgeWestendToRococoMessagesPalletInstance, + >, + // Provides the status of the XCMP queue's outbound queue, indicating whether messages can + // be dispatched to the sibling. + cumulus_pallet_xcmp_queue::bridging::OutXcmpChannelStatusProvider, + >; + type CongestionLimits = (); +} + +/// XCM router instance to the local `pallet_xcm_bridge::` with +/// direct bridging capabilities for `Rococo` global consensus with dynamic fees and back-pressure. +pub type ToRococoOverAssetHubRococoXcmRouterInstance = pallet_xcm_bridge_router::Instance2; +impl pallet_xcm_bridge_router::Config for Runtime { + type WeightInfo = + weights::pallet_xcm_bridge_router_to_rococo_over_asset_hub_rococo::WeightInfo; + + type DestinationVersion = PolkadotXcm; + + // We use `LocalExporter` to ensure that `pallet_xcm_bridge_router` can directly trigger + // `pallet_xcm_bridge` as an exporter. + type MessageExporter = LocalExporter; + + // For congestion - resolves `BridgeId` using the same algorithm as `pallet_xcm_bridge` on + // the BH. + type BridgeIdResolver = + pallet_xcm_bridge_router::impls::EnsureIsRemoteBridgeIdResolver; + // We don't expect here `update_bridge_status` calls, but let's allow just for root (governance, + // ...). + type UpdateBridgeStatusOrigin = EnsureRoot; + + // For adding message size fees + type ByteFee = xcm_config::bridging::XcmBridgeHubRouterByteFee; + // For adding message size fees + type FeeAsset = xcm_config::bridging::XcmBridgeHubRouterFeeAssetId; +} + +#[cfg(test)] +mod tests { + use super::*; + use bridge_runtime_common::{ + assert_complete_bridge_types, + integrity::{ + assert_standalone_messages_bridge_constants, check_message_lane_weights, + AssertChainConstants, AssertCompleteBridgeConstants, + }, + }; + + /// 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 = 2 * WND; + + #[test] + fn ensure_bridge_hub_westend_message_lane_weights_are_correct() { + check_message_lane_weights::< + bp_asset_hub_westend::AssetHubWestend, + Runtime, + WithAssetHubRococoMessagesInstance, + >( + bp_asset_hub_rococo::EXTRA_STORAGE_PROOF_SIZE, + bp_asset_hub_westend::MAX_UNREWARDED_RELAYERS_IN_CONFIRMATION_TX, + bp_asset_hub_westend::MAX_UNCONFIRMED_MESSAGES_IN_CONFIRMATION_TX, + true, + ); + } + + #[test] + fn ensure_bridge_integrity() { + assert_complete_bridge_types!( + runtime: Runtime, + with_bridged_chain_messages_instance: WithAssetHubRococoMessagesInstance, + this_chain: bp_asset_hub_westend::AssetHubWestend, + bridged_chain: bp_asset_hub_rococo::AssetHubRococo, + expected_payload_type: XcmAsPlainPayload, + ); + + assert_standalone_messages_bridge_constants::( + AssertCompleteBridgeConstants { + this_chain_constants: AssertChainConstants { + block_length: bp_bridge_hub_westend::BlockLength::get(), + block_weights: bp_bridge_hub_westend::BlockWeightsForAsyncBacking::get(), + }, + }, + ); + + pallet_bridge_relayers::extension::per_message::ensure_priority_boost_is_sane::< + Runtime, + WithAssetHubRococoMessagesInstance, + PriorityBoostPerMessage, + >(FEE_BOOST_PER_MESSAGE); + + let expected: InteriorLocation = [PalletInstance( + bp_asset_hub_westend::WITH_BRIDGE_WESTEND_TO_ROCOCO_MESSAGES_PALLET_INDEX, + )] + .into(); + assert_eq!(BridgeWestendToRococoMessagesPalletInstance::get(), expected); + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs index f4408a8d7084e..c0689c6fc340c 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/lib.rs @@ -24,7 +24,9 @@ #[cfg(feature = "std")] include!(concat!(env!("OUT_DIR"), "/wasm_binary.rs")); +pub mod bridge_common_config; mod bridge_to_ethereum_config; +pub mod bridge_to_rococo_config; mod genesis_config_presets; mod weights; pub mod xcm_config; @@ -124,7 +126,7 @@ use frame_support::traits::PalletInfoAccess; #[cfg(feature = "runtime-benchmarks")] use xcm::latest::prelude::{ Asset, Assets as XcmAssets, Fungible, Here, InteriorLocation, Junction, Junction::*, Location, - NetworkId, NonFungible, Parent, ParentThen, Response, WeightLimit, + NetworkId, NonFungible, Parent, ParentThen, Response, WeightLimit, XCM_VERSION, }; use xcm_runtime_apis::{ @@ -1135,10 +1137,12 @@ impl pallet_nfts::Config for Runtime { } /// XCM router instance to BridgeHub with bridging capabilities for `Rococo` global -/// consensus with dynamic fees and back-pressure. +/// consensus with dynamic fees and back-pressure +/// (legacy routing with `ExportMessage` over BridgeHub). pub type ToRococoXcmRouterInstance = pallet_xcm_bridge_router::Instance1; impl pallet_xcm_bridge_router::Config for Runtime { - type WeightInfo = weights::pallet_xcm_bridge_router::WeightInfo; + type WeightInfo = + weights::pallet_xcm_bridge_router_to_rococo_over_bridge_hub::WeightInfo; type DestinationVersion = PolkadotXcm; @@ -1356,6 +1360,12 @@ construct_runtime!( AssetRewards: pallet_asset_rewards = 61, + // Bridges permissionless lanes. + XcmOverAssetHubRococo: pallet_xcm_bridge:: = 62, + BridgeRococoMessages: pallet_bridge_messages:: = 63, + BridgeRelayers: pallet_bridge_relayers:: = 64, + ToRococoOverAssetHubRococoXcmRouter: pallet_xcm_bridge_router:: = 65, + StateTrieMigration: pallet_state_trie_migration = 70, // Staking. @@ -1388,6 +1398,12 @@ construct_runtime!( } ); +bridge_runtime_common::generate_bridge_reject_obsolete_headers_and_messages! { + RuntimeCall, AccountId, + // Messages + BridgeRococoMessages +} + /// The address format for describing accounts. pub type Address = sp_runtime::MultiAddress; /// Block type as expected by this runtime. @@ -1410,6 +1426,8 @@ pub type TxExtension = cumulus_pallet_weight_reclaim::StorageWeightReclaim< frame_system::CheckWeight, pallet_asset_conversion_tx_payment::ChargeAssetTxPayment, frame_metadata_hash_extension::CheckMetadataHash, + BridgeRejectObsoleteHeadersAndMessages, + (bridge_to_rococo_config::OnAssetHubWestendRefundAssetHubRococoMessages,), ), >; @@ -1433,6 +1451,8 @@ impl EthExtra for EthExtraImpl { frame_system::CheckWeight::::new(), pallet_asset_conversion_tx_payment::ChargeAssetTxPayment::::from(tip, None), frame_metadata_hash_extension::CheckMetadataHash::::new(false), + BridgeRejectObsoleteHeadersAndMessages, + (bridge_to_rococo_config::OnAssetHubWestendRefundAssetHubRococoMessages::default(),), ) .into() } @@ -1694,9 +1714,13 @@ mod benches { [pallet_treasury, Treasury] [pallet_vesting, Vesting] [pallet_whitelist, Whitelist] - [pallet_xcm_bridge_router, ToRococo] - [pallet_asset_conversion_ops, AssetConversionMigration] [pallet_revive, Revive] + // Bridge pallets + [pallet_xcm_bridge_router, ToRococoOverBridgeHub] + [pallet_xcm_bridge_router, ToRococoOverAssetHubRococo] + [pallet_bridge_messages, WestendToRococo] + [pallet_bridge_relayers, BridgeRelayersBench::] + [pallet_xcm_bridge, OverRococo] // XCM [pallet_xcm, PalletXcmExtrinsicsBenchmark::] // NOTE: Make sure you point to the individual modules below. @@ -2159,7 +2183,8 @@ pallet_revive::impl_runtime_apis_plus_revive!( use frame_system_benchmarking::extensions::Pallet as SystemExtensionsBench; use cumulus_pallet_session_benchmarking::Pallet as SessionBench; use pallet_xcm::benchmarking::Pallet as PalletXcmExtrinsicsBenchmark; - use pallet_xcm_bridge_router::benchmarking::Pallet as XcmBridgeHubRouterBench; + use pallet_xcm_bridge_router::benchmarking::Pallet as XcmBridgeRouterBench; + use pallet_bridge_relayers::benchmarking::Pallet as BridgeRelayersBench; // This is defined once again in dispatch_benchmark, because list_benchmarks! // and add_benchmarks! are macros exported by define_benchmarks! macros and those types @@ -2175,7 +2200,10 @@ pallet_revive::impl_runtime_apis_plus_revive!( type Foreign = pallet_assets::Pallet::; type Pool = pallet_assets::Pallet::; - type ToRococo = XcmBridgeHubRouterBench; + type ToRococoOverBridgeHub = XcmBridgeRouterBench; + type ToRococoOverAssetHubRococo = XcmBridgeRouterBench; + type OverRococo = pallet_xcm_bridge::benchmarking::Pallet::; + type WestendToRococo = pallet_bridge_messages::benchmarking::Pallet::; let mut list = Vec::::new(); list_benchmarks!(list, extra); @@ -2335,11 +2363,11 @@ pallet_revive::impl_runtime_apis_plus_revive!( } use pallet_xcm_bridge_router::benchmarking::{ - Pallet as XcmBridgeHubRouterBench, - Config as XcmBridgeHubRouterConfig, + Pallet as XcmBridgeRouterBench, + Config as XcmBridgeRouterConfig, }; - impl XcmBridgeHubRouterConfig for Runtime { + impl XcmBridgeRouterConfig for Runtime { fn ensure_bridged_target_destination() -> Result { Ok(xcm_config::bridging::to_rococo::AssetHubRococo::get()) } @@ -2348,6 +2376,15 @@ pallet_revive::impl_runtime_apis_plus_revive!( } } + impl XcmBridgeRouterConfig for Runtime { + fn ensure_bridged_target_destination() -> Result { + Ok(xcm_config::bridging::to_rococo::AssetHubRococo::get()) + } + fn update_bridge_status_origin() -> Option { + None + } + } + use xcm_config::{MaxAssetsIntoHolding, WestendLocation}; use pallet_xcm_benchmarks::asset_instance_from; @@ -2524,7 +2561,50 @@ pallet_revive::impl_runtime_apis_plus_revive!( fn export_message_origin_and_destination( ) -> Result<(Location, NetworkId, InteriorLocation), BenchmarkError> { - Err(BenchmarkError::Skip) + // save XCM version for remote permissionless lanes on bridged asset hub + let _ = PolkadotXcm::force_xcm_version( + RuntimeOrigin::root(), + alloc::boxed::Box::new(bridge_to_rococo_config::AssetHubRococoLocation::get()), + XCM_VERSION, + ).map_err(|e| { + log::error!( + "Failed to dispatch `force_xcm_version({:?}, {:?}, {:?})`, error: {:?}", + RuntimeOrigin::root(), + bridge_to_rococo_config::AssetHubRococoLocation::get(), + XCM_VERSION, + e + ); + BenchmarkError::Stop("XcmVersion was not stored!") + })?; + + // open bridge + let rococo = bridge_to_rococo_config::RococoGlobalConsensusNetwork::get(); + let sibling_parachain_location = Location::new(1, [Parachain(8765)]); + let bridge_destination_universal_location: InteriorLocation = [GlobalConsensus(rococo), Parachain(5678)].into(); + let _ = XcmOverAssetHubRococo::open_bridge_for_benchmarks( + ::try_new(1, 2).unwrap(), + sibling_parachain_location.clone(), + bridge_destination_universal_location.clone(), + true, + None, + || ExistentialDeposit::get(), + ).map_err(|e| { + log::error!( + "Failed to `XcmOverAssetHubRococo::open_bridge`({:?}, {:?})`, error: {:?}", + sibling_parachain_location, + bridge_destination_universal_location, + e + ); + BenchmarkError::Stop("Bridge was not opened!") + })?; + + Ok( + ( + sibling_parachain_location, + rococo, + [Parachain(5678)].into() + ) + ) } fn alias_origin() -> Result<(Location, Location), BenchmarkError> { @@ -2544,7 +2624,138 @@ pallet_revive::impl_runtime_apis_plus_revive!( type Foreign = pallet_assets::Pallet::; type Pool = pallet_assets::Pallet::; - type ToRococo = XcmBridgeHubRouterBench; + type ToRococoOverBridgeHub = XcmBridgeRouterBench; + type ToRococoOverAssetHubRococo = XcmBridgeRouterBench; + type OverRococo = pallet_xcm_bridge::benchmarking::Pallet::; + type WestendToRococo = pallet_bridge_messages::benchmarking::Pallet::; + + use pallet_bridge_relayers::benchmarking::{ + Config as BridgeRelayersConfig, + Pallet as BridgeRelayersBench + }; + + impl BridgeRelayersConfig for Runtime { + fn bench_reward() -> Self::Reward { + bp_relayers::RewardsAccountParams::new( + bp_messages::HashedLaneId::default(), + *b"test", + bp_relayers::RewardsAccountOwner::ThisChain + ).into() + } + + fn prepare_rewards_account( + reward_kind: Self::Reward, + reward: Balance, + ) -> Option> { + let bridge_common_config::BridgeReward::RococoWestend(reward_kind) = reward_kind; + let rewards_account = bp_relayers::PayRewardFromAccount::< + Balances, + AccountId, + bp_messages::HashedLaneId, + u128, + >::rewards_account(reward_kind); + Self::deposit_account(rewards_account, reward); + + None + } + + fn deposit_account(account: AccountId, balance: Balance) { + use frame_support::traits::fungible::Mutate; + Balances::mint_into(&account, balance.saturating_add(ExistentialDeposit::get())).unwrap(); + } + } + + impl pallet_xcm_bridge::benchmarking::Config for Runtime { + fn open_bridge_origin() -> Option<(RuntimeOrigin, Balance)> { + // We allow bridges to be opened for sibling parachains. + Some(( + pallet_xcm::Origin::Xcm(Location::new(1, [Parachain(42)])).into(), + ExistentialDeposit::get(), + )) + } + } + + use pallet_bridge_messages::{BridgedChainOf, LaneIdOf}; + use pallet_bridge_messages::benchmarking::{ + Config as BridgeMessagesConfig, + MessageDeliveryProofParams, + MessageProofParams, + }; + + impl BridgeMessagesConfig for Runtime { + fn is_relayer_rewarded(relayer: &Self::AccountId) -> bool { + let bench_lane_id = >::bench_lane_id(); + use bp_runtime::Chain; + let bridged_chain_id =>::BridgedChain::ID; + pallet_bridge_relayers::Pallet::::relayer_reward( + relayer, + bridge_common_config::BridgeReward::RococoWestend( + bp_relayers::RewardsAccountParams::new( + bench_lane_id, + bridged_chain_id, + bp_relayers::RewardsAccountOwner::BridgedChain + ) + ) + ).is_some() + } + + fn prepare_message_proof( + params: MessageProofParams>, + ) -> ( + bp_messages::target_chain::FromBridgedChainMessagesProof< + bp_runtime::HashOf>, + LaneIdOf + >, + 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()); + let _bridge_locations = XcmOverAssetHubRococo::open_bridge_for_benchmarks( + params.lane, + Location::new(1, [Parachain(42)]), + [GlobalConsensus(bridge_to_rococo_config::RococoGlobalConsensusNetwork::get()), Parachain(2075)].into(), + // do not create lanes, because they are already created `params.lane` + false, + None, + || ExistentialDeposit::get(), + ).expect("valid bridge opened"); + todo!("TODO: FAIL-CI - prepare storage proof for synced proof") + // prepare_message_proof_from_parachain::< + // Runtime, + // bridge_common_config::BridgeGrandpaWestendInstance, + // bridge_to_westend_config::WithAssetHubWestendMessagesInstance, + // >(params, generate_xcm_builder_bridge_message_sample(bridge_locations.bridge_origin_universal_location().clone())) + } + + fn prepare_message_delivery_proof( + params: MessageDeliveryProofParams>, + ) -> bp_messages::source_chain::FromBridgedChainMessagesDeliveryProof< + bp_runtime::HashOf>, + LaneIdOf + > { + let _ = XcmOverAssetHubRococo::open_bridge_for_benchmarks( + params.lane, + Location::new(1, [Parachain(42)]), + [GlobalConsensus(bridge_to_rococo_config::RococoGlobalConsensusNetwork::get()), Parachain(2075)].into(), + // do not create lanes, because they are already created `params.lane` + false, + None, + || ExistentialDeposit::get(), + ); + todo!("TODO: FAIL-CI - prepare storage proof for synced proof") + // prepare_message_delivery_proof_from_parachain::< + // Runtime, + // bridge_common_config::BridgeGrandpaRococoInstance, + // bridge_to_rococo_config::WithAssetHubRococoMessagesInstance, + // >(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 frame_support::traits::WhitelistedStorageKeys; let whitelist: Vec = AllPalletsWithSystem::whitelisted_storage_keys(); diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/staking.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/staking.rs index 55f614508f0ee..0664e1860ca72 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/staking.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/staking.rs @@ -476,6 +476,8 @@ where frame_system::CheckWeight::::new(), pallet_asset_conversion_tx_payment::ChargeAssetTxPayment::::from(tip, None), frame_metadata_hash_extension::CheckMetadataHash::::new(true), + crate::BridgeRejectObsoleteHeadersAndMessages::default(), + (bridge_to_rococo_config::OnAssetHubWestendRefundAssetHubRococoMessages::default(),), )); let raw_payload = SignedPayload::new(call, tx_ext) .map_err(|e| { diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs index b02954b1ba6f9..4af701978d4de 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/mod.rs @@ -32,6 +32,8 @@ pub mod pallet_assets_local; pub mod pallet_assets_pool; pub mod pallet_bags_list; pub mod pallet_balances; +pub mod pallet_bridge_messages; +pub mod pallet_bridge_relayers; pub mod pallet_collator_selection; pub mod pallet_conviction_voting; pub mod pallet_fast_unstake; @@ -57,7 +59,9 @@ pub mod pallet_utility; pub mod pallet_vesting; pub mod pallet_whitelist; pub mod pallet_xcm; -pub mod pallet_xcm_bridge_router; +pub mod pallet_xcm_bridge; +pub mod pallet_xcm_bridge_router_to_rococo_over_asset_hub_rococo; +pub mod pallet_xcm_bridge_router_to_rococo_over_bridge_hub; pub mod paritydb_weights; pub mod rocksdb_weights; pub mod snowbridge_pallet_system_backend; @@ -67,3 +71,23 @@ pub mod xcm; pub use block_weights::constants::BlockExecutionWeight; pub use extrinsic_weights::constants::ExtrinsicBaseWeight; pub use inmemorydb_weights::constants::InMemoryDbWeight; + +use ::pallet_bridge_messages::WeightInfoExt as MessagesWeightInfoExt; +use ::pallet_bridge_relayers::WeightInfoExt as _; + +use crate::{Runtime, Weight}; + +impl MessagesWeightInfoExt for pallet_bridge_messages::WeightInfo { + fn expected_extra_storage_proof_size() -> u32 { + bp_bridge_hub_rococo::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() + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_bridge_messages.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_bridge_messages.rs new file mode 100644 index 0000000000000..183dec296bb40 --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_bridge_messages.rs @@ -0,0 +1,273 @@ +// Copyright (C) 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 32.0.0 +//! DATE: 2024-11-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-wiukf8gn-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-westend-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/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_bridge_messages +// --chain=bridge-hub-westend-dev TODO: FAIL-CI regenerate +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/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: `BridgeWestendMessages::PalletOperatingMode` (r:1 w:0) + /// Proof: `BridgeWestendMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendParachains::ImportedParaHeads` (r:1 w:0) + /// Proof: `BridgeWestendParachains::ImportedParaHeads` (`max_values`: Some(64), `max_size`: Some(196), added: 1186, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::InboundLanes` (r:1 w:1) + /// Proof: `BridgeWestendMessages::InboundLanes` (`max_values`: None, `max_size`: Some(49180), added: 51655, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::LaneToBridge` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::LaneToBridge` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::Bridges` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::Bridges` (`max_values`: None, `max_size`: Some(1893), added: 4368, mode: `MaxEncodedLen`) + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: Some(1282), added: 1777, 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: `940` + // Estimated: `52645` + // Minimum execution time: 62_868_000 picoseconds. + Weight::from_parts(65_210_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `BridgeWestendMessages::PalletOperatingMode` (r:1 w:0) + /// Proof: `BridgeWestendMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendParachains::ImportedParaHeads` (r:1 w:0) + /// Proof: `BridgeWestendParachains::ImportedParaHeads` (`max_values`: Some(64), `max_size`: Some(196), added: 1186, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::InboundLanes` (r:1 w:1) + /// Proof: `BridgeWestendMessages::InboundLanes` (`max_values`: None, `max_size`: Some(49180), added: 51655, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::LaneToBridge` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::LaneToBridge` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::Bridges` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::Bridges` (`max_values`: None, `max_size`: Some(1893), added: 4368, mode: `MaxEncodedLen`) + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: Some(1282), added: 1777, mode: `MaxEncodedLen`) + /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) + /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 4076]`. + /// The range of component `n` is `[1, 4076]`. + fn receive_n_messages_proof(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `940` + // Estimated: `52645` + // Minimum execution time: 62_893_000 picoseconds. + Weight::from_parts(63_992_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + // Standard Error: 13_856 + .saturating_add(Weight::from_parts(12_332_627, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `BridgeWestendMessages::PalletOperatingMode` (r:1 w:0) + /// Proof: `BridgeWestendMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendParachains::ImportedParaHeads` (r:1 w:0) + /// Proof: `BridgeWestendParachains::ImportedParaHeads` (`max_values`: Some(64), `max_size`: Some(196), added: 1186, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::InboundLanes` (r:1 w:1) + /// Proof: `BridgeWestendMessages::InboundLanes` (`max_values`: None, `max_size`: Some(49180), added: 51655, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::LaneToBridge` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::LaneToBridge` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::Bridges` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::Bridges` (`max_values`: None, `max_size`: Some(1893), added: 4368, mode: `MaxEncodedLen`) + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: Some(1282), added: 1777, 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: `940` + // Estimated: `52645` + // Minimum execution time: 68_193_000 picoseconds. + Weight::from_parts(70_799_000, 0) + .saturating_add(Weight::from_parts(0, 52645)) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `BridgeWestendMessages::PalletOperatingMode` (r:1 w:0) + /// Proof: `BridgeWestendMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendParachains::ImportedParaHeads` (r:1 w:0) + /// Proof: `BridgeWestendParachains::ImportedParaHeads` (`max_values`: Some(64), `max_size`: Some(196), added: 1186, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::InboundLanes` (r:1 w:1) + /// Proof: `BridgeWestendMessages::InboundLanes` (`max_values`: None, `max_size`: Some(49180), added: 51655, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::LaneToBridge` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::LaneToBridge` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::Bridges` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::Bridges` (`max_values`: None, `max_size`: Some(1893), added: 4368, mode: `MaxEncodedLen`) + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: Some(1282), added: 1777, mode: `MaxEncodedLen`) + /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) + /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 16384]`. + /// The range of component `n` is `[1, 16384]`. + fn receive_single_n_bytes_message_proof(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `940` + // Estimated: `52645` + // Minimum execution time: 61_230_000 picoseconds. + Weight::from_parts(65_437_770, 0) + .saturating_add(Weight::from_parts(0, 52645)) + // Standard Error: 9 + .saturating_add(Weight::from_parts(2_168, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(1)) + } + /// Storage: `BridgeWestendMessages::PalletOperatingMode` (r:1 w:0) + /// Proof: `BridgeWestendMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendParachains::ImportedParaHeads` (r:1 w:0) + /// Proof: `BridgeWestendParachains::ImportedParaHeads` (`max_values`: Some(64), `max_size`: Some(196), added: 1186, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::OutboundLanes` (r:1 w:1) + /// Proof: `BridgeWestendMessages::OutboundLanes` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Proof: UNKNOWN KEY `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`) + /// Storage: `XcmOverBridgeHubRococo::LaneToBridge` (r:1 w:0) + /// Proof: `XcmOverBridgeHubRococo::LaneToBridge` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubRococo::Bridges` (r:1 w:0) + /// Proof: `XcmOverBridgeHubRococo::Bridges` (`max_values`: None, `max_size`: Some(1893), added: 4368, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoMessages::OutboundMessages` (r:0 w:1) + /// Proof: `BridgeRococoMessages::OutboundMessages` (`max_values`: None, `max_size`: Some(65568), added: 68043, mode: `MaxEncodedLen`) + fn receive_delivery_proof_for_single_message() -> Weight { + // Proof Size summary in bytes: + // Measured: `711` + // Estimated: `5358` + // Minimum execution time: 51_650_000 picoseconds. + Weight::from_parts(53_190_000, 0) + .saturating_add(Weight::from_parts(0, 5358)) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(3)) + } + /// Storage: `BridgeRococoMessages::PalletOperatingMode` (r:1 w:0) + /// Proof: `BridgeRococoMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoParachains::ImportedParaHeads` (r:1 w:0) + /// Proof: `BridgeRococoParachains::ImportedParaHeads` (`max_values`: Some(64), `max_size`: Some(196), added: 1186, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoMessages::OutboundLanes` (r:1 w:1) + /// Proof: `BridgeRococoMessages::OutboundLanes` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Proof: UNKNOWN KEY `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`) + /// Storage: `XcmOverBridgeHubRococo::LaneToBridge` (r:1 w:0) + /// Proof: `XcmOverBridgeHubRococo::LaneToBridge` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubRococo::Bridges` (r:1 w:0) + /// Proof: `XcmOverBridgeHubRococo::Bridges` (`max_values`: None, `max_size`: Some(1893), added: 4368, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoMessages::OutboundMessages` (r:0 w:2) + /// Proof: `BridgeRococoMessages::OutboundMessages` (`max_values`: None, `max_size`: Some(65568), added: 68043, mode: `MaxEncodedLen`) + fn receive_delivery_proof_for_two_messages_by_single_relayer() -> Weight { + // Proof Size summary in bytes: + // Measured: `711` + // Estimated: `5358` + // Minimum execution time: 51_836_000 picoseconds. + Weight::from_parts(53_960_000, 0) + .saturating_add(Weight::from_parts(0, 5358)) + .saturating_add(T::DbWeight::get().reads(7)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: `BridgeRococoMessages::PalletOperatingMode` (r:1 w:0) + /// Proof: `BridgeRococoMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoParachains::ImportedParaHeads` (r:1 w:0) + /// Proof: `BridgeRococoParachains::ImportedParaHeads` (`max_values`: Some(64), `max_size`: Some(196), added: 1186, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoMessages::OutboundLanes` (r:1 w:1) + /// Proof: `BridgeRococoMessages::OutboundLanes` (`max_values`: None, `max_size`: Some(45), added: 2520, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x6e0a18b62a1de81c5f519181cc611e18` (r:1 w:0) + /// Proof: UNKNOWN KEY `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`) + /// Storage: `XcmOverBridgeHubRococo::LaneToBridge` (r:1 w:0) + /// Proof: `XcmOverBridgeHubRococo::LaneToBridge` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubRococo::Bridges` (r:1 w:0) + /// Proof: `XcmOverBridgeHubRococo::Bridges` (`max_values`: None, `max_size`: Some(1893), added: 4368, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoMessages::OutboundMessages` (r:0 w:2) + /// Proof: `BridgeRococoMessages::OutboundMessages` (`max_values`: None, `max_size`: Some(65568), added: 68043, mode: `MaxEncodedLen`) + fn receive_delivery_proof_for_two_messages_by_two_relayers() -> Weight { + // Proof Size summary in bytes: + // Measured: `711` + // Estimated: `6086` + // Minimum execution time: 56_606_000 picoseconds. + Weight::from_parts(58_528_000, 0) + .saturating_add(Weight::from_parts(0, 6086)) + .saturating_add(T::DbWeight::get().reads(8)) + .saturating_add(T::DbWeight::get().writes(5)) + } + /// Storage: `BridgeWestendMessages::PalletOperatingMode` (r:1 w:0) + /// Proof: `BridgeWestendMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendParachains::ImportedParaHeads` (r:1 w:0) + /// Proof: `BridgeWestendParachains::ImportedParaHeads` (`max_values`: Some(64), `max_size`: Some(196), added: 1186, mode: `MaxEncodedLen`) + /// Storage: `BridgeWestendMessages::InboundLanes` (r:1 w:1) + /// Proof: `BridgeWestendMessages::InboundLanes` (`max_values`: None, `max_size`: Some(49180), added: 51655, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::LaneToBridge` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::LaneToBridge` (`max_values`: None, `max_size`: Some(36), added: 2511, mode: `MaxEncodedLen`) + /// Storage: `XcmOverBridgeHubWestend::Bridges` (r:1 w:0) + /// Proof: `XcmOverBridgeHubWestend::Bridges` (`max_values`: None, `max_size`: Some(1893), added: 4368, mode: `MaxEncodedLen`) + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:1) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: Some(1282), added: 1777, 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: `XcmpQueue::DeliveryFeeFactor` (r:1 w:0) + /// Proof: `XcmpQueue::DeliveryFeeFactor` (`max_values`: None, `max_size`: Some(28), added: 2503, 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::OutboundXcmpMessages` (r:0 w:1) + /// Proof: `XcmpQueue::OutboundXcmpMessages` (`max_values`: None, `max_size`: Some(105506), added: 107981, mode: `MaxEncodedLen`) + /// The range of component `n` is `[1, 16384]`. + /// The range of component `n` is `[1, 16384]`. + fn receive_single_n_bytes_message_proof_with_dispatch(n: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `1071` + // Estimated: `52645` + // Minimum execution time: 85_179_000 picoseconds. + Weight::from_parts(91_600_892, 0) + .saturating_add(Weight::from_parts(0, 52645)) + // Standard Error: 11 + .saturating_add(Weight::from_parts(7_210, 0).saturating_mul(n.into())) + .saturating_add(T::DbWeight::get().reads(12)) + .saturating_add(T::DbWeight::get().writes(4)) + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_bridge_relayers.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_bridge_relayers.rs new file mode 100644 index 0000000000000..74ebabe3e49b8 --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_bridge_relayers.rs @@ -0,0 +1,132 @@ +// Copyright (C) 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 32.0.0 +//! DATE: 2024-08-15, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-696hpswk-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("bridge-hub-westend-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/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_bridge_relayers +// --chain=bridge-hub-westend-dev TODO: FAIL-CI regenerate +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/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(102), added: 2577, 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: `306` + // Estimated: `3593` + // Minimum execution time: 53_924_000 picoseconds. + Weight::from_parts(54_736_000, 0) + .saturating_add(Weight::from_parts(0, 3593)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(2)) + } + /// Storage: `Benchmark::Override` (r:0 w:0) + /// Proof: `Benchmark::Override` (`max_values`: None, `max_size`: None, mode: `Measured`) + fn claim_rewards_to() -> Weight { + // Proof Size summary in bytes: + // Measured: `0` + // Estimated: `0` + // Minimum execution time: 18_446_744_073_709_551_000 picoseconds. + Weight::from_parts(18_446_744_073_709_551_000, 0) + .saturating_add(Weight::from_parts(0, 0)) + } + /// Storage: `BridgeRelayers::RegisteredRelayers` (r:1 w:1) + /// Proof: `BridgeRelayers::RegisteredRelayers` (`max_values`: None, `max_size`: Some(68), added: 2543, mode: `MaxEncodedLen`) + /// Storage: UNKNOWN KEY `0x1e8445dc201eeb8560e5579a5dd54655` (r:1 w:0) + /// Proof: UNKNOWN KEY `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: 28_608_000 picoseconds. + Weight::from_parts(29_081_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: 29_738_000 picoseconds. + Weight::from_parts(30_242_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: 33_174_000 picoseconds. + Weight::from_parts(33_992_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(102), added: 2577, mode: `MaxEncodedLen`) + fn register_relayer_reward() -> Weight { + // Proof Size summary in bytes: + // Measured: `76` + // Estimated: `3567` + // Minimum execution time: 7_950_000 picoseconds. + Weight::from_parts(8_123_000, 0) + .saturating_add(Weight::from_parts(0, 3567)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_xcm_bridge.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_xcm_bridge.rs new file mode 100644 index 0000000000000..0ab2e7b184a23 --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_xcm_bridge.rs @@ -0,0 +1,109 @@ +// Copyright (C) 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` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 32.0.0 +//! DATE: 2024-11-18, STEPS: `2`, REPEAT: `1`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `toaster1`, CPU: `AMD Ryzen Threadripper 7980X 64-Cores` +//! WASM-EXECUTION: `Compiled`, CHAIN: `None`, DB CACHE: 1024 +// Executed Command: +// ./target/release/frame-omni-bencher +// v1 +// benchmark +// pallet +// --runtime +// ./target/debug/wbuild/asset-hub-rococo-runtime/asset_hub_rococo_runtime.wasm +// --pallet +// pallet_xcm_bridge_hub +// --extrinsic +// * +// --steps +// 2 +// --repeat +// 1 +// --output +// ./remote-builds -- TODO: FAIL-CI new 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`. +pub struct WeightInfo(PhantomData); +impl pallet_xcm_bridge::WeightInfo for WeightInfo { + /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) + /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `XcmOverAssetHubRococo::Bridges` (r:1 w:1) + /// Proof: `XcmOverAssetHubRococo::Bridges` (`max_values`: None, `max_size`: Some(1922), added: 4397, mode: `MaxEncodedLen`) + /// Storage: `XcmOverAssetHubRococo::LaneToBridge` (r:1 w:1) + /// Proof: `XcmOverAssetHubRococo::LaneToBridge` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoMessages::InboundLanes` (r:1 w:1) + /// Proof: `BridgeRococoMessages::InboundLanes` (`max_values`: None, `max_size`: Some(49208), added: 51683, mode: `MaxEncodedLen`) + /// Storage: `XcmpQueue::OutboundXcmpStatus` (r:1 w:0) + /// Proof: `XcmpQueue::OutboundXcmpStatus` (`max_values`: Some(1), `max_size`: Some(1282), added: 1777, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoMessages::OutboundLanes` (r:1 w:1) + /// Proof: `BridgeRococoMessages::OutboundLanes` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + fn open_bridge() -> Weight { + // Proof Size summary in bytes: + // Measured: `214` + // Estimated: `52673` + // Minimum execution time: 40_171_000 picoseconds. + Weight::from_parts(40_171_000, 0) + .saturating_add(Weight::from_parts(0, 52673)) + .saturating_add(T::DbWeight::get().reads(6)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) + /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `XcmOverAssetHubRococo::Bridges` (r:1 w:1) + /// Proof: `XcmOverAssetHubRococo::Bridges` (`max_values`: None, `max_size`: Some(1922), added: 4397, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoMessages::InboundLanes` (r:1 w:1) + /// Proof: `BridgeRococoMessages::InboundLanes` (`max_values`: None, `max_size`: Some(49208), added: 51683, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoMessages::OutboundLanes` (r:1 w:1) + /// Proof: `BridgeRococoMessages::OutboundLanes` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `XcmOverAssetHubRococo::LaneToBridge` (r:0 w:1) + /// Proof: `XcmOverAssetHubRococo::LaneToBridge` (`max_values`: None, `max_size`: Some(64), added: 2539, mode: `MaxEncodedLen`) + fn close_bridge() -> Weight { + // Proof Size summary in bytes: + // Measured: `488` + // Estimated: `52673` + // Minimum execution time: 30_096_000 picoseconds. + Weight::from_parts(30_096_000, 0) + .saturating_add(Weight::from_parts(0, 52673)) + .saturating_add(T::DbWeight::get().reads(4)) + .saturating_add(T::DbWeight::get().writes(4)) + } + /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) + /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `XcmOverAssetHubRococo::Bridges` (r:1 w:1) + /// Proof: `XcmOverAssetHubRococo::Bridges` (`max_values`: None, `max_size`: Some(1922), added: 4397, mode: `MaxEncodedLen`) + fn update_notification_receiver() -> Weight { + // Proof Size summary in bytes: + // Measured: `212` + // Estimated: `5387` + // Minimum execution time: 15_994_000 picoseconds. + Weight::from_parts(15_994_000, 0) + .saturating_add(Weight::from_parts(0, 5387)) + .saturating_add(T::DbWeight::get().reads(2)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_xcm_bridge_router_to_rococo_over_asset_hub_rococo.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_xcm_bridge_router_to_rococo_over_asset_hub_rococo.rs new file mode 100644 index 0000000000000..c0437f3a570da --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_xcm_bridge_router_to_rococo_over_asset_hub_rococo.rs @@ -0,0 +1,65 @@ + +// Copyright (C) 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 32.0.0 +//! DATE: 2024-12-07, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-acd6uxux-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-westend-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/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_xcm_bridge_hub_router +// --chain=asset-hub-westend-dev +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/assets/asset-hub-westend/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_router::WeightInfo for WeightInfo { + /// Storage: `ToWestendXcmRouter::Bridges` (r:1 w:1) + /// Proof: `ToWestendXcmRouter::Bridges` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + fn update_bridge_status() -> Weight { + // TODO: FAIL-CI new weights + // Proof Size summary in bytes: + // Measured: `109` + // Estimated: `3530` + // Minimum execution time: 12_193_000 picoseconds. + Weight::from_parts(12_658_000, 0) + .saturating_add(Weight::from_parts(0, 3530)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_xcm_bridge_router_to_rococo_over_bridge_hub.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_xcm_bridge_router_to_rococo_over_bridge_hub.rs new file mode 100644 index 0000000000000..9d51c6f181ef3 --- /dev/null +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/pallet_xcm_bridge_router_to_rococo_over_bridge_hub.rs @@ -0,0 +1,63 @@ +// Copyright (C) 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 32.0.0 +//! DATE: 2024-11-09, STEPS: `50`, REPEAT: `20`, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! WORST CASE MAP SIZE: `1000000` +//! HOSTNAME: `runner-wiukf8gn-project-674-concurrent-0`, CPU: `Intel(R) Xeon(R) CPU @ 2.60GHz` +//! WASM-EXECUTION: `Compiled`, CHAIN: `Some("asset-hub-westend-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/polkadot-sdk/.git/.artifacts/bench.json +// --pallet=pallet_xcm_bridge_hub_router +// --chain=asset-hub-westend-dev +// --header=./cumulus/file_header.txt +// --output=./cumulus/parachains/runtimes/assets/asset-hub-westend/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_router::WeightInfo for WeightInfo { + /// Storage: `ToWestendXcmRouter::Bridges` (r:1 w:1) + /// Proof: `ToWestendXcmRouter::Bridges` (`max_values`: None, `max_size`: Some(65), added: 2540, mode: `MaxEncodedLen`) + fn update_bridge_status() -> Weight { + // TODO: FAIL-CI fresh weights + // Proof Size summary in bytes: + // Measured: `109` + // Estimated: `3530` + // Minimum execution time: 12_193_000 picoseconds. + Weight::from_parts(12_658_000, 0) + .saturating_add(Weight::from_parts(0, 3530)) + .saturating_add(T::DbWeight::get().reads(1)) + .saturating_add(T::DbWeight::get().writes(1)) + } +} diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/xcm/mod.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/xcm/mod.rs index 27532ac431e7a..e85a7cc83f7a3 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/xcm/mod.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/xcm/mod.rs @@ -21,6 +21,7 @@ use crate::{ Runtime, }; use alloc::vec::Vec; +use codec::Encode; use assets_common::IsLocalAccountKey20; use frame_support::{traits::Contains, weights::Weight}; use pallet_xcm_benchmarks_fungible::WeightInfo as XcmFungibleWeight; @@ -269,8 +270,9 @@ impl XcmWeightInfo for AssetHubWestendXcmWeight { fn universal_origin(_: &Junction) -> Weight { XcmGeneric::::universal_origin() } - 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(_: &Asset, _: &Location) -> Weight { Weight::MAX diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/xcm/pallet_xcm_benchmarks_generic.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/xcm/pallet_xcm_benchmarks_generic.rs index 16ad43529bf89..f36d8d59da7c5 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/xcm/pallet_xcm_benchmarks_generic.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/weights/xcm/pallet_xcm_benchmarks_generic.rs @@ -368,6 +368,30 @@ impl WeightInfo { Weight::from_parts(5_429_000, 1489) .saturating_add(T::DbWeight::get().reads(1)) } + /// Storage: `ParachainInfo::ParachainId` (r:1 w:0) + /// Proof: `ParachainInfo::ParachainId` (`max_values`: Some(1), `max_size`: Some(4), added: 499, mode: `MaxEncodedLen`) + /// Storage: `XcmOverAssetHubRococo::Bridges` (r:1 w:0) + /// Proof: `XcmOverAssetHubRococo::Bridges` (`max_values`: None, `max_size`: Some(1922), added: 4397, mode: `MaxEncodedLen`) + /// Storage: `PolkadotXcm::SupportedVersion` (r:2 w:0) + /// Proof: `PolkadotXcm::SupportedVersion` (`max_values`: None, `max_size`: None, mode: `Measured`) + /// Storage: `BridgeRococoMessages::PalletOperatingMode` (r:1 w:0) + /// Proof: `BridgeRococoMessages::PalletOperatingMode` (`max_values`: Some(1), `max_size`: Some(2), added: 497, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoMessages::OutboundLanes` (r:1 w:1) + /// Proof: `BridgeRococoMessages::OutboundLanes` (`max_values`: None, `max_size`: Some(73), added: 2548, mode: `MaxEncodedLen`) + /// Storage: `BridgeRococoMessages::OutboundMessages` (r:0 w:1) + /// Proof: `BridgeRococoMessages::OutboundMessages` (`max_values`: None, `max_size`: Some(65596), added: 68071, mode: `MaxEncodedLen`) + /// The range of component `x` is `[1, 1000]`. + pub fn export_message(x: u32, ) -> Weight { + // Proof Size summary in bytes: + // Measured: `546` + // Estimated: `6486` + // Minimum execution time: 59_944_000 picoseconds. + Weight::from_parts(63_325_816, 6486) + // Standard Error: 326 + .saturating_add(Weight::from_parts(58_420, 0).saturating_mul(x.into())) + .saturating_add(T::DbWeight::get().reads(6)) + .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/assets/asset-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs index 34412d3ad1729..1e675d5b4a1fe 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/src/xcm_config.rs @@ -18,7 +18,8 @@ use super::{ BaseDeliveryFee, CollatorSelection, DepositPerByte, DepositPerItem, FeeAssetId, FellowshipAdmin, ForeignAssets, GeneralAdmin, ParachainInfo, ParachainSystem, PolkadotXcm, PoolAssets, Runtime, RuntimeCall, RuntimeEvent, RuntimeHoldReason, RuntimeOrigin, StakingAdmin, - ToRococoXcmRouter, TransactionByteFee, Treasurer, Uniques, WeightToFee, XcmpQueue, + ToRococoOverAssetHubRococoXcmRouter, ToRococoXcmRouter, TransactionByteFee, Treasurer, Uniques, + WeightToFee, XcmOverAssetHubRococo, XcmpQueue, }; use assets_common::{ matching::{FromSiblingParachain, IsForeignConcreteAsset, ParentLocation}, @@ -66,11 +67,11 @@ use xcm_executor::XcmExecutor; parameter_types! { pub const RootLocation: Location = Location::here(); pub const WestendLocation: Location = Location::parent(); - pub const RelayNetwork: Option = Some(NetworkId::ByGenesis(WESTEND_GENESIS_HASH)); + pub const RelayNetwork: NetworkId = NetworkId::ByGenesis(WESTEND_GENESIS_HASH); pub const AssetHubParaId: crate::ParaId = crate::ParaId::new(ASSET_HUB_ID); pub RelayChainOrigin: RuntimeOrigin = cumulus_pallet_xcm::Origin::Relay.into(); pub UniversalLocation: InteriorLocation = - [GlobalConsensus(RelayNetwork::get().unwrap()), Parachain(ParachainInfo::parachain_id().into())].into(); + [GlobalConsensus(RelayNetwork::get()), Parachain(ParachainInfo::parachain_id().into())].into(); pub UniversalLocationNetworkId: NetworkId = UniversalLocation::get().global_consensus().unwrap(); pub TrustBackedAssetsPalletLocation: Location = PalletInstance(TrustBackedAssetsPalletIndex::get()).into(); @@ -452,7 +453,10 @@ impl xcm_executor::Config for XcmConfig { WaivedLocations, SendXcmFeeToAccount, >; - type MessageExporter = (); + type MessageExporter = ( + // AH's permissionless lanes support exporting to Rococo. + XcmOverAssetHubRococo, + ); type UniversalAliases = (bridging::to_rococo::UniversalAliases, bridging::to_ethereum::UniversalAliases); type CallDispatcher = RuntimeCall; @@ -512,7 +516,7 @@ pub type PriceForParentDelivery = ExponentialPrice; /// For routing XCM messages which do not cross local consensus boundary. -type LocalXcmRouter = ( +pub(crate) type LocalXcmRouter = ( // Two routers - use UMP to communicate with the relay chain: cumulus_primitives_utility::ParentAsUmp, // ..and XCMP to communicate with the sibling chains. @@ -525,6 +529,15 @@ pub type XcmRouter = WithUniqueTopic<( LocalXcmRouter, // Router which wraps and sends xcm to BridgeHub to be delivered to the Rococo // GlobalConsensus + // Router that exports messages to be delivered to the Rococo GlobalConsensus, + // when a permissionless lane is created between the origin and destination. + // + // Note: `ToRococoOverAssetHubRococoXcmRouter` must come before `ToRococoXcmRouter` + // because it checks if the lane is created dynamically, whereas `ToRococoXcmRouter` has a + // static configuration. + ToRococoOverAssetHubRococoXcmRouter, + // Router which wraps (`ExportMessage`) and sends xcm to BridgeHub to be delivered to the + // Rococo GlobalConsensus ToRococoXcmRouter, // Router which wraps and sends xcm to BridgeHub to be delivered to the Ethereum // GlobalConsensus with a pausable flag, if the flag is set true then the Router is paused @@ -608,10 +621,12 @@ pub mod bridging { use assets_common::matching; parameter_types! { + /// (for AH -> -> BH -> BH -> AH route) + /// /// Base price of every byte of the Westend -> Rococo message. Can be adjusted via /// governance `set_storage` call. /// - /// Default value is our estimation of the: + /// The default value is our estimation of the: /// /// 1) an approximate cost of XCM execution (`ExportMessage` and surroundings) at Westend bridge hub; /// @@ -623,6 +638,26 @@ pub mod bridging { bp_bridge_hub_westend::BridgeHubWestendBaseXcmFeeInWnds::get() .saturating_add(bp_bridge_hub_rococo::BridgeHubRococoBaseDeliveryFeeInRocs::get()) .saturating_add(bp_bridge_hub_westend::BridgeHubWestendBaseConfirmationFeeInWnds::get()); + + /// (for direct AH -> AH route) + /// + /// Base price of every byte of the Westend -> Rococo message. Can be adjusted via + /// governance `set_storage` call. + /// + /// The default value is our estimation of the: + /// + /// 1) the approximate cost of Westend -> Rococo message delivery transaction on Rococo Asset Hub, + /// converted into WNDs using 1:1 conversion rate; + /// + /// 2) the approximate cost of Westend -> Rococo message confirmation transaction on Westend Asset Hub. + /// + /// Note: We do not account for `ExportMessage`, because we are doing direct `ExportXcm`, + /// which should be already accounted for benchmarked extrinsic cost. + pub storage ToRococoOverAssetHubRococoXcmRouterBaseFee: Balance = DefaultToRococoOverAssetHubRococoXcmRouterBaseFee::get(); + pub const DefaultToRococoOverAssetHubRococoXcmRouterBaseFee: Balance = + bp_asset_hub_rococo::AssetHubRococoBaseDeliveryFeeInRocs::get() + .saturating_add(bp_asset_hub_westend::AssetHubWestendBaseConfirmationFeeInWnds::get()); + /// Price of every byte of the Westend -> Rococo message. Can be adjusted via /// governance `set_storage` call. pub storage XcmBridgeHubRouterByteFee: Balance = TransactionByteFee::get(); @@ -645,6 +680,12 @@ pub mod bridging { PalletInstance(bp_bridge_hub_westend::WITH_BRIDGE_WESTEND_TO_ROCOCO_MESSAGES_PALLET_INDEX) ] ); + pub LocalBridge: Location = Location::new( + 0, + [ + PalletInstance(bp_asset_hub_westend::WITH_BRIDGE_WESTEND_TO_ROCOCO_MESSAGES_PALLET_INDEX) + ] + ); pub const RococoNetwork: NetworkId = NetworkId::ByGenesis(ROCOCO_GENESIS_HASH); pub RococoEcosystem: Location = Location::new(2, [GlobalConsensus(RococoNetwork::get())]); @@ -674,7 +715,10 @@ pub mod bridging { /// Universal aliases pub UniversalAliases: BTreeSet<(Location, Junction)> = BTreeSet::from_iter( alloc::vec![ - (SiblingBridgeHubWithBridgeHubRococoInstance::get(), GlobalConsensus(RococoNetwork::get())) + // The bridge over BridgeHubs (legacy). + (SiblingBridgeHubWithBridgeHubRococoInstance::get(), GlobalConsensus(RococoNetwork::get())), + // The direct bridge over AssetHubs. + (LocalBridge::get(), GlobalConsensus(RococoNetwork::get())) ] ); } diff --git a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs index f22cc74de5381..ecfeb5470c6c0 100644 --- a/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs +++ b/cumulus/parachains/runtimes/assets/asset-hub-westend/tests/tests.rs @@ -22,24 +22,30 @@ use alloy_core::{ sol_types::{sol_data, SolType}, }; use asset_hub_westend_runtime::{ - governance, xcm_config, + bridge_common_config::{BridgeRelayersInstance, BridgeReward}, + bridge_to_rococo_config, governance, xcm_config::{ - bridging, CheckingAccount, LocationToAccountId, StakingPot, + self, bridging, CheckingAccount, LocationToAccountId, StakingPot, TrustBackedAssetsPalletLocation, WestendLocation, XcmConfig, }, - AllPalletsWithoutSystem, Assets, Balances, Block, ExistentialDeposit, ForeignAssets, - ForeignAssetsInstance, MetadataDepositBase, MetadataDepositPerByte, ParachainSystem, - PolkadotXcm, Revive, Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin, SessionKeys, - ToRococoXcmRouterInstance, TrustBackedAssetsInstance, XcmpQueue, + AllPalletsWithoutSystem, Assets, Balances, Block, BridgeRejectObsoleteHeadersAndMessages, + BridgeRelayers, ExistentialDeposit, ForeignAssets, ForeignAssetsInstance, MetadataDepositBase, + MetadataDepositPerByte, ParachainSystem, PolkadotXcm, Revive, Runtime, RuntimeCall, + RuntimeEvent, RuntimeOrigin, SessionKeys, ToRococoXcmRouterInstance, TransactionPayment, + TrustBackedAssetsInstance, TxExtension, UncheckedExtrinsic, XcmpQueue, }; pub use asset_hub_westend_runtime::{AssetConversion, AssetDeposit, CollatorSelection, System}; use asset_test_utils::{ test_cases_over_bridge::TestBridgingConfig, CollatorSessionKey, CollatorSessionKeys, ExtBuilder, GovernanceOrigin, SlotDurations, }; +use bp_asset_hub_westend::Signature; +use bridge_hub_test_utils::test_cases::run_test; use codec::{Decode, Encode}; use frame_support::{ - assert_err, assert_noop, assert_ok, parameter_types, + assert_err, assert_noop, assert_ok, + dispatch::GetDispatchInfo, + parameter_types, traits::{ fungible::{self, Inspect, Mutate}, fungibles::{ @@ -58,7 +64,12 @@ use pallet_revive_fixtures::compile_module; use parachains_common::{AccountId, AssetIdForTrustBackedAssets, AuraId, Balance}; use sp_consensus_aura::SlotDuration; use sp_core::crypto::Ss58Codec; -use sp_runtime::{traits::MaybeEquivalence, Either}; +use sp_keyring::Sr25519Keyring::Alice; +use sp_runtime::{ + generic::{self, Era, SignedPayload}, + traits::MaybeEquivalence, + Either, +}; use std::convert::Into; use testnet_parachains_constants::westend::{consensus::*, currency::UNITS, fee::WeightToFee}; use xcm::{ @@ -97,6 +108,47 @@ fn collator_session_keys() -> CollatorSessionKeys { CollatorSessionKeys::default().add(collator_session_key(ALICE)) } +fn construct_extrinsic( + sender: sp_keyring::Sr25519Keyring, + call: RuntimeCall, +) -> UncheckedExtrinsic { + let account_id = sp_runtime::AccountId32::from(sender.public()); + let tx_ext: TxExtension = ( + frame_system::AuthorizeCall::::new(), + 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( + frame_system::Pallet::::account(&account_id).nonce, + ), + frame_system::CheckWeight::::new(), + pallet_asset_conversion_tx_payment::ChargeAssetTxPayment::::from( + Balance::MIN, + None, + ), + frame_metadata_hash_extension::CheckMetadataHash::new(false), + BridgeRejectObsoleteHeadersAndMessages::default(), + (bridge_to_rococo_config::OnAssetHubWestendRefundAssetHubRococoMessages::default(),), + ) + .into(); + let payload = SignedPayload::new(call.clone(), tx_ext.clone()).unwrap(); + let signature = payload.using_encoded(|e| sender.sign(e)); + UncheckedExtrinsic::from(generic::UncheckedExtrinsic::new_signed( + call, + account_id.into(), + Signature::Sr25519(signature), + tx_ext, + )) +} + +fn construct_and_estimate_extrinsic_fee(call: RuntimeCall) -> Balance { + let info = call.get_dispatch_info(); + let xt = construct_extrinsic(Alice, call); + TransactionPayment::compute_fee(xt.encoded_size() as _, &info, 0) +} + fn slot_durations() -> SlotDurations { SlotDurations { relay: SlotDuration::from_millis(RELAY_CHAIN_SLOT_DURATION_MILLIS.into()), @@ -838,6 +890,7 @@ asset_test_utils::include_create_and_manage_foreign_assets_for_local_consensus_p }) ); +/// The bridge over BridgeHubs: AHW <-> BHW <-> BHR <-> AHR fn bridging_to_asset_hub_rococo() -> TestBridgingConfig { let _ = PolkadotXcm::force_xcm_version( RuntimeOrigin::root(), @@ -853,6 +906,24 @@ fn bridging_to_asset_hub_rococo() -> TestBridgingConfig { } } +/// The direct bridge over AssetHubs: AHW <-> AHR +fn direct_bridging_to_asset_hub_rococo() -> TestBridgingConfig { + let _ = PolkadotXcm::force_xcm_version( + RuntimeOrigin::root(), + Box::new(bridging::to_rococo::AssetHubRococo::get()), + XCM_VERSION, + ) + .expect("version saved!"); + TestBridgingConfig { + bridged_network: bridging::to_rococo::RococoNetwork::get(), + // Local AH para_id. + local_bridge_hub_para_id: bp_asset_hub_westend::ASSET_HUB_WESTEND_PARACHAIN_ID, + // The bridge is deployed `Here` on the AH chain. + local_bridge_hub_location: Location::here(), + bridged_target_location: bridging::to_rococo::AssetHubRococo::get(), + } +} + #[test] fn limited_reserve_transfer_assets_for_native_asset_to_asset_hub_rococo_works() { asset_test_utils::test_cases_over_bridge::limited_reserve_transfer_assets_for_native_asset_works::< @@ -888,21 +959,28 @@ fn limited_reserve_transfer_assets_for_native_asset_to_asset_hub_rococo_works() #[test] fn receive_reserve_asset_deposited_roc_from_asset_hub_rococo_fees_paid_by_pool_swap_works() { - const BLOCK_AUTHOR_ACCOUNT: [u8; 32] = [13; 32]; - let block_author_account = AccountId::from(BLOCK_AUTHOR_ACCOUNT); - let staking_pot = StakingPot::get(); - - let foreign_asset_id_location = xcm::v5::Location::new( - 2, - [xcm::v5::Junction::GlobalConsensus(xcm::v5::NetworkId::ByGenesis(ROCOCO_GENESIS_HASH))], - ); - let foreign_asset_id_minimum_balance = 1_000_000_000; - // sovereign account as foreign asset owner (can be whoever for this scenario) - let foreign_asset_owner = LocationToAccountId::convert_location(&Location::parent()).unwrap(); - let foreign_asset_create_params = - (foreign_asset_owner, foreign_asset_id_location.clone(), foreign_asset_id_minimum_balance); - - asset_test_utils::test_cases_over_bridge::receive_reserve_asset_deposited_from_different_consensus_works::< + fn test_with(bridging_cfg: impl Fn() -> TestBridgingConfig, bridge_instance: InteriorLocation) { + const BLOCK_AUTHOR_ACCOUNT: [u8; 32] = [13; 32]; + let block_author_account = AccountId::from(BLOCK_AUTHOR_ACCOUNT); + let staking_pot = StakingPot::get(); + + let foreign_asset_id_location = xcm::v5::Location::new( + 2, + [xcm::v5::Junction::GlobalConsensus(xcm::v5::NetworkId::ByGenesis( + ROCOCO_GENESIS_HASH, + ))], + ); + let foreign_asset_id_minimum_balance = 1_000_000_000; + // sovereign account as a foreign asset owner (can be whoever for this scenario) + let foreign_asset_owner = + LocationToAccountId::convert_location(&Location::parent()).unwrap(); + let foreign_asset_create_params = ( + foreign_asset_owner, + foreign_asset_id_location.clone(), + foreign_asset_id_minimum_balance, + ); + + asset_test_utils::test_cases_over_bridge::receive_reserve_asset_deposited_from_different_consensus_works::< Runtime, AllPalletsWithoutSystem, XcmConfig, @@ -921,10 +999,10 @@ fn receive_reserve_asset_deposited_roc_from_asset_hub_rococo_fees_paid_by_pool_s // staking pot account for collecting local native fees from `BuyExecution` let _ = Balances::force_set_balance(RuntimeOrigin::root(), StakingPot::get().into(), ExistentialDeposit::get()); // prepare bridge configuration - bridging_to_asset_hub_rococo() + bridging_cfg() }, ( - [PalletInstance(bp_bridge_hub_westend::WITH_BRIDGE_WESTEND_TO_ROCOCO_MESSAGES_PALLET_INDEX)].into(), + bridge_instance, GlobalConsensus(ByGenesis(ROCOCO_GENESIS_HASH)), [Parachain(1000)].into() ), @@ -955,6 +1033,22 @@ fn receive_reserve_asset_deposited_roc_from_asset_hub_rococo_fees_paid_by_pool_s ); } ) + } + + // The bridge with BHs is working. + test_with( + bridging_to_asset_hub_rococo, + [PalletInstance( + bp_bridge_hub_westend::WITH_BRIDGE_WESTEND_TO_ROCOCO_MESSAGES_PALLET_INDEX, + )] + .into(), + ); + // The bridge with direct AHs is working. + test_with( + direct_bridging_to_asset_hub_rococo, + [PalletInstance(bp_asset_hub_westend::WITH_BRIDGE_WESTEND_TO_ROCOCO_MESSAGES_PALLET_INDEX)] + .into(), + ); } #[test] @@ -1754,3 +1848,472 @@ fn expensive_erc20_runs_out_of_gas() { .is_err()); }); } + +mod bridge_to_rococo_tests { + use super::{ + collator_session_keys, construct_and_estimate_extrinsic_fee, slot_durations, AccountId, + ExtBuilder, Governance, RuntimeHelper, + }; + use asset_hub_westend_runtime::{ + bridge_common_config::DeliveryRewardInBalance, + bridge_to_rococo_config::{ + AssetHubRococoLocation, RococoGlobalConsensusNetwork, + WithAssetHubRococoMessagesInstance, XcmOverAssetHubRococoInstance, + }, + xcm_config::{bridging, LocationToAccountId, RelayNetwork, WestendLocation, XcmConfig}, + AllPalletsWithoutSystem, ExistentialDeposit, ParachainSystem, PolkadotXcm, Runtime, + RuntimeEvent, RuntimeOrigin, + }; + use bp_runtime::RangeInclusiveExt; + use bridge_hub_test_utils::{mock_open_hrmp_channel, test_cases}; + use codec::Decode; + use cumulus_primitives_core::UpwardMessageSender; + use frame_support::traits::{ConstU8, ProcessMessageError}; + use sp_runtime::Perbill; + use testnet_parachains_constants::westend::fee::WeightToFee; + use xcm::latest::prelude::*; + use xcm_builder::{CreateMatcher, MatchXcm}; + + // Random para id of sibling chain used in tests. + pub const SIBLING_PARACHAIN_ID: u32 = 2053; + // Random para id of bridged chain from different global consensus used in tests. + pub const BRIDGED_LOCATION_PARACHAIN_ID: u32 = 1075; + const RUNTIME_PARA_ID: u32 = bp_asset_hub_westend::ASSET_HUB_WESTEND_PARACHAIN_ID; + + frame_support::parameter_types! { + pub SiblingParachainLocation: Location = Location::new(1, [Parachain(SIBLING_PARACHAIN_ID)]); + pub BridgedUniversalLocation: InteriorLocation = [GlobalConsensus(RococoGlobalConsensusNetwork::get()), Parachain(BRIDGED_LOCATION_PARACHAIN_ID)].into(); + } + + #[test] + fn change_bridge_messages_pallet_mode_by_governance_works() { + bridge_hub_test_utils::test_cases::change_bridge_messages_pallet_mode_by_governance_works::< + Runtime, + WithAssetHubRococoMessagesInstance, + >(collator_session_keys(), RUNTIME_PARA_ID, Governance::get()) + } + + #[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(), + RUNTIME_PARA_ID, + Governance::get(), + || (DeliveryRewardInBalance::key().to_vec(), DeliveryRewardInBalance::get()), + |old_value| old_value.checked_mul(2).unwrap(), + ) + } + + #[test] + fn handle_export_message_from_sibling_parachain_and_add_to_outbound_queue_works() { + // for Westend + bridge_hub_test_utils::test_cases::handle_export_message_from_system_parachain_to_outbound_queue_works::< + Runtime, + XcmConfig, + WithAssetHubRococoMessagesInstance, + >( + collator_session_keys(), + RUNTIME_PARA_ID, + SIBLING_PARACHAIN_ID, + Box::new(|runtime_event_encoded: Vec| { + match RuntimeEvent::decode(&mut &runtime_event_encoded[..]) { + Ok(RuntimeEvent::BridgeRococoMessages(event)) => Some(event), + _ => None, + } + }), + || ExportMessage { network: RococoGlobalConsensusNetwork::get(), destination: [Parachain(BRIDGED_LOCATION_PARACHAIN_ID)].into(), xcm: Xcm(vec![]) }, + Some((WestendLocation::get(), ExistentialDeposit::get()).into()), + // value should be >= than value generated by `can_calculate_weight_for_paid_export_message_with_reserve_transfer` + Some(( + WestendLocation::get(), + bp_asset_hub_westend::AssetHubWestendBaseXcmFeeInWnds::get() + + bridging::DefaultToRococoOverAssetHubRococoXcmRouterBaseFee::get() + ).into()), + || { + PolkadotXcm::force_xcm_version(RuntimeOrigin::root(), Box::new(AssetHubRococoLocation::get()), XCM_VERSION).expect("version saved!"); + + // we need to create lane between sibling parachain and remote destination + bridge_hub_test_utils::ensure_opened_xcm_bridge::< + Runtime, + XcmOverAssetHubRococoInstance, + LocationToAccountId, + WestendLocation, + >( + SiblingParachainLocation::get(), + BridgedUniversalLocation::get(), + true, + |locations, fee| { + bridge_hub_test_utils::open_xcm_bridge_with_extrinsic::< + Runtime, + XcmOverAssetHubRococoInstance + >((locations.bridge_origin_relative_location().clone(), OriginKind::Xcm), locations.bridge_destination_universal_location().clone(), fee) + } + ).1 + }, + ) + } + + #[test] + fn message_dispatch_routing_works() { + // from Westend + bridge_hub_test_utils::test_cases::message_dispatch_routing_works::< + Runtime, + AllPalletsWithoutSystem, + XcmConfig, + ParachainSystem, + WithAssetHubRococoMessagesInstance, + RelayNetwork, + RococoGlobalConsensusNetwork, + ConstU8<2>, + >( + collator_session_keys(), + slot_durations(), + RUNTIME_PARA_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, + } + }), + || ::ensure_successful_delivery(), + ) + } + + #[test] + fn open_and_close_bridge_for_sibling_parachain_works() { + bridge_hub_test_utils::test_cases::open_and_close_xcm_bridge_works::< + Runtime, + XcmOverAssetHubRococoInstance, + LocationToAccountId, + WestendLocation, + >( + collator_session_keys(), + RUNTIME_PARA_ID, + SiblingParachainLocation::get(), + BridgedUniversalLocation::get(), + (SiblingParachainLocation::get(), OriginKind::Xcm), + true, + ) + } + + #[test] + fn open_and_close_bridge_for_relay_works() { + bridge_hub_test_utils::test_cases::open_and_close_xcm_bridge_works::< + Runtime, + XcmOverAssetHubRococoInstance, + LocationToAccountId, + WestendLocation, + >( + collator_session_keys(), + RUNTIME_PARA_ID, + Location::parent(), + BridgedUniversalLocation::get(), + (Location::parent(), OriginKind::Xcm), + false, + ) + } + + #[test] + fn open_and_close_bridge_for_local_works() { + bridge_hub_test_utils::test_cases::open_and_close_xcm_bridge_works::< + Runtime, + XcmOverAssetHubRococoInstance, + LocationToAccountId, + WestendLocation, + >( + collator_session_keys(), + RUNTIME_PARA_ID, + // The source is `here` as the local chain, e.g., AssetHub itself can open its lanes. + Location::here(), + BridgedUniversalLocation::get(), + // This should represent `RuntimeOrigin::root()` which represents `Location::here()` + // for `OpenBridgeOrigin` + (Location::parent(), OriginKind::Superuser), + false, + ) + } + + #[test] + fn rococo_xcm_routing_works() { + let runtime_para_id = 1000; + ExtBuilder::::default() + .with_collators(collator_session_keys().collators()) + .with_session_keys(collator_session_keys().session_keys()) + .with_para_id(runtime_para_id.into()) + .build() + .execute_with(|| { + frame_support::__private::sp_tracing::try_init_simple(); + let sibling_bridge_hub_para_id = bridging::SiblingBridgeHubParaId::get(); + let bridged_destination = bridging::to_rococo::AssetHubRococo::get(); + let bridged_universal_destination = bridged_destination.interior().clone(); + + // Common setup + frame_support::assert_ok!(PolkadotXcm::force_xcm_version( + RuntimeOrigin::root(), + Box::new(bridging::to_rococo::AssetHubRococo::get()), + XCM_VERSION, + )); + + // Setup for `ExportMessage` to the `BridgeHub` + let mut alice = [0u8; 32]; + alice[0] = 1; + let included_head = RuntimeHelper::run_to_block(2, AccountId::from(alice)); + mock_open_hrmp_channel::( + runtime_para_id.into(), + sibling_bridge_hub_para_id.into(), + included_head, + &alice, + &slot_durations(), + ); + frame_support::assert_ok!(PolkadotXcm::force_xcm_version( + RuntimeOrigin::root(), + Box::new(bridging::SiblingBridgeHub::get()), + XCM_VERSION, + )); + + // check no bridge/lane exists + assert_eq!( + 0, + pallet_bridge_messages::OutboundLanes::< + Runtime, + WithAssetHubRococoMessagesInstance, + >::iter() + .count() + ); + + // send to the `bridged_destination` + frame_support::assert_ok!(PolkadotXcm::send_xcm( + Here, + bridged_destination.clone(), + Xcm::<()>::default() + )); + + // check HRMP message contains `ExportMessage`. + assert!(asset_test_utils::RuntimeHelper::< + cumulus_pallet_xcmp_queue::Pallet, + AllPalletsWithoutSystem, + >::take_xcm(sibling_bridge_hub_para_id.into()) + .map(|m| { + let mut m: Xcm<()> = m.try_into().expect("valid XCM version"); + m.0.matcher() + .skip_inst_while(|inst| !matches!(inst, ExportMessage { .. })) + .expect("no instruction ExportMessage?") + .match_next_inst(|instr| match instr { + ExportMessage { ref network, .. } => { + assert_eq!( + network, + &bridged_destination + .interior + .global_consensus() + .expect("valid NetworkId") + ); + Ok(()) + }, + _ => Err(ProcessMessageError::BadFormat), + }) + .is_ok() + }) + .unwrap_or(false)); + + // open permissionless lane between this AH and bridged AH + let (_, lane_id) = bridge_hub_test_utils::ensure_opened_xcm_bridge::< + Runtime, + XcmOverAssetHubRococoInstance, + LocationToAccountId, + WestendLocation, + >( + Here.into(), + bridged_universal_destination, + false, + |locations, maybe_paid_execution| { + bridge_hub_test_utils::open_xcm_bridge_with_extrinsic::< + Runtime, + XcmOverAssetHubRococoInstance, + >( + // This should represent `RuntimeOrigin::root()` which represents + // `Location::here()` for `OpenBridgeOrigin` + (Location::parent(), OriginKind::Superuser), + locations.bridge_destination_universal_location().clone(), + maybe_paid_execution, + ) + }, + ); + // lane created + assert_eq!( + 1, + pallet_bridge_messages::OutboundLanes::< + Runtime, + WithAssetHubRococoMessagesInstance, + >::iter() + .count() + ); + + // send to the `bridged_destination` again + frame_support::assert_ok!(PolkadotXcm::send_xcm( + Here, + bridged_destination.clone(), + Xcm::<()>::default() + )); + + // messages pallet holds outbound message for expected lane_id + assert_eq!( + 1, + pallet_bridge_messages::OutboundLanes::< + Runtime, + WithAssetHubRococoMessagesInstance, + >::get(lane_id) + .map(|d| d.queued_messages().saturating_len()) + .unwrap_or(0) + ); + + // no hrmp message was fired + assert!(asset_test_utils::RuntimeHelper::< + cumulus_pallet_xcmp_queue::Pallet, + AllPalletsWithoutSystem, + >::take_xcm(sibling_bridge_hub_para_id.into()) + .is_none()); + }); + } + + #[test] + pub fn can_calculate_weight_for_paid_export_message_with_reserve_transfer() { + bridge_hub_test_utils::check_sane_fees_values( + "bp_asset_hub_westend::AssetHubWestendBaseXcmFeeInWnds", + bp_asset_hub_westend::AssetHubWestendBaseXcmFeeInWnds::get(), + || { + bridge_hub_test_utils::test_cases::can_calculate_weight_for_paid_export_message_with_reserve_transfer::< + Runtime, + XcmConfig, + WeightToFee, + >() + }, + Perbill::from_percent(33), + Some(-33), + &format!( + "Estimate fee for `ExportMessage` for runtime: {:?}", + ::Version::get() + ), + ) + } + + #[test] + fn can_calculate_fee_for_standalone_message_delivery_transaction() { + bridge_hub_test_utils::check_sane_fees_values( + "bp_asset_hub_westend::AssetHubWestendBaseDeliveryFeeInWnds", + bp_asset_hub_westend::AssetHubWestendBaseDeliveryFeeInWnds::get(), + || { + test_cases::can_calculate_fee_for_standalone_message_delivery_transaction( + collator_session_keys(), + 1000, + construct_and_estimate_extrinsic_fee, + ) + }, + Perbill::from_percent(25), + Some(-25), + &format!( + "Estimate fee for `single message delivery` for runtime: {:?}", + ::Version::get() + ), + ) + } + + #[test] + fn can_calculate_fee_for_standalone_message_confirmation_transaction() { + bridge_hub_test_utils::check_sane_fees_values( + "bp_asset_hub_westend::AssetHubWestendBaseConfirmationFeeInWnds", + bp_asset_hub_westend::AssetHubWestendBaseConfirmationFeeInWnds::get(), + || { + test_cases::can_calculate_fee_for_standalone_message_confirmation_transaction( + collator_session_keys(), + 1000, + construct_and_estimate_extrinsic_fee, + ) + }, + Perbill::from_percent(25), + Some(-25), + &format!( + "Estimate fee for `single message confirmation` for runtime: {:?}", + ::Version::get() + ), + ) + } +} + +#[test] +pub fn bridge_rewards_works() { + use bp_messages::{HashedLaneId, LaneIdType}; + use bp_relayers::{PayRewardFromAccount, RewardsAccountOwner, RewardsAccountParams}; + use sp_keyring::Sr25519Keyring::{Alice, Bob}; + use sp_runtime::AccountId32; + + run_test::( + collator_session_keys(), + bp_bridge_hub_westend::BRIDGE_HUB_WESTEND_PARACHAIN_ID, + vec![], + || { + // reward in WNDs + let reward1: u128 = 2_000_000_000; + + // prepare accounts + let account1 = AccountId32::from(Alice); + let account2 = AccountId32::from(Bob); + let reward1_for = RewardsAccountParams::new( + HashedLaneId::try_new(1, 2).unwrap(), + *b"test", + RewardsAccountOwner::ThisChain, + ); + let expected_reward1_account = + PayRewardFromAccount::<(), AccountId, HashedLaneId, ()>::rewards_account( + reward1_for, + ); + assert_ok!(Balances::mint_into(&expected_reward1_account, ExistentialDeposit::get())); + assert_ok!(Balances::mint_into(&expected_reward1_account, reward1.into())); + assert_ok!(Balances::mint_into(&account1, ExistentialDeposit::get())); + + // register rewards + use bp_relayers::RewardLedger; + BridgeRelayers::register_reward(&account1, BridgeReward::from(reward1_for), reward1); + + // check stored rewards + assert_eq!( + BridgeRelayers::relayer_reward(&account1, BridgeReward::from(reward1_for)), + Some(reward1) + ); + assert_eq!( + BridgeRelayers::relayer_reward(&account2, BridgeReward::from(reward1_for)), + None, + ); + + // claim rewards + assert_ok!(BridgeRelayers::claim_rewards( + RuntimeOrigin::signed(account1.clone()), + reward1_for.into() + )); + assert_eq!(Balances::total_balance(&account1), ExistentialDeposit::get() + reward1); + assert_eq!( + BridgeRelayers::relayer_reward(&account1, BridgeReward::from(reward1_for)), + None, + ); + + // already claimed + assert_err!( + BridgeRelayers::claim_rewards( + RuntimeOrigin::signed(account1.clone()), + reward1_for.into() + ), + pallet_bridge_relayers::Error::::NoRewardForRelayer + ); + }, + ); +} diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_common_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_common_config.rs index b627f903a2ea7..9fb2552971d8f 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_common_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-rococo/src/bridge_common_config.rs @@ -22,7 +22,6 @@ //! GRANDPA tracking pallet only needs to be aware of one chain. use super::{weights, AccountId, Balance, Balances, BlockNumber, Runtime, RuntimeEvent}; -use bp_parachains::SingleParaStoredHeaderDataBuilder; use bp_relayers::RewardsAccountParams; use frame_support::{parameter_types, traits::ConstU32}; @@ -59,7 +58,7 @@ impl pallet_bridge_parachains::Config for Runtim type BridgesGrandpaPalletInstance = BridgeGrandpaWestendInstance; type ParasPalletName = WestendBridgeParachainPalletName; type ParaStoredHeaderDataBuilder = - SingleParaStoredHeaderDataBuilder; + (bp_bridge_hub_westend::BridgeHubWestend, bp_asset_hub_westend::AssetHubWestend); type HeadsToKeep = ParachainHeadsToKeep; type MaxParaHeadDataSize = MaxWestendParaHeadDataSize; type OnNewHead = (); 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 4181ff7a3c03f..d1b60e33d7618 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 @@ -422,6 +422,7 @@ mod bridge_hub_westend_tests { }, construct_and_apply_extrinsic, true, + true, ) } @@ -457,6 +458,7 @@ mod bridge_hub_westend_tests { }, construct_and_apply_extrinsic, false, + true, ) } @@ -704,6 +706,7 @@ mod bridge_hub_bulletin_tests { }, construct_and_apply_extrinsic, false, + true, ) } @@ -738,6 +741,7 @@ mod bridge_hub_bulletin_tests { }, construct_and_apply_extrinsic, false, + true, ) } } diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_common_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_common_config.rs index 34b82993a5cce..e40ebcfb64bd4 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_common_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_common_config.rs @@ -23,9 +23,8 @@ use super::{weights, AccountId, Balance, Balances, BlockNumber, Runtime, RuntimeEvent}; use crate::{ - bridge_to_ethereum_config::{AssetHubLocation, InboundQueueV2Location}, - xcm_config::XcmConfig, - RuntimeCall, XcmRouter, + bridge_to_ethereum_config::InboundQueueV2Location, xcm_config::XcmConfig, RuntimeCall, + XcmRouter, }; use bp_messages::LegacyLaneId; use bp_relayers::RewardsAccountParams; @@ -33,10 +32,15 @@ use codec::{Decode, DecodeWithMemTracking, Encode, MaxEncodedLen}; use frame_support::parameter_types; use scale_info::TypeInfo; use testnet_parachains_constants::westend::snowbridge::EthereumNetwork; -use xcm::{opaque::latest::Location, VersionedLocation}; +use westend_runtime_constants::system_parachain::ASSET_HUB_ID; +use xcm::{ + latest::{prelude::Parachain, Location}, + VersionedLocation, +}; use xcm_executor::XcmExecutor; parameter_types! { + pub AssetHubLocation: Location = Location::new(1, [Parachain(ASSET_HUB_ID)]); pub storage RequiredStakeForStakeAndSlash: Balance = 1_000_000; pub const RelayerStakeLease: u32 = 8; pub const RelayerStakeReserveId: [u8; 8] = *b"brdgrlrs"; diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_ethereum_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_ethereum_config.rs index f295326839fe9..54716a5074bd0 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_ethereum_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_ethereum_config.rs @@ -85,7 +85,6 @@ parameter_types! { }; pub AssetHubFromEthereum: Location = Location::new(1, [GlobalConsensus(RelayNetwork::get()), Parachain(ASSET_HUB_ID)]); pub AssetHubUniversalLocation: InteriorLocation = [GlobalConsensus(RelayNetwork::get()), Parachain(ASSET_HUB_ID)].into(); - pub AssetHubLocation: Location = Location::new(1, [Parachain(ASSET_HUB_ID)]); pub EthereumUniversalLocation: InteriorLocation = [GlobalConsensus(EthereumNetwork::get())].into(); pub InboundQueueV2Location: InteriorLocation = [PalletInstance(INBOUND_QUEUE_PALLET_INDEX_V2)].into(); pub SnowbridgeFrontendLocation: Location = Location::new(1, [Parachain(ASSET_HUB_ID), PalletInstance(FRONTEND_PALLET_INDEX)]); diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_rococo_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_rococo_config.rs index 0b2ce0d27c2e7..8c4216149c633 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_rococo_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/bridge_to_rococo_config.rs @@ -25,7 +25,6 @@ use bp_messages::{ source_chain::FromBridgedChainMessagesDeliveryProof, target_chain::FromBridgedChainMessagesProof, LegacyLaneId, }; -use bp_parachains::SingleParaStoredHeaderDataBuilder; use bridge_hub_common::xcm_version::XcmVersionOfDestAndRemoteBridge; use pallet_xcm_bridge_hub::{BridgeId, XcmAsPlainPayload}; @@ -123,7 +122,7 @@ impl pallet_bridge_parachains::Config for Runtime type BridgesGrandpaPalletInstance = BridgeGrandpaRococoInstance; type ParasPalletName = RococoBridgeParachainPalletName; type ParaStoredHeaderDataBuilder = - SingleParaStoredHeaderDataBuilder; + (bp_bridge_hub_rococo::BridgeHubRococo, bp_asset_hub_rococo::AssetHubRococo); type HeadsToKeep = ParachainHeadsToKeep; type MaxParaHeadDataSize = MaxRococoParaHeadDataSize; type OnNewHead = (); diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs index c7387ba04078b..9591f7e5b7c32 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/src/xcm_config.rs @@ -19,7 +19,9 @@ use super::{ ParachainSystem, PolkadotXcm, Runtime, RuntimeCall, RuntimeEvent, RuntimeHoldReason, RuntimeOrigin, TransactionByteFee, WeightToFee, XcmOverBridgeHubRococo, XcmpQueue, }; -use crate::bridge_to_ethereum_config::{AssetHubLocation, SnowbridgeFrontendLocation}; +use crate::{ + bridge_common_config::AssetHubLocation, bridge_to_ethereum_config::SnowbridgeFrontendLocation, +}; use bridge_hub_common::DenyExportMessageFrom; use frame_support::{ parameter_types, diff --git a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs index e9717be13cfec..a4f8b55607001 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/bridge-hub-westend/tests/tests.rs @@ -350,6 +350,7 @@ fn relayed_incoming_message_works() { }, construct_and_apply_extrinsic, true, + true, ) } @@ -385,6 +386,7 @@ fn free_relay_extrinsic_works() { }, construct_and_apply_extrinsic, true, + true, ) } diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_grandpa_chain.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_grandpa_chain.rs index 4f1c073c35ffc..f5859fa8079f9 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_grandpa_chain.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_grandpa_chain.rs @@ -112,6 +112,7 @@ pub fn relayed_incoming_message_works( RuntimeCallOf, ) -> sp_runtime::DispatchOutcome, expect_rewards: bool, + expect_descend_origin_with_messaging_pallet_instance: bool, ) where RuntimeHelper: WithRemoteGrandpaChainHelper, AccountIdOf: From, @@ -130,6 +131,7 @@ pub fn relayed_incoming_message_works( sibling_parachain_id, local_relay_chain_id, construct_and_apply_extrinsic, + expect_descend_origin_with_messaging_pallet_instance, |relayer_id_at_this_chain, relayer_id_at_bridged_chain, message_destination, @@ -219,6 +221,7 @@ pub fn free_relay_extrinsic_works( RuntimeCallOf, ) -> sp_runtime::DispatchOutcome, expect_rewards: bool, + expect_descend_origin_with_messaging_pallet_instance: bool, ) where RuntimeHelper: WithRemoteGrandpaChainHelper, RuntimeHelper::Runtime: pallet_balances::Config, @@ -244,6 +247,7 @@ pub fn free_relay_extrinsic_works( sibling_parachain_id, local_relay_chain_id, construct_and_apply_extrinsic, + expect_descend_origin_with_messaging_pallet_instance, |relayer_id_at_this_chain, relayer_id_at_bridged_chain, message_destination, @@ -352,6 +356,7 @@ pub fn complex_relay_extrinsic_works( sp_keyring::Sr25519Keyring, RuntimeCallOf, ) -> sp_runtime::DispatchOutcome, + expect_descend_origin_with_messaging_pallet_instance: bool, ) where RuntimeHelper: WithRemoteGrandpaChainHelper, RuntimeHelper::Runtime: @@ -373,6 +378,7 @@ pub fn complex_relay_extrinsic_works( sibling_parachain_id, local_relay_chain_id, construct_and_apply_extrinsic, + expect_descend_origin_with_messaging_pallet_instance, |relayer_id_at_this_chain, relayer_id_at_bridged_chain, message_destination, diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_parachain.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_parachain.rs index 523ea5dc0db4a..5ed8626ab8adc 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_parachain.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/from_parachain.rs @@ -121,6 +121,7 @@ pub fn relayed_incoming_message_works( ::RuntimeCall, ) -> sp_runtime::DispatchOutcome, expect_rewards: bool, + expect_descend_origin_with_messaging_pallet_instance: bool, ) where RuntimeHelper: WithRemoteParachainHelper, AccountIdOf: From, @@ -142,6 +143,7 @@ pub fn relayed_incoming_message_works( sibling_parachain_id, local_relay_chain_id, construct_and_apply_extrinsic, + expect_descend_origin_with_messaging_pallet_instance, |relayer_id_at_this_chain, relayer_id_at_bridged_chain, message_destination, @@ -255,6 +257,7 @@ pub fn free_relay_extrinsic_works( ::RuntimeCall, ) -> sp_runtime::DispatchOutcome, expect_rewards: bool, + expect_descend_origin_with_messaging_pallet_instance: bool, ) where RuntimeHelper: WithRemoteParachainHelper, RuntimeHelper::Runtime: pallet_balances::Config, @@ -283,6 +286,7 @@ pub fn free_relay_extrinsic_works( sibling_parachain_id, local_relay_chain_id, construct_and_apply_extrinsic, + expect_descend_origin_with_messaging_pallet_instance, |relayer_id_at_this_chain, relayer_id_at_bridged_chain, message_destination, @@ -422,6 +426,7 @@ pub fn complex_relay_extrinsic_works( sp_keyring::Sr25519Keyring, ::RuntimeCall, ) -> sp_runtime::DispatchOutcome, + expect_descend_origin_with_messaging_pallet_instance: bool, ) where RuntimeHelper: WithRemoteParachainHelper, RuntimeHelper::Runtime: @@ -446,6 +451,7 @@ pub fn complex_relay_extrinsic_works( sibling_parachain_id, local_relay_chain_id, construct_and_apply_extrinsic, + expect_descend_origin_with_messaging_pallet_instance, |relayer_id_at_this_chain, relayer_id_at_bridged_chain, message_destination, diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/helpers.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/helpers.rs index 9b7238f8fc2f6..e65228c0c61a7 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/helpers.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/helpers.rs @@ -265,6 +265,7 @@ pub fn relayed_incoming_message_works( sp_keyring::Sr25519Keyring, RuntimeCallOf, ) -> sp_runtime::DispatchOutcome, + expect_descend_origin_with_messaging_pallet_instance: bool, prepare_message_proof_import: impl FnOnce( Runtime::AccountId, InboundRelayerId, @@ -325,14 +326,16 @@ pub fn relayed_incoming_message_works( let xcm = vec![Instruction::<()>::ClearOrigin; 42]; let expected_dispatch = xcm::latest::Xcm::<()>({ let mut expected_instructions = xcm.clone(); - // dispatch prepends bridge pallet instance - expected_instructions.insert( - 0, - DescendOrigin([PalletInstance( - as PalletInfoAccess>::index() - as u8, - )].into()), - ); + if expect_descend_origin_with_messaging_pallet_instance { + // dispatch prepends bridge pallet instance + expected_instructions.insert( + 0, + DescendOrigin([PalletInstance( + as PalletInfoAccess>::index() + as u8, + )].into()), + ); + } expected_instructions }); diff --git a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/mod.rs b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/mod.rs index b17e853b3505b..1e366186893f7 100644 --- a/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/mod.rs +++ b/cumulus/parachains/runtimes/bridge-hubs/test-utils/src/test_cases/mod.rs @@ -28,8 +28,11 @@ use crate::{test_cases::bridges_prelude::*, test_data}; use asset_test_utils::BasicParachainRuntime; use bp_messages::{ - target_chain::{DispatchMessage, DispatchMessageData, MessageDispatch}, - LaneState, MessageKey, MessagesOperatingMode, OutboundLaneData, + source_chain::FromBridgedChainMessagesDeliveryProof, + target_chain::{ + DispatchMessage, DispatchMessageData, FromBridgedChainMessagesProof, MessageDispatch, + }, + LaneState, MessageKey, MessagesOperatingMode, OutboundLaneData, UnrewardedRelayersState, }; use bp_runtime::BasicOperatingMode; use codec::Encode; @@ -70,7 +73,7 @@ pub use for_pallet_xcm_bridge_hub::open_and_close_bridge_works; // Re-export test_case from assets pub use asset_test_utils::include_teleports_for_native_asset_works; -use pallet_bridge_messages::LaneIdOf; +use pallet_bridge_messages::{BridgedChainOf, LaneIdOf, ThisChainOf}; pub type RuntimeHelper = parachains_runtimes_test_utils::RuntimeHelper; @@ -660,6 +663,127 @@ where estimated_fee.into() } +/// Estimates transaction fee for default message delivery transaction (`receive_messages_proof`) +/// from bridged parachain. +pub fn can_calculate_fee_for_standalone_message_delivery_transaction( + collator_session_key: CollatorSessionKeys, + runtime_para_id: u32, + compute_extrinsic_fee: fn(::RuntimeCall) -> u128, +) -> u128 +where + Runtime: BasicParachainRuntime + pallet_bridge_messages::Config, + MPI: 'static, + RuntimeCallOf: From>, +{ + use pallet_bridge_messages::messages_generation::{ + encode_all_messages, encode_lane_data, prepare_messages_storage_proof, + }; + run_test::(collator_session_key, runtime_para_id, vec![], || { + // prepare para storage proof containing a message + let lane_id = LaneIdOf::::default(); + let message_nonce = 1; + let message_payload = crate::test_data::prepare_inbound_xcm( + vec![Instruction::<()>::ClearOrigin; 1_024].into(), + [GlobalConsensus(ByGenesis([0; 32])), Parachain(1234)].into(), + ); + let (_, para_storage_proof) = prepare_messages_storage_proof::< + BridgedChainOf, + ThisChainOf, + LaneIdOf, + >( + lane_id, + message_nonce..=message_nonce, + None, + bp_runtime::UnverifiedStorageProofParams::from_db_size(message_payload.len() as u32), + |_| message_payload.clone(), + encode_all_messages, + encode_lane_data, + false, + false, + ); + + let message_proof = FromBridgedChainMessagesProof { + bridged_header_hash: Default::default(), + storage_proof: para_storage_proof, + lane: lane_id, + nonces_start: message_nonce, + nonces_end: message_nonce, + }; + + let call = pallet_bridge_messages::Call::::receive_messages_proof { + relayer_id_at_bridged_chain: helpers::relayer_id_at_bridged_chain::(), + proof: Box::new(message_proof), + messages_count: 1, + dispatch_weight: Weight::from_parts(1000000000, 0), + }; + + compute_extrinsic_fee(call.into()) + }) +} + +/// Estimates transaction fee for default message confirmation transaction +/// (`receive_messages_delivery_proof`) from bridged parachain. +pub fn can_calculate_fee_for_standalone_message_confirmation_transaction( + collator_session_key: CollatorSessionKeys, + runtime_para_id: u32, + compute_extrinsic_fee: fn(::RuntimeCall) -> u128, +) -> u128 +where + Runtime: + BasicParachainRuntime + BridgeMessagesConfig + pallet_bridge_messages::Config, + MPI: 'static, + RuntimeCallOf: From>, +{ + run_test::(collator_session_key, runtime_para_id, vec![], || { + let relayers_state = UnrewardedRelayersState { + unrewarded_relayer_entries: 1, + total_messages: 1, + ..Default::default() + }; + + let lane_id = LaneIdOf::::default(); + let relayer_id_at_this_chain: bp_runtime::AccountIdOf> = + codec::Decode::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) + .expect("valid account id"); + + // prepare para storage proof containing message delivery proof + let (_, para_storage_proof) = + pallet_bridge_messages::messages_generation::prepare_message_delivery_storage_proof::< + BridgedChainOf, + ThisChainOf, + LaneIdOf, + >( + lane_id, + bp_messages::InboundLaneData { + state: LaneState::Opened, + relayers: vec![ + bp_messages::UnrewardedRelayer { + relayer: relayer_id_at_this_chain.into(), + messages: bp_messages::DeliveredMessages::new(1) + }; + relayers_state.unrewarded_relayer_entries as usize + ] + .into(), + last_confirmed_nonce: 1, + }, + bp_runtime::UnverifiedStorageProofParams::default(), + ); + + let message_delivery_proof = FromBridgedChainMessagesDeliveryProof { + bridged_header_hash: Default::default(), + storage_proof: para_storage_proof, + lane: lane_id, + }; + + let call = pallet_bridge_messages::Call::::receive_messages_delivery_proof { + proof: message_delivery_proof, + relayers_state, + }; + + compute_extrinsic_fee(call.into()) + }) +} + pub(crate) mod for_pallet_xcm_bridge_hub { use super::*; use crate::test_cases::helpers::for_pallet_xcm_bridge_hub::{