staging_xcm_builder/controller.rs
1// Copyright (C) Parity Technologies (UK) Ltd.
2// This file is part of Polkadot.
3
4// Polkadot is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8
9// Polkadot is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12// GNU General Public License for more details.
13
14// You should have received a copy of the GNU General Public License
15// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
16
17//! A set of traits that define how a pallet interface with XCM.
18//! Controller traits defined in this module are high-level traits that will rely on other traits
19//! from `xcm-executor` to perform their tasks.
20
21use alloc::boxed::Box;
22use frame_support::{
23 dispatch::{DispatchErrorWithPostInfo, WithPostDispatchInfo},
24 pallet_prelude::DispatchError,
25};
26use xcm::prelude::*;
27pub use xcm_executor::traits::QueryHandler;
28
29/// Umbrella trait for all Controller traits.
30pub trait Controller<Origin, RuntimeCall, Timeout>:
31 ExecuteController<Origin, RuntimeCall> + SendController<Origin> + QueryController<Origin, Timeout>
32{
33}
34
35impl<T, Origin, RuntimeCall, Timeout> Controller<Origin, RuntimeCall, Timeout> for T where
36 T: ExecuteController<Origin, RuntimeCall>
37 + SendController<Origin>
38 + QueryController<Origin, Timeout>
39{
40}
41
42/// Weight functions needed for [`ExecuteController`].
43pub trait ExecuteControllerWeightInfo {
44 /// Weight for [`ExecuteController::execute`]
45 fn execute() -> Weight;
46}
47
48/// Execute an XCM locally, for a given origin.
49///
50/// An implementation of that trait will handle the low-level details of the execution, such as:
51/// - Validating and Converting the origin to a Location.
52/// - Handling versioning.
53/// - Calling the internal executor, which implements [`ExecuteXcm`].
54pub trait ExecuteController<Origin, RuntimeCall> {
55 /// Weight information for ExecuteController functions.
56 type WeightInfo: ExecuteControllerWeightInfo;
57
58 /// Attempt to execute an XCM locally, returns Ok with the weight consumed if the execution
59 /// complete successfully, Err otherwise.
60 ///
61 /// # Parameters
62 ///
63 /// - `origin`: the origin of the call.
64 /// - `message`: the XCM program to be executed.
65 /// - `max_weight`: the maximum weight that can be consumed by the execution.
66 fn execute(
67 origin: Origin,
68 message: Box<VersionedXcm<RuntimeCall>>,
69 max_weight: Weight,
70 ) -> Result<Weight, DispatchErrorWithPostInfo>;
71}
72
73/// Weight functions needed for [`SendController`].
74pub trait SendControllerWeightInfo {
75 /// Weight for [`SendController::send`]
76 fn send() -> Weight;
77}
78
79/// Send an XCM from a given origin.
80///
81/// An implementation of that trait will handle the low-level details of dispatching an XCM, such
82/// as:
83/// - Validating and Converting the origin to an interior location.
84/// - Handling versioning.
85/// - Calling the internal router, which implements [`SendXcm`].
86pub trait SendController<Origin> {
87 /// Weight information for SendController functions.
88 type WeightInfo: SendControllerWeightInfo;
89
90 /// Send an XCM to be executed by a remote location.
91 ///
92 /// # Parameters
93 ///
94 /// - `origin`: the origin of the call.
95 /// - `dest`: the destination of the message.
96 /// - `msg`: the XCM to be sent.
97 fn send(
98 origin: Origin,
99 dest: Box<VersionedLocation>,
100 message: Box<VersionedXcm<()>>,
101 ) -> Result<XcmHash, DispatchError>;
102}
103
104/// Weight functions needed for [`QueryController`].
105pub trait QueryControllerWeightInfo {
106 /// Weight for [`QueryController::query`]
107 fn query() -> Weight;
108
109 /// Weight for [`QueryHandler::take_response`]
110 fn take_response() -> Weight;
111}
112
113/// Query a remote location, from a given origin.
114///
115/// An implementation of that trait will handle the low-level details of querying a remote location,
116/// such as:
117/// - Validating and Converting the origin to an interior location.
118/// - Handling versioning.
119/// - Calling the [`QueryHandler`] to register the query.
120pub trait QueryController<Origin, Timeout>: QueryHandler {
121 /// Weight information for QueryController functions.
122 type WeightInfo: QueryControllerWeightInfo;
123
124 /// Query a remote location.
125 ///
126 /// # Parameters
127 ///
128 /// - `origin`: the origin of the call, used to determine the responder.
129 /// - `timeout`: the maximum block number that the query should be responded to.
130 /// - `match_querier`: the querier that the query should be responded to.
131 fn query(
132 origin: Origin,
133 timeout: Timeout,
134 match_querier: VersionedLocation,
135 ) -> Result<QueryId, DispatchError>;
136}
137
138impl<Origin, RuntimeCall> ExecuteController<Origin, RuntimeCall> for () {
139 type WeightInfo = ();
140 fn execute(
141 _origin: Origin,
142 _message: Box<VersionedXcm<RuntimeCall>>,
143 _max_weight: Weight,
144 ) -> Result<Weight, DispatchErrorWithPostInfo> {
145 Err(DispatchError::Other("ExecuteController::execute not implemented")
146 .with_weight(Weight::zero()))
147 }
148}
149
150impl ExecuteControllerWeightInfo for () {
151 fn execute() -> Weight {
152 Weight::zero()
153 }
154}
155
156impl<Origin> SendController<Origin> for () {
157 type WeightInfo = ();
158 fn send(
159 _origin: Origin,
160 _dest: Box<VersionedLocation>,
161 _message: Box<VersionedXcm<()>>,
162 ) -> Result<XcmHash, DispatchError> {
163 Ok(Default::default())
164 }
165}
166
167impl SendControllerWeightInfo for () {
168 fn send() -> Weight {
169 Weight::zero()
170 }
171}
172
173impl QueryControllerWeightInfo for () {
174 fn query() -> Weight {
175 Weight::zero()
176 }
177 fn take_response() -> Weight {
178 Weight::zero()
179 }
180}
181
182impl<Origin, Timeout> QueryController<Origin, Timeout> for () {
183 type WeightInfo = ();
184
185 fn query(
186 _origin: Origin,
187 _timeout: Timeout,
188 _match_querier: VersionedLocation,
189 ) -> Result<QueryId, DispatchError> {
190 Ok(Default::default())
191 }
192}