git.delta.rocks / unique-network / refs/commits / d53cfa28fa64

difftreelog

source

pallets/common/src/account.rs4.6 KiBsourcehistory
1use crate::Config;2use codec::{Encode, EncodeLike, Decode};3use sp_core::H160;4use scale_info::{Type, TypeInfo};5use core::cmp::Ordering;6use serde::{Serialize, Deserialize};7use pallet_evm::AddressMapping;8use sp_std::vec::Vec;9use sp_std::clone::Clone;10use up_evm_mapping::EvmBackwardsAddressMapping;1112pub trait CrossAccountId<AccountId>:13	Encode + EncodeLike + Decode + TypeInfo + Clone + PartialEq + Ord + core::fmt::Debug + Default14// +15// Serialize + Deserialize<'static>16{17	fn as_sub(&self) -> &AccountId;18	fn as_eth(&self) -> &H160;1920	fn from_sub(account: AccountId) -> Self;21	fn from_eth(account: H160) -> Self;2223	fn conv_eq(&self, other: &Self) -> bool;24}2526#[derive(Encode, Decode, Serialize, Deserialize, TypeInfo)]27#[serde(rename_all = "camelCase")]28enum BasicCrossAccountIdRepr<AccountId> {29	Substrate(AccountId),30	Ethereum(H160),31}3233#[derive(PartialEq, Eq)]34pub struct BasicCrossAccountId<T: Config> {35	/// If true - then ethereum is canonical encoding36	from_ethereum: bool,37	substrate: T::AccountId,38	ethereum: H160,39}4041impl<T: Config> TypeInfo for BasicCrossAccountId<T> {42	type Identity = Self;4344	fn type_info() -> Type {45		<BasicCrossAccountIdRepr<T::AccountId>>::type_info()46	}47}4849impl<T: Config> Default for BasicCrossAccountId<T> {50	fn default() -> Self {51		Self::from_sub(T::AccountId::default())52	}53}5455impl<T: Config> core::fmt::Debug for BasicCrossAccountId<T> {56	fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {57		if self.from_ethereum {58			fmt.debug_tuple("CrossAccountId::Ethereum")59				.field(&self.ethereum)60				.finish()61		} else {62			fmt.debug_tuple("CrossAccountId::Substrate")63				.field(&self.substrate)64				.finish()65		}66	}67}6869impl<T: Config> PartialOrd for BasicCrossAccountId<T> {70	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {71		Some(self.substrate.cmp(&other.substrate))72	}73}7475impl<T: Config> Ord for BasicCrossAccountId<T> {76	fn cmp(&self, other: &Self) -> Ordering {77		self.partial_cmp(other)78			.expect("substrate account is total ordered")79	}80}8182impl<T: Config> Clone for BasicCrossAccountId<T> {83	fn clone(&self) -> Self {84		Self {85			from_ethereum: self.from_ethereum,86			substrate: self.substrate.clone(),87			ethereum: self.ethereum,88		}89	}90}91impl<T: Config> Encode for BasicCrossAccountId<T> {92	fn encode(&self) -> Vec<u8> {93		BasicCrossAccountIdRepr::from(self.clone()).encode()94	}95}96impl<T: Config> EncodeLike for BasicCrossAccountId<T> {}97impl<T: Config> Decode for BasicCrossAccountId<T> {98	fn decode<I>(input: &mut I) -> Result<Self, codec::Error>99	where100		I: codec::Input,101	{102		Ok(BasicCrossAccountIdRepr::decode(input)?.into())103	}104}105impl<T> Serialize for BasicCrossAccountId<T>106where107	T: Config,108	T::AccountId: Serialize,109{110	fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>111	where112		S: serde::Serializer,113	{114		let repr = BasicCrossAccountIdRepr::from(self.clone());115		(&repr).serialize(serializer)116	}117}118impl<'de, T> Deserialize<'de> for BasicCrossAccountId<T>119where120	T: Config,121	T::AccountId: Deserialize<'de>,122{123	fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>124	where125		D: serde::Deserializer<'de>,126	{127		Ok(BasicCrossAccountIdRepr::deserialize(deserializer)?.into())128	}129}130impl<T: Config> CrossAccountId<T::AccountId> for BasicCrossAccountId<T> {131	fn as_sub(&self) -> &T::AccountId {132		&self.substrate133	}134	fn as_eth(&self) -> &H160 {135		&self.ethereum136	}137	fn from_sub(substrate: T::AccountId) -> Self {138		Self {139			ethereum: T::EvmBackwardsAddressMapping::from_account_id(substrate.clone()),140			substrate,141			from_ethereum: false,142		}143	}144	fn from_eth(ethereum: H160) -> Self {145		Self {146			ethereum,147			substrate: T::EvmAddressMapping::into_account_id(ethereum),148			from_ethereum: true,149		}150	}151	fn conv_eq(&self, other: &Self) -> bool {152		if self.from_ethereum == other.from_ethereum {153			self.substrate == other.substrate && self.ethereum == other.ethereum154		} else if self.from_ethereum {155			// ethereum is canonical encoding, but we need to compare derived address156			self.substrate == other.substrate157		} else {158			self.ethereum == other.ethereum159		}160	}161}162impl<T: Config> From<BasicCrossAccountIdRepr<T::AccountId>> for BasicCrossAccountId<T> {163	fn from(repr: BasicCrossAccountIdRepr<T::AccountId>) -> Self {164		match repr {165			BasicCrossAccountIdRepr::Substrate(s) => Self::from_sub(s),166			BasicCrossAccountIdRepr::Ethereum(e) => Self::from_eth(e),167		}168	}169}170impl<T: Config> From<BasicCrossAccountId<T>> for BasicCrossAccountIdRepr<T::AccountId> {171	fn from(v: BasicCrossAccountId<T>) -> Self {172		if v.from_ethereum {173			BasicCrossAccountIdRepr::Ethereum(*v.as_eth())174		} else {175			BasicCrossAccountIdRepr::Substrate(v.as_sub().clone())176		}177	}178}