diff --git a/runtime/kusama/src/lib.rs b/runtime/kusama/src/lib.rs index fe41607dda43..aafa9647d66b 100644 --- a/runtime/kusama/src/lib.rs +++ b/runtime/kusama/src/lib.rs @@ -60,7 +60,7 @@ use xcm_builder::{ AccountId32Aliases, ChildParachainConvertsVia, SovereignSignedViaLocation, CurrencyAdapter as XcmCurrencyAdapter, ChildParachainAsNative, SignedAccountId32AsNative, ChildSystemParachainAsSuperuser, LocationInverter, IsConcrete, FixedWeightBounds, TakeWeightCredit, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, - IsChildSystemParachain, UsingComponents, BackingToPlurality, SignedToAccountId32, + IsChildSystemParachain, UsingComponents, BackingToPlurality, SignedToAccountId32, DerivedParachainAccountId32, }; use xcm_executor::XcmExecutor; use sp_arithmetic::Perquintill; @@ -1222,6 +1222,8 @@ pub type SovereignAccountOf = ( ChildParachainConvertsVia, // We can directly alias an `AccountId32` into a local account. AccountId32Aliases, + // We can generate local account ids for accounts originating on parachains. + DerivedParachainAccountId32, ); /// Our asset transactor. This is what allows us to interest with the runtime facilities from the point of diff --git a/runtime/rococo/src/lib.rs b/runtime/rococo/src/lib.rs index 04c7adc96f55..374438e9a3a0 100644 --- a/runtime/rococo/src/lib.rs +++ b/runtime/rococo/src/lib.rs @@ -94,7 +94,7 @@ use xcm_builder::{ AccountId32Aliases, ChildParachainConvertsVia, SovereignSignedViaLocation, CurrencyAdapter as XcmCurrencyAdapter, ChildParachainAsNative, SignedAccountId32AsNative, ChildSystemParachainAsSuperuser, LocationInverter, IsConcrete, FixedWeightBounds, - BackingToPlurality, SignedToAccountId32, UsingComponents, + BackingToPlurality, SignedToAccountId32, UsingComponents, DerivedParachainAccountId32, }; use constants::{time::*, currency::*, fee::*}; use frame_support::traits::InstanceFilter; @@ -608,6 +608,8 @@ parameter_types! { pub type SovereignAccountOf = ( ChildParachainConvertsVia, AccountId32Aliases, + // We can generate local account ids for accounts originating on parachains. + DerivedParachainAccountId32, ); pub type LocalAssetTransactor = diff --git a/runtime/westend/src/lib.rs b/runtime/westend/src/lib.rs index 0ee78b5d19c4..964b386d2c16 100644 --- a/runtime/westend/src/lib.rs +++ b/runtime/westend/src/lib.rs @@ -61,7 +61,7 @@ use xcm_builder::{ AccountId32Aliases, ChildParachainConvertsVia, SovereignSignedViaLocation, CurrencyAdapter as XcmCurrencyAdapter, ChildParachainAsNative, SignedAccountId32AsNative, ChildSystemParachainAsSuperuser, LocationInverter, IsConcrete, FixedWeightBounds, TakeWeightCredit, AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, - IsChildSystemParachain, UsingComponents, SignedToAccountId32, + IsChildSystemParachain, UsingComponents, SignedToAccountId32, DerivedParachainAccountId32, }; use sp_runtime::{ @@ -880,6 +880,8 @@ parameter_types! { pub type LocationConverter = ( ChildParachainConvertsVia, AccountId32Aliases, + // We can generate local account ids for accounts originating on parachains. + DerivedParachainAccountId32, ); pub type LocalAssetTransactor = diff --git a/xcm/xcm-builder/src/lib.rs b/xcm/xcm-builder/src/lib.rs index 534261a9998d..6dc43042c79a 100644 --- a/xcm/xcm-builder/src/lib.rs +++ b/xcm/xcm-builder/src/lib.rs @@ -28,7 +28,7 @@ mod tests; mod location_conversion; pub use location_conversion::{ Account32Hash, ParentIsDefault, ChildParachainConvertsVia, SiblingParachainConvertsVia, AccountId32Aliases, - AccountKey20Aliases, LocationInverter, + AccountKey20Aliases, LocationInverter, DerivedParachainAccountId32, }; mod origin_conversion; diff --git a/xcm/xcm-builder/src/location_conversion.rs b/xcm/xcm-builder/src/location_conversion.rs index cdf0a2bf5171..80cf0eaf8aae 100644 --- a/xcm/xcm-builder/src/location_conversion.rs +++ b/xcm/xcm-builder/src/location_conversion.rs @@ -123,6 +123,7 @@ impl< } } +/// Extracts the `AccountKey20` from the passed `location` if the network matches. pub struct AccountKey20Aliases(PhantomData<(Network, AccountId)>); impl< Network: Get, @@ -143,6 +144,41 @@ impl< } } +/// Generates a unique `AccountId` for a given parachain + account combination. +/// +/// Used for giving parachains control over some accounts on the interpreting chain. +/// +/// Note: Not reversible. +pub struct DerivedParachainAccountId32(PhantomData<(Network, AccountId)>); +impl< + Network: Get, + AccountId: From<[u8; 32]> + Into<[u8; 32]> + Clone, +> Convert for DerivedParachainAccountId32 { + fn convert(location: MultiLocation) -> Result { + use Junction::*; + use MultiLocation::*; + let id = match location { + X2(Parachain(para_id), AccountId32 { id, network }) + if network == NetworkId::Any || &network == &Network::get() => + { + (para_id, id).using_encoded(blake2_256) + }, + X2(Parachain(para_id), AccountKey20 { key, network }) + if network == NetworkId::Any || &network == &Network::get() => + { + (para_id, key).using_encoded(blake2_256) + }, + l => return Err(l), + }; + Ok(id.into()) + } + + // reverse conversion is not implemented + fn reverse(who: AccountId) -> Result { + Err(who) + } +} + /// Simple location inverter; give it this location's ancestry and it'll figure out the inverted /// location. ///