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 {