diff --git a/cumulus/Cargo.lock b/cumulus/Cargo.lock index d249158bfcc46fde1296c412ec80b4b1bdb231bd..f2c36dfacdef5828107a21a003ff28ec53dfb69a 100644 --- a/cumulus/Cargo.lock +++ b/cumulus/Cargo.lock @@ -1304,6 +1304,7 @@ dependencies = [ "parity-scale-codec", "sp-std", "xcm", + "xcm-executor", ] [[package]] diff --git a/cumulus/pallets/xcm-handler/Cargo.toml b/cumulus/pallets/xcm-handler/Cargo.toml index b982c1dba69d0b02b140c70edf43c7309d13a8d9..c5d57a2b329b4282718eb1ab68c39aa27d52afd7 100644 --- a/cumulus/pallets/xcm-handler/Cargo.toml +++ b/cumulus/pallets/xcm-handler/Cargo.toml @@ -16,6 +16,7 @@ frame-system = { git = "https://github.com/paritytech/substrate", default-featur # Polkadot Dependencies xcm = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" } +xcm-executor = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" } # Cumulus Dependencies cumulus-primitives-core = { path = "../../primitives/core", default-features = false } @@ -29,5 +30,6 @@ std = [ "frame-support/std", "frame-system/std", "cumulus-primitives-core/std", - "xcm/std" + "xcm/std", + "xcm-executor/std", ] diff --git a/cumulus/pallets/xcm-handler/src/lib.rs b/cumulus/pallets/xcm-handler/src/lib.rs index 1f80eee78075ed0d8b347a29726d0a416f2b1634..03d50fa19ac8fe30d601393a96ed3b202d455d42 100644 --- a/cumulus/pallets/xcm-handler/src/lib.rs +++ b/cumulus/pallets/xcm-handler/src/lib.rs @@ -27,12 +27,13 @@ use cumulus_primitives_core::{ DownwardMessageHandler, HrmpMessageHandler, HrmpMessageSender, InboundDownwardMessage, InboundHrmpMessage, OutboundHrmpMessage, ParaId, UpwardMessageSender, }; -use frame_support::{decl_error, decl_event, decl_module, sp_runtime::traits::Hash, traits::EnsureOrigin}; +use frame_support::{decl_error, decl_event, decl_module, dispatch::DispatchResult, sp_runtime::traits::Hash, traits::EnsureOrigin}; use sp_std::convert::{TryFrom, TryInto}; use xcm::{ v0::{Error as XcmError, ExecuteXcm, Junction, MultiLocation, SendXcm, Xcm}, VersionedXcm, }; +use xcm_executor::traits::LocationConversion; pub trait Config: frame_system::Config { type Event: From<Event<Self>> + Into<<Self as frame_system::Config>::Event>; @@ -45,6 +46,9 @@ pub trait Config: frame_system::Config { /// Required origin for sending XCM messages. Typically Root or parachain /// council majority. type SendXcmOrigin: EnsureOrigin<Self::Origin>; + /// Utility for converting from the signed origin (of type `Self::AccountId`) into a sensible + /// `MultiLocation` ready for passing to the XCM interpreter. + type AccountIdConverter: LocationConversion<Self::AccountId>; } decl_event! { @@ -68,6 +72,8 @@ decl_error! { pub enum Error for Module<T: Config> { /// Failed to send XCM message. FailedToSend, + /// Bad XCM origin. + BadXcmOrigin, } } @@ -101,6 +107,21 @@ decl_module! { } } +impl<T: Config> Module<T> { + /// Execute an XCM message locally. Returns `DispatchError` if failed. + pub fn execute_xcm(origin: T::AccountId, xcm: Xcm) -> DispatchResult { + let xcm_origin = T::AccountIdConverter::try_into_location(origin) + .map_err(|_| Error::<T>::BadXcmOrigin)?; + let hash = T::Hashing::hash(&xcm.encode()); + let event = match T::XcmExecutor::execute_xcm(xcm_origin, xcm) { + Ok(_) => Event::<T>::Success(hash), + Err(e) => Event::<T>::Fail(hash, e), + }; + Self::deposit_event(event); + Ok(()) + } +} + impl<T: Config> DownwardMessageHandler for Module<T> { fn handle_downward_message(msg: InboundDownwardMessage) { let hash = msg.using_encoded(T::Hashing::hash); diff --git a/cumulus/rococo-parachains/runtime/src/lib.rs b/cumulus/rococo-parachains/runtime/src/lib.rs index 3c1741a6210841ec8aaef49b71116451d0fcce12..b056057149cc4808e7b29454c1fba07d814282f5 100644 --- a/cumulus/rococo-parachains/runtime/src/lib.rs +++ b/cumulus/rococo-parachains/runtime/src/lib.rs @@ -290,6 +290,7 @@ impl cumulus_pallet_xcm_handler::Config for Runtime { type UpwardMessageSender = ParachainSystem; type HrmpMessageSender = ParachainSystem; type SendXcmOrigin = EnsureRoot<AccountId>; + type AccountIdConverter = LocationConverter; } construct_runtime! {