referrerpolicy=no-referrer-when-downgrade

staging_xcm_executor/traits/
on_response.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
17use crate::{Junctions::Here, Xcm};
18use codec::{Decode, Encode};
19use core::{fmt::Debug, result};
20use frame_support::{pallet_prelude::Get, parameter_types};
21use sp_arithmetic::traits::Zero;
22use xcm::latest::{
23	Error as XcmError, InteriorLocation, Location, QueryId, Response, Result as XcmResult, Weight,
24	XcmContext,
25};
26
27/// Define what needs to be done upon receiving a query response.
28pub trait OnResponse {
29	/// Returns `true` if we are expecting a response from `origin` for query `query_id` that was
30	/// queried by `querier`.
31	fn expecting_response(origin: &Location, query_id: u64, querier: Option<&Location>) -> bool;
32	/// Handler for receiving a `response` from `origin` relating to `query_id` initiated by
33	/// `querier`.
34	fn on_response(
35		origin: &Location,
36		query_id: u64,
37		querier: Option<&Location>,
38		response: Response,
39		max_weight: Weight,
40		context: &XcmContext,
41	) -> Weight;
42}
43impl OnResponse for () {
44	fn expecting_response(_origin: &Location, _query_id: u64, _querier: Option<&Location>) -> bool {
45		false
46	}
47	fn on_response(
48		_origin: &Location,
49		_query_id: u64,
50		_querier: Option<&Location>,
51		_response: Response,
52		_max_weight: Weight,
53		_context: &XcmContext,
54	) -> Weight {
55		Weight::zero()
56	}
57}
58
59/// Trait for a type which handles notifying a destination of XCM version changes.
60pub trait VersionChangeNotifier {
61	/// Start notifying `location` should the XCM version of this chain change.
62	///
63	/// When it does, this type should ensure a `QueryResponse` message is sent with the given
64	/// `query_id` & `max_weight` and with a `response` of `Response::Version`. This should happen
65	/// until/unless `stop` is called with the correct `query_id`.
66	///
67	/// If the `location` has an ongoing notification and when this function is called, then an
68	/// error should be returned.
69	fn start(
70		location: &Location,
71		query_id: QueryId,
72		max_weight: Weight,
73		context: &XcmContext,
74	) -> XcmResult;
75
76	/// Stop notifying `location` should the XCM change. Returns an error if there is no existing
77	/// notification set up.
78	fn stop(location: &Location, context: &XcmContext) -> XcmResult;
79
80	/// Return true if a location is subscribed to XCM version changes.
81	fn is_subscribed(location: &Location) -> bool;
82}
83
84impl VersionChangeNotifier for () {
85	fn start(_: &Location, _: QueryId, _: Weight, _: &XcmContext) -> XcmResult {
86		Err(XcmError::Unimplemented)
87	}
88	fn stop(_: &Location, _: &XcmContext) -> XcmResult {
89		Err(XcmError::Unimplemented)
90	}
91	fn is_subscribed(_: &Location) -> bool {
92		false
93	}
94}
95
96/// The possible state of an XCM query response.
97#[derive(Debug, PartialEq, Eq, Encode, Decode)]
98pub enum QueryResponseStatus<BlockNumber> {
99	/// The response has arrived, and includes the inner Response and the block number it arrived
100	/// at.
101	Ready { response: Response, at: BlockNumber },
102	/// The response has not yet arrived, the XCM might still be executing or the response might be
103	/// in transit.
104	Pending { timeout: BlockNumber },
105	/// No response with the given `QueryId` was found, or the response was already queried and
106	/// removed from local storage.
107	NotFound,
108	/// Got an unexpected XCM version.
109	UnexpectedVersion,
110}
111
112/// Provides methods to expect responses from XCMs and query their status.
113pub trait QueryHandler {
114	type BlockNumber: Zero + Encode;
115	type Error;
116	type UniversalLocation: Get<InteriorLocation>;
117
118	/// Attempt to create a new query ID and register it as a query that is yet to respond.
119	fn new_query(
120		responder: impl Into<Location>,
121		timeout: Self::BlockNumber,
122		match_querier: impl Into<Location>,
123	) -> QueryId;
124
125	/// Consume `message` and return another which is equivalent to it except that it reports
126	/// back the outcome.
127	///
128	/// - `message`: The message whose outcome should be reported.
129	/// - `responder`: The origin from which a response should be expected.
130	/// - `timeout`: The block number after which it is permissible to return `NotFound` from
131	///   `take_response`.
132	///
133	/// `report_outcome` may return an error if the `responder` is not invertible.
134	///
135	/// It is assumed that the querier of the response will be `Here`.
136	/// The response can be queried with `take_response`.
137	fn report_outcome(
138		message: &mut Xcm<()>,
139		responder: impl Into<Location>,
140		timeout: Self::BlockNumber,
141	) -> result::Result<QueryId, Self::Error>;
142
143	/// Attempt to remove and return the response of query with ID `query_id`.
144	fn take_response(id: QueryId) -> QueryResponseStatus<Self::BlockNumber>;
145
146	/// Makes sure to expect a response with the given id.
147	#[cfg(feature = "runtime-benchmarks")]
148	fn expect_response(id: QueryId, response: Response);
149}
150
151parameter_types! {
152	pub UniversalLocation: InteriorLocation = Here;
153}
154
155impl QueryHandler for () {
156	type BlockNumber = u64;
157	type Error = ();
158	type UniversalLocation = UniversalLocation;
159
160	fn take_response(_query_id: QueryId) -> QueryResponseStatus<Self::BlockNumber> {
161		QueryResponseStatus::NotFound
162	}
163	fn new_query(
164		_responder: impl Into<Location>,
165		_timeout: Self::BlockNumber,
166		_match_querier: impl Into<Location>,
167	) -> QueryId {
168		0u64
169	}
170
171	fn report_outcome(
172		_message: &mut Xcm<()>,
173		_responder: impl Into<Location>,
174		_timeout: Self::BlockNumber,
175	) -> Result<QueryId, Self::Error> {
176		Err(())
177	}
178
179	#[cfg(feature = "runtime-benchmarks")]
180	fn expect_response(_id: QueryId, _response: crate::Response) {}
181}