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}