From adaa63098b2c33179319ffedf8eff6ad476623b5 Mon Sep 17 00:00:00 2001 From: Shawn Tabrizi Date: Mon, 14 Dec 2020 02:11:08 -0800 Subject: [PATCH] Add Basic XCM (#1934) * basic setup * fix compile * add back xcmsink * Update primitives.rs * add downward xcm for sudo * Update paras_sudo_wrapper.rs * Update Cargo.lock * some cleanups * Add error log Co-authored-by: Sergei Shulepov --- polkadot/Cargo.lock | 5 ++ polkadot/runtime/common/Cargo.toml | 3 ++ .../runtime/common/src/paras_sudo_wrapper.rs | 7 +-- polkadot/runtime/parachains/Cargo.toml | 2 + polkadot/runtime/parachains/src/ump.rs | 36 +++++++++++++ polkadot/runtime/rococo/Cargo.toml | 7 +++ polkadot/runtime/rococo/src/lib.rs | 52 ++++++++++++++++++- 7 files changed, 108 insertions(+), 4 deletions(-) diff --git a/polkadot/Cargo.lock b/polkadot/Cargo.lock index a892de4394..549cf44670 100644 --- a/polkadot/Cargo.lock +++ b/polkadot/Cargo.lock @@ -5509,6 +5509,7 @@ dependencies = [ "sp-trie", "static_assertions", "trie-db", + "xcm", ] [[package]] @@ -5558,6 +5559,7 @@ dependencies = [ "sp-trie", "sp-version", "xcm", + "xcm-executor", ] [[package]] @@ -6535,6 +6537,9 @@ dependencies = [ "sp-transaction-pool", "sp-version", "substrate-wasm-builder", + "xcm", + "xcm-builder", + "xcm-executor", ] [[package]] diff --git a/polkadot/runtime/common/Cargo.toml b/polkadot/runtime/common/Cargo.toml index 05c1ca1e51..81195872bd 100644 --- a/polkadot/runtime/common/Cargo.toml +++ b/polkadot/runtime/common/Cargo.toml @@ -39,6 +39,8 @@ primitives = { package = "polkadot-primitives", path = "../../primitives", defau libsecp256k1 = { version = "0.3.5", default-features = false, optional = true } runtime-parachains = { package = "polkadot-runtime-parachains", path = "../parachains", default-features = false } +xcm = { path = "../../xcm", default-features = false } + [dev-dependencies] hex-literal = "0.3.1" keyring = { package = "sp-keyring", git = "https://github.com/paritytech/substrate", branch = "master" } @@ -81,6 +83,7 @@ std = [ "pallet-vesting/std", "pallet-transaction-payment/std", "runtime-parachains/std", + "xcm/std", ] runtime-benchmarks = [ "libsecp256k1/hmac", diff --git a/polkadot/runtime/common/src/paras_sudo_wrapper.rs b/polkadot/runtime/common/src/paras_sudo_wrapper.rs index c0eb9426fc..796051a27e 100644 --- a/polkadot/runtime/common/src/paras_sudo_wrapper.rs +++ b/polkadot/runtime/common/src/paras_sudo_wrapper.rs @@ -28,6 +28,7 @@ use runtime_parachains::{ configuration, dmp, ump, hrmp, paras::{self, ParaGenesisArgs}, }; use primitives::v1::Id as ParaId; +use parity_scale_codec::Encode; /// The module's configuration trait. pub trait Config: @@ -73,16 +74,16 @@ decl_module! { Ok(()) } - /// Send a downward message to the given para. + /// Send a downward XCM to the given para. /// /// The given parachain should exist and the payload should not exceed the preconfigured size /// `config.max_downward_message_size`. #[weight = (1_000, DispatchClass::Operational)] - pub fn sudo_queue_downward_message(origin, id: ParaId, payload: Vec) -> DispatchResult { + pub fn sudo_queue_downward_xcm(origin, id: ParaId, xcm: xcm::VersionedXcm) -> DispatchResult { ensure_root(origin)?; ensure!(>::is_valid_para(id), Error::::ParaDoesntExist); let config = >::config(); - >::queue_downward_message(&config, id, payload) + >::queue_downward_message(&config, id, xcm.encode()) .map_err(|e| match e { dmp::QueueDownwardMessageError::ExceedsMaxMessageSize => Error::::ExceedsMaxMessageSize.into(), diff --git a/polkadot/runtime/parachains/Cargo.toml b/polkadot/runtime/parachains/Cargo.toml index 58e84a1241..9899a77986 100644 --- a/polkadot/runtime/parachains/Cargo.toml +++ b/polkadot/runtime/parachains/Cargo.toml @@ -35,6 +35,7 @@ pallet-offences = { git = "https://github.com/paritytech/substrate", branch = "m frame-benchmarking = { git = "https://github.com/paritytech/substrate", branch = "master", default-features = false, optional = true } xcm = { package = "xcm", path = "../../xcm", default-features = false } +xcm-executor = { package = "xcm-executor", path = "../../xcm/xcm-executor", default-features = false } primitives = { package = "polkadot-primitives", path = "../../primitives", default-features = false } libsecp256k1 = { version = "0.3.5", default-features = false, optional = true } @@ -84,6 +85,7 @@ std = [ "pallet-timestamp/std", "pallet-vesting/std", "xcm/std", + "xcm-executor/std", ] runtime-benchmarks = [ "libsecp256k1/hmac", diff --git a/polkadot/runtime/parachains/src/ump.rs b/polkadot/runtime/parachains/src/ump.rs index f18ad250b9..8974f9c9ff 100644 --- a/polkadot/runtime/parachains/src/ump.rs +++ b/polkadot/runtime/parachains/src/ump.rs @@ -52,6 +52,42 @@ impl UmpSink for () { } } +/// A specific implementation of a UmpSink where messages are in the XCM format +/// and will be forwarded to the XCM Executor. +pub struct XcmSink(sp_std::marker::PhantomData); + +impl UmpSink for XcmSink { + fn process_upward_message(origin: ParaId, msg: Vec) -> Weight { + use parity_scale_codec::Decode; + use xcm::VersionedXcm; + use xcm::v0::{Junction, MultiLocation, ExecuteXcm}; + use xcm_executor::XcmExecutor; + + let weight: Weight = 0; + + if let Ok(versioned_xcm_message) = VersionedXcm::decode(&mut &msg[..]) { + match versioned_xcm_message { + VersionedXcm::V0(xcm_message) => { + let xcm_junction: Junction = Junction::Parachain { id: origin.into() }; + let xcm_location: MultiLocation = xcm_junction.into(); + // TODO: Do something with result. + let _result = XcmExecutor::::execute_xcm(xcm_location, xcm_message); + } + } + } else { + frame_support::debug::error!( + target: "xcm", + "Failed to decode versioned XCM from upward message.", + ); + } + + // TODO: to be sound, this implementation must ensure that returned (and thus consumed) + // weight is limited to some small portion of the total block weight (as a ballpark, 1/4, 1/8 + // or lower). + weight + } +} + /// An error returned by [`check_upward_messages`] that indicates a violation of one of acceptance /// criteria rules. pub enum AcceptanceCheckErr { diff --git a/polkadot/runtime/rococo/Cargo.toml b/polkadot/runtime/rococo/Cargo.toml index 1ca7f44774..1854e860ca 100644 --- a/polkadot/runtime/rococo/Cargo.toml +++ b/polkadot/runtime/rococo/Cargo.toml @@ -53,6 +53,10 @@ primitives = { package = "polkadot-primitives", path = "../../primitives", defau polkadot-parachain = { path = "../../parachain", default-features = false } runtime-parachains = { package = "polkadot-runtime-parachains", path = "../parachains", default-features = false } +xcm = { package = "xcm", path = "../../xcm", default-features = false } +xcm-executor = { package = "xcm-executor", path = "../../xcm/xcm-executor", default-features = false } +xcm-builder = { package = "xcm-builder", path = "../../xcm/xcm-builder", default-features = false } + [build-dependencies] substrate-wasm-builder = "3.0.0" @@ -99,6 +103,9 @@ std = [ "sp-version/std", "serde_derive", "serde/std", + "xcm/std", + "xcm-executor/std", + "xcm-builder/std", ] # When enabled, the runtime api will not be build. # diff --git a/polkadot/runtime/rococo/src/lib.rs b/polkadot/runtime/rococo/src/lib.rs index 4eeaf3b1be..da437e71c0 100644 --- a/polkadot/runtime/rococo/src/lib.rs +++ b/polkadot/runtime/rococo/src/lib.rs @@ -82,6 +82,15 @@ use runtime_parachains::scheduler as parachains_scheduler; pub use pallet_balances::Call as BalancesCall; pub use pallet_staking::StakerStatus; +use polkadot_parachain::primitives::Id as ParaId; +use xcm::v0::{MultiLocation, NetworkId}; +use xcm_executor::traits::IsConcrete; +use xcm_builder::{ + AccountId32Aliases, ChildParachainConvertsVia, SovereignSignedViaLocation, + CurrencyAdapter as XcmCurrencyAdapter, ChildParachainAsNative, + SignedAccountId32AsNative, ChildSystemParachainAsSuperuser, LocationInverter, +}; + /// Constant values used within the runtime. pub mod constants; use constants::{time::*, currency::*, fee::*}; @@ -535,10 +544,51 @@ impl parachains_paras::Config for Runtime { type Origin = Origin; } +parameter_types! { + pub const RocLocation: MultiLocation = MultiLocation::Null; + pub const RococoNetwork: NetworkId = NetworkId::Polkadot; + pub const Ancestry: MultiLocation = MultiLocation::Null; +} + +pub type LocationConverter = ( + ChildParachainConvertsVia, + AccountId32Aliases, +); + +pub type LocalAssetTransactor = + XcmCurrencyAdapter< + // Use this currency: + Balances, + // Use this currency when it is a fungible asset matching the given location or name: + IsConcrete, + // We can convert the MultiLocations with our converter above: + LocationConverter, + // Our chain's account ID type (we can't get away without mentioning it explicitly): + AccountId, + >; + +type LocalOriginConverter = ( + SovereignSignedViaLocation, + ChildParachainAsNative, + SignedAccountId32AsNative, + ChildSystemParachainAsSuperuser, +); + +pub struct XcmConfig; +impl xcm_executor::Config for XcmConfig { + type Call = Call; + type XcmSender = (); + type AssetTransactor = LocalAssetTransactor; + type OriginConverter = LocalOriginConverter; + type IsReserve = (); + type IsTeleporter = (); + type LocationInverter = LocationInverter; +} + impl parachains_session_info::Config for Runtime {} impl parachains_ump::Config for Runtime { - type UmpSink = (); // TODO: #1873 To be handled by the XCM receiver. + type UmpSink = crate::parachains_ump::XcmSink; } impl parachains_dmp::Config for Runtime {}