Skip to content

Commit

Permalink
add migration for authorized aliases
Browse files Browse the repository at this point in the history
  • Loading branch information
acatangiu committed Nov 6, 2024
1 parent d0111c3 commit 6bbafbb
Show file tree
Hide file tree
Showing 3 changed files with 113 additions and 22 deletions.
14 changes: 8 additions & 6 deletions polkadot/xcm/pallet-xcm/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -387,11 +387,12 @@ benchmarks! {

add_authorized_alias {
let origin = RawOrigin::Root;
let origin_location = T::ExecuteXcmOrigin::ensure_origin(origin.clone().into()).unwrap();
let mut existing_aliases = BoundedVec::<Location, MaxAuthorizedAliases>::new();
let origin_location: VersionedLocation =
T::ExecuteXcmOrigin::ensure_origin(origin.clone().into()).unwrap().into();
let mut existing_aliases = BoundedVec::<VersionedLocation, MaxAuthorizedAliases>::new();
// prepopulate list with `max-1` aliases to benchmark worst case
for i in 1..MaxAuthorizedAliases::get() {
let alias = Location::new(1, [Parachain(i), AccountId32 { network: None, id: [42_u8; 32] }]);
let alias = Location::new(1, [Parachain(i), AccountId32 { network: None, id: [42_u8; 32] }]).into();
existing_aliases.try_push(alias).unwrap()
}
AuthorizedAliasesMap::<T>::insert(&origin_location, existing_aliases);
Expand All @@ -402,11 +403,12 @@ benchmarks! {

remove_authorized_alias {
let origin = RawOrigin::Root;
let origin_location = T::ExecuteXcmOrigin::ensure_origin(origin.clone().into()).unwrap();
let mut existing_aliases = BoundedVec::<Location, MaxAuthorizedAliases>::new();
let origin_location: VersionedLocation =
T::ExecuteXcmOrigin::ensure_origin(origin.clone().into()).unwrap().into();
let mut existing_aliases = BoundedVec::<VersionedLocation, MaxAuthorizedAliases>::new();
// prepopulate list with `max` aliases to benchmark worst case
for i in 1..MaxAuthorizedAliases::get()+1 {
let alias = Location::new(1, [Parachain(i), AccountId32 { network: None, id: [42_u8; 32] }]);
let alias = Location::new(1, [Parachain(i), AccountId32 { network: None, id: [42_u8; 32] }]).into();
existing_aliases.try_push(alias).unwrap()
}
AuthorizedAliasesMap::<T>::insert(&origin_location, existing_aliases);
Expand Down
45 changes: 29 additions & 16 deletions polkadot/xcm/pallet-xcm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -815,8 +815,8 @@ pub mod pallet {
pub(super) type AuthorizedAliasesMap<T: Config> = StorageMap<
_,
Blake2_128Concat,
Location,
BoundedVec<Location, MaxAuthorizedAliases>,
VersionedLocation,
BoundedVec<VersionedLocation, MaxAuthorizedAliases>,
ValueQuery,
>;

Expand Down Expand Up @@ -1466,15 +1466,17 @@ pub mod pallet {
origin: OriginFor<T>,
aliaser: Box<VersionedLocation>,
) -> DispatchResult {
let origin = T::ExecuteXcmOrigin::ensure_origin(origin)?;
let aliaser = (*aliaser).try_into().map_err(|()| Error::<T>::BadVersion)?;
let origin: Location = T::ExecuteXcmOrigin::ensure_origin(origin)?;
let aliaser: Location = (*aliaser).try_into().map_err(|()| Error::<T>::BadVersion)?;
ensure!(origin != aliaser, Error::<T>::BadLocation);
let mut authorized_aliases = AuthorizedAliasesMap::<T>::get(&origin);
if !authorized_aliases.contains(&aliaser) {
let v_origin = VersionedLocation::from(origin);
let v_aliaser = VersionedLocation::from(aliaser);
let mut authorized_aliases = AuthorizedAliasesMap::<T>::get(&v_origin);
if !authorized_aliases.contains(&v_aliaser) {
authorized_aliases
.try_push(aliaser)
.try_push(v_aliaser)
.map_err(|_| Error::<T>::TooManyAuthorizedAliases)?;
AuthorizedAliasesMap::<T>::insert(&origin, authorized_aliases);
AuthorizedAliasesMap::<T>::insert(&v_origin, authorized_aliases);
}
Ok(())
}
Expand All @@ -1486,14 +1488,16 @@ pub mod pallet {
origin: OriginFor<T>,
aliaser: Box<VersionedLocation>,
) -> DispatchResult {
let origin = T::ExecuteXcmOrigin::ensure_origin(origin)?;
let to_remove = (*aliaser).try_into().map_err(|()| Error::<T>::BadVersion)?;
let origin: Location = T::ExecuteXcmOrigin::ensure_origin(origin)?;
let to_remove: Location = (*aliaser).try_into().map_err(|()| Error::<T>::BadVersion)?;
ensure!(origin != to_remove, Error::<T>::BadLocation);
let mut authorized_aliases = AuthorizedAliasesMap::<T>::get(&origin);
let v_origin = VersionedLocation::from(origin);
let v_to_remove = VersionedLocation::from(to_remove);
let mut authorized_aliases = AuthorizedAliasesMap::<T>::get(&v_origin);
let original_length = authorized_aliases.len();
authorized_aliases.retain(|alias| to_remove.ne(alias));
authorized_aliases.retain(|alias| v_to_remove.ne(alias));
if original_length != authorized_aliases.len() {
AuthorizedAliasesMap::<T>::insert(&origin, authorized_aliases);
AuthorizedAliasesMap::<T>::insert(&v_origin, authorized_aliases);
}
Ok(())
}
Expand Down Expand Up @@ -3507,11 +3511,20 @@ where
/// Note: users can authorize other locations to alias them by using
/// `pallet_xcm::add_authorized_alias()`.
pub struct AuthorizedAliases<T>(PhantomData<T>);
impl<T: Config> ContainsPair<Location, Location> for AuthorizedAliases<T> {
fn contains(origin: &Location, target: &Location) -> bool {
AuthorizedAliasesMap::<T>::get(&origin).contains(target)
impl<L: Into<VersionedLocation> + Clone, T: Config> ContainsPair<L, L> for AuthorizedAliases<T> {
fn contains(origin: &L, target: &L) -> bool {
let origin: VersionedLocation = origin.clone().into();
let target: VersionedLocation = target.clone().into();
AuthorizedAliasesMap::<T>::get(&origin).contains(&target)
}
}
// pub struct AuthorizedAliases<T>(PhantomData<T>);
// impl<T: Config> ContainsPair<Location, Location> for AuthorizedAliases<T> {
// fn contains(origin: &Location, target: &Location) -> bool {
// let target = VersionedLocation::from(target.clone());
// AuthorizedAliasesMap::<T>::get(&origin).contains(&target)
// }
// }

/// Filter for `Location` to find those which represent a strict majority approval of an
/// identified plurality.
Expand Down
76 changes: 76 additions & 0 deletions polkadot/xcm/pallet-xcm/src/migration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,49 @@ pub mod data {
}
}

/// Implementation of `NeedsMigration` for `AuthorizedAliasesMap` data.
impl<M: Get<u32>> NeedsMigration for (&VersionedLocation, &BoundedVec<VersionedLocation, M>) {
type MigratedData = (VersionedLocation, BoundedVec<VersionedLocation, M>);

fn needs_migration(&self, _: XcmVersion) -> bool {
self.0.identify_version() < XCM_VERSION ||
self.1.iter().any(|alias| alias.identify_version() < XCM_VERSION)
}

fn try_migrate(self, new_version: XcmVersion) -> Result<Option<Self::MigratedData>, ()> {
if !self.needs_migration(new_version) {
return Ok(None)
}

let key = if self.0.identify_version() < new_version {
let Ok(converted_key) = self.0.clone().into_version(new_version) else {
return Err(())
};
converted_key
} else {
self.0.clone()
};
let mut aliases = BoundedVec::<VersionedLocation, M>::new();
for alias in self.1 {
if aliases
.try_push(if alias.identify_version() < new_version {
let Ok(new_alias) = alias.clone().into_version(new_version) else {
return Err(())
};
new_alias
} else {
alias.clone()
})
.is_err()
{
return Err(())
};
}

Ok(Some((key, aliases)))
}
}

impl<T: Config> Pallet<T> {
/// Migrates relevant data to the `required_xcm_version`.
pub(crate) fn migrate_data_to_xcm_version(
Expand Down Expand Up @@ -323,6 +366,39 @@ pub mod data {
>(&old_key, &new_key);
weight.saturating_add(T::DbWeight::get().writes(1));
}

// check and migrate `AuthorizedAliasesMap`
let aliases_to_migrate = AuthorizedAliasesMap::<T>::iter().filter_map(|(id, data)| {
weight.saturating_add(T::DbWeight::get().reads(1));
match (&id, &data).try_migrate(required_xcm_version) {
Ok(Some((new_id, new_data))) => Some((id, new_id, new_data)),
Ok(None) => None,
Err(_) => {
tracing::error!(
target: LOG_TARGET,
?id,
?data,
?required_xcm_version,
"`AuthorizedAliasesMap` cannot be migrated!"
);
None
},
}
});
let mut count = 0;
for (old_id, new_id, new_data) in aliases_to_migrate {
tracing::info!(
target: LOG_TARGET,
?new_id,
?new_data,
"Migrating `AuthorizedAliasesMap`"
);
AuthorizedAliasesMap::<T>::remove(old_id);
AuthorizedAliasesMap::<T>::insert(new_id, new_data);
count = count + 1;
}
// two writes per key, one to remove old entry, one to write new entry
weight.saturating_add(T::DbWeight::get().writes(count * 2));
}
}
}
Expand Down

0 comments on commit 6bbafbb

Please sign in to comment.