1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
// 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 <http://www.gnu.org/licenses/>.
//! 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 alloc::boxed::Box;
use frame_support::{
dispatch::{DispatchErrorWithPostInfo, WithPostDispatchInfo},
pallet_prelude::DispatchError,
};
use xcm::prelude::*;
pub use xcm_executor::traits::QueryHandler;
/// Umbrella trait for all Controller traits.
pub trait Controller<Origin, RuntimeCall, Timeout>:
ExecuteController<Origin, RuntimeCall> + SendController<Origin> + QueryController<Origin, Timeout>
{
}
impl<T, Origin, RuntimeCall, Timeout> Controller<Origin, RuntimeCall, Timeout> for T where
T: ExecuteController<Origin, RuntimeCall>
+ SendController<Origin>
+ QueryController<Origin, Timeout>
{
}
/// 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<Origin, RuntimeCall> {
/// 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<VersionedXcm<RuntimeCall>>,
max_weight: Weight,
) -> Result<Weight, DispatchErrorWithPostInfo>;
}
/// 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<Origin> {
/// 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<VersionedLocation>,
message: Box<VersionedXcm<()>>,
) -> Result<XcmHash, DispatchError>;
}
/// 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<Origin, Timeout>: 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<QueryId, DispatchError>;
}
impl<Origin, RuntimeCall> ExecuteController<Origin, RuntimeCall> for () {
type WeightInfo = ();
fn execute(
_origin: Origin,
_message: Box<VersionedXcm<RuntimeCall>>,
_max_weight: Weight,
) -> Result<Weight, DispatchErrorWithPostInfo> {
Err(DispatchError::Other("ExecuteController::execute not implemented")
.with_weight(Weight::zero()))
}
}
impl ExecuteControllerWeightInfo for () {
fn execute() -> Weight {
Weight::zero()
}
}
impl<Origin> SendController<Origin> for () {
type WeightInfo = ();
fn send(
_origin: Origin,
_dest: Box<VersionedLocation>,
_message: Box<VersionedXcm<()>>,
) -> Result<XcmHash, DispatchError> {
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<Origin, Timeout> QueryController<Origin, Timeout> for () {
type WeightInfo = ();
fn query(
_origin: Origin,
_timeout: Timeout,
_match_querier: VersionedLocation,
) -> Result<QueryId, DispatchError> {
Ok(Default::default())
}
}