// Copyright (C) Parity Technologies (UK) Ltd. // This file is part of Polkadot. // Polkadot 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. // Polkadot 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 Polkadot. If not, see . //! A set of traits that define how a pallet interface with XCM. //! Controller traits defined in this module are high-level traits that will rely on other traits //! from `xcm-executor` to perform their tasks. use frame_support::{ dispatch::{DispatchErrorWithPostInfo, WithPostDispatchInfo}, pallet_prelude::DispatchError, }; use sp_std::boxed::Box; use xcm::prelude::*; pub use xcm_executor::traits::QueryHandler; /// Umbrella trait for all Controller traits. pub trait Controller: ExecuteController + SendController + QueryController { } impl Controller for T where T: ExecuteController + SendController + QueryController { } /// Weight functions needed for [`ExecuteController`]. pub trait ExecuteControllerWeightInfo { /// Weight for [`ExecuteController::execute`] fn execute() -> Weight; } /// Execute an XCM locally, for a given origin. /// /// An implementation of that trait will handle the low-level details of the execution, such as: /// - Validating and Converting the origin to a Location. /// - Handling versioning. /// - Calling the internal executor, which implements [`ExecuteXcm`]. pub trait ExecuteController { /// Weight information for ExecuteController functions. type WeightInfo: ExecuteControllerWeightInfo; /// Attempt to execute an XCM locally, returns Ok with the weight consumed if the execution /// complete successfully, Err otherwise. /// /// # Parameters /// /// - `origin`: the origin of the call. /// - `message`: the XCM program to be executed. /// - `max_weight`: the maximum weight that can be consumed by the execution. fn execute( origin: Origin, message: Box>, max_weight: Weight, ) -> Result; } /// Weight functions needed for [`SendController`]. pub trait SendControllerWeightInfo { /// Weight for [`SendController::send`] fn send() -> Weight; } /// Send an XCM from a given origin. /// /// An implementation of that trait will handle the low-level details of dispatching an XCM, such /// as: /// - Validating and Converting the origin to an interior location. /// - Handling versioning. /// - Calling the internal router, which implements [`SendXcm`]. pub trait SendController { /// Weight information for SendController functions. type WeightInfo: SendControllerWeightInfo; /// Send an XCM to be executed by a remote location. /// /// # Parameters /// /// - `origin`: the origin of the call. /// - `dest`: the destination of the message. /// - `msg`: the XCM to be sent. fn send( origin: Origin, dest: Box, message: Box>, ) -> Result; } /// Weight functions needed for [`QueryController`]. pub trait QueryControllerWeightInfo { /// Weight for [`QueryController::query`] fn query() -> Weight; /// Weight for [`QueryHandler::take_response`] fn take_response() -> Weight; } /// Query a remote location, from a given origin. /// /// An implementation of that trait will handle the low-level details of querying a remote location, /// such as: /// - Validating and Converting the origin to an interior location. /// - Handling versioning. /// - Calling the [`QueryHandler`] to register the query. pub trait QueryController: QueryHandler { /// Weight information for QueryController functions. type WeightInfo: QueryControllerWeightInfo; /// Query a remote location. /// /// # Parameters /// /// - `origin`: the origin of the call, used to determine the responder. /// - `timeout`: the maximum block number that the query should be responded to. /// - `match_querier`: the querier that the query should be responded to. fn query( origin: Origin, timeout: Timeout, match_querier: VersionedLocation, ) -> Result; } impl ExecuteController for () { type WeightInfo = (); fn execute( _origin: Origin, _message: Box>, _max_weight: Weight, ) -> Result { Err(DispatchError::Other("ExecuteController::execute not implemented") .with_weight(Weight::zero())) } } impl ExecuteControllerWeightInfo for () { fn execute() -> Weight { Weight::zero() } } impl SendController for () { type WeightInfo = (); fn send( _origin: Origin, _dest: Box, _message: Box>, ) -> Result { Ok(Default::default()) } } impl SendControllerWeightInfo for () { fn send() -> Weight { Weight::zero() } } impl QueryControllerWeightInfo for () { fn query() -> Weight { Weight::zero() } fn take_response() -> Weight { Weight::zero() } } impl QueryController for () { type WeightInfo = (); fn query( _origin: Origin, _timeout: Timeout, _match_querier: VersionedLocation, ) -> Result { Ok(Default::default()) } }