staging_xcm/v3/
mod.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//! Version 3 of the Cross-Consensus Message format data structures.
18
19#[allow(deprecated)]
20use super::v2::{
21	Instruction as OldInstruction, OriginKind as OldOriginKind, Response as OldResponse,
22	WeightLimit as OldWeightLimit, Xcm as OldXcm,
23};
24use super::v4::{
25	Instruction as NewInstruction, PalletInfo as NewPalletInfo,
26	QueryResponseInfo as NewQueryResponseInfo, Response as NewResponse, Xcm as NewXcm,
27};
28use crate::DoubleEncoded;
29use alloc::{vec, vec::Vec};
30use bounded_collections::{parameter_types, BoundedVec};
31use codec::{
32	self, decode_vec_with_len, Compact, Decode, Encode, Error as CodecError, Input as CodecInput,
33	MaxEncodedLen,
34};
35use core::{fmt::Debug, result};
36use derivative::Derivative;
37use scale_info::TypeInfo;
38
39mod junction;
40pub(crate) mod junctions;
41mod multiasset;
42mod multilocation;
43mod traits;
44
45pub use junction::{BodyId, BodyPart, Junction, NetworkId};
46pub use junctions::Junctions;
47pub use multiasset::{
48	AssetId, AssetInstance, Fungibility, MultiAsset, MultiAssetFilter, MultiAssets,
49	WildFungibility, WildMultiAsset, MAX_ITEMS_IN_MULTIASSETS,
50};
51pub use multilocation::{
52	Ancestor, AncestorThen, InteriorMultiLocation, Location, MultiLocation, Parent, ParentThen,
53};
54pub use traits::{
55	send_xcm, validate_send, Error, ExecuteXcm, GetWeight, Outcome, PreparedMessage, Result,
56	SendError, SendResult, SendXcm, Weight, XcmHash,
57};
58
59/// Basically just the XCM (more general) version of `ParachainDispatchOrigin`.
60#[derive(Copy, Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)]
61#[scale_info(replace_segment("staging_xcm", "xcm"))]
62#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
63pub enum OriginKind {
64	/// Origin should just be the native dispatch origin representation for the sender in the
65	/// local runtime framework. For Cumulus/Frame chains this is the `Parachain` or `Relay` origin
66	/// if coming from a chain, though there may be others if the `MultiLocation` XCM origin has a
67	/// primary/native dispatch origin form.
68	Native,
69
70	/// Origin should just be the standard account-based origin with the sovereign account of
71	/// the sender. For Cumulus/Frame chains, this is the `Signed` origin.
72	SovereignAccount,
73
74	/// Origin should be the super-user. For Cumulus/Frame chains, this is the `Root` origin.
75	/// This will not usually be an available option.
76	Superuser,
77
78	/// Origin should be interpreted as an XCM native origin and the `MultiLocation` should be
79	/// encoded directly in the dispatch origin unchanged. For Cumulus/Frame chains, this will be
80	/// the `pallet_xcm::Origin::Xcm` type.
81	Xcm,
82}
83
84impl From<OldOriginKind> for OriginKind {
85	fn from(old: OldOriginKind) -> Self {
86		use OldOriginKind::*;
87		match old {
88			Native => Self::Native,
89			SovereignAccount => Self::SovereignAccount,
90			Superuser => Self::Superuser,
91			Xcm => Self::Xcm,
92		}
93	}
94}
95
96/// This module's XCM version.
97pub const VERSION: super::Version = 3;
98
99/// An identifier for a query.
100pub type QueryId = u64;
101
102#[derive(Derivative, Default, Encode, TypeInfo)]
103#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))]
104#[codec(encode_bound())]
105#[scale_info(bounds(), skip_type_params(Call))]
106#[scale_info(replace_segment("staging_xcm", "xcm"))]
107#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
108pub struct Xcm<Call>(pub Vec<Instruction<Call>>);
109
110/// The maximal number of instructions in an XCM before decoding fails.
111///
112/// This is a deliberate limit - not a technical one.
113pub const MAX_INSTRUCTIONS_TO_DECODE: u8 = 100;
114
115environmental::environmental!(instructions_count: u8);
116
117impl<Call> Decode for Xcm<Call> {
118	fn decode<I: CodecInput>(input: &mut I) -> core::result::Result<Self, CodecError> {
119		instructions_count::using_once(&mut 0, || {
120			let number_of_instructions: u32 = <Compact<u32>>::decode(input)?.into();
121			instructions_count::with(|count| {
122				*count = count.saturating_add(number_of_instructions as u8);
123				if *count > MAX_INSTRUCTIONS_TO_DECODE {
124					return Err(CodecError::from("Max instructions exceeded"))
125				}
126				Ok(())
127			})
128			.unwrap_or(Ok(()))?;
129			let decoded_instructions = decode_vec_with_len(input, number_of_instructions as usize)?;
130			Ok(Self(decoded_instructions))
131		})
132	}
133}
134
135impl<Call> Xcm<Call> {
136	/// Create an empty instance.
137	pub fn new() -> Self {
138		Self(vec![])
139	}
140
141	/// Return `true` if no instructions are held in `self`.
142	pub fn is_empty(&self) -> bool {
143		self.0.is_empty()
144	}
145
146	/// Return the number of instructions held in `self`.
147	pub fn len(&self) -> usize {
148		self.0.len()
149	}
150
151	/// Return a reference to the inner value.
152	pub fn inner(&self) -> &[Instruction<Call>] {
153		&self.0
154	}
155
156	/// Return a mutable reference to the inner value.
157	pub fn inner_mut(&mut self) -> &mut Vec<Instruction<Call>> {
158		&mut self.0
159	}
160
161	/// Consume and return the inner value.
162	pub fn into_inner(self) -> Vec<Instruction<Call>> {
163		self.0
164	}
165
166	/// Return an iterator over references to the items.
167	pub fn iter(&self) -> impl Iterator<Item = &Instruction<Call>> {
168		self.0.iter()
169	}
170
171	/// Return an iterator over mutable references to the items.
172	pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut Instruction<Call>> {
173		self.0.iter_mut()
174	}
175
176	/// Consume and return an iterator over the items.
177	pub fn into_iter(self) -> impl Iterator<Item = Instruction<Call>> {
178		self.0.into_iter()
179	}
180
181	/// Consume and either return `self` if it contains some instructions, or if it's empty, then
182	/// instead return the result of `f`.
183	pub fn or_else(self, f: impl FnOnce() -> Self) -> Self {
184		if self.0.is_empty() {
185			f()
186		} else {
187			self
188		}
189	}
190
191	/// Return the first instruction, if any.
192	pub fn first(&self) -> Option<&Instruction<Call>> {
193		self.0.first()
194	}
195
196	/// Return the last instruction, if any.
197	pub fn last(&self) -> Option<&Instruction<Call>> {
198		self.0.last()
199	}
200
201	/// Return the only instruction, contained in `Self`, iff only one exists (`None` otherwise).
202	pub fn only(&self) -> Option<&Instruction<Call>> {
203		if self.0.len() == 1 {
204			self.0.first()
205		} else {
206			None
207		}
208	}
209
210	/// Return the only instruction, contained in `Self`, iff only one exists (returns `self`
211	/// otherwise).
212	pub fn into_only(mut self) -> core::result::Result<Instruction<Call>, Self> {
213		if self.0.len() == 1 {
214			self.0.pop().ok_or(self)
215		} else {
216			Err(self)
217		}
218	}
219}
220
221impl<Call> From<Vec<Instruction<Call>>> for Xcm<Call> {
222	fn from(c: Vec<Instruction<Call>>) -> Self {
223		Self(c)
224	}
225}
226
227impl<Call> From<Xcm<Call>> for Vec<Instruction<Call>> {
228	fn from(c: Xcm<Call>) -> Self {
229		c.0
230	}
231}
232
233/// A prelude for importing all types typically used when interacting with XCM messages.
234pub mod prelude {
235	mod contents {
236		pub use super::super::{
237			send_xcm, validate_send, Ancestor, AncestorThen,
238			AssetId::{self, *},
239			AssetInstance::{self, *},
240			BodyId, BodyPart, Error as XcmError, ExecuteXcm,
241			Fungibility::{self, *},
242			GetWeight,
243			Instruction::*,
244			InteriorMultiLocation,
245			Junction::{self, *},
246			Junctions::{self, *},
247			Location, MaybeErrorCode, MultiAsset,
248			MultiAssetFilter::{self, *},
249			MultiAssets, MultiLocation,
250			NetworkId::{self, *},
251			OriginKind, Outcome, PalletInfo, Parent, ParentThen, PreparedMessage, QueryId,
252			QueryResponseInfo, Response, Result as XcmResult, SendError, SendResult, SendXcm,
253			Weight,
254			WeightLimit::{self, *},
255			WildFungibility::{self, Fungible as WildFungible, NonFungible as WildNonFungible},
256			WildMultiAsset::{self, *},
257			XcmContext, XcmHash, XcmWeightInfo, VERSION as XCM_VERSION,
258		};
259	}
260	pub use super::{Instruction, Xcm};
261	pub use contents::*;
262	pub mod opaque {
263		pub use super::{
264			super::opaque::{Instruction, Xcm},
265			contents::*,
266		};
267	}
268}
269
270parameter_types! {
271	#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
272	pub MaxPalletNameLen: u32 = 48;
273	/// Maximum size of the encoded error code coming from a `Dispatch` result, used for
274	/// `MaybeErrorCode`. This is not (yet) enforced, so it's just an indication of expectation.
275	#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
276	pub MaxDispatchErrorLen: u32 = 128;
277	#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
278	pub MaxPalletsInfo: u32 = 64;
279}
280
281#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
282#[scale_info(replace_segment("staging_xcm", "xcm"))]
283#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
284pub struct PalletInfo {
285	#[codec(compact)]
286	pub index: u32,
287	pub name: BoundedVec<u8, MaxPalletNameLen>,
288	pub module_name: BoundedVec<u8, MaxPalletNameLen>,
289	#[codec(compact)]
290	pub major: u32,
291	#[codec(compact)]
292	pub minor: u32,
293	#[codec(compact)]
294	pub patch: u32,
295}
296
297impl PalletInfo {
298	pub fn new(
299		index: u32,
300		name: Vec<u8>,
301		module_name: Vec<u8>,
302		major: u32,
303		minor: u32,
304		patch: u32,
305	) -> result::Result<Self, Error> {
306		let name = BoundedVec::try_from(name).map_err(|_| Error::Overflow)?;
307		let module_name = BoundedVec::try_from(module_name).map_err(|_| Error::Overflow)?;
308
309		Ok(Self { index, name, module_name, major, minor, patch })
310	}
311}
312
313impl TryInto<NewPalletInfo> for PalletInfo {
314	type Error = ();
315
316	fn try_into(self) -> result::Result<NewPalletInfo, Self::Error> {
317		NewPalletInfo::new(
318			self.index,
319			self.name.into_inner(),
320			self.module_name.into_inner(),
321			self.major,
322			self.minor,
323			self.patch,
324		)
325		.map_err(|_| ())
326	}
327}
328
329#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
330#[scale_info(replace_segment("staging_xcm", "xcm"))]
331#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
332pub enum MaybeErrorCode {
333	Success,
334	Error(BoundedVec<u8, MaxDispatchErrorLen>),
335	TruncatedError(BoundedVec<u8, MaxDispatchErrorLen>),
336}
337
338impl From<Vec<u8>> for MaybeErrorCode {
339	fn from(v: Vec<u8>) -> Self {
340		match BoundedVec::try_from(v) {
341			Ok(error) => MaybeErrorCode::Error(error),
342			Err(error) => MaybeErrorCode::TruncatedError(BoundedVec::truncate_from(error)),
343		}
344	}
345}
346
347impl Default for MaybeErrorCode {
348	fn default() -> MaybeErrorCode {
349		MaybeErrorCode::Success
350	}
351}
352
353/// Response data to a query.
354#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
355#[scale_info(replace_segment("staging_xcm", "xcm"))]
356#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
357pub enum Response {
358	/// No response. Serves as a neutral default.
359	Null,
360	/// Some assets.
361	Assets(MultiAssets),
362	/// The outcome of an XCM instruction.
363	ExecutionResult(Option<(u32, Error)>),
364	/// An XCM version.
365	Version(super::Version),
366	/// The index, instance name, pallet name and version of some pallets.
367	PalletsInfo(BoundedVec<PalletInfo, MaxPalletsInfo>),
368	/// The status of a dispatch attempt using `Transact`.
369	DispatchResult(MaybeErrorCode),
370}
371
372impl Default for Response {
373	fn default() -> Self {
374		Self::Null
375	}
376}
377
378impl TryFrom<NewResponse> for Response {
379	type Error = ();
380
381	fn try_from(new: NewResponse) -> result::Result<Self, Self::Error> {
382		use NewResponse::*;
383		Ok(match new {
384			Null => Self::Null,
385			Assets(assets) => Self::Assets(assets.try_into()?),
386			ExecutionResult(result) =>
387				Self::ExecutionResult(result.map(|(num, old_error)| (num, old_error.into()))),
388			Version(version) => Self::Version(version),
389			PalletsInfo(pallet_info) => {
390				let inner = pallet_info
391					.into_iter()
392					.map(TryInto::try_into)
393					.collect::<result::Result<Vec<_>, _>>()?;
394				Self::PalletsInfo(
395					BoundedVec::<PalletInfo, MaxPalletsInfo>::try_from(inner).map_err(|_| ())?,
396				)
397			},
398			DispatchResult(maybe_error) =>
399				Self::DispatchResult(maybe_error.try_into().map_err(|_| ())?),
400		})
401	}
402}
403
404/// Information regarding the composition of a query response.
405#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)]
406#[scale_info(replace_segment("staging_xcm", "xcm"))]
407#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
408pub struct QueryResponseInfo {
409	/// The destination to which the query response message should be send.
410	pub destination: MultiLocation,
411	/// The `query_id` field of the `QueryResponse` message.
412	#[codec(compact)]
413	pub query_id: QueryId,
414	/// The `max_weight` field of the `QueryResponse` message.
415	pub max_weight: Weight,
416}
417
418impl TryFrom<NewQueryResponseInfo> for QueryResponseInfo {
419	type Error = ();
420
421	fn try_from(new: NewQueryResponseInfo) -> result::Result<Self, Self::Error> {
422		Ok(Self {
423			destination: new.destination.try_into()?,
424			query_id: new.query_id,
425			max_weight: new.max_weight,
426		})
427	}
428}
429
430/// An optional weight limit.
431#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug, TypeInfo)]
432#[scale_info(replace_segment("staging_xcm", "xcm"))]
433#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
434pub enum WeightLimit {
435	/// No weight limit imposed.
436	Unlimited,
437	/// Weight limit imposed of the inner value.
438	Limited(Weight),
439}
440
441impl From<Option<Weight>> for WeightLimit {
442	fn from(x: Option<Weight>) -> Self {
443		match x {
444			Some(w) => WeightLimit::Limited(w),
445			None => WeightLimit::Unlimited,
446		}
447	}
448}
449
450impl From<WeightLimit> for Option<Weight> {
451	fn from(x: WeightLimit) -> Self {
452		match x {
453			WeightLimit::Limited(w) => Some(w),
454			WeightLimit::Unlimited => None,
455		}
456	}
457}
458
459impl From<OldWeightLimit> for WeightLimit {
460	fn from(x: OldWeightLimit) -> Self {
461		use OldWeightLimit::*;
462		match x {
463			Limited(w) => Self::Limited(Weight::from_parts(w, DEFAULT_PROOF_SIZE)),
464			Unlimited => Self::Unlimited,
465		}
466	}
467}
468
469/// Contextual data pertaining to a specific list of XCM instructions.
470#[derive(Clone, Eq, PartialEq, Encode, Decode, Debug)]
471pub struct XcmContext {
472	/// The current value of the Origin register of the `XCVM`.
473	pub origin: Option<MultiLocation>,
474	/// The identity of the XCM; this may be a hash of its versioned encoding but could also be
475	/// a high-level identity set by an appropriate barrier.
476	pub message_id: XcmHash,
477	/// The current value of the Topic register of the `XCVM`.
478	pub topic: Option<[u8; 32]>,
479}
480
481impl XcmContext {
482	/// Constructor which sets the message ID to the supplied parameter and leaves the origin and
483	/// topic unset.
484	#[deprecated = "Use `with_message_id` instead."]
485	pub fn with_message_hash(message_id: XcmHash) -> XcmContext {
486		XcmContext { origin: None, message_id, topic: None }
487	}
488
489	/// Constructor which sets the message ID to the supplied parameter and leaves the origin and
490	/// topic unset.
491	pub fn with_message_id(message_id: XcmHash) -> XcmContext {
492		XcmContext { origin: None, message_id, topic: None }
493	}
494}
495
496/// Cross-Consensus Message: A message from one consensus system to another.
497///
498/// Consensus systems that may send and receive messages include blockchains and smart contracts.
499///
500/// All messages are delivered from a known *origin*, expressed as a `MultiLocation`.
501///
502/// This is the inner XCM format and is version-sensitive. Messages are typically passed using the
503/// outer XCM format, known as `VersionedXcm`.
504#[derive(
505	Derivative,
506	Encode,
507	Decode,
508	TypeInfo,
509	xcm_procedural::XcmWeightInfoTrait,
510	xcm_procedural::Builder,
511)]
512#[derivative(Clone(bound = ""), Eq(bound = ""), PartialEq(bound = ""), Debug(bound = ""))]
513#[codec(encode_bound())]
514#[codec(decode_bound())]
515#[scale_info(bounds(), skip_type_params(Call))]
516#[scale_info(replace_segment("staging_xcm", "xcm"))]
517#[cfg_attr(feature = "json-schema", derive(schemars::JsonSchema))]
518pub enum Instruction<Call> {
519	/// Withdraw asset(s) (`assets`) from the ownership of `origin` and place them into the Holding
520	/// Register.
521	///
522	/// - `assets`: The asset(s) to be withdrawn into holding.
523	///
524	/// Kind: *Command*.
525	///
526	/// Errors:
527	#[builder(loads_holding)]
528	WithdrawAsset(MultiAssets),
529
530	/// Asset(s) (`assets`) have been received into the ownership of this system on the `origin`
531	/// system and equivalent derivatives should be placed into the Holding Register.
532	///
533	/// - `assets`: The asset(s) that are minted into holding.
534	///
535	/// Safety: `origin` must be trusted to have received and be storing `assets` such that they
536	/// may later be withdrawn should this system send a corresponding message.
537	///
538	/// Kind: *Trusted Indication*.
539	///
540	/// Errors:
541	#[builder(loads_holding)]
542	ReserveAssetDeposited(MultiAssets),
543
544	/// Asset(s) (`assets`) have been destroyed on the `origin` system and equivalent assets should
545	/// be created and placed into the Holding Register.
546	///
547	/// - `assets`: The asset(s) that are minted into the Holding Register.
548	///
549	/// Safety: `origin` must be trusted to have irrevocably destroyed the corresponding `assets`
550	/// prior as a consequence of sending this message.
551	///
552	/// Kind: *Trusted Indication*.
553	///
554	/// Errors:
555	#[builder(loads_holding)]
556	ReceiveTeleportedAsset(MultiAssets),
557
558	/// Respond with information that the local system is expecting.
559	///
560	/// - `query_id`: The identifier of the query that resulted in this message being sent.
561	/// - `response`: The message content.
562	/// - `max_weight`: The maximum weight that handling this response should take.
563	/// - `querier`: The location responsible for the initiation of the response, if there is one.
564	///   In general this will tend to be the same location as the receiver of this message. NOTE:
565	///   As usual, this is interpreted from the perspective of the receiving consensus system.
566	///
567	/// Safety: Since this is information only, there are no immediate concerns. However, it should
568	/// be remembered that even if the Origin behaves reasonably, it can always be asked to make
569	/// a response to a third-party chain who may or may not be expecting the response. Therefore
570	/// the `querier` should be checked to match the expected value.
571	///
572	/// Kind: *Information*.
573	///
574	/// Errors:
575	QueryResponse {
576		#[codec(compact)]
577		query_id: QueryId,
578		response: Response,
579		max_weight: Weight,
580		querier: Option<MultiLocation>,
581	},
582
583	/// Withdraw asset(s) (`assets`) from the ownership of `origin` and place equivalent assets
584	/// under the ownership of `beneficiary`.
585	///
586	/// - `assets`: The asset(s) to be withdrawn.
587	/// - `beneficiary`: The new owner for the assets.
588	///
589	/// Safety: No concerns.
590	///
591	/// Kind: *Command*.
592	///
593	/// Errors:
594	TransferAsset { assets: MultiAssets, beneficiary: MultiLocation },
595
596	/// Withdraw asset(s) (`assets`) from the ownership of `origin` and place equivalent assets
597	/// under the ownership of `dest` within this consensus system (i.e. its sovereign account).
598	///
599	/// Send an onward XCM message to `dest` of `ReserveAssetDeposited` with the given
600	/// `xcm`.
601	///
602	/// - `assets`: The asset(s) to be withdrawn.
603	/// - `dest`: The location whose sovereign account will own the assets and thus the effective
604	///   beneficiary for the assets and the notification target for the reserve asset deposit
605	///   message.
606	/// - `xcm`: The instructions that should follow the `ReserveAssetDeposited` instruction, which
607	///   is sent onwards to `dest`.
608	///
609	/// Safety: No concerns.
610	///
611	/// Kind: *Command*.
612	///
613	/// Errors:
614	TransferReserveAsset { assets: MultiAssets, dest: MultiLocation, xcm: Xcm<()> },
615
616	/// Apply the encoded transaction `call`, whose dispatch-origin should be `origin` as expressed
617	/// by the kind of origin `origin_kind`.
618	///
619	/// The Transact Status Register is set according to the result of dispatching the call.
620	///
621	/// - `origin_kind`: The means of expressing the message origin as a dispatch origin.
622	/// - `require_weight_at_most`: The weight of `call`; this should be at least the chain's
623	///   calculated weight and will be used in the weight determination arithmetic.
624	/// - `call`: The encoded transaction to be applied.
625	///
626	/// Safety: No concerns.
627	///
628	/// Kind: *Command*.
629	///
630	/// Errors:
631	Transact { origin_kind: OriginKind, require_weight_at_most: Weight, call: DoubleEncoded<Call> },
632
633	/// A message to notify about a new incoming HRMP channel. This message is meant to be sent by
634	/// the relay-chain to a para.
635	///
636	/// - `sender`: The sender in the to-be opened channel. Also, the initiator of the channel
637	///   opening.
638	/// - `max_message_size`: The maximum size of a message proposed by the sender.
639	/// - `max_capacity`: The maximum number of messages that can be queued in the channel.
640	///
641	/// Safety: The message should originate directly from the relay-chain.
642	///
643	/// Kind: *System Notification*
644	HrmpNewChannelOpenRequest {
645		#[codec(compact)]
646		sender: u32,
647		#[codec(compact)]
648		max_message_size: u32,
649		#[codec(compact)]
650		max_capacity: u32,
651	},
652
653	/// A message to notify about that a previously sent open channel request has been accepted by
654	/// the recipient. That means that the channel will be opened during the next relay-chain
655	/// session change. This message is meant to be sent by the relay-chain to a para.
656	///
657	/// Safety: The message should originate directly from the relay-chain.
658	///
659	/// Kind: *System Notification*
660	///
661	/// Errors:
662	HrmpChannelAccepted {
663		// NOTE: We keep this as a structured item to a) keep it consistent with the other Hrmp
664		// items; and b) because the field's meaning is not obvious/mentioned from the item name.
665		#[codec(compact)]
666		recipient: u32,
667	},
668
669	/// A message to notify that the other party in an open channel decided to close it. In
670	/// particular, `initiator` is going to close the channel opened from `sender` to the
671	/// `recipient`. The close will be enacted at the next relay-chain session change. This message
672	/// is meant to be sent by the relay-chain to a para.
673	///
674	/// Safety: The message should originate directly from the relay-chain.
675	///
676	/// Kind: *System Notification*
677	///
678	/// Errors:
679	HrmpChannelClosing {
680		#[codec(compact)]
681		initiator: u32,
682		#[codec(compact)]
683		sender: u32,
684		#[codec(compact)]
685		recipient: u32,
686	},
687
688	/// Clear the origin.
689	///
690	/// This may be used by the XCM author to ensure that later instructions cannot command the
691	/// authority of the origin (e.g. if they are being relayed from an untrusted source, as often
692	/// the case with `ReserveAssetDeposited`).
693	///
694	/// Safety: No concerns.
695	///
696	/// Kind: *Command*.
697	///
698	/// Errors:
699	ClearOrigin,
700
701	/// Mutate the origin to some interior location.
702	///
703	/// Kind: *Command*
704	///
705	/// Errors:
706	DescendOrigin(InteriorMultiLocation),
707
708	/// Immediately report the contents of the Error Register to the given destination via XCM.
709	///
710	/// A `QueryResponse` message of type `ExecutionOutcome` is sent to the described destination.
711	///
712	/// - `response_info`: Information for making the response.
713	///
714	/// Kind: *Command*
715	///
716	/// Errors:
717	ReportError(QueryResponseInfo),
718
719	/// Remove the asset(s) (`assets`) from the Holding Register and place equivalent assets under
720	/// the ownership of `beneficiary` within this consensus system.
721	///
722	/// - `assets`: The asset(s) to remove from holding.
723	/// - `beneficiary`: The new owner for the assets.
724	///
725	/// Kind: *Command*
726	///
727	/// Errors:
728	DepositAsset { assets: MultiAssetFilter, beneficiary: MultiLocation },
729
730	/// Remove the asset(s) (`assets`) from the Holding Register and place equivalent assets under
731	/// the ownership of `dest` within this consensus system (i.e. deposit them into its sovereign
732	/// account).
733	///
734	/// Send an onward XCM message to `dest` of `ReserveAssetDeposited` with the given `effects`.
735	///
736	/// - `assets`: The asset(s) to remove from holding.
737	/// - `dest`: The location whose sovereign account will own the assets and thus the effective
738	///   beneficiary for the assets and the notification target for the reserve asset deposit
739	///   message.
740	/// - `xcm`: The orders that should follow the `ReserveAssetDeposited` instruction which is
741	///   sent onwards to `dest`.
742	///
743	/// Kind: *Command*
744	///
745	/// Errors:
746	DepositReserveAsset { assets: MultiAssetFilter, dest: MultiLocation, xcm: Xcm<()> },
747
748	/// Remove the asset(s) (`want`) from the Holding Register and replace them with alternative
749	/// assets.
750	///
751	/// The minimum amount of assets to be received into the Holding Register for the order not to
752	/// fail may be stated.
753	///
754	/// - `give`: The maximum amount of assets to remove from holding.
755	/// - `want`: The minimum amount of assets which `give` should be exchanged for.
756	/// - `maximal`: If `true`, then prefer to give as much as possible up to the limit of `give`
757	///   and receive accordingly more. If `false`, then prefer to give as little as possible in
758	///   order to receive as little as possible while receiving at least `want`.
759	///
760	/// Kind: *Command*
761	///
762	/// Errors:
763	ExchangeAsset { give: MultiAssetFilter, want: MultiAssets, maximal: bool },
764
765	/// Remove the asset(s) (`assets`) from holding and send a `WithdrawAsset` XCM message to a
766	/// reserve location.
767	///
768	/// - `assets`: The asset(s) to remove from holding.
769	/// - `reserve`: A valid location that acts as a reserve for all asset(s) in `assets`. The
770	///   sovereign account of this consensus system *on the reserve location* will have
771	///   appropriate assets withdrawn and `effects` will be executed on them. There will typically
772	///   be only one valid location on any given asset/chain combination.
773	/// - `xcm`: The instructions to execute on the assets once withdrawn *on the reserve
774	///   location*.
775	///
776	/// Kind: *Command*
777	///
778	/// Errors:
779	InitiateReserveWithdraw { assets: MultiAssetFilter, reserve: MultiLocation, xcm: Xcm<()> },
780
781	/// Remove the asset(s) (`assets`) from holding and send a `ReceiveTeleportedAsset` XCM message
782	/// to a `dest` location.
783	///
784	/// - `assets`: The asset(s) to remove from holding.
785	/// - `dest`: A valid location that respects teleports coming from this location.
786	/// - `xcm`: The instructions to execute on the assets once arrived *on the destination
787	///   location*.
788	///
789	/// NOTE: The `dest` location *MUST* respect this origin as a valid teleportation origin for
790	/// all `assets`. If it does not, then the assets may be lost.
791	///
792	/// Kind: *Command*
793	///
794	/// Errors:
795	InitiateTeleport { assets: MultiAssetFilter, dest: MultiLocation, xcm: Xcm<()> },
796
797	/// Report to a given destination the contents of the Holding Register.
798	///
799	/// A `QueryResponse` message of type `Assets` is sent to the described destination.
800	///
801	/// - `response_info`: Information for making the response.
802	/// - `assets`: A filter for the assets that should be reported back. The assets reported back
803	///   will be, asset-wise, *the lesser of this value and the holding register*. No wildcards
804	///   will be used when reporting assets back.
805	///
806	/// Kind: *Command*
807	///
808	/// Errors:
809	ReportHolding { response_info: QueryResponseInfo, assets: MultiAssetFilter },
810
811	/// Pay for the execution of some XCM `xcm` and `orders` with up to `weight`
812	/// picoseconds of execution time, paying for this with up to `fees` from the Holding Register.
813	///
814	/// - `fees`: The asset(s) to remove from the Holding Register to pay for fees.
815	/// - `weight_limit`: The maximum amount of weight to purchase; this must be at least the
816	///   expected maximum weight of the total XCM to be executed for the
817	///   `AllowTopLevelPaidExecutionFrom` barrier to allow the XCM be executed.
818	///
819	/// Kind: *Command*
820	///
821	/// Errors:
822	BuyExecution { fees: MultiAsset, weight_limit: WeightLimit },
823
824	/// Refund any surplus weight previously bought with `BuyExecution`.
825	///
826	/// Kind: *Command*
827	///
828	/// Errors: None.
829	RefundSurplus,
830
831	/// Set the Error Handler Register. This is code that should be called in the case of an error
832	/// happening.
833	///
834	/// An error occurring within execution of this code will _NOT_ result in the error register
835	/// being set, nor will an error handler be called due to it. The error handler and appendix
836	/// may each still be set.
837	///
838	/// The apparent weight of this instruction is inclusive of the inner `Xcm`; the executing
839	/// weight however includes only the difference between the previous handler and the new
840	/// handler, which can reasonably be negative, which would result in a surplus.
841	///
842	/// Kind: *Command*
843	///
844	/// Errors: None.
845	SetErrorHandler(Xcm<Call>),
846
847	/// Set the Appendix Register. This is code that should be called after code execution
848	/// (including the error handler if any) is finished. This will be called regardless of whether
849	/// an error occurred.
850	///
851	/// Any error occurring due to execution of this code will result in the error register being
852	/// set, and the error handler (if set) firing.
853	///
854	/// The apparent weight of this instruction is inclusive of the inner `Xcm`; the executing
855	/// weight however includes only the difference between the previous appendix and the new
856	/// appendix, which can reasonably be negative, which would result in a surplus.
857	///
858	/// Kind: *Command*
859	///
860	/// Errors: None.
861	SetAppendix(Xcm<Call>),
862
863	/// Clear the Error Register.
864	///
865	/// Kind: *Command*
866	///
867	/// Errors: None.
868	ClearError,
869
870	/// Create some assets which are being held on behalf of the origin.
871	///
872	/// - `assets`: The assets which are to be claimed. This must match exactly with the assets
873	///   claimable by the origin of the ticket.
874	/// - `ticket`: The ticket of the asset; this is an abstract identifier to help locate the
875	///   asset.
876	///
877	/// Kind: *Command*
878	///
879	/// Errors:
880	#[builder(loads_holding)]
881	ClaimAsset { assets: MultiAssets, ticket: MultiLocation },
882
883	/// Always throws an error of type `Trap`.
884	///
885	/// Kind: *Command*
886	///
887	/// Errors:
888	/// - `Trap`: All circumstances, whose inner value is the same as this item's inner value.
889	Trap(#[codec(compact)] u64),
890
891	/// Ask the destination system to respond with the most recent version of XCM that they
892	/// support in a `QueryResponse` instruction. Any changes to this should also elicit similar
893	/// responses when they happen.
894	///
895	/// - `query_id`: An identifier that will be replicated into the returned XCM message.
896	/// - `max_response_weight`: The maximum amount of weight that the `QueryResponse` item which
897	///   is sent as a reply may take to execute. NOTE: If this is unexpectedly large then the
898	///   response may not execute at all.
899	///
900	/// Kind: *Command*
901	///
902	/// Errors: *Fallible*
903	SubscribeVersion {
904		#[codec(compact)]
905		query_id: QueryId,
906		max_response_weight: Weight,
907	},
908
909	/// Cancel the effect of a previous `SubscribeVersion` instruction.
910	///
911	/// Kind: *Command*
912	///
913	/// Errors: *Fallible*
914	UnsubscribeVersion,
915
916	/// Reduce Holding by up to the given assets.
917	///
918	/// Holding is reduced by as much as possible up to the assets in the parameter. It is not an
919	/// error if the Holding does not contain the assets (to make this an error, use `ExpectAsset`
920	/// prior).
921	///
922	/// Kind: *Command*
923	///
924	/// Errors: *Infallible*
925	BurnAsset(MultiAssets),
926
927	/// Throw an error if Holding does not contain at least the given assets.
928	///
929	/// Kind: *Command*
930	///
931	/// Errors:
932	/// - `ExpectationFalse`: If Holding Register does not contain the assets in the parameter.
933	ExpectAsset(MultiAssets),
934
935	/// Ensure that the Origin Register equals some given value and throw an error if not.
936	///
937	/// Kind: *Command*
938	///
939	/// Errors:
940	/// - `ExpectationFalse`: If Origin Register is not equal to the parameter.
941	ExpectOrigin(Option<MultiLocation>),
942
943	/// Ensure that the Error Register equals some given value and throw an error if not.
944	///
945	/// Kind: *Command*
946	///
947	/// Errors:
948	/// - `ExpectationFalse`: If the value of the Error Register is not equal to the parameter.
949	ExpectError(Option<(u32, Error)>),
950
951	/// Ensure that the Transact Status Register equals some given value and throw an error if
952	/// not.
953	///
954	/// Kind: *Command*
955	///
956	/// Errors:
957	/// - `ExpectationFalse`: If the value of the Transact Status Register is not equal to the
958	///   parameter.
959	ExpectTransactStatus(MaybeErrorCode),
960
961	/// Query the existence of a particular pallet type.
962	///
963	/// - `module_name`: The module name of the pallet to query.
964	/// - `response_info`: Information for making the response.
965	///
966	/// Sends a `QueryResponse` to Origin whose data field `PalletsInfo` containing the information
967	/// of all pallets on the local chain whose name is equal to `name`. This is empty in the case
968	/// that the local chain is not based on Substrate Frame.
969	///
970	/// Safety: No concerns.
971	///
972	/// Kind: *Command*
973	///
974	/// Errors: *Fallible*.
975	QueryPallet { module_name: Vec<u8>, response_info: QueryResponseInfo },
976
977	/// Ensure that a particular pallet with a particular version exists.
978	///
979	/// - `index: Compact`: The index which identifies the pallet. An error if no pallet exists at
980	///   this index.
981	/// - `name: Vec<u8>`: Name which must be equal to the name of the pallet.
982	/// - `module_name: Vec<u8>`: Module name which must be equal to the name of the module in
983	///   which the pallet exists.
984	/// - `crate_major: Compact`: Version number which must be equal to the major version of the
985	///   crate which implements the pallet.
986	/// - `min_crate_minor: Compact`: Version number which must be at most the minor version of the
987	///   crate which implements the pallet.
988	///
989	/// Safety: No concerns.
990	///
991	/// Kind: *Command*
992	///
993	/// Errors:
994	/// - `ExpectationFalse`: In case any of the expectations are broken.
995	ExpectPallet {
996		#[codec(compact)]
997		index: u32,
998		name: Vec<u8>,
999		module_name: Vec<u8>,
1000		#[codec(compact)]
1001		crate_major: u32,
1002		#[codec(compact)]
1003		min_crate_minor: u32,
1004	},
1005
1006	/// Send a `QueryResponse` message containing the value of the Transact Status Register to some
1007	/// destination.
1008	///
1009	/// - `query_response_info`: The information needed for constructing and sending the
1010	///   `QueryResponse` message.
1011	///
1012	/// Safety: No concerns.
1013	///
1014	/// Kind: *Command*
1015	///
1016	/// Errors: *Fallible*.
1017	ReportTransactStatus(QueryResponseInfo),
1018
1019	/// Set the Transact Status Register to its default, cleared, value.
1020	///
1021	/// Safety: No concerns.
1022	///
1023	/// Kind: *Command*
1024	///
1025	/// Errors: *Infallible*.
1026	ClearTransactStatus,
1027
1028	/// Set the Origin Register to be some child of the Universal Ancestor.
1029	///
1030	/// Safety: Should only be usable if the Origin is trusted to represent the Universal Ancestor
1031	/// child in general. In general, no Origin should be able to represent the Universal Ancestor
1032	/// child which is the root of the local consensus system since it would by extension
1033	/// allow it to act as any location within the local consensus.
1034	///
1035	/// The `Junction` parameter should generally be a `GlobalConsensus` variant since it is only
1036	/// these which are children of the Universal Ancestor.
1037	///
1038	/// Kind: *Command*
1039	///
1040	/// Errors: *Fallible*.
1041	UniversalOrigin(Junction),
1042
1043	/// Send a message on to Non-Local Consensus system.
1044	///
1045	/// This will tend to utilize some extra-consensus mechanism, the obvious one being a bridge.
1046	/// A fee may be charged; this may be determined based on the contents of `xcm`. It will be
1047	/// taken from the Holding register.
1048	///
1049	/// - `network`: The remote consensus system to which the message should be exported.
1050	/// - `destination`: The location relative to the remote consensus system to which the message
1051	///   should be sent on arrival.
1052	/// - `xcm`: The message to be exported.
1053	///
1054	/// As an example, to export a message for execution on Asset Hub (parachain #1000 in the
1055	/// Kusama network), you would call with `network: NetworkId::Kusama` and
1056	/// `destination: X1(Parachain(1000))`. Alternatively, to export a message for execution on
1057	/// Polkadot, you would call with `network: NetworkId:: Polkadot` and `destination: Here`.
1058	///
1059	/// Kind: *Command*
1060	///
1061	/// Errors: *Fallible*.
1062	ExportMessage { network: NetworkId, destination: InteriorMultiLocation, xcm: Xcm<()> },
1063
1064	/// Lock the locally held asset and prevent further transfer or withdrawal.
1065	///
1066	/// This restriction may be removed by the `UnlockAsset` instruction being called with an
1067	/// Origin of `unlocker` and a `target` equal to the current `Origin`.
1068	///
1069	/// If the locking is successful, then a `NoteUnlockable` instruction is sent to `unlocker`.
1070	///
1071	/// - `asset`: The asset(s) which should be locked.
1072	/// - `unlocker`: The value which the Origin must be for a corresponding `UnlockAsset`
1073	///   instruction to work.
1074	///
1075	/// Kind: *Command*.
1076	///
1077	/// Errors:
1078	LockAsset { asset: MultiAsset, unlocker: MultiLocation },
1079
1080	/// Remove the lock over `asset` on this chain and (if nothing else is preventing it) allow the
1081	/// asset to be transferred.
1082	///
1083	/// - `asset`: The asset to be unlocked.
1084	/// - `target`: The owner of the asset on the local chain.
1085	///
1086	/// Safety: No concerns.
1087	///
1088	/// Kind: *Command*.
1089	///
1090	/// Errors:
1091	UnlockAsset { asset: MultiAsset, target: MultiLocation },
1092
1093	/// Asset (`asset`) has been locked on the `origin` system and may not be transferred. It may
1094	/// only be unlocked with the receipt of the `UnlockAsset` instruction from this chain.
1095	///
1096	/// - `asset`: The asset(s) which are now unlockable from this origin.
1097	/// - `owner`: The owner of the asset on the chain in which it was locked. This may be a
1098	///   location specific to the origin network.
1099	///
1100	/// Safety: `origin` must be trusted to have locked the corresponding `asset`
1101	/// prior as a consequence of sending this message.
1102	///
1103	/// Kind: *Trusted Indication*.
1104	///
1105	/// Errors:
1106	NoteUnlockable { asset: MultiAsset, owner: MultiLocation },
1107
1108	/// Send an `UnlockAsset` instruction to the `locker` for the given `asset`.
1109	///
1110	/// This may fail if the local system is making use of the fact that the asset is locked or,
1111	/// of course, if there is no record that the asset actually is locked.
1112	///
1113	/// - `asset`: The asset(s) to be unlocked.
1114	/// - `locker`: The location from which a previous `NoteUnlockable` was sent and to which an
1115	///   `UnlockAsset` should be sent.
1116	///
1117	/// Kind: *Command*.
1118	///
1119	/// Errors:
1120	RequestUnlock { asset: MultiAsset, locker: MultiLocation },
1121
1122	/// Sets the Fees Mode Register.
1123	///
1124	/// - `jit_withdraw`: The fees mode item; if set to `true` then fees for any instructions are
1125	///   withdrawn as needed using the same mechanism as `WithdrawAssets`.
1126	///
1127	/// Kind: *Command*.
1128	///
1129	/// Errors:
1130	SetFeesMode { jit_withdraw: bool },
1131
1132	/// Set the Topic Register.
1133	///
1134	/// The 32-byte array identifier in the parameter is not guaranteed to be
1135	/// unique; if such a property is desired, it is up to the code author to
1136	/// enforce uniqueness.
1137	///
1138	/// Safety: No concerns.
1139	///
1140	/// Kind: *Command*
1141	///
1142	/// Errors:
1143	SetTopic([u8; 32]),
1144
1145	/// Clear the Topic Register.
1146	///
1147	/// Kind: *Command*
1148	///
1149	/// Errors: None.
1150	ClearTopic,
1151
1152	/// Alter the current Origin to another given origin.
1153	///
1154	/// Kind: *Command*
1155	///
1156	/// Errors: If the existing state would not allow such a change.
1157	AliasOrigin(MultiLocation),
1158
1159	/// A directive to indicate that the origin expects free execution of the message.
1160	///
1161	/// At execution time, this instruction just does a check on the Origin register.
1162	/// However, at the barrier stage messages starting with this instruction can be disregarded if
1163	/// the origin is not acceptable for free execution or the `weight_limit` is `Limited` and
1164	/// insufficient.
1165	///
1166	/// Kind: *Indication*
1167	///
1168	/// Errors: If the given origin is `Some` and not equal to the current Origin register.
1169	UnpaidExecution { weight_limit: WeightLimit, check_origin: Option<MultiLocation> },
1170}
1171
1172impl<Call> Xcm<Call> {
1173	pub fn into<C>(self) -> Xcm<C> {
1174		Xcm::from(self)
1175	}
1176	pub fn from<C>(xcm: Xcm<C>) -> Self {
1177		Self(xcm.0.into_iter().map(Instruction::<Call>::from).collect())
1178	}
1179}
1180
1181impl<Call> Instruction<Call> {
1182	pub fn into<C>(self) -> Instruction<C> {
1183		Instruction::from(self)
1184	}
1185	pub fn from<C>(xcm: Instruction<C>) -> Self {
1186		use Instruction::*;
1187		match xcm {
1188			WithdrawAsset(assets) => WithdrawAsset(assets),
1189			ReserveAssetDeposited(assets) => ReserveAssetDeposited(assets),
1190			ReceiveTeleportedAsset(assets) => ReceiveTeleportedAsset(assets),
1191			QueryResponse { query_id, response, max_weight, querier } =>
1192				QueryResponse { query_id, response, max_weight, querier },
1193			TransferAsset { assets, beneficiary } => TransferAsset { assets, beneficiary },
1194			TransferReserveAsset { assets, dest, xcm } =>
1195				TransferReserveAsset { assets, dest, xcm },
1196			HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity } =>
1197				HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity },
1198			HrmpChannelAccepted { recipient } => HrmpChannelAccepted { recipient },
1199			HrmpChannelClosing { initiator, sender, recipient } =>
1200				HrmpChannelClosing { initiator, sender, recipient },
1201			Transact { origin_kind, require_weight_at_most, call } =>
1202				Transact { origin_kind, require_weight_at_most, call: call.into() },
1203			ReportError(response_info) => ReportError(response_info),
1204			DepositAsset { assets, beneficiary } => DepositAsset { assets, beneficiary },
1205			DepositReserveAsset { assets, dest, xcm } => DepositReserveAsset { assets, dest, xcm },
1206			ExchangeAsset { give, want, maximal } => ExchangeAsset { give, want, maximal },
1207			InitiateReserveWithdraw { assets, reserve, xcm } =>
1208				InitiateReserveWithdraw { assets, reserve, xcm },
1209			InitiateTeleport { assets, dest, xcm } => InitiateTeleport { assets, dest, xcm },
1210			ReportHolding { response_info, assets } => ReportHolding { response_info, assets },
1211			BuyExecution { fees, weight_limit } => BuyExecution { fees, weight_limit },
1212			ClearOrigin => ClearOrigin,
1213			DescendOrigin(who) => DescendOrigin(who),
1214			RefundSurplus => RefundSurplus,
1215			SetErrorHandler(xcm) => SetErrorHandler(xcm.into()),
1216			SetAppendix(xcm) => SetAppendix(xcm.into()),
1217			ClearError => ClearError,
1218			ClaimAsset { assets, ticket } => ClaimAsset { assets, ticket },
1219			Trap(code) => Trap(code),
1220			SubscribeVersion { query_id, max_response_weight } =>
1221				SubscribeVersion { query_id, max_response_weight },
1222			UnsubscribeVersion => UnsubscribeVersion,
1223			BurnAsset(assets) => BurnAsset(assets),
1224			ExpectAsset(assets) => ExpectAsset(assets),
1225			ExpectOrigin(origin) => ExpectOrigin(origin),
1226			ExpectError(error) => ExpectError(error),
1227			ExpectTransactStatus(transact_status) => ExpectTransactStatus(transact_status),
1228			QueryPallet { module_name, response_info } =>
1229				QueryPallet { module_name, response_info },
1230			ExpectPallet { index, name, module_name, crate_major, min_crate_minor } =>
1231				ExpectPallet { index, name, module_name, crate_major, min_crate_minor },
1232			ReportTransactStatus(response_info) => ReportTransactStatus(response_info),
1233			ClearTransactStatus => ClearTransactStatus,
1234			UniversalOrigin(j) => UniversalOrigin(j),
1235			ExportMessage { network, destination, xcm } =>
1236				ExportMessage { network, destination, xcm },
1237			LockAsset { asset, unlocker } => LockAsset { asset, unlocker },
1238			UnlockAsset { asset, target } => UnlockAsset { asset, target },
1239			NoteUnlockable { asset, owner } => NoteUnlockable { asset, owner },
1240			RequestUnlock { asset, locker } => RequestUnlock { asset, locker },
1241			SetFeesMode { jit_withdraw } => SetFeesMode { jit_withdraw },
1242			SetTopic(topic) => SetTopic(topic),
1243			ClearTopic => ClearTopic,
1244			AliasOrigin(location) => AliasOrigin(location),
1245			UnpaidExecution { weight_limit, check_origin } =>
1246				UnpaidExecution { weight_limit, check_origin },
1247		}
1248	}
1249}
1250
1251// TODO: Automate Generation
1252impl<Call, W: XcmWeightInfo<Call>> GetWeight<W> for Instruction<Call> {
1253	fn weight(&self) -> Weight {
1254		use Instruction::*;
1255		match self {
1256			WithdrawAsset(assets) => W::withdraw_asset(assets),
1257			ReserveAssetDeposited(assets) => W::reserve_asset_deposited(assets),
1258			ReceiveTeleportedAsset(assets) => W::receive_teleported_asset(assets),
1259			QueryResponse { query_id, response, max_weight, querier } =>
1260				W::query_response(query_id, response, max_weight, querier),
1261			TransferAsset { assets, beneficiary } => W::transfer_asset(assets, beneficiary),
1262			TransferReserveAsset { assets, dest, xcm } =>
1263				W::transfer_reserve_asset(&assets, dest, xcm),
1264			Transact { origin_kind, require_weight_at_most, call } =>
1265				W::transact(origin_kind, require_weight_at_most, call),
1266			HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity } =>
1267				W::hrmp_new_channel_open_request(sender, max_message_size, max_capacity),
1268			HrmpChannelAccepted { recipient } => W::hrmp_channel_accepted(recipient),
1269			HrmpChannelClosing { initiator, sender, recipient } =>
1270				W::hrmp_channel_closing(initiator, sender, recipient),
1271			ClearOrigin => W::clear_origin(),
1272			DescendOrigin(who) => W::descend_origin(who),
1273			ReportError(response_info) => W::report_error(&response_info),
1274			DepositAsset { assets, beneficiary } => W::deposit_asset(assets, beneficiary),
1275			DepositReserveAsset { assets, dest, xcm } =>
1276				W::deposit_reserve_asset(assets, dest, xcm),
1277			ExchangeAsset { give, want, maximal } => W::exchange_asset(give, want, maximal),
1278			InitiateReserveWithdraw { assets, reserve, xcm } =>
1279				W::initiate_reserve_withdraw(assets, reserve, xcm),
1280			InitiateTeleport { assets, dest, xcm } => W::initiate_teleport(assets, dest, xcm),
1281			ReportHolding { response_info, assets } => W::report_holding(&response_info, &assets),
1282			BuyExecution { fees, weight_limit } => W::buy_execution(fees, weight_limit),
1283			RefundSurplus => W::refund_surplus(),
1284			SetErrorHandler(xcm) => W::set_error_handler(xcm),
1285			SetAppendix(xcm) => W::set_appendix(xcm),
1286			ClearError => W::clear_error(),
1287			ClaimAsset { assets, ticket } => W::claim_asset(assets, ticket),
1288			Trap(code) => W::trap(code),
1289			SubscribeVersion { query_id, max_response_weight } =>
1290				W::subscribe_version(query_id, max_response_weight),
1291			UnsubscribeVersion => W::unsubscribe_version(),
1292			BurnAsset(assets) => W::burn_asset(assets),
1293			ExpectAsset(assets) => W::expect_asset(assets),
1294			ExpectOrigin(origin) => W::expect_origin(origin),
1295			ExpectError(error) => W::expect_error(error),
1296			ExpectTransactStatus(transact_status) => W::expect_transact_status(transact_status),
1297			QueryPallet { module_name, response_info } =>
1298				W::query_pallet(module_name, response_info),
1299			ExpectPallet { index, name, module_name, crate_major, min_crate_minor } =>
1300				W::expect_pallet(index, name, module_name, crate_major, min_crate_minor),
1301			ReportTransactStatus(response_info) => W::report_transact_status(response_info),
1302			ClearTransactStatus => W::clear_transact_status(),
1303			UniversalOrigin(j) => W::universal_origin(j),
1304			ExportMessage { network, destination, xcm } =>
1305				W::export_message(network, destination, xcm),
1306			LockAsset { asset, unlocker } => W::lock_asset(asset, unlocker),
1307			UnlockAsset { asset, target } => W::unlock_asset(asset, target),
1308			NoteUnlockable { asset, owner } => W::note_unlockable(asset, owner),
1309			RequestUnlock { asset, locker } => W::request_unlock(asset, locker),
1310			SetFeesMode { jit_withdraw } => W::set_fees_mode(jit_withdraw),
1311			SetTopic(topic) => W::set_topic(topic),
1312			ClearTopic => W::clear_topic(),
1313			AliasOrigin(location) => W::alias_origin(location),
1314			UnpaidExecution { weight_limit, check_origin } =>
1315				W::unpaid_execution(weight_limit, check_origin),
1316		}
1317	}
1318}
1319
1320pub mod opaque {
1321	/// The basic concrete type of `Xcm`, which doesn't make any assumptions about the
1322	/// format of a call other than it is pre-encoded.
1323	pub type Xcm = super::Xcm<()>;
1324
1325	/// The basic concrete type of `Instruction`, which doesn't make any assumptions about the
1326	/// format of a call other than it is pre-encoded.
1327	pub type Instruction = super::Instruction<()>;
1328}
1329
1330// Convert from a v2 response to a v3 response.
1331impl TryFrom<OldResponse> for Response {
1332	type Error = ();
1333	fn try_from(old_response: OldResponse) -> result::Result<Self, ()> {
1334		match old_response {
1335			OldResponse::Assets(assets) => Ok(Self::Assets(assets.try_into()?)),
1336			OldResponse::Version(version) => Ok(Self::Version(version)),
1337			OldResponse::ExecutionResult(error) => Ok(Self::ExecutionResult(match error {
1338				Some((i, e)) => Some((i, e.try_into()?)),
1339				None => None,
1340			})),
1341			OldResponse::Null => Ok(Self::Null),
1342		}
1343	}
1344}
1345
1346// Convert from a v2 XCM to a v3 XCM.
1347#[allow(deprecated)]
1348impl<Call> TryFrom<OldXcm<Call>> for Xcm<Call> {
1349	type Error = ();
1350	fn try_from(old_xcm: OldXcm<Call>) -> result::Result<Self, ()> {
1351		Ok(Xcm(old_xcm.0.into_iter().map(TryInto::try_into).collect::<result::Result<_, _>>()?))
1352	}
1353}
1354
1355// Convert from a v4 XCM to a v3 XCM.
1356impl<Call> TryFrom<NewXcm<Call>> for Xcm<Call> {
1357	type Error = ();
1358	fn try_from(new_xcm: NewXcm<Call>) -> result::Result<Self, Self::Error> {
1359		Ok(Xcm(new_xcm.0.into_iter().map(TryInto::try_into).collect::<result::Result<_, _>>()?))
1360	}
1361}
1362
1363// Convert from a v4 instruction to a v3 instruction.
1364impl<Call> TryFrom<NewInstruction<Call>> for Instruction<Call> {
1365	type Error = ();
1366	fn try_from(new_instruction: NewInstruction<Call>) -> result::Result<Self, Self::Error> {
1367		use NewInstruction::*;
1368		Ok(match new_instruction {
1369			WithdrawAsset(assets) => Self::WithdrawAsset(assets.try_into()?),
1370			ReserveAssetDeposited(assets) => Self::ReserveAssetDeposited(assets.try_into()?),
1371			ReceiveTeleportedAsset(assets) => Self::ReceiveTeleportedAsset(assets.try_into()?),
1372			QueryResponse { query_id, response, max_weight, querier: Some(querier) } =>
1373				Self::QueryResponse {
1374					query_id,
1375					querier: querier.try_into()?,
1376					response: response.try_into()?,
1377					max_weight,
1378				},
1379			QueryResponse { query_id, response, max_weight, querier: None } =>
1380				Self::QueryResponse {
1381					query_id,
1382					querier: None,
1383					response: response.try_into()?,
1384					max_weight,
1385				},
1386			TransferAsset { assets, beneficiary } => Self::TransferAsset {
1387				assets: assets.try_into()?,
1388				beneficiary: beneficiary.try_into()?,
1389			},
1390			TransferReserveAsset { assets, dest, xcm } => Self::TransferReserveAsset {
1391				assets: assets.try_into()?,
1392				dest: dest.try_into()?,
1393				xcm: xcm.try_into()?,
1394			},
1395			HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity } =>
1396				Self::HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity },
1397			HrmpChannelAccepted { recipient } => Self::HrmpChannelAccepted { recipient },
1398			HrmpChannelClosing { initiator, sender, recipient } =>
1399				Self::HrmpChannelClosing { initiator, sender, recipient },
1400			Transact { origin_kind, require_weight_at_most, call } =>
1401				Self::Transact { origin_kind, require_weight_at_most, call: call.into() },
1402			ReportError(response_info) => Self::ReportError(QueryResponseInfo {
1403				query_id: response_info.query_id,
1404				destination: response_info.destination.try_into().map_err(|_| ())?,
1405				max_weight: response_info.max_weight,
1406			}),
1407			DepositAsset { assets, beneficiary } => {
1408				let beneficiary = beneficiary.try_into()?;
1409				let assets = assets.try_into()?;
1410				Self::DepositAsset { assets, beneficiary }
1411			},
1412			DepositReserveAsset { assets, dest, xcm } => {
1413				let dest = dest.try_into()?;
1414				let xcm = xcm.try_into()?;
1415				let assets = assets.try_into()?;
1416				Self::DepositReserveAsset { assets, dest, xcm }
1417			},
1418			ExchangeAsset { give, want, maximal } => {
1419				let give = give.try_into()?;
1420				let want = want.try_into()?;
1421				Self::ExchangeAsset { give, want, maximal }
1422			},
1423			InitiateReserveWithdraw { assets, reserve, xcm } => {
1424				// No `max_assets` here, so if there's a connt, then we cannot translate.
1425				let assets = assets.try_into()?;
1426				let reserve = reserve.try_into()?;
1427				let xcm = xcm.try_into()?;
1428				Self::InitiateReserveWithdraw { assets, reserve, xcm }
1429			},
1430			InitiateTeleport { assets, dest, xcm } => {
1431				// No `max_assets` here, so if there's a connt, then we cannot translate.
1432				let assets = assets.try_into()?;
1433				let dest = dest.try_into()?;
1434				let xcm = xcm.try_into()?;
1435				Self::InitiateTeleport { assets, dest, xcm }
1436			},
1437			ReportHolding { response_info, assets } => {
1438				let response_info = QueryResponseInfo {
1439					destination: response_info.destination.try_into().map_err(|_| ())?,
1440					query_id: response_info.query_id,
1441					max_weight: response_info.max_weight,
1442				};
1443				Self::ReportHolding { response_info, assets: assets.try_into()? }
1444			},
1445			BuyExecution { fees, weight_limit } => {
1446				let fees = fees.try_into()?;
1447				let weight_limit = weight_limit.into();
1448				Self::BuyExecution { fees, weight_limit }
1449			},
1450			ClearOrigin => Self::ClearOrigin,
1451			DescendOrigin(who) => Self::DescendOrigin(who.try_into()?),
1452			RefundSurplus => Self::RefundSurplus,
1453			SetErrorHandler(xcm) => Self::SetErrorHandler(xcm.try_into()?),
1454			SetAppendix(xcm) => Self::SetAppendix(xcm.try_into()?),
1455			ClearError => Self::ClearError,
1456			ClaimAsset { assets, ticket } => {
1457				let assets = assets.try_into()?;
1458				let ticket = ticket.try_into()?;
1459				Self::ClaimAsset { assets, ticket }
1460			},
1461			Trap(code) => Self::Trap(code),
1462			SubscribeVersion { query_id, max_response_weight } =>
1463				Self::SubscribeVersion { query_id, max_response_weight },
1464			UnsubscribeVersion => Self::UnsubscribeVersion,
1465			BurnAsset(assets) => Self::BurnAsset(assets.try_into()?),
1466			ExpectAsset(assets) => Self::ExpectAsset(assets.try_into()?),
1467			ExpectOrigin(maybe_origin) =>
1468				Self::ExpectOrigin(maybe_origin.map(|origin| origin.try_into()).transpose()?),
1469			ExpectError(maybe_error) => Self::ExpectError(maybe_error),
1470			ExpectTransactStatus(maybe_error_code) => Self::ExpectTransactStatus(maybe_error_code),
1471			QueryPallet { module_name, response_info } =>
1472				Self::QueryPallet { module_name, response_info: response_info.try_into()? },
1473			ExpectPallet { index, name, module_name, crate_major, min_crate_minor } =>
1474				Self::ExpectPallet { index, name, module_name, crate_major, min_crate_minor },
1475			ReportTransactStatus(response_info) =>
1476				Self::ReportTransactStatus(response_info.try_into()?),
1477			ClearTransactStatus => Self::ClearTransactStatus,
1478			UniversalOrigin(junction) => Self::UniversalOrigin(junction.try_into()?),
1479			ExportMessage { network, destination, xcm } => Self::ExportMessage {
1480				network: network.into(),
1481				destination: destination.try_into()?,
1482				xcm: xcm.try_into()?,
1483			},
1484			LockAsset { asset, unlocker } =>
1485				Self::LockAsset { asset: asset.try_into()?, unlocker: unlocker.try_into()? },
1486			UnlockAsset { asset, target } =>
1487				Self::UnlockAsset { asset: asset.try_into()?, target: target.try_into()? },
1488			NoteUnlockable { asset, owner } =>
1489				Self::NoteUnlockable { asset: asset.try_into()?, owner: owner.try_into()? },
1490			RequestUnlock { asset, locker } =>
1491				Self::RequestUnlock { asset: asset.try_into()?, locker: locker.try_into()? },
1492			SetFeesMode { jit_withdraw } => Self::SetFeesMode { jit_withdraw },
1493			SetTopic(topic) => Self::SetTopic(topic),
1494			ClearTopic => Self::ClearTopic,
1495			AliasOrigin(location) => Self::AliasOrigin(location.try_into()?),
1496			UnpaidExecution { weight_limit, check_origin } => Self::UnpaidExecution {
1497				weight_limit,
1498				check_origin: check_origin.map(|origin| origin.try_into()).transpose()?,
1499			},
1500		})
1501	}
1502}
1503
1504/// Default value for the proof size weight component when converting from V2. Set at 64 KB.
1505/// NOTE: Make sure this is removed after we properly account for PoV weights.
1506const DEFAULT_PROOF_SIZE: u64 = 64 * 1024;
1507
1508// Convert from a v2 instruction to a v3 instruction.
1509impl<Call> TryFrom<OldInstruction<Call>> for Instruction<Call> {
1510	type Error = ();
1511	fn try_from(old_instruction: OldInstruction<Call>) -> result::Result<Self, ()> {
1512		use OldInstruction::*;
1513		Ok(match old_instruction {
1514			WithdrawAsset(assets) => Self::WithdrawAsset(assets.try_into()?),
1515			ReserveAssetDeposited(assets) => Self::ReserveAssetDeposited(assets.try_into()?),
1516			ReceiveTeleportedAsset(assets) => Self::ReceiveTeleportedAsset(assets.try_into()?),
1517			QueryResponse { query_id, response, max_weight } => Self::QueryResponse {
1518				query_id,
1519				response: response.try_into()?,
1520				max_weight: Weight::from_parts(max_weight, DEFAULT_PROOF_SIZE),
1521				querier: None,
1522			},
1523			TransferAsset { assets, beneficiary } => Self::TransferAsset {
1524				assets: assets.try_into()?,
1525				beneficiary: beneficiary.try_into()?,
1526			},
1527			TransferReserveAsset { assets, dest, xcm } => Self::TransferReserveAsset {
1528				assets: assets.try_into()?,
1529				dest: dest.try_into()?,
1530				xcm: xcm.try_into()?,
1531			},
1532			HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity } =>
1533				Self::HrmpNewChannelOpenRequest { sender, max_message_size, max_capacity },
1534			HrmpChannelAccepted { recipient } => Self::HrmpChannelAccepted { recipient },
1535			HrmpChannelClosing { initiator, sender, recipient } =>
1536				Self::HrmpChannelClosing { initiator, sender, recipient },
1537			Transact { origin_type, require_weight_at_most, call } => Self::Transact {
1538				origin_kind: origin_type.into(),
1539				require_weight_at_most: Weight::from_parts(
1540					require_weight_at_most,
1541					DEFAULT_PROOF_SIZE,
1542				),
1543				call: call.into(),
1544			},
1545			ReportError { query_id, dest, max_response_weight } => {
1546				let response_info = QueryResponseInfo {
1547					destination: dest.try_into()?,
1548					query_id,
1549					max_weight: Weight::from_parts(max_response_weight, DEFAULT_PROOF_SIZE),
1550				};
1551				Self::ReportError(response_info)
1552			},
1553			DepositAsset { assets, max_assets, beneficiary } => Self::DepositAsset {
1554				assets: (assets, max_assets).try_into()?,
1555				beneficiary: beneficiary.try_into()?,
1556			},
1557			DepositReserveAsset { assets, max_assets, dest, xcm } => {
1558				let assets = (assets, max_assets).try_into()?;
1559				Self::DepositReserveAsset { assets, dest: dest.try_into()?, xcm: xcm.try_into()? }
1560			},
1561			ExchangeAsset { give, receive } => {
1562				let give = give.try_into()?;
1563				let want = receive.try_into()?;
1564				Self::ExchangeAsset { give, want, maximal: true }
1565			},
1566			InitiateReserveWithdraw { assets, reserve, xcm } => Self::InitiateReserveWithdraw {
1567				assets: assets.try_into()?,
1568				reserve: reserve.try_into()?,
1569				xcm: xcm.try_into()?,
1570			},
1571			InitiateTeleport { assets, dest, xcm } => Self::InitiateTeleport {
1572				assets: assets.try_into()?,
1573				dest: dest.try_into()?,
1574				xcm: xcm.try_into()?,
1575			},
1576			QueryHolding { query_id, dest, assets, max_response_weight } => {
1577				let response_info = QueryResponseInfo {
1578					destination: dest.try_into()?,
1579					query_id,
1580					max_weight: Weight::from_parts(max_response_weight, DEFAULT_PROOF_SIZE),
1581				};
1582				Self::ReportHolding { response_info, assets: assets.try_into()? }
1583			},
1584			BuyExecution { fees, weight_limit } =>
1585				Self::BuyExecution { fees: fees.try_into()?, weight_limit: weight_limit.into() },
1586			ClearOrigin => Self::ClearOrigin,
1587			DescendOrigin(who) => Self::DescendOrigin(who.try_into()?),
1588			RefundSurplus => Self::RefundSurplus,
1589			SetErrorHandler(xcm) => Self::SetErrorHandler(xcm.try_into()?),
1590			SetAppendix(xcm) => Self::SetAppendix(xcm.try_into()?),
1591			ClearError => Self::ClearError,
1592			ClaimAsset { assets, ticket } => {
1593				let assets = assets.try_into()?;
1594				let ticket = ticket.try_into()?;
1595				Self::ClaimAsset { assets, ticket }
1596			},
1597			Trap(code) => Self::Trap(code),
1598			SubscribeVersion { query_id, max_response_weight } => Self::SubscribeVersion {
1599				query_id,
1600				max_response_weight: Weight::from_parts(max_response_weight, DEFAULT_PROOF_SIZE),
1601			},
1602			UnsubscribeVersion => Self::UnsubscribeVersion,
1603		})
1604	}
1605}
1606
1607#[cfg(test)]
1608mod tests {
1609	use super::{prelude::*, *};
1610
1611	#[test]
1612	fn decoding_respects_limit() {
1613		let max_xcm = Xcm::<()>(vec![ClearOrigin; MAX_INSTRUCTIONS_TO_DECODE as usize]);
1614		let encoded = max_xcm.encode();
1615		assert!(Xcm::<()>::decode(&mut &encoded[..]).is_ok());
1616
1617		let big_xcm = Xcm::<()>(vec![ClearOrigin; MAX_INSTRUCTIONS_TO_DECODE as usize + 1]);
1618		let encoded = big_xcm.encode();
1619		assert!(Xcm::<()>::decode(&mut &encoded[..]).is_err());
1620
1621		let nested_xcm = Xcm::<()>(vec![
1622			DepositReserveAsset {
1623				assets: All.into(),
1624				dest: Here.into(),
1625				xcm: max_xcm,
1626			};
1627			(MAX_INSTRUCTIONS_TO_DECODE / 2) as usize
1628		]);
1629		let encoded = nested_xcm.encode();
1630		assert!(Xcm::<()>::decode(&mut &encoded[..]).is_err());
1631
1632		let even_more_nested_xcm = Xcm::<()>(vec![SetAppendix(nested_xcm); 64]);
1633		let encoded = even_more_nested_xcm.encode();
1634		assert_eq!(encoded.len(), 342530);
1635		// This should not decode since the limit is 100
1636		assert_eq!(MAX_INSTRUCTIONS_TO_DECODE, 100, "precondition");
1637		assert!(Xcm::<()>::decode(&mut &encoded[..]).is_err());
1638	}
1639}