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

difftreelog

source

pallets/nft/src/eth/account.rs4.4 KiBsourcehistory
1use crate::Config;2use codec::{Encode, EncodeLike, Decode};3use scale_info::build::{FieldsBuilder, UnnamedFields, Variants};4use scale_info::{Path, Type, TypeInfo};5use sp_core::crypto::AccountId32;6use primitive_types::H160;7use core::cmp::Ordering;8use serde::{Serialize, Deserialize};9use pallet_evm::AddressMapping;10use sp_std::vec::Vec;11use sp_std::clone::Clone;1213pub trait CrossAccountId<AccountId>:14	Encode + EncodeLike + Decode + TypeInfo + Clone + PartialEq + Ord + core::fmt::Debug15// +16// Serialize + Deserialize<'static>17{18	fn as_sub(&self) -> &AccountId;19	fn as_eth(&self) -> &H160;2021	fn from_sub(account: AccountId) -> Self;22	fn from_eth(account: H160) -> Self;23}2425#[derive(Eq, Serialize, Deserialize)]26pub struct BasicCrossAccountId<T: Config> {27	/// If true - then ethereum is canonical encoding28	from_ethereum: bool,29	substrate: T::AccountId,30	ethereum: H160,31}3233impl<T: Config> TypeInfo for BasicCrossAccountId<T> {34	type Identity = Self;3536	fn type_info() -> Type {37		Type::builder()38			.path(Path::new("BasicCrossAccountId", "pallet_nft::eth::account"))39			// At runtime side this type has no type parameters, as AccountId is inlined?40			// .type_params([TypeParameter::new(41			// 	"AccountId",42			// 	Some(scale_info::meta_type::<T::AccountId>()),43			// )])44			.variant(45				Variants::new()46					.variant("Substrate", |t| {47						t.fields(48							<FieldsBuilder<UnnamedFields>>::default()49								.field(|f| f.ty::<T::AccountId>()),50						)51						.index(0)52					})53					.variant("Ethereum", |t| {54						t.fields(55							<FieldsBuilder<UnnamedFields>>::default().field(|f| f.ty::<H160>()),56						)57						.index(1)58					}),59			)60	}61}6263impl<T: Config> core::fmt::Debug for BasicCrossAccountId<T> {64	fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {65		if self.from_ethereum {66			fmt.debug_tuple("CrossAccountId::Ethereum")67				.field(&self.ethereum)68				.finish()69		} else {70			fmt.debug_tuple("CrossAccountId::Substrate")71				.field(&self.substrate)72				.finish()73		}74	}75}7677impl<T: Config> PartialOrd for BasicCrossAccountId<T> {78	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {79		Some(self.substrate.cmp(&other.substrate))80	}81}8283impl<T: Config> Ord for BasicCrossAccountId<T> {84	fn cmp(&self, other: &Self) -> Ordering {85		self.partial_cmp(other)86			.expect("substrate account is total ordered")87	}88}8990impl<T: Config> PartialEq for BasicCrossAccountId<T> {91	fn eq(&self, other: &Self) -> bool {92		if self.from_ethereum == other.from_ethereum {93			self.substrate == other.substrate && self.ethereum == other.ethereum94		} else if self.from_ethereum {95			// ethereum is canonical encoding, but we need to compare derived address96			self.substrate == other.substrate97		} else {98			self.ethereum == other.ethereum99		}100	}101}102impl<T: Config> Clone for BasicCrossAccountId<T> {103	fn clone(&self) -> Self {104		Self {105			from_ethereum: self.from_ethereum,106			substrate: self.substrate.clone(),107			ethereum: self.ethereum,108		}109	}110}111impl<T: Config> Encode for BasicCrossAccountId<T> {112	fn encode(&self) -> Vec<u8> {113		let as_result = if !self.from_ethereum {114			Ok(self.substrate.clone())115		} else {116			Err(self.ethereum)117		};118		as_result.encode()119	}120}121impl<T: Config> EncodeLike for BasicCrossAccountId<T> {}122impl<T: Config> Decode for BasicCrossAccountId<T> {123	fn decode<I>(input: &mut I) -> Result<Self, codec::Error>124	where125		I: codec::Input,126	{127		Ok(match <Result<T::AccountId, H160>>::decode(input)? {128			Ok(s) => Self::from_sub(s),129			Err(e) => Self::from_eth(e),130		})131	}132}133impl<T: Config> CrossAccountId<T::AccountId> for BasicCrossAccountId<T> {134	fn as_sub(&self) -> &T::AccountId {135		&self.substrate136	}137	fn as_eth(&self) -> &H160 {138		&self.ethereum139	}140	fn from_sub(substrate: T::AccountId) -> Self {141		Self {142			ethereum: T::EvmBackwardsAddressMapping::from_account_id(substrate.clone()),143			substrate,144			from_ethereum: false,145		}146	}147	fn from_eth(ethereum: H160) -> Self {148		Self {149			ethereum,150			substrate: T::EvmAddressMapping::into_account_id(ethereum),151			from_ethereum: true,152		}153	}154}155156pub trait EvmBackwardsAddressMapping<AccountId> {157	fn from_account_id(account_id: AccountId) -> H160;158}159160/// Should have same mapping as EnsureAddressTruncated161pub struct MapBackwardsAddressTruncated;162impl EvmBackwardsAddressMapping<AccountId32> for MapBackwardsAddressTruncated {163	fn from_account_id(account_id: AccountId32) -> H160 {164		let mut out = [0; 20];165		out.copy_from_slice(&(account_id.as_ref() as &[u8])[0..20]);166		H160(out)167	}168}