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

            
21
use alloc::boxed::Box;
22
use frame_support::{
23
	dispatch::{DispatchErrorWithPostInfo, WithPostDispatchInfo},
24
	pallet_prelude::DispatchError,
25
};
26
use xcm::prelude::*;
27
pub use xcm_executor::traits::QueryHandler;
28

            
29
/// Umbrella trait for all Controller traits.
30
pub trait Controller<Origin, RuntimeCall, Timeout>:
31
	ExecuteController<Origin, RuntimeCall> + SendController<Origin> + QueryController<Origin, Timeout>
32
{
33
}
34

            
35
impl<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`].
43
pub 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`].
54
pub 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`].
74
pub 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`].
86
pub 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`].
105
pub 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.
120
pub 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

            
138
impl<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

            
150
impl ExecuteControllerWeightInfo for () {
151
	fn execute() -> Weight {
152
		Weight::zero()
153
	}
154
}
155

            
156
impl<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

            
167
impl SendControllerWeightInfo for () {
168
	fn send() -> Weight {
169
		Weight::zero()
170
	}
171
}
172

            
173
impl QueryControllerWeightInfo for () {
174
	fn query() -> Weight {
175
		Weight::zero()
176
	}
177
	fn take_response() -> Weight {
178
		Weight::zero()
179
	}
180
}
181

            
182
impl<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
}