staging_xcm/v2/
junction.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//! Support data structures for `MultiLocation`, primarily the `Junction` datatype.
18
19use super::{BodyId, BodyPart, Junctions, MultiLocation, NetworkId};
20use crate::v3::Junction as NewJunction;
21use bounded_collections::{ConstU32, WeakBoundedVec};
22use codec::{Decode, Encode, MaxEncodedLen};
23use scale_info::TypeInfo;
24
25/// A single item in a path to describe the relative location of a consensus system.
26///
27/// Each item assumes a pre-existing location as its context and is defined in terms of it.
28#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, Debug, TypeInfo, MaxEncodedLen)]
29#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
30#[scale_info(replace_segment("staging_xcm", "xcm"))]
31pub enum Junction {
32	/// An indexed parachain belonging to and operated by the context.
33	///
34	/// Generally used when the context is a Polkadot Relay-chain.
35	Parachain(#[codec(compact)] u32),
36	/// A 32-byte identifier for an account of a specific network that is respected as a sovereign
37	/// endpoint within the context.
38	///
39	/// Generally used when the context is a Substrate-based chain.
40	AccountId32 { network: NetworkId, id: [u8; 32] },
41	/// An 8-byte index for an account of a specific network that is respected as a sovereign
42	/// endpoint within the context.
43	///
44	/// May be used when the context is a Frame-based chain and includes e.g. an indices pallet.
45	AccountIndex64 {
46		network: NetworkId,
47		#[codec(compact)]
48		index: u64,
49	},
50	/// A 20-byte identifier for an account of a specific network that is respected as a sovereign
51	/// endpoint within the context.
52	///
53	/// May be used when the context is an Ethereum or Bitcoin chain or smart-contract.
54	AccountKey20 { network: NetworkId, key: [u8; 20] },
55	/// An instanced, indexed pallet that forms a constituent part of the context.
56	///
57	/// Generally used when the context is a Frame-based chain.
58	PalletInstance(u8),
59	/// A non-descript index within the context location.
60	///
61	/// Usage will vary widely owing to its generality.
62	///
63	/// NOTE: Try to avoid using this and instead use a more specific item.
64	GeneralIndex(#[codec(compact)] u128),
65	/// A nondescript datum acting as a key within the context location.
66	///
67	/// Usage will vary widely owing to its generality.
68	///
69	/// NOTE: Try to avoid using this and instead use a more specific item.
70	GeneralKey(WeakBoundedVec<u8, ConstU32<32>>),
71	/// The unambiguous child.
72	///
73	/// Not currently used except as a fallback when deriving ancestry.
74	OnlyChild,
75	/// A pluralistic body existing within consensus.
76	///
77	/// Typical to be used to represent a governance origin of a chain, but could in principle be
78	/// used to represent things such as multisigs also.
79	Plurality { id: BodyId, part: BodyPart },
80}
81
82impl TryFrom<NewJunction> for Junction {
83	type Error = ();
84
85	fn try_from(value: NewJunction) -> Result<Self, Self::Error> {
86		use NewJunction::*;
87		Ok(match value {
88			Parachain(id) => Self::Parachain(id),
89			AccountId32 { network, id } => Self::AccountId32 { network: network.try_into()?, id },
90			AccountIndex64 { network, index } =>
91				Self::AccountIndex64 { network: network.try_into()?, index },
92			AccountKey20 { network, key } =>
93				Self::AccountKey20 { network: network.try_into()?, key },
94			PalletInstance(index) => Self::PalletInstance(index),
95			GeneralIndex(id) => Self::GeneralIndex(id),
96			GeneralKey { length, data } => Self::GeneralKey(
97				data[0..data.len().min(length as usize)]
98					.to_vec()
99					.try_into()
100					.expect("key is bounded to 32 and so will never be out of bounds; qed"),
101			),
102			OnlyChild => Self::OnlyChild,
103			Plurality { id, part } => Self::Plurality { id: id.into(), part: part.into() },
104			_ => return Err(()),
105		})
106	}
107}
108
109impl Junction {
110	/// Convert `self` into a `MultiLocation` containing 0 parents.
111	///
112	/// Similar to `Into::into`, except that this method can be used in a const evaluation context.
113	pub const fn into(self) -> MultiLocation {
114		MultiLocation { parents: 0, interior: Junctions::X1(self) }
115	}
116
117	/// Convert `self` into a `MultiLocation` containing `n` parents.
118	///
119	/// Similar to `Self::into`, with the added ability to specify the number of parent junctions.
120	pub const fn into_exterior(self, n: u8) -> MultiLocation {
121		MultiLocation { parents: n, interior: Junctions::X1(self) }
122	}
123}