diff --git a/Cargo.lock b/Cargo.lock index 49c51546..da77b45c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -689,7 +689,7 @@ dependencies = [ [[package]] name = "bp-crab" version = "0.1.0" -source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#584bc52933ce28d4a16a442fd66227410594c178" +source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#fda68630945112553da5fafae8c21609bc86f36c" dependencies = [ "bp-darwinia-core", "bp-messages", @@ -704,7 +704,7 @@ dependencies = [ [[package]] name = "bp-crab-parachain" version = "0.1.0" -source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#584bc52933ce28d4a16a442fd66227410594c178" +source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#fda68630945112553da5fafae8c21609bc86f36c" dependencies = [ "bp-darwinia-core", "bp-messages", @@ -719,7 +719,7 @@ dependencies = [ [[package]] name = "bp-darwinia-core" version = "0.1.0" -source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#584bc52933ce28d4a16a442fd66227410594c178" +source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#fda68630945112553da5fafae8c21609bc86f36c" dependencies = [ "bp-messages", "bp-runtime", @@ -735,7 +735,7 @@ dependencies = [ [[package]] name = "bp-header-chain" version = "0.1.0" -source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#584bc52933ce28d4a16a442fd66227410594c178" +source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#fda68630945112553da5fafae8c21609bc86f36c" dependencies = [ "bp-runtime", "finality-grandpa", @@ -752,7 +752,7 @@ dependencies = [ [[package]] name = "bp-message-dispatch" version = "0.1.0" -source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#584bc52933ce28d4a16a442fd66227410594c178" +source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#fda68630945112553da5fafae8c21609bc86f36c" dependencies = [ "bp-runtime", "frame-support", @@ -765,7 +765,7 @@ dependencies = [ [[package]] name = "bp-messages" version = "0.1.0" -source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#584bc52933ce28d4a16a442fd66227410594c178" +source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#fda68630945112553da5fafae8c21609bc86f36c" dependencies = [ "bitvec 1.0.1", "bp-runtime", @@ -782,7 +782,7 @@ dependencies = [ [[package]] name = "bp-pangolin" version = "0.1.0" -source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#584bc52933ce28d4a16a442fd66227410594c178" +source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#fda68630945112553da5fafae8c21609bc86f36c" dependencies = [ "bp-darwinia-core", "bp-messages", @@ -797,7 +797,22 @@ dependencies = [ [[package]] name = "bp-pangolin-parachain" version = "0.1.0" -source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#584bc52933ce28d4a16a442fd66227410594c178" +source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#fda68630945112553da5fafae8c21609bc86f36c" +dependencies = [ + "bp-darwinia-core", + "bp-messages", + "bp-runtime", + "frame-support", + "sp-api", + "sp-runtime", + "sp-std", + "sp-version", +] + +[[package]] +name = "bp-pangolin-parachain-alpha" +version = "0.1.0" +source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#fda68630945112553da5fafae8c21609bc86f36c" dependencies = [ "bp-darwinia-core", "bp-messages", @@ -812,7 +827,7 @@ dependencies = [ [[package]] name = "bp-parachains" version = "0.1.0" -source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#584bc52933ce28d4a16a442fd66227410594c178" +source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#fda68630945112553da5fafae8c21609bc86f36c" dependencies = [ "bp-polkadot-core", "bp-runtime", @@ -826,7 +841,7 @@ dependencies = [ [[package]] name = "bp-polkadot-core" version = "0.1.0" -source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#584bc52933ce28d4a16a442fd66227410594c178" +source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#fda68630945112553da5fafae8c21609bc86f36c" dependencies = [ "bp-messages", "bp-runtime", @@ -846,7 +861,7 @@ dependencies = [ [[package]] name = "bp-runtime" version = "0.1.0" -source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#584bc52933ce28d4a16a442fd66227410594c178" +source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#fda68630945112553da5fafae8c21609bc86f36c" dependencies = [ "frame-support", "hash-db", @@ -864,7 +879,7 @@ dependencies = [ [[package]] name = "bp-test-utils" version = "0.1.0" -source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#584bc52933ce28d4a16a442fd66227410594c178" +source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#fda68630945112553da5fafae8c21609bc86f36c" dependencies = [ "bp-header-chain", "ed25519-dalek", @@ -879,7 +894,7 @@ dependencies = [ [[package]] name = "bridge-runtime-common" version = "0.1.0" -source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#584bc52933ce28d4a16a442fd66227410594c178" +source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#fda68630945112553da5fafae8c21609bc86f36c" dependencies = [ "bp-message-dispatch", "bp-messages", @@ -2451,7 +2466,11 @@ dependencies = [ "pallet-fee-market", "pallet-timestamp", "pallet-transaction-payment", + "pallet-xcm", "parity-scale-codec 3.2.1", + "polkadot-core-primitives", + "polkadot-parachain", + "polkadot-runtime-parachains", "scale-info", "smallvec", "sp-core", @@ -2459,6 +2478,7 @@ dependencies = [ "sp-runtime", "sp-std", "xcm", + "xcm-builder", "xcm-executor", ] @@ -5643,7 +5663,7 @@ dependencies = [ [[package]] name = "pallet-bridge-dispatch" version = "0.1.0" -source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#584bc52933ce28d4a16a442fd66227410594c178" +source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#fda68630945112553da5fafae8c21609bc86f36c" dependencies = [ "bp-message-dispatch", "bp-runtime", @@ -5660,7 +5680,7 @@ dependencies = [ [[package]] name = "pallet-bridge-grandpa" version = "0.1.0" -source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#584bc52933ce28d4a16a442fd66227410594c178" +source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#fda68630945112553da5fafae8c21609bc86f36c" dependencies = [ "bp-header-chain", "bp-runtime", @@ -5683,7 +5703,7 @@ dependencies = [ [[package]] name = "pallet-bridge-messages" version = "0.1.0" -source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#584bc52933ce28d4a16a442fd66227410594c178" +source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#fda68630945112553da5fafae8c21609bc86f36c" dependencies = [ "bitvec 1.0.1", "bp-message-dispatch", @@ -5705,7 +5725,7 @@ dependencies = [ [[package]] name = "pallet-bridge-parachains" version = "0.1.0" -source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#584bc52933ce28d4a16a442fd66227410594c178" +source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#fda68630945112553da5fafae8c21609bc86f36c" dependencies = [ "bp-parachains", "bp-polkadot-core", @@ -5852,7 +5872,7 @@ dependencies = [ [[package]] name = "pallet-fee-market" version = "0.1.0" -source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#584bc52933ce28d4a16a442fd66227410594c178" +source = "git+https://github.com/darwinia-network/darwinia-messages-substrate?branch=polkadot-v0.9.27#fda68630945112553da5fafae8c21609bc86f36c" dependencies = [ "bp-messages", "bp-runtime", @@ -6452,6 +6472,7 @@ dependencies = [ "bp-messages", "bp-pangolin", "bp-pangolin-parachain", + "bp-pangolin-parachain-alpha", "bp-polkadot-core", "bp-runtime", "bridge-runtime-common", @@ -11664,7 +11685,7 @@ version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 1.0.0", + "cfg-if 0.1.10", "digest 0.10.5", "rand 0.8.5", "static_assertions", diff --git a/runtime/common/Cargo.toml b/runtime/common/Cargo.toml index d2358195..afe827c5 100644 --- a/runtime/common/Cargo.toml +++ b/runtime/common/Cargo.toml @@ -34,11 +34,17 @@ frame-system = { default-features = false, git = "https://github.c pallet-balances = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } pallet-transaction-payment = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } sp-core = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } +sp-io = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } sp-runtime = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } sp-std = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } # polkadot -xcm = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.27" } -xcm-executor = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.27" } +pallet-xcm = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.27" } +polkadot-core-primitives = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.27" } +polkadot-parachain = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.27" } +polkadot-runtime-parachains = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.27" } +xcm = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.27" } +xcm-builder = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.27" } +xcm-executor = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.27" } [dev-dependencies] pallet-timestamp = { default-features = false, git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.27" } @@ -73,7 +79,12 @@ std = [ "sp-runtime/std", "sp-std/std", # polkadot + "pallet-xcm/std", + "polkadot-core-primitives/std", + "polkadot-parachain/std", + "polkadot-runtime-parachains/std", "xcm/std", + "xcm-builder/std", "xcm-executor/std", ] diff --git a/runtime/common/src/lib.rs b/runtime/common/src/lib.rs index a7073754..c408196e 100644 --- a/runtime/common/src/lib.rs +++ b/runtime/common/src/lib.rs @@ -19,6 +19,7 @@ #![cfg_attr(not(feature = "std"), no_std)] pub mod helixbridge; +pub mod message_router; pub mod remote_governance; pub mod xcm_config; diff --git a/runtime/common/src/message_router/barriers.rs b/runtime/common/src/message_router/barriers.rs new file mode 100644 index 00000000..af69d4f1 --- /dev/null +++ b/runtime/common/src/message_router/barriers.rs @@ -0,0 +1,78 @@ +// This file is part of Darwinia. +// +// Copyright (C) 2018-2022 Darwinia Network +// SPDX-License-Identifier: GPL-3.0 +// +// Darwinia 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. +// +// Darwinia 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 Darwinia. If not, see . + +//! Various implementations for `ShouldExecute`. + +use frame_support::{ensure, log, traits::Contains, weights::Weight}; +use sp_std::{marker::PhantomData, result::Result}; +use xcm::latest::{Instruction::*, MultiLocation, WeightLimit::*, Xcm}; +use xcm_executor::traits::ShouldExecute; + +/// Allows execution from `origin` if it is contained in `T` (i.e. `T::Contains(origin)`) taking +/// payments into account. +/// +/// Only allows for `TeleportAsset`, `WithdrawAsset`, `ClaimAsset` and `ReserveAssetDeposit` XCMs +/// because they are the only ones that place assets in the Holding Register to pay for execution. +/// Copy from https://github.com/paritytech/polkadot/blob/release-v0.9.26/xcm/xcm-builder/src/barriers.rs#L53 +/// Allow `DescendOrigin` as the first instruction to specify the payment account +pub struct AllowDescendOriginPaidExecutionFrom(PhantomData); +impl> ShouldExecute for AllowDescendOriginPaidExecutionFrom { + fn should_execute( + origin: &MultiLocation, + message: &mut Xcm, + max_weight: Weight, + _weight_credit: &mut Weight, + ) -> Result<(), ()> { + log::trace!( + target: "xcm::barriers", + "AllowDescendOriginPaidExecutionFrom origin: {:?}, message: {:?}, max_weight: {:?}, weight_credit: {:?}", + origin, message, max_weight, _weight_credit, + ); + ensure!(T::contains(origin), ()); + let mut iter = message.0.iter_mut(); + let i = iter.next().ok_or(())?; + // Modified: Only allows `DescendOrigin` as the first instruction + match i { + DescendOrigin(_) => (), + _ => return Err(()), + } + let i = iter.next().ok_or(())?; + match i { + ReceiveTeleportedAsset(..) + | WithdrawAsset(..) + | ReserveAssetDeposited(..) + | ClaimAsset { .. } => (), + _ => return Err(()), + } + let mut i = iter.next().ok_or(())?; + while let ClearOrigin = i { + i = iter.next().ok_or(())?; + } + match i { + BuyExecution { weight_limit: Limited(ref mut weight), .. } if *weight >= max_weight => { + *weight = max_weight; + Ok(()) + }, + BuyExecution { ref mut weight_limit, .. } if weight_limit == &Unlimited => { + *weight_limit = Limited(max_weight); + Ok(()) + }, + _ => Err(()), + } + } +} diff --git a/runtime/common/src/message_router/benchmarking.rs b/runtime/common/src/message_router/benchmarking.rs new file mode 100644 index 00000000..20ea9eb2 --- /dev/null +++ b/runtime/common/src/message_router/benchmarking.rs @@ -0,0 +1,51 @@ +// This file is part of Darwinia. +// +// Copyright (C) 2018-2022 Darwinia Network +// SPDX-License-Identifier: GPL-3.0 +// +// Darwinia 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. +// +// Darwinia 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 Darwinia. If not, see . + +#![cfg(feature = "runtime-benchmarks")] + +// --- paritytech --- +use frame_benchmarking::{account, benchmarks}; +use frame_support::{assert_ok, traits::Get}; +use frame_system::RawOrigin; +use sp_std::{boxed::Box, vec}; +use xcm::{latest::prelude::*, VersionedXcm::V2}; +// --- darwinia --- +use crate::message_router::{Call, Config, Pallet}; +use dc_primitives::COIN; + +benchmarks! { + set_target_xcm_exec_config { + let target_location = T::MoonbeamLocation::get(); + let local_asset_units_per_second: u128 = 14719736222326895902025_u128; + }:_(RawOrigin::Root, target_location.clone(), local_asset_units_per_second) + verify { + assert_eq!(Pallet::::target_xcm_exec_config(target_location), Some(local_asset_units_per_second)); + } + + forward_to_moonbeam { + let target_location = T::MoonbeamLocation::get(); + let local_asset_units_per_second: u128 = 14719736222326895902025_u128; + assert_ok!(Pallet::::set_target_xcm_exec_config(RawOrigin::Root.into(), target_location.clone(), local_asset_units_per_second)); + let xcm = Xcm(vec![ + DescendOrigin(X1(AccountKey20 { + network: Any, + key: [0u8;20].into() + })), + ]); + }:_(RawOrigin::Root, Box::new(V2(xcm))) +} diff --git a/runtime/common/src/message_router/location_conversion.rs b/runtime/common/src/message_router/location_conversion.rs new file mode 100644 index 00000000..4c9b8a06 --- /dev/null +++ b/runtime/common/src/message_router/location_conversion.rs @@ -0,0 +1,57 @@ +// This file is part of Darwinia. +// +// Copyright (C) 2018-2022 Darwinia Network +// SPDX-License-Identifier: GPL-3.0 +// +// Darwinia 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. +// +// Darwinia 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 Darwinia. If not, see . + +use sp_std::marker::PhantomData; +use xcm::{latest::MultiLocation, prelude::*}; +use xcm_executor::traits::Convert; + +/// The address prefix for dvm address +const ADDR_PREFIX: &[u8] = b"dvm:"; + +/// Derive AccountKey20 in MultiLocation to AccountId32 +/// Refer to https://github.com/darwinia-network/darwinia-common/blob/main/frame/support/src/evm.rs#L85 +pub struct AccountKey20Derive(PhantomData); +impl + Into<[u8; 32]> + Clone> Convert + for AccountKey20Derive +{ + fn convert(location: MultiLocation) -> Result { + // Extract AccountKey20 from MultiLocation + let key = match location { + MultiLocation { parents: 0, interior: X1(AccountKey20 { key, network: _ }) } => key, + MultiLocation { + parents: 1, + interior: X2(Parachain(_), AccountKey20 { key, network: _ }), + } => key, + _ => return Err(location), + }; + let mut raw_account = [0u8; 32]; + + raw_account[0..4].copy_from_slice(ADDR_PREFIX); + raw_account[11..31].copy_from_slice(&key[..]); + raw_account[31] = checksum_of(&raw_account); + Ok(raw_account.into()) + } + + fn reverse(who: AccountId) -> Result { + Err(who) + } +} + +fn checksum_of(account_id: &[u8; 32]) -> u8 { + account_id[1..31].iter().fold(account_id[0], |sum, &byte| sum ^ byte) +} diff --git a/runtime/common/src/message_router/mod.rs b/runtime/common/src/message_router/mod.rs new file mode 100644 index 00000000..463457e3 --- /dev/null +++ b/runtime/common/src/message_router/mod.rs @@ -0,0 +1,300 @@ +// This file is part of Darwinia. +// +// Copyright (C) 2018-2022 Darwinia Network +// SPDX-License-Identifier: GPL-3.0 +// +// Darwinia 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. +// +// Darwinia 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 Darwinia. If not, see . + +//! Prototype module for message router. + +pub mod barriers; +#[cfg(feature = "runtime-benchmarks")] +mod benchmarking; +pub mod location_conversion; +mod weights; + +// --- paritytech --- +use frame_support::{pallet_prelude::*, traits::Get}; +use xcm::prelude::*; +use xcm_executor::traits::WeightBounds; + +pub type AssetUnitsPerSecond = u128; + +/// router target +#[derive(Clone, Encode, Decode, TypeInfo, PartialEq, Debug)] +pub enum Target { + Moonbeam, + Astar, +} + +#[frame_support::pallet] +pub mod pallet { + use super::*; + use crate::message_router::weights::WeightInfo; + use frame_support::{log, weights::constants::WEIGHT_PER_SECOND}; + use frame_system::pallet_prelude::*; + use sp_std::{boxed::Box, vec}; + use xcm_executor::traits::InvertLocation; + + #[pallet::config] + pub trait Config: frame_system::Config { + type ConfigModifierOrigin: EnsureOrigin; + type Event: From> + IsType<::Event>; + /// Required origin for executing XCM messages. + type ExecuteXcmOrigin: EnsureOrigin< + ::Origin, + Success = MultiLocation, + >; + type LocalAssetId: Get; + /// Used to calculate the weight required for the local execution of xcm. + type LocalWeigher: WeightBounds; + /// Means of inverting a location. + type LocationInverter: InvertLocation; + type MoonbeamLocation: Get; + /// Used to calculate the weight required for the moonbeam execution of xcm. + type MoonbeamWeigher: WeightBounds; + type AstarLocation: Get; + /// Used to calculate the weight required for the moonbeam execution of xcm. + type AstarWeigher: WeightBounds; + /// This chain location relative to sibling chain + type SelfLocationInSibl: Get; + type WeightInfo: WeightInfo; + type XcmExecutor: ExecuteXcm; + type XcmSender: SendXcm; + } + + #[pallet::event] + #[pallet::generate_deposit(pub (super) fn deposit_event)] + pub enum Event { + /// Changed the amount of units target chain charging per execution second for local asset + TargetXcmExecConfigChanged { + target_location: MultiLocation, + local_asset_units_per_second: AssetUnitsPerSecond, + }, + /// Deposited when successfully routed. + /// (send origin, route target, remote xcm, required weight, tokens used) + ForwardTo(MultiLocation, Target, Xcm<()>, Weight, u128), + } + + #[pallet::error] + pub enum Error { + /// Not config the target paraId's info for XCM execution. + TargetXcmExecNotConfig, + /// The message's weight could not be determined. + UnweighableMessage, + /// Failed to transfer xcm fee. + FailedPayXcmFee, + BadVersion, + /// MultiLocation value too large to descend further. + MultiLocationFull, + /// Failed to send xcm. + XcmSendFailed, + /// Failed to convert account id to [u8; 32]. + AccountIdConversionFailed, + } + + /// Stores the units per second executed by the target chain for local asset(e.g. CRAB). + /// This is used to know how to pay for XCM remote execution use local asset. + /// For example: + /// key: {parents: 1, Parachain(2023)}, val: 14719736222326895902025 + /// represents the units per second of CRAB token on moonriver + #[pallet::storage] + #[pallet::getter(fn target_xcm_exec_config)] + pub type TargetXcmExecConfig = + StorageMap<_, Blake2_128Concat, MultiLocation, AssetUnitsPerSecond>; + + #[pallet::pallet] + #[pallet::generate_store(pub (super) trait Store)] + pub struct Pallet(PhantomData); + + #[pallet::call] + impl Pallet { + /// Update the units per second of local asset used in target chain. + #[pallet::weight( + ::WeightInfo::set_target_xcm_exec_config() + )] + pub fn set_target_xcm_exec_config( + origin: OriginFor, + target_location: MultiLocation, + local_asset_units_per_second: AssetUnitsPerSecond, + ) -> DispatchResultWithPostInfo { + T::ConfigModifierOrigin::ensure_origin(origin)?; + + TargetXcmExecConfig::::insert(&target_location, &local_asset_units_per_second); + + Self::deposit_event(Event::TargetXcmExecConfigChanged { + target_location, + local_asset_units_per_second, + }); + + Ok(().into()) + } + + /// Deliver received LCMP messages to other parachains. + /// 1. Calculate the fee for xcm remote execution + /// 2. Transfer xcm fee to target sovereign account + /// 3. Assemble xcm that needs to be executed remotely + /// 4. Send xcm to target chain + #[pallet::weight( + ::WeightInfo::forward() + )] + pub fn forward( + origin: OriginFor, + target: Target, + message: Box::Call>>, + ) -> DispatchResultWithPostInfo { + // MultiLocation origin used to execute xcm + let origin_location = T::ExecuteXcmOrigin::ensure_origin(origin.clone())?; + let account_id = ensure_signed(origin)?; + // U8 account used in DescendOrigin instruction + let raw_account = <[u8; 32]>::try_from(account_id.encode()) + .map_err(|_| Error::::AccountIdConversionFailed)?; + + let mut remote_xcm: Xcm<::Call> = + (*message).try_into().map_err(|()| Error::::BadVersion)?; + + // Calculate the execution fee required for remote xcm execution + // fee = fee_per_second * (weight/weight_per_second) + let local_asset_units_per_second: AssetUnitsPerSecond; + let remote_weight: Weight; + match target { + Target::Moonbeam => { + local_asset_units_per_second = + TargetXcmExecConfig::::get(T::MoonbeamLocation::get()) + .ok_or(Error::::TargetXcmExecNotConfig)?; + remote_weight = T::MoonbeamWeigher::weight(&mut Self::extend_remote_xcm( + raw_account.clone(), + remote_xcm.clone(), + MultiAsset { id: AssetId::from(T::LocalAssetId::get()), fun: Fungible(0) }, + )) + .map_err(|()| Error::::UnweighableMessage)?; + }, + Target::Astar => { + local_asset_units_per_second = + TargetXcmExecConfig::::get(T::AstarLocation::get()) + .ok_or(Error::::TargetXcmExecNotConfig)?; + remote_weight = T::AstarWeigher::weight(&mut Self::extend_remote_xcm( + raw_account.clone(), + remote_xcm.clone(), + MultiAsset { id: AssetId::from(T::LocalAssetId::get()), fun: Fungible(0) }, + )) + .map_err(|()| Error::::UnweighableMessage)?; + }, + } + let amount = local_asset_units_per_second.saturating_mul(remote_weight as u128) + / (WEIGHT_PER_SECOND as u128); + let remote_xcm_fee = + MultiAsset { id: AssetId::from(T::LocalAssetId::get()), fun: Fungible(amount) }; + + // Transfer xcm execution fee to target sovereign account + let mut local_xcm; + match target { + Target::Moonbeam => { + local_xcm = Xcm(vec![TransferAsset { + assets: remote_xcm_fee.clone().into(), + beneficiary: T::MoonbeamLocation::get(), + }]); + }, + Target::Astar => { + local_xcm = Xcm(vec![TransferAsset { + assets: remote_xcm_fee.clone().into(), + beneficiary: T::AstarLocation::get(), + }]); + }, + } + let local_weight = T::LocalWeigher::weight(&mut local_xcm) + .map_err(|()| Error::::UnweighableMessage)?; + T::XcmExecutor::execute_xcm_in_credit( + origin_location.clone(), + local_xcm, + local_weight, + local_weight, + ) + .ensure_complete() + .map_err(|error| { + log::error!("Failed transfer xcm fee with {:?}", error); + Error::::FailedPayXcmFee + })?; + + // Toggle the xcm_fee relative to a target context + let ancestry = T::LocationInverter::ancestry(); + let mut remote_xcm_fee_anchor_dest = remote_xcm_fee.clone(); + match target { + Target::Moonbeam => { + remote_xcm_fee_anchor_dest + .reanchor(&T::MoonbeamLocation::get(), &ancestry) + .map_err(|()| Error::::MultiLocationFull)?; + remote_xcm = Self::extend_remote_xcm( + raw_account, + remote_xcm, + remote_xcm_fee_anchor_dest, + ); + // Send remote xcm to target + T::XcmSender::send_xcm(T::MoonbeamLocation::get(), remote_xcm.clone().into()) + .map_err(|_| Error::::XcmSendFailed)?; + }, + Target::Astar => { + remote_xcm_fee_anchor_dest + .reanchor(&T::AstarLocation::get(), &ancestry) + .map_err(|()| Error::::MultiLocationFull)?; + remote_xcm = Self::extend_remote_xcm( + raw_account, + remote_xcm, + remote_xcm_fee_anchor_dest, + ); + // Send remote xcm to target + T::XcmSender::send_xcm(T::AstarLocation::get(), remote_xcm.clone().into()) + .map_err(|_| Error::::XcmSendFailed)?; + }, + } + + Self::deposit_event(Event::ForwardTo( + origin_location, + target, + remote_xcm.into(), + remote_weight, + amount, + )); + Ok(().into()) + } + } + + impl Pallet { + /// Extend xcm for remote execution + fn extend_remote_xcm( + raw_account: [u8; 32], + xcm: Xcm<::Call>, + fee: MultiAsset, + ) -> Xcm<::Call> { + let mut extend_xcm = Xcm(vec![ + ReserveAssetDeposited(fee.clone().into()), + BuyExecution { fees: fee, weight_limit: WeightLimit::Unlimited }, + // Deposit surplus tokens back into our sovereign account + SetAppendix(Xcm(vec![ + RefundSurplus, + DepositAsset { + assets: Wild(All), + max_assets: 1, + beneficiary: T::SelfLocationInSibl::get(), + }, + ])), + DescendOrigin(X1(AccountId32 { network: NetworkId::Any, id: raw_account })), + ]); + extend_xcm.0.extend(xcm.0.into_iter()); + return extend_xcm; + } + } +} + +pub use pallet::*; diff --git a/runtime/common/src/message_router/weights.rs b/runtime/common/src/message_router/weights.rs new file mode 100644 index 00000000..059fc4f4 --- /dev/null +++ b/runtime/common/src/message_router/weights.rs @@ -0,0 +1,102 @@ +// This file is part of Darwinia. +// +// Copyright (C) 2018-2022 Darwinia Network +// SPDX-License-Identifier: GPL-3.0 +// +// Darwinia 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. +// +// Darwinia 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 Darwinia. If not, see . + +//! Autogenerated weights for `message_router` +//! +//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 4.0.0-dev +//! DATE: 2022-08-29, STEPS: `50`, REPEAT: 20, LOW RANGE: `[]`, HIGH RANGE: `[]` +//! HOSTNAME: `Debian`, CPU: `12th Gen Intel(R) Core(TM) i9-12900K` +//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("pangolin-parachain-dev"), DB CACHE: 1024 + +// Executed Command: +// ./target/release/darwinia-parachain +// benchmark +// pallet +// --chain +// pangolin-parachain-dev +// --execution +// wasm +// --wasm-execution +// compiled +// --pallet +// message_router +// --extrinsic +// * +// --steps +// 50 +// --repeat +// 20 +// --heap-pages=4096 +// --output +// ./runtime/pangolin-parachain/src/weights/ +// --header=.maintain/lincense-header + +#![cfg_attr(rustfmt, rustfmt_skip)] +#![allow(unused_parens)] +#![allow(unused_imports)] + +use frame_support::{traits::Get, weights::Weight}; +use frame_support::weights::constants::RocksDbWeight; +use sp_std::marker::PhantomData; + +pub trait WeightInfo { + fn set_target_xcm_exec_config() -> Weight; + fn forward() -> Weight; +} + +/// Weight functions for `message_router`. +pub struct SubstrateWeightInfo(PhantomData); +impl WeightInfo for SubstrateWeightInfo { + // Storage: MessageRouter TargetXcmExecConfig (r:0 w:1) + fn set_target_xcm_exec_config() -> Weight { + (10_337_000 as Weight) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } + // Storage: MessageRouter TargetXcmExecConfig (r:1 w:0) + // Storage: ParachainInfo ParachainId (r:1 w:0) + // Storage: System Account (r:2 w:0) + // Storage: PolkadotXcm SupportedVersion (r:1 w:0) + // Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + // Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + // Storage: ParachainSystem RelevantMessagingState (r:1 w:0) + fn forward() -> Weight { + (37_239_000 as Weight) + .saturating_add(T::DbWeight::get().reads(8 as Weight)) + .saturating_add(T::DbWeight::get().writes(1 as Weight)) + } +} + +impl WeightInfo for () { + // Storage: MessageRouter TargetXcmExecConfig (r:0 w:1) + fn set_target_xcm_exec_config() -> Weight { + (10_337_000 as Weight) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } + // Storage: MessageRouter TargetXcmExecConfig (r:1 w:0) + // Storage: ParachainInfo ParachainId (r:1 w:0) + // Storage: System Account (r:2 w:0) + // Storage: PolkadotXcm SupportedVersion (r:1 w:0) + // Storage: PolkadotXcm VersionDiscoveryQueue (r:1 w:1) + // Storage: PolkadotXcm SafeXcmVersion (r:1 w:0) + // Storage: ParachainSystem RelevantMessagingState (r:1 w:0) + fn forward() -> Weight { + (37_239_000 as Weight) + .saturating_add(RocksDbWeight::get().reads(8 as Weight)) + .saturating_add(RocksDbWeight::get().writes(1 as Weight)) + } +} \ No newline at end of file diff --git a/runtime/crab-parachain/src/lib.rs b/runtime/crab-parachain/src/lib.rs index a4c85389..34e6b6ed 100644 --- a/runtime/crab-parachain/src/lib.rs +++ b/runtime/crab-parachain/src/lib.rs @@ -177,6 +177,8 @@ frame_support::construct_runtime! { CrabFeeMarket: pallet_fee_market::::{Pallet, Call, Storage, Event} = 23, FromCrabIssuing: dp_common_runtime::helixbridge::{Pallet, Call, Storage, Event} = 24, + + MessageRouter: dp_common_runtime::message_router::{Pallet, Call, Storage, Event} = 26, } } diff --git a/runtime/crab-parachain/src/pallets/message_router.rs b/runtime/crab-parachain/src/pallets/message_router.rs new file mode 100644 index 00000000..bfa70594 --- /dev/null +++ b/runtime/crab-parachain/src/pallets/message_router.rs @@ -0,0 +1,50 @@ +// --- paritytech --- +use frame_support::{traits::PalletInfoAccess, weights::Weight}; +use frame_system::EnsureRoot; +use xcm::prelude::*; +use xcm_builder::{EnsureXcmOrigin, FixedWeightBounds, LocationInverter}; +use xcm_executor::XcmExecutor; +// --- darwinia-network --- +use crate::*; +use dp_common_runtime::message_router::Config; + +frame_support::parameter_types! { + // https://github.com/PureStake/moonbeam/blob/master/runtime/moonriver/src/xcm_config.rs#L208 + pub MoonbeamUnitWeightCost: Weight = 200_000_000; + // https://github.com/AstarNetwork/Astar/blob/master/runtime/shiden/src/xcm_config.rs#L108 + pub ShidenUnitWeightCost: Weight = 1_000_000_000; + pub SelfLocationInSibl: MultiLocation = MultiLocation::new( + 1, + X1(Parachain(ParachainInfo::parachain_id().into())) + ); + pub AnchoringSelfReserve: MultiLocation = MultiLocation::new( + 0, + X1(PalletInstance(::index() as u8)) + ); + pub MoonriverLocation: MultiLocation = MultiLocation::new( + 1, + X1(Parachain(2023)) + ); + pub ShidenLocation: MultiLocation = MultiLocation::new( + 1, + X1(Parachain(2007)) + ); +} + +impl Config for Runtime { + type AstarLocation = ShidenLocation; + type AstarWeigher = FixedWeightBounds; + type ConfigModifierOrigin = EnsureRoot; + type Event = Event; + type ExecuteXcmOrigin = EnsureXcmOrigin; + type LocalAssetId = AnchoringSelfReserve; + type LocalWeigher = FixedWeightBounds; + type LocationInverter = LocationInverter; + type MoonbeamLocation = MoonriverLocation; + type MoonbeamWeigher = FixedWeightBounds; + type SelfLocationInSibl = SelfLocationInSibl; + // Dont update the weights. + type WeightInfo = (); + type XcmExecutor = XcmExecutor; + type XcmSender = XcmRouter; +} diff --git a/runtime/crab-parachain/src/pallets/mod.rs b/runtime/crab-parachain/src/pallets/mod.rs index a175975c..eac8f4c7 100644 --- a/runtime/crab-parachain/src/pallets/mod.rs +++ b/runtime/crab-parachain/src/pallets/mod.rs @@ -72,3 +72,6 @@ pub use fee_market::*; pub mod helixbridge; pub use helixbridge::*; + +pub mod message_router; +pub use message_router::*; diff --git a/runtime/crab-parachain/src/pallets/polkadot_xcm.rs b/runtime/crab-parachain/src/pallets/polkadot_xcm.rs index 149ca64d..3291b0eb 100644 --- a/runtime/crab-parachain/src/pallets/polkadot_xcm.rs +++ b/runtime/crab-parachain/src/pallets/polkadot_xcm.rs @@ -14,7 +14,12 @@ use xcm_builder::*; use xcm_executor::{Config as XcmCExecutorConfig, XcmExecutor}; // --- darwinia-network --- use crate::*; -use dp_common_runtime::xcm_config::{DenyReserveTransferToRelayChain, DenyThenTry}; +use dp_common_runtime::{ + message_router::{ + barriers::AllowDescendOriginPaidExecutionFrom, location_conversion::AccountKey20Derive, + }, + xcm_config::{DenyReserveTransferToRelayChain, DenyThenTry}, +}; /// Converts a local signed origin into an XCM multilocation. /// Forms the basis for local origins sending/executing XCMs. @@ -48,6 +53,7 @@ pub type Barrier = DenyThenTry< ( TakeWeightCredit, AllowTopLevelPaidExecutionFrom, + AllowDescendOriginPaidExecutionFrom, // Parent and its exec plurality get free execution AllowUnpaidExecutionFrom, // Expected responses are OK. @@ -67,6 +73,8 @@ pub type LocationToAccountId = ( SiblingParachainConvertsVia, // Straight up local `AccountId32` origins just alias directly to `AccountId`. AccountId32Aliases, + // Derive AccountKey20 to AccountId32 + AccountKey20Derive, ); /// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, @@ -118,6 +126,20 @@ frame_support::match_types! { MultiLocation { parents: 1, interior: X1(_) } }; } +frame_support::match_types! { + pub type AllowDescendOrigin: impl Contains = { + // Moonriver Location + MultiLocation { + parents: 1, + interior: X1(Parachain(2023)) + } | + // Astar Shiden Location + MultiLocation { + parents: 1, + interior: X1(Parachain(2007)) + } + }; +} pub struct XcmConfig; impl XcmCExecutorConfig for XcmConfig { diff --git a/runtime/darwinia-parachain/src/lib.rs b/runtime/darwinia-parachain/src/lib.rs index 0cc1eb82..28d7f283 100644 --- a/runtime/darwinia-parachain/src/lib.rs +++ b/runtime/darwinia-parachain/src/lib.rs @@ -161,6 +161,8 @@ frame_support::construct_runtime! { Multisig: pallet_multisig::{Pallet, Call, Storage, Event} = 17, Proxy: pallet_proxy::{Pallet, Call, Storage, Event} = 18, Sudo: pallet_sudo::{Pallet, Call, Storage, Config, Event} = 19, + + MessageRouter: dp_common_runtime::message_router::{Pallet, Call, Storage, Event} = 26, } } diff --git a/runtime/darwinia-parachain/src/pallets/message_router.rs b/runtime/darwinia-parachain/src/pallets/message_router.rs new file mode 100644 index 00000000..132967dd --- /dev/null +++ b/runtime/darwinia-parachain/src/pallets/message_router.rs @@ -0,0 +1,50 @@ +// --- paritytech --- +use frame_support::{traits::PalletInfoAccess, weights::Weight}; +use frame_system::EnsureRoot; +use xcm::prelude::*; +use xcm_builder::{EnsureXcmOrigin, FixedWeightBounds, LocationInverter}; +use xcm_executor::XcmExecutor; +// --- darwinia-network --- +use crate::*; +use dp_common_runtime::message_router::Config; + +frame_support::parameter_types! { + // https://github.com/PureStake/moonbeam/blob/master/runtime/moonbeam/src/xcm_config.rs#L201 + pub MoonbeamUnitWeightCost: Weight = 200_000_000; + // https://github.com/AstarNetwork/Astar/blob/master/runtime/astar/src/xcm_config.rs#L108 + pub AstarUnitWeightCost: Weight = 1_000_000_000; + pub SelfLocationInSibl: MultiLocation = MultiLocation::new( + 1, + X1(Parachain(ParachainInfo::parachain_id().into())) + ); + pub AnchoringSelfReserve: MultiLocation = MultiLocation::new( + 0, + X1(PalletInstance(::index() as u8)) + ); + pub MoonbeamLocation: MultiLocation = MultiLocation::new( + 1, + X1(Parachain(2004)) + ); + pub AstarLocation: MultiLocation = MultiLocation::new( + 1, + X1(Parachain(2006)) + ); +} + +impl Config for Runtime { + type AstarLocation = AstarLocation; + type AstarWeigher = FixedWeightBounds; + type ConfigModifierOrigin = EnsureRoot; + type Event = Event; + type ExecuteXcmOrigin = EnsureXcmOrigin; + type LocalAssetId = AnchoringSelfReserve; + type LocalWeigher = FixedWeightBounds; + type LocationInverter = LocationInverter; + type MoonbeamLocation = MoonbeamLocation; + type MoonbeamWeigher = FixedWeightBounds; + type SelfLocationInSibl = SelfLocationInSibl; + // Dont update the weights. + type WeightInfo = (); + type XcmExecutor = XcmExecutor; + type XcmSender = XcmRouter; +} diff --git a/runtime/darwinia-parachain/src/pallets/mod.rs b/runtime/darwinia-parachain/src/pallets/mod.rs index 31108982..db01c8aa 100644 --- a/runtime/darwinia-parachain/src/pallets/mod.rs +++ b/runtime/darwinia-parachain/src/pallets/mod.rs @@ -54,3 +54,6 @@ pub use proxy::*; pub mod sudo; pub use sudo::*; + +pub mod message_router; +pub use message_router::*; diff --git a/runtime/darwinia-parachain/src/pallets/polkadot_xcm.rs b/runtime/darwinia-parachain/src/pallets/polkadot_xcm.rs index bda5a590..f6f55c9a 100644 --- a/runtime/darwinia-parachain/src/pallets/polkadot_xcm.rs +++ b/runtime/darwinia-parachain/src/pallets/polkadot_xcm.rs @@ -14,7 +14,12 @@ use xcm_builder::*; use xcm_executor::{Config as XcmCExecutorConfig, XcmExecutor}; // --- darwinia-network --- use crate::*; -use dp_common_runtime::xcm_config::{DenyReserveTransferToRelayChain, DenyThenTry}; +use dp_common_runtime::{ + message_router::{ + barriers::AllowDescendOriginPaidExecutionFrom, location_conversion::AccountKey20Derive, + }, + xcm_config::{DenyReserveTransferToRelayChain, DenyThenTry}, +}; /// Converts a local signed origin into an XCM multilocation. /// Forms the basis for local origins sending/executing XCMs. @@ -48,6 +53,7 @@ pub type Barrier = DenyThenTry< ( TakeWeightCredit, AllowTopLevelPaidExecutionFrom, + AllowDescendOriginPaidExecutionFrom, // Parent and its exec plurality get free execution AllowUnpaidExecutionFrom, // Expected responses are OK. @@ -67,6 +73,8 @@ pub type LocationToAccountId = ( SiblingParachainConvertsVia, // Straight up local `AccountId32` origins just alias directly to `AccountId`. AccountId32Aliases, + // Derive AccountKey20 to AccountId32 + AccountKey20Derive, ); /// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, @@ -118,6 +126,20 @@ frame_support::match_types! { MultiLocation { parents: 1, interior: X1(_) } }; } +frame_support::match_types! { + pub type AllowDescendOrigin: impl Contains = { + // Moonbeam Location + MultiLocation { + parents: 1, + interior: X1(Parachain(2004)) + } | + // Astar Location + MultiLocation { + parents: 1, + interior: X1(Parachain(2006)) + } + }; +} pub struct XcmConfig; impl XcmCExecutorConfig for XcmConfig { diff --git a/runtime/pangolin-parachain/Cargo.toml b/runtime/pangolin-parachain/Cargo.toml index 574b57ca..856fa504 100644 --- a/runtime/pangolin-parachain/Cargo.toml +++ b/runtime/pangolin-parachain/Cargo.toml @@ -31,17 +31,18 @@ parachain-info = { default-features = false, git = "https://git dc-primitives = { default-features = false, path = "../../primitives" } dp-common-runtime = { default-features = false, path = "../common" } # darwinia-messages-substrate -bp-message-dispatch = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } -bp-messages = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } -bp-pangolin = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } -bp-pangolin-parachain = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } -bp-polkadot-core = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } -bp-runtime = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } -bridge-runtime-common = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } -pallet-bridge-dispatch = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } -pallet-bridge-grandpa = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } -pallet-bridge-messages = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } -pallet-fee-market = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } +bp-message-dispatch = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } +bp-messages = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } +bp-pangolin = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } +bp-pangolin-parachain = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } +bp-pangolin-parachain-alpha = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } +bp-polkadot-core = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } +bp-runtime = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } +bridge-runtime-common = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } +pallet-bridge-dispatch = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } +pallet-bridge-grandpa = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } +pallet-bridge-messages = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } +pallet-fee-market = { default-features = false, git = "https://github.com/darwinia-network/darwinia-messages-substrate", branch = "polkadot-v0.9.27" } # polkadot pallet-xcm = { default-features = false, git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.27" } pallet-xcm-benchmarks = { optional = true, default-features = false, git = "https://github.com/paritytech/polkadot", branch = "release-v0.9.27" } diff --git a/runtime/pangolin-parachain/src/bridges_message/pangolin.rs b/runtime/pangolin-parachain/src/bridges_message/pangolin.rs index 644cffc5..92717b6a 100644 --- a/runtime/pangolin-parachain/src/bridges_message/pangolin.rs +++ b/runtime/pangolin-parachain/src/bridges_message/pangolin.rs @@ -10,7 +10,7 @@ use crate::*; use bp_messages::{source_chain::*, target_chain::*, *}; use bp_runtime::*; use bridge_runtime_common::{ - lanes::PANGOLIN_PANGOLIN_PARACHAIN_LANE, + lanes::*, messages::{source::*, target::*, *}, }; use dp_common_runtime::FromThisChainMessageVerifier; @@ -68,10 +68,17 @@ impl MessageBridge for WithPangolinMessageBridge { type ThisChain = PangolinParachain; const BRIDGED_CHAIN_ID: ChainId = PANGOLIN_CHAIN_ID; + #[cfg(not(feature = "alpha"))] const BRIDGED_MESSAGES_PALLET_NAME: &'static str = bp_pangolin_parachain::WITH_PANGOLIN_PARACHAIN_MESSAGES_PALLET_NAME; + #[cfg(feature = "alpha")] + const BRIDGED_MESSAGES_PALLET_NAME: &'static str = + bp_pangolin_parachain_alpha::WITH_PANGOLIN_PARACHAIN_MESSAGES_PALLET_NAME; const RELAYER_FEE_PERCENT: u32 = 10; + #[cfg(not(feature = "alpha"))] const THIS_CHAIN_ID: ChainId = PANGOLIN_PARACHAIN_CHAIN_ID; + #[cfg(feature = "alpha")] + const THIS_CHAIN_ID: ChainId = PANGOLIN_PARACHAIN_ALPHA_CHAIN_ID; } #[derive(Clone, Copy, RuntimeDebug)] @@ -88,10 +95,18 @@ impl ThisChainWithMessages for PangolinParachain { type Call = Call; type Origin = Origin; + #[cfg(not(feature = "alpha"))] fn is_message_accepted(_send_origin: &Self::Origin, lane: &LaneId) -> bool { *lane == [0, 0, 0, 0] || *lane == [0, 0, 0, 1] || *lane == PANGOLIN_PANGOLIN_PARACHAIN_LANE } + #[cfg(feature = "alpha")] + fn is_message_accepted(_send_origin: &Self::Origin, lane: &LaneId) -> bool { + *lane == [0, 0, 0, 0] + || *lane == [0, 0, 0, 1] + || *lane == PANGOLIN_PANGOLIN_PARACHAIN_ALPHA_LANE + } + fn maximal_pending_messages_at_outbound_lane() -> MessageNonce { MessageNonce::MAX } diff --git a/runtime/pangolin-parachain/src/lib.rs b/runtime/pangolin-parachain/src/lib.rs index 0ec51038..80b5386d 100644 --- a/runtime/pangolin-parachain/src/lib.rs +++ b/runtime/pangolin-parachain/src/lib.rs @@ -188,6 +188,8 @@ frame_support::construct_runtime! { PangolinFeeMarket: pallet_fee_market::::{Pallet, Call, Storage, Event} = 23, FromPangolinIssuing: dp_common_runtime::helixbridge::{Pallet, Call, Storage, Event} = 24, + + MessageRouter: dp_common_runtime::message_router::{Pallet, Call, Storage, Event} = 26, } } diff --git a/runtime/pangolin-parachain/src/pallets/bridge_messages.rs b/runtime/pangolin-parachain/src/pallets/bridge_messages.rs index 86816bce..aea85582 100644 --- a/runtime/pangolin-parachain/src/pallets/bridge_messages.rs +++ b/runtime/pangolin-parachain/src/pallets/bridge_messages.rs @@ -1,7 +1,7 @@ pub use pallet_bridge_messages::Instance1 as WithPangolinMessages; // --- darwinia-network --- -use crate::{weights::pallet_bridge_messages::WeightInfo, *}; +use crate::*; use bp_messages::{source_chain::SenderOrigin, MessageNonce}; use bp_runtime::{ChainId, PANGOLIN_CHAIN_ID}; use pallet_bridge_messages::Config; @@ -52,5 +52,5 @@ impl Config for Runtime { type Parameter = bm_pangolin::PangolinParachainToPangolinParameter; type SourceHeaderChain = bm_pangolin::Pangolin; type TargetHeaderChain = bm_pangolin::Pangolin; - type WeightInfo = WeightInfo; + type WeightInfo = (); } diff --git a/runtime/pangolin-parachain/src/pallets/message_router.rs b/runtime/pangolin-parachain/src/pallets/message_router.rs new file mode 100644 index 00000000..c5de6640 --- /dev/null +++ b/runtime/pangolin-parachain/src/pallets/message_router.rs @@ -0,0 +1,50 @@ +// --- paritytech --- +use frame_support::{traits::PalletInfoAccess, weights::Weight}; +use frame_system::EnsureRoot; +use xcm::prelude::*; +use xcm_builder::{EnsureXcmOrigin, FixedWeightBounds, LocationInverter}; +use xcm_executor::XcmExecutor; +// --- darwinia-network --- +use crate::*; +use dp_common_runtime::message_router::Config; + +frame_support::parameter_types! { + // https://github.com/PureStake/moonbeam/blob/master/runtime/moonbase/src/xcm_config.rs#L214 + pub MoonbeamUnitWeightCost: Weight = 200_000_000; + // https://github.com/AstarNetwork/Astar/blob/master/runtime/shibuya/src/xcm_config.rs#L108 + pub RocstarUnitWeightCost: Weight = 1_000_000_000; + pub SelfLocationInSibl: MultiLocation = MultiLocation::new( + 1, + X1(Parachain(ParachainInfo::parachain_id().into())) + ); + pub AnchoringSelfReserve: MultiLocation = MultiLocation::new( + 0, + X1(PalletInstance(::index() as u8)) + ); + pub MoonbaseAlphaLocation: MultiLocation = MultiLocation::new( + 1, + X1(Parachain(1000)) + ); + pub RocstarLocation: MultiLocation = MultiLocation::new( + 1, + X1(Parachain(2006)) + ); +} + +impl Config for Runtime { + type AstarLocation = RocstarLocation; + type AstarWeigher = FixedWeightBounds; + type ConfigModifierOrigin = EnsureRoot; + type Event = Event; + type ExecuteXcmOrigin = EnsureXcmOrigin; + type LocalAssetId = AnchoringSelfReserve; + type LocalWeigher = FixedWeightBounds; + type LocationInverter = LocationInverter; + type MoonbeamLocation = MoonbaseAlphaLocation; + type MoonbeamWeigher = FixedWeightBounds; + type SelfLocationInSibl = SelfLocationInSibl; + // Dont update the weights. + type WeightInfo = (); + type XcmExecutor = XcmExecutor; + type XcmSender = XcmRouter; +} diff --git a/runtime/pangolin-parachain/src/pallets/mod.rs b/runtime/pangolin-parachain/src/pallets/mod.rs index bd358b83..69d5aeba 100644 --- a/runtime/pangolin-parachain/src/pallets/mod.rs +++ b/runtime/pangolin-parachain/src/pallets/mod.rs @@ -72,3 +72,6 @@ pub use fee_market::*; pub mod helixbridge; pub use helixbridge::*; + +pub mod message_router; +pub use message_router::*; diff --git a/runtime/pangolin-parachain/src/pallets/polkadot_xcm.rs b/runtime/pangolin-parachain/src/pallets/polkadot_xcm.rs index 149ca64d..a31e2209 100644 --- a/runtime/pangolin-parachain/src/pallets/polkadot_xcm.rs +++ b/runtime/pangolin-parachain/src/pallets/polkadot_xcm.rs @@ -14,7 +14,12 @@ use xcm_builder::*; use xcm_executor::{Config as XcmCExecutorConfig, XcmExecutor}; // --- darwinia-network --- use crate::*; -use dp_common_runtime::xcm_config::{DenyReserveTransferToRelayChain, DenyThenTry}; +use dp_common_runtime::{ + message_router::{ + barriers::AllowDescendOriginPaidExecutionFrom, location_conversion::AccountKey20Derive, + }, + xcm_config::{DenyReserveTransferToRelayChain, DenyThenTry}, +}; /// Converts a local signed origin into an XCM multilocation. /// Forms the basis for local origins sending/executing XCMs. @@ -48,6 +53,7 @@ pub type Barrier = DenyThenTry< ( TakeWeightCredit, AllowTopLevelPaidExecutionFrom, + AllowDescendOriginPaidExecutionFrom, // Parent and its exec plurality get free execution AllowUnpaidExecutionFrom, // Expected responses are OK. @@ -67,6 +73,8 @@ pub type LocationToAccountId = ( SiblingParachainConvertsVia, // Straight up local `AccountId32` origins just alias directly to `AccountId`. AccountId32Aliases, + // Derive AccountKey20 to AccountId32 + AccountKey20Derive, ); /// This is the type we use to convert an (incoming) XCM origin into a local `Origin` instance, @@ -118,6 +126,20 @@ frame_support::match_types! { MultiLocation { parents: 1, interior: X1(_) } }; } +frame_support::match_types! { + pub type AllowDescendOrigin: impl Contains = { + // MoonbaseAlpha location + MultiLocation { + parents: 1, + interior: X1(Parachain(1000)) + } | + // Astar RocstarTestnet location + MultiLocation { + parents: 1, + interior: X1(Parachain(2006)) + } + }; +} pub struct XcmConfig; impl XcmCExecutorConfig for XcmConfig {