diff --git a/Cargo.lock b/Cargo.lock index 0bfb6b03..fcbace75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3919,7 +3919,6 @@ dependencies = [ [[package]] name = "invarch-primitives" version = "0.1.0-dev" -source = "git+https://github.com/InvArch/InvArch-Frames?rev=82061c35b7b73d77b3a073789ef03fd56771e9fb#82061c35b7b73d77b3a073789ef03fd56771e9fb" dependencies = [ "frame-system", "parity-scale-codec", @@ -6094,7 +6093,6 @@ dependencies = [ [[package]] name = "pallet-checked-inflation" version = "0.1.0-dev" -source = "git+https://github.com/InvArch/InvArch-Frames?rev=82061c35b7b73d77b3a073789ef03fd56771e9fb#82061c35b7b73d77b3a073789ef03fd56771e9fb" dependencies = [ "frame-benchmarking", "frame-support", @@ -6184,6 +6182,20 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-core-assets" +version = "0.0.1" +dependencies = [ + "frame-support", + "frame-system", + "num-traits", + "parity-scale-codec", + "scale-info", + "sp-arithmetic", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-democracy" version = "4.0.0-dev" @@ -6353,7 +6365,6 @@ dependencies = [ [[package]] name = "pallet-inv4" version = "0.1.0-dev" -source = "git+https://github.com/InvArch/InvArch-Frames?rev=82061c35b7b73d77b3a073789ef03fd56771e9fb#82061c35b7b73d77b3a073789ef03fd56771e9fb" dependencies = [ "frame-benchmarking", "frame-support", @@ -6362,6 +6373,7 @@ dependencies = [ "log", "orml-tokens 0.4.1-dev (git+https://github.com/arrudagates//open-runtime-module-library?rev=7ecebeab7e3dbc2226ed58d32ee159271a8176ae)", "pallet-balances", + "pallet-nft-origins", "parity-scale-codec", "scale-info", "serde", @@ -6458,6 +6470,27 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-nft-origins" +version = "0.1.0-dev" +dependencies = [ + "frame-support", + "frame-system", + "log", + "pallet-xcm", + "parity-scale-codec", + "primitive-types", + "scale-info", + "serde", + "sp-arithmetic", + "sp-core", + "sp-io", + "sp-runtime", + "sp-std", + "xcm", + "xcm-executor", +] + [[package]] name = "pallet-nis" version = "4.0.0-dev" @@ -6525,7 +6558,6 @@ dependencies = [ [[package]] name = "pallet-ocif-staking" version = "0.1.0-dev" -source = "git+https://github.com/InvArch/InvArch-Frames?rev=82061c35b7b73d77b3a073789ef03fd56771e9fb#82061c35b7b73d77b3a073789ef03fd56771e9fb" dependencies = [ "frame-benchmarking", "frame-support", @@ -6674,7 +6706,6 @@ dependencies = [ [[package]] name = "pallet-rings" version = "0.1.0-dev" -source = "git+https://github.com/InvArch/InvArch-Frames?rev=82061c35b7b73d77b3a073789ef03fd56771e9fb#82061c35b7b73d77b3a073789ef03fd56771e9fb" dependencies = [ "frame-benchmarking", "frame-support", @@ -12447,10 +12478,12 @@ dependencies = [ "pallet-balances", "pallet-checked-inflation", "pallet-collator-selection", + "pallet-core-assets", "pallet-identity", "pallet-inv4", "pallet-maintenance-mode", "pallet-multisig", + "pallet-nft-origins", "pallet-ocif-staking", "pallet-preimage", "pallet-rings", diff --git a/node/src/chain_spec.rs b/node/src/chain_spec.rs index 0e3ee067..9314e8eb 100644 --- a/node/src/chain_spec.rs +++ b/node/src/chain_spec.rs @@ -343,6 +343,6 @@ fn testnet_genesis( asset_registry: Default::default(), #[cfg(feature = "tinkernet")] tokens: Default::default(), - core_assets: Default::default(), + // core_assets: Default::default(), } } diff --git a/runtime/tinkernet/Cargo.toml b/runtime/tinkernet/Cargo.toml index 9835f0f2..878920aa 100644 --- a/runtime/tinkernet/Cargo.toml +++ b/runtime/tinkernet/Cargo.toml @@ -24,15 +24,18 @@ smallvec = "1.6.1" getrandom = { version = "0.2.4", default-features = false, features = ["js"] } # InvArch Pallets -pallet-inv4 = { git = "https://github.com/InvArch/InvArch-Frames", rev = "82061c35b7b73d77b3a073789ef03fd56771e9fb", default-features = false } -pallet-ocif-staking = { git = "https://github.com/InvArch/InvArch-Frames", rev = "82061c35b7b73d77b3a073789ef03fd56771e9fb", default-features = false } -pallet-checked-inflation = { git = "https://github.com/InvArch/InvArch-Frames", rev = "82061c35b7b73d77b3a073789ef03fd56771e9fb", default-features = false } -pallet-rings = { git = "https://github.com/InvArch/InvArch-Frames", rev = "82061c35b7b73d77b3a073789ef03fd56771e9fb", default-features = false } +#pallet-inv4 = { git = "https://github.com/InvArch/InvArch-Frames", rev = "82061c35b7b73d77b3a073789ef03fd56771e9fb", default-features = false } +#pallet-ocif-staking = { git = "https://github.com/InvArch/InvArch-Frames", rev = "82061c35b7b73d77b3a073789ef03fd56771e9fb", default-features = false } +#pallet-checked-inflation = { git = "https://github.com/InvArch/InvArch-Frames", rev = "82061c35b7b73d77b3a073789ef03fd56771e9fb", default-features = false } +#pallet-rings = { git = "https://github.com/InvArch/InvArch-Frames", rev = "82061c35b7b73d77b3a073789ef03fd56771e9fb", default-features = false } -#pallet-inv4 = { path = "../../../InvArch-Frames/INV4/pallet-inv4", default-features = false } -#pallet-ocif-staking = { path = "../../../InvArch-Frames/OCIF/staking", default-features = false } -#pallet-checked-inflation = { path = "../../../InvArch-Frames/pallet-checked-inflation", default-features = false } -#pallet-rings = { path = "../../../InvArch-Frames/pallet-rings", default-features = false } +pallet-inv4 = { path = "../../../InvArch-Frames/INV4/pallet-inv4", default-features = false } +pallet-ocif-staking = { path = "../../../InvArch-Frames/OCIF/staking", default-features = false } +pallet-checked-inflation = { path = "../../../InvArch-Frames/pallet-checked-inflation", default-features = false } +pallet-rings = { path = "../../../InvArch-Frames/pallet-rings", default-features = false } +pallet-nft-origins = { path = "../../../InvArch-Frames/pallet-nft-origins", default-features = false } + +pallet-core-assets = { path = "../../../InvArch-Frames/pallet-core-assets", default-features = false } pallet-maintenance-mode = { git = "https://github.com/Moonsong-Labs/moonkit", default-features = false, features = ["xcm-support"], rev = "51e3068808fb58f30ffb16bfdaa81d0890f98fd8" } @@ -208,6 +211,7 @@ std = [ "pallet-rings/std", "pallet-asset-tx-payment/std", "modified-construct-runtime/std", + "pallet-nft-origins/std", ] runtime-benchmarks = [ diff --git a/runtime/tinkernet/src/inv4.rs b/runtime/tinkernet/src/inv4.rs index 17f02b7c..c0e80d8b 100644 --- a/runtime/tinkernet/src/inv4.rs +++ b/runtime/tinkernet/src/inv4.rs @@ -9,13 +9,13 @@ use crate::{ use codec::{Decode, Encode}; use frame_support::{ parameter_types, - traits::{fungibles::Credit, Contains, Currency, OnUnbalanced}, + traits::{fungibles::Credit, Currency, OnUnbalanced}, }; use pallet_asset_tx_payment::ChargeAssetTxPayment; use pallet_inv4::fee_handling::{FeeAsset, FeeAssetNegativeImbalance, MultisigFeeHandler}; use scale_info::TypeInfo; -use sp_core::{ConstU32, H256}; -use sp_runtime::traits::{One, SignedExtension, Zero}; +use sp_core::H256; +use sp_runtime::traits::{SignedExtension, Zero}; parameter_types! { pub const MaxMetadata: u32 = 10000; @@ -42,7 +42,6 @@ impl pallet_inv4::Config for Runtime { type CoreSeedBalance = CoreSeedBalance; type AssetsProvider = CoreAssets; type RuntimeOrigin = RuntimeOrigin; - // type AssetFreezer = AssetFreezer; type CoreCreationFee = CoreCreationFee; type FeeCharger = FeeCharger; type GenesisHash = GenesisHash; @@ -121,86 +120,89 @@ impl MultisigFeeHandler for FeeCharger { } } -orml_traits2::parameter_type_with_key! { - pub CoreExistentialDeposits: |_currency_id: ::CoreId| -> Balance { - Balance::one() - }; -} - -pub struct CoreDustRemovalWhitelist; -impl Contains for CoreDustRemovalWhitelist { - fn contains(_: &AccountId) -> bool { - true - } -} - -pub struct DisallowIfFrozen; -impl - orml_traits2::currency::OnTransfer::CoreId, Balance> - for DisallowIfFrozen -{ - fn on_transfer( - currency_id: ::CoreId, - _from: &AccountId, - _to: &AccountId, - _amount: Balance, - ) -> sp_runtime::DispatchResult { - if let Some(true) = crate::INV4::is_asset_frozen(currency_id) { - Err(sp_runtime::DispatchError::Token( - sp_runtime::TokenError::Frozen, - )) - } else { - Ok(()) - } - } -} - -pub struct HandleNewMembers; -impl orml_traits2::Happened<(AccountId, ::CoreId)> - for HandleNewMembers -{ - fn happened((member, core_id): &(AccountId, ::CoreId)) { - crate::INV4::add_member(core_id, member) - } -} - -pub struct HandleRemovedMembers; -impl orml_traits2::Happened<(AccountId, ::CoreId)> - for HandleRemovedMembers -{ - fn happened((member, core_id): &(AccountId, ::CoreId)) { - crate::INV4::remove_member(core_id, member) - } -} - -pub struct INV4TokenHooks; -impl - orml_traits2::currency::MutationHooks< - AccountId, - ::CoreId, - Balance, - > for INV4TokenHooks -{ - type PreTransfer = DisallowIfFrozen; - type OnDust = (); - type OnSlash = (); - type PreDeposit = (); - type PostDeposit = (); - type PostTransfer = (); - type OnNewTokenAccount = HandleNewMembers; - type OnKilledTokenAccount = HandleRemovedMembers; -} - -impl orml_tokens2::Config for Runtime { +// pub struct DisallowIfFrozen; +// impl +// orml_tokens_fork::OnTransfer< +// pallet_inv4::multisig::MultisigMemberOf, +// ::CoreId, +// Balance, +// > for DisallowIfFrozen +// { +// fn on_transfer( +// currency_id: ::CoreId, +// _from: &pallet_inv4::multisig::MultisigMemberOf, +// _to: &pallet_inv4::multisig::MultisigMemberOf, +// _amount: Balance, +// ) -> sp_runtime::DispatchResult { +// if let Some(true) = crate::INV4::is_asset_frozen(currency_id) { +// Err(sp_runtime::DispatchError::Token( +// sp_runtime::TokenError::Frozen, +// )) +// } else { +// Ok(()) +// } +// } +// } + +// pub struct HandleNewMembers; +// impl +// orml_tokens_fork::Happened<( +// pallet_inv4::multisig::MultisigMemberOf, +// ::CoreId, +// )> for HandleNewMembers +// { +// fn happened( +// (member, core_id): &( +// pallet_inv4::multisig::MultisigMemberOf, +// ::CoreId, +// ), +// ) { +// crate::INV4::add_member(core_id, member) +// } +// } + +// pub struct HandleRemovedMembers; +// impl +// orml_tokens_fork::Happened<( +// pallet_inv4::multisig::MultisigMemberOf, +// ::CoreId, +// )> for HandleRemovedMembers +// { +// fn happened( +// (member, core_id): &( +// pallet_inv4::multisig::MultisigMemberOf, +// ::CoreId, +// ), +// ) { +// crate::INV4::remove_member(core_id, member) +// } +// } + +// pub struct INV4TokenHooks; +// impl +// orml_tokens_fork::MutationHooks< +// pallet_inv4::multisig::MultisigMemberOf, +// ::CoreId, +// Balance, +// > for INV4TokenHooks +// { +// type PreTransfer = DisallowIfFrozen; +// type OnDust = (); +// type OnSlash = (); +// type PreDeposit = (); +// type PostDeposit = (); +// type PostTransfer = (); +// type OnNewTokenAccount = HandleNewMembers; +// type OnKilledTokenAccount = HandleRemovedMembers; +// } + +impl pallet_core_assets::Config for Runtime { type RuntimeEvent = RuntimeEvent; type Balance = Balance; - type Amount = i128; type CurrencyId = ::CoreId; type WeightInfo = (); - type ExistentialDeposits = CoreExistentialDeposits; - type MaxLocks = ConstU32<0u32>; - type MaxReserves = ConstU32<0u32>; - type DustRemovalWhitelist = CoreDustRemovalWhitelist; - type ReserveIdentifier = [u8; 8]; - type CurrencyHooks = INV4TokenHooks; + + type AccountId = pallet_inv4::multisig::MultisigMemberOf; + type Lookup = + sp_runtime::traits::IdentityLookup>; } diff --git a/runtime/tinkernet/src/lib.rs b/runtime/tinkernet/src/lib.rs index 3dc62aa0..06a57a02 100644 --- a/runtime/tinkernet/src/lib.rs +++ b/runtime/tinkernet/src/lib.rs @@ -101,6 +101,7 @@ use fee_handling::TnkrToKsm; mod inflation; mod inv4; mod nft; +mod nft_origins; mod rings; mod staking; mod weights; @@ -834,8 +835,9 @@ construct_runtime_modified!( OcifStaking: pallet_ocif_staking::{Pallet, Call, Storage, Event} = 51, INV4: pallet_inv4::{Pallet, Call, Storage, Event, Origin} = 71, - CoreAssets: orml_tokens2::{Pallet, Storage, Call, Event, Config} = 72, + CoreAssets: pallet_core_assets::{Pallet, Storage, Call, Event} = 72, Rings: pallet_rings::{Pallet, Call, Storage, Event} = 73, + NftOrigins: pallet_nft_origins::{Pallet, Origin, Event, Call, Storage} = 74, Uniques: pallet_uniques::{Pallet, Storage, Event} = 80, diff --git a/runtime/tinkernet/src/nft_origins.rs b/runtime/tinkernet/src/nft_origins.rs new file mode 100644 index 00000000..ddf95568 --- /dev/null +++ b/runtime/tinkernet/src/nft_origins.rs @@ -0,0 +1,173 @@ +use crate::{Runtime, RuntimeCall, RuntimeEvent, RuntimeOrigin}; +use codec::{Decode, Encode}; +use frame_support::dispatch::GetDispatchInfo; +use pallet_nft_origins::{ChainVerifier, Parachain}; +use scale_info::TypeInfo; +use sp_runtime::{traits::Dispatchable, BoundedVec}; +use sp_std::boxed::Box; +use xcm::latest::Junction; + +impl pallet_nft_origins::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type RuntimeCall = RuntimeCall; + type RuntimeOrigin = RuntimeOrigin; + + type Chains = RegisteredChains; + type RegisteredCalls = RegisteredCalls; +} + +pub enum RegisteredChains { + Moonriver, + TinkernetTest, +} + +impl ChainVerifier for RegisteredChains { + fn get_chain_from_verifier(para_id: u32, verifier_part: Junction) -> Option { + match (para_id, verifier_part) { + // Moonriver + ( + 2023, + Junction::AccountKey20 { + network: None, + key: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + }, + ) => Some(Parachain(2023)), + + (2126, Junction::GeneralIndex(69)) => Some(Parachain(2126)), + + // Fallback to storage for testing purposes. + // In reality these won't change much, so storage won't be necessary. + _ => { + if let Some(Parachain(p)) = + pallet_nft_origins::RegisteredChains::::get(verifier_part) + { + if p == para_id { + Some(Parachain(p)) + } else { + None + } + } else { + None + } + } + } + } +} + +#[derive(Encode, Decode, Clone, PartialEq, Eq, Debug, TypeInfo)] +#[repr(u8)] +pub enum RegisteredCalls { + VoteInMultisig { + core_id: ::CoreId, + call_hash: ::Hash, + aye: bool, + } = 0, + + WithdrawVoteInMultisig { + core_id: ::CoreId, + call_hash: ::Hash, + } = 1, + + OperateMultisig { + core_id: ::CoreId, + metadata: Option::MaxMetadata>>, + fee_asset: pallet_inv4::fee_handling::FeeAsset, + call: Box<::RuntimeCall>, + } = 2, + + TestNftCall = 3, +} + +impl Dispatchable for RegisteredCalls { + type RuntimeOrigin = ::RuntimeOrigin; + type Config = ::Config; + type Info = ::Info; + type PostInfo = ::PostInfo; + + fn dispatch( + self, + origin: Self::RuntimeOrigin, + ) -> sp_runtime::DispatchResultWithInfo { + match self { + Self::VoteInMultisig { + core_id, + call_hash, + aye, + } => Ok(pallet_inv4::Pallet::::nft_vote_multisig( + origin.into(), + core_id, + call_hash, + aye, + )? + .into()), + + Self::WithdrawVoteInMultisig { core_id, call_hash } => { + Ok(pallet_inv4::Pallet::::nft_withdraw_vote_multisig( + origin.into(), + core_id, + call_hash, + )? + .into()) + } + + Self::OperateMultisig { + core_id, + metadata, + fee_asset, + call, + } => Ok(pallet_inv4::Pallet::::nft_operate_multisig( + origin.into(), + core_id, + metadata, + fee_asset, + call, + )? + .into()), + + Self::TestNftCall => { + Ok(pallet_nft_origins::Pallet::::test_nft_location(origin.into())?.into()) + } + } + } +} + +impl GetDispatchInfo for RegisteredCalls { + fn get_dispatch_info(&self) -> frame_support::dispatch::DispatchInfo { + match self.clone() { + Self::VoteInMultisig { + core_id, + call_hash, + aye, + } => pallet_inv4::pallet::Call::::nft_vote_multisig { + core_id, + call_hash, + aye, + } + .get_dispatch_info(), + + Self::WithdrawVoteInMultisig { core_id, call_hash } => { + pallet_inv4::pallet::Call::::nft_withdraw_vote_multisig { + core_id, + call_hash, + } + .get_dispatch_info() + } + + Self::OperateMultisig { + core_id, + metadata, + fee_asset, + call, + } => pallet_inv4::pallet::Call::::nft_operate_multisig { + core_id, + metadata, + fee_asset, + call, + } + .get_dispatch_info(), + + Self::TestNftCall => pallet_nft_origins::pallet::Call::::test_nft_location {} + .get_dispatch_info(), + } + } +} diff --git a/runtime/tinkernet/src/xcm_config.rs b/runtime/tinkernet/src/xcm_config.rs index 0734ddf2..30256770 100644 --- a/runtime/tinkernet/src/xcm_config.rs +++ b/runtime/tinkernet/src/xcm_config.rs @@ -32,7 +32,7 @@ use xcm_builder::{ AllowTopLevelPaidExecutionFrom, AllowUnpaidExecutionFrom, EnsureXcmOrigin, FixedWeightBounds, ParentIsPreset, RelayChainAsNative, SiblingParachainAsNative, SiblingParachainConvertsVia, SignedAccountId32AsNative, SignedToAccountId32, SovereignSignedViaLocation, TakeRevenue, - TakeWeightCredit, UsingComponents, + TakeWeightCredit, UsingComponents, WithComputedOrigin, }; use xcm_executor::XcmExecutor; @@ -42,8 +42,12 @@ pub struct AssetLocation(pub MultiLocation); pub type LocalOriginToLocation = SignedToAccountId32; pub type Barrier = ( + // \/ FOR TESTING ONLY \/ + //xcm_builder::AllowUnpaidExecutionFrom, + // /\ FOR TESTING ONLY /\ TakeWeightCredit, AllowTopLevelPaidExecutionFrom, + WithComputedOrigin, UniversalLocation, ConstU32<8>>, // Parent and its plurality get free execution AllowUnpaidExecutionFrom, // Expected responses are OK. @@ -75,6 +79,10 @@ match_types! { /// ready for dispatching a transaction with Xcm's `Transact`. There is an `OriginKind` which can /// biases the kind of local `Origin` it will become. pub type XcmOriginToTransactDispatchOrigin = ( + // If XCM origin is an NFT from a registered chain we give it NftOrigin::Nft. + pallet_nft_origins::NftMultilocationAsOrigin, + // If XCM origin is an NFT Origin verifier from a registered chain we give it NftOrigin::Verifier. + pallet_nft_origins::VerifierMultilocationAsOrigin, // Sovereign account converter; this attempts to derive an `AccountId` from the origin location // using `LocationToAccountId` and then turn that into the usual `Signed` origin. Useful for // foreign chains who want to have a local sovereign account on this chain which they control. @@ -226,7 +234,7 @@ impl xcm_executor::Config for XcmConfig { type MaxAssetsIntoHolding = ConstU32<8>; type UniversalAliases = Nothing; type CallDispatcher = RuntimeCall; - type SafeCallFilter = (); + type SafeCallFilter = Everything; } impl cumulus_pallet_xcm::Config for Runtime { @@ -334,6 +342,7 @@ pub type XcmRouter = ( /// when determining ownership of accounts for asset transacting and when attempting to use XCM /// `Transact` in order to determine the dispatch Origin. pub type LocationToAccountId = ( + HashedDescription>, // The parent (Relay-chain) origin converts to the default `AccountId`. ParentIsPreset, // Sibling parachain origins convert to AccountId via the `ParaId::into`. @@ -352,3 +361,130 @@ pub type LocalAssetTransactor = MultiCurrencyAdapter< CurrencyIdConvert, DepositToAlternative, >; + +// Temporary \/ + +use codec::Compact; +use core::marker::PhantomData; +use sp_io::hashing::blake2_256; +use sp_std::prelude::*; +use xcm_executor::traits::Convert as XcmConvert; + +/// Means of converting a location into a stable and unique descriptive identifier. +pub trait DescribeLocation { + /// Create a description of the given `location` if possible. No two locations should have the + /// same descriptor. + fn describe_location(location: &MultiLocation) -> Option>; +} + +impl + DescribeLocation for (A, B, C, D) +{ + fn describe_location(l: &MultiLocation) -> Option> { + match A::describe_location(l) { + Some(result) => Some(result), + None => match B::describe_location(l) { + Some(result) => Some(result), + None => match C::describe_location(l) { + Some(result) => Some(result), + None => match D::describe_location(l) { + Some(result) => Some(result), + None => None, + }, + }, + }, + } + } +} + +pub struct DescribeTerminus; +impl DescribeLocation for DescribeTerminus { + fn describe_location(l: &MultiLocation) -> Option> { + match (l.parents, &l.interior) { + (0, Here) => Some(Vec::new()), + _ => return None, + } + } +} + +pub struct DescribePalletTerminal; +impl DescribeLocation for DescribePalletTerminal { + fn describe_location(l: &MultiLocation) -> Option> { + match (l.parents, &l.interior) { + (0, X1(PalletInstance(i))) => { + Some((b"Pallet", Compact::::from(*i as u32)).encode()) + } + _ => return None, + } + } +} + +pub struct DescribeAccountId32Terminal; +impl DescribeLocation for DescribeAccountId32Terminal { + fn describe_location(l: &MultiLocation) -> Option> { + match (l.parents, &l.interior) { + (0, X1(AccountId32 { id, .. })) => Some((b"AccountId32", id).encode()), + _ => return None, + } + } +} + +pub struct DescribeAccountKey20Terminal; +impl DescribeLocation for DescribeAccountKey20Terminal { + fn describe_location(l: &MultiLocation) -> Option> { + match (l.parents, &l.interior) { + (0, X1(AccountKey20 { key, .. })) => Some((b"AccountKey20", key).encode()), + _ => return None, + } + } +} + +pub type DescribeAllTerminal = ( + DescribeTerminus, + DescribePalletTerminal, + DescribeAccountId32Terminal, + DescribeAccountKey20Terminal, +); + +pub struct DescribeFamily(PhantomData); +impl DescribeLocation for DescribeFamily { + fn describe_location(l: &MultiLocation) -> Option> { + match (l.parents, l.interior.first()) { + (0, Some(Parachain(index))) => { + let tail = l.interior.split_first().0; + let interior = Suffix::describe_location(&tail.into())?; + Some((b"ChildChain", Compact::::from(*index), interior).encode()) + } + (1, Some(Parachain(index))) => { + let tail = l.interior.split_first().0; + let interior = Suffix::describe_location(&tail.into())?; + Some((b"SiblingChain", Compact::::from(*index), interior).encode()) + } + (1, _) => { + let tail = l.interior.into(); + let interior = Suffix::describe_location(&tail)?; + Some((b"ParentChain", interior).encode()) + } + _ => return None, + } + } +} + +pub struct HashedDescription(PhantomData<(AccountId, Describe)>); +impl + Clone + core::fmt::Debug, Describe: DescribeLocation> + XcmConvert for HashedDescription +{ + fn convert(value: MultiLocation) -> Result { + if let Some(description) = Describe::describe_location(&value) { + log::trace!( + target: "xcm::LocationToAccountId", + "HashedDescription location: {:?}, account_id: {:?}", + value, AccountId::from(blake2_256(&description)) + ); + + Ok(blake2_256(&description).into()) + } else { + Err(value) + } + } +}