Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

v3::Junction supports small (32-byte max) "vecs". #6716

Merged
merged 3 commits into from Feb 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions xcm/src/v2/junction.rs
Expand Up @@ -92,11 +92,11 @@ impl TryFrom<NewJunction> for Junction {
Self::AccountKey20 { network: network.try_into()?, key },
PalletInstance(index) => Self::PalletInstance(index),
GeneralIndex(id) => Self::GeneralIndex(id),
GeneralKey(key) => Self::GeneralKey(
key[..]
GeneralKey { length, data } => Self::GeneralKey(
data[0..data.len().min(length as usize)]
.to_vec()
.try_into()
.expect("array is of size 32 and so will never be out of bounds; qed"),
.expect("key is bounded to 32 and so will never be out of bounds; qed"),
),
OnlyChild => Self::OnlyChild,
Plurality { id, part } => Self::Plurality { id: id.into(), part: part.into() },
Expand Down
72 changes: 69 additions & 3 deletions xcm/src/v3/junction.rs
Expand Up @@ -24,6 +24,7 @@ use crate::{
},
VersionedMultiLocation,
};
use bounded_collections::{BoundedSlice, BoundedVec, ConstU32};
use core::convert::{TryFrom, TryInto};
use parity_scale_codec::{self, Decode, Encode, MaxEncodedLen};
use scale_info::TypeInfo;
Expand Down Expand Up @@ -237,12 +238,15 @@ pub enum Junction {
///
/// NOTE: Try to avoid using this and instead use a more specific item.
GeneralIndex(#[codec(compact)] u128),
/// A nondescript 128-byte datum acting as a key within the context location.
/// A nondescript array datum, 32 bytes, acting as a key within the context
/// location.
///
/// Usage will vary widely owing to its generality.
///
/// NOTE: Try to avoid using this and instead use a more specific item.
GeneralKey([u8; 32]),
// Note this is implemented as an array with a length rather than using `BoundedVec` owing to
// the bound for `Copy`.
GeneralKey { length: u8, data: [u8; 32] },
/// The unambiguous child.
///
/// Not currently used except as a fallback when deriving context.
Expand All @@ -269,6 +273,31 @@ impl From<[u8; 32]> for Junction {
}
}

impl From<BoundedVec<u8, ConstU32<32>>> for Junction {
fn from(key: BoundedVec<u8, ConstU32<32>>) -> Self {
key.as_bounded_slice().into()
}
}

impl<'a> From<BoundedSlice<'a, u8, ConstU32<32>>> for Junction {
fn from(key: BoundedSlice<'a, u8, ConstU32<32>>) -> Self {
let mut data = [0u8; 32];
data[..key.len()].copy_from_slice(&key[..]);
Self::GeneralKey { length: key.len() as u8, data }
}
}

impl<'a> TryFrom<&'a Junction> for BoundedSlice<'a, u8, ConstU32<32>> {
type Error = ();
fn try_from(key: &'a Junction) -> Result<Self, ()> {
match key {
Junction::GeneralKey { length, data } =>
BoundedSlice::try_from(&data[..data.len().min(*length as usize)]).map_err(|_| ()),
_ => Err(()),
}
}
}

impl From<[u8; 20]> for Junction {
fn from(key: [u8; 20]) -> Self {
Self::AccountKey20 { network: None, key }
Expand Down Expand Up @@ -299,7 +328,17 @@ impl TryFrom<OldJunction> for Junction {
AccountKey20 { network, key } => Self::AccountKey20 { network: network.into(), key },
PalletInstance(index) => Self::PalletInstance(index),
GeneralIndex(id) => Self::GeneralIndex(id),
GeneralKey(_key) => return Err(()),
GeneralKey(key) => match key.len() {
len @ 0..=32 => Self::GeneralKey {
length: len as u8,
data: {
let mut data = [0u8; 32];
data[..len].copy_from_slice(&key[..]);
data
},
},
_ => return Err(()),
},
OnlyChild => Self::OnlyChild,
Plurality { id, part } =>
Self::Plurality { id: id.try_into()?, part: part.try_into()? },
Expand Down Expand Up @@ -340,3 +379,30 @@ impl Junction {
}
}
}

#[cfg(test)]
mod tests {
use super::*;
use alloc::vec;

#[test]
fn junction_round_trip_works() {
let j = Junction::GeneralKey { length: 32, data: [1u8; 32] };
let k = Junction::try_from(OldJunction::try_from(j).unwrap()).unwrap();
assert_eq!(j, k);

let j = OldJunction::GeneralKey(vec![1u8; 32].try_into().unwrap());
let k = OldJunction::try_from(Junction::try_from(j.clone()).unwrap()).unwrap();
assert_eq!(j, k);

let j = Junction::from(BoundedVec::try_from(vec![1u8, 2, 3, 4]).unwrap());
let k = Junction::try_from(OldJunction::try_from(j).unwrap()).unwrap();
assert_eq!(j, k);
let s: BoundedSlice<_, _> = (&k).try_into().unwrap();
assert_eq!(s, &[1u8, 2, 3, 4][..]);

let j = OldJunction::GeneralKey(vec![1u8, 2, 3, 4].try_into().unwrap());
let k = OldJunction::try_from(Junction::try_from(j.clone()).unwrap()).unwrap();
assert_eq!(j, k);
}
}