git.delta.rocks / unique-network / refs/commits / 415e3d612ac1

difftreelog

feat eth address mapping

Yaroslav Bolyukin2021-04-30parent: #9936e25.patch.diff
in: master

5 files changed

addedpallets/nft/src/eth/account.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/nft/src/eth/account.rs
@@ -0,0 +1,135 @@
+use crate::Config;
+use codec::{Encode, EncodeLike, Decode};
+use sp_core::{H160, H256, crypto::AccountId32};
+use core::cmp::Ordering;
+#[cfg(feature = "std")]
+use serde::{Serialize, Deserialize};
+use pallet_evm::AddressMapping;
+use sp_std::vec::Vec;
+use sp_std::clone::Clone;
+
+pub trait CrossAccountId<AccountId>: 
+    Encode + EncodeLike + Decode + 
+    Clone + PartialEq + Ord + core::fmt::Debug // + 
+    // Serialize + Deserialize<'static> 
+{
+    fn as_sub(&self) -> &AccountId;
+    fn as_eth(&self) -> &H160;
+
+    fn from_sub(account: AccountId) -> Self;
+    fn from_eth(account: H160) -> Self;
+}
+
+#[derive(Eq)]
+#[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
+pub struct BasicCrossAccountId<T: Config> {
+    /// If true - then ethereum is canonical encoding
+    from_ethereum: bool,
+    substrate: T::AccountId,
+    ethereum: H160,
+}
+
+impl<T: Config> core::fmt::Debug for BasicCrossAccountId<T> {
+    fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result {
+        if self.from_ethereum {
+            fmt.debug_tuple("CrossAccountId::Ethereum")
+                .field(&self.ethereum)
+                .finish()
+        } else {
+            fmt.debug_tuple("CrossAccountId::Substrate")
+                .field(&self.substrate)
+                .finish()
+        }
+    }
+}
+
+impl<T: Config> PartialOrd for BasicCrossAccountId<T> {
+    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
+        Some(self.substrate.cmp(&other.substrate))
+    }
+}
+
+impl<T: Config> Ord for BasicCrossAccountId<T> {
+    fn cmp(&self, other: &Self) -> Ordering {
+        self.partial_cmp(other).expect("substrate account is total ordered")
+    }
+}
+
+impl<T: Config> PartialEq for BasicCrossAccountId<T> {
+    fn eq(&self, other: &Self) -> bool {
+        if self.from_ethereum == other.from_ethereum {
+            self.substrate == other.substrate && self.ethereum == other.ethereum
+        } else if self.from_ethereum {
+            // ethereum is canonical encoding, but we need to compare derived address
+            self.substrate == other.substrate
+        } else {
+            self.ethereum == other.ethereum
+        }
+    }
+}
+impl<T: Config> Clone for BasicCrossAccountId<T> {
+    fn clone(&self) -> Self {
+        Self {
+            from_ethereum: self.from_ethereum,
+            substrate: self.substrate.clone(),
+            ethereum: self.ethereum,
+        }
+    }
+}
+impl<T: Config> Encode for BasicCrossAccountId<T> {
+    fn encode(&self) -> Vec<u8> {
+        let as_result = if !self.from_ethereum {
+            Ok(self.substrate.clone())
+        } else {
+            Err(self.ethereum)
+        };
+        as_result.encode()
+    }
+}
+impl<T: Config> EncodeLike for BasicCrossAccountId<T> {}
+impl<T: Config> Decode for BasicCrossAccountId<T> {
+    fn decode<I>(input: &mut I) -> Result<Self, codec::Error>
+        where I: codec::Input
+    {
+        Ok(match <Result<T::AccountId, H160>>::decode(input)? {
+            Ok(s) => Self::from_sub(s),
+            Err(e) => Self::from_eth(e),
+        })
+    }
+}
+impl<T: Config> CrossAccountId<T::AccountId> for BasicCrossAccountId<T> {
+    fn as_sub(&self) -> &T::AccountId {
+        &self.substrate
+    }
+    fn as_eth(&self) -> &H160 {
+        &self.ethereum
+    }
+    fn from_sub(substrate: T::AccountId) -> Self {
+        Self {
+            ethereum: T::EvmBackwardsAddressMapping::from_account_id(substrate.clone()),
+            substrate,
+            from_ethereum: false,
+        }
+    }
+    fn from_eth(ethereum: H160) -> Self {
+        Self {
+            ethereum,
+            substrate: T::EvmAddressMapping::into_account_id(ethereum),
+            from_ethereum: true,
+        }
+    }
+}
+
+pub trait EvmBackwardsAddressMapping<AccountId> {
+    fn from_account_id(account_id: AccountId) -> H160;
+}
+
+/// Should have same mapping as EnsureAddressTruncated
+pub struct MapBackwardsAddressTruncated;
+impl EvmBackwardsAddressMapping<AccountId32> for MapBackwardsAddressTruncated {
+    fn from_account_id(account_id: AccountId32) -> H160 {
+        let mut out = [0; 20];
+        out.copy_from_slice(&(account_id.as_ref() as &[u8])[0..20]);
+        H160(out)
+    }
+}
\ No newline at end of file
addedpallets/nft/src/eth/mod.rsdiffbeforeafterboth
--- /dev/null
+++ b/pallets/nft/src/eth/mod.rs
@@ -0,0 +1,2 @@
+pub mod account;
+use account::CrossAccountId;
modifiedpallets/nft/src/lib.rsdiffbeforeafterboth
--- a/pallets/nft/src/lib.rs
+++ b/pallets/nft/src/lib.rs
@@ -8,9 +8,6 @@
 #![cfg_attr(not(feature = "std"), no_std)]
 
 #[cfg(feature = "std")]
-pub use std::*;
-
-#[cfg(feature = "std")]
 pub use serde::*;
 
 use core::ops::{Deref, DerefMut};
@@ -33,6 +30,7 @@
 };
 
 use frame_system::{self as system, ensure_signed, ensure_root};
+use sp_core::{H160, H256};
 use sp_runtime::sp_std::prelude::Vec;
 use sp_runtime::{
     traits::{
@@ -45,6 +43,7 @@
 };
 use sp_runtime::traits::StaticLookup;
 use pallet_contracts::chain_extension::UncheckedFrom;
+use pallet_evm::AddressMapping;
 use pallet_transaction_payment::OnChargeTransaction;
 
 #[cfg(test)]
@@ -54,6 +53,9 @@
 mod tests;
 
 mod default_weights;
+mod eth;
+
+pub use eth::account::*;
 
 pub const MAX_DECIMAL_POINTS: DecimalPoints = 30;
 pub const MAX_REFUNGIBLE_PIECES: u128 = 1_000_000_000_000_000_000_000;
@@ -164,7 +166,7 @@
 #[derive(Encode, Decode, Clone, PartialEq)]
 #[cfg_attr(feature = "std", derive(Serialize, Deserialize))]
 pub struct Collection<T: Config> {
-    pub owner: T::AccountId,
+    pub owner: T::CrossAccountId,
     pub mode: CollectionMode,
     pub access: AccessMode,
     pub decimal_points: DecimalPoints,
@@ -174,7 +176,7 @@
     pub mint_mode: bool,
     pub offchain_schema: Vec<u8>,
     pub schema_version: SchemaVersion,
-    pub sponsorship: SponsorshipState<T::AccountId>,
+    pub sponsorship: SponsorshipState<T::CrossAccountId>,
     pub limits: CollectionLimits<T::BlockNumber>, // Collection private restrictions 
     pub variable_on_chain_schema: Vec<u8>, //
     pub const_on_chain_schema: Vec<u8>, //
@@ -461,6 +463,11 @@
     /// Weight information for extrinsics in this pallet.
 	type WeightInfo: WeightInfo;
 
+    type EvmAddressMapping: pallet_evm::AddressMapping<Self::AccountId>;
+    type EvmBackwardsAddressMapping: EvmBackwardsAddressMapping<Self::AccountId>;
+    type EvmWithdrawOrigin: pallet_evm::EnsureAddressOrigin<Self::Origin, Success = Self::AccountId>;
+
+	type CrossAccountId: CrossAccountId<Self::AccountId>;
     type Currency: Currency<Self::AccountId>;
     type CollectionCreationPrice: Get<<<Self as Config>::Currency as Currency<Self::AccountId>>::Balance>;
     type TreasuryAccountId: Get<Self::AccountId>;
@@ -525,7 +532,7 @@
         pub CollectionById get(fn collection_id) config(): map hasher(blake2_128_concat) CollectionId => Option<Collection<T>> = None;
         /// List of collection admins
         /// Collection id (controlled?2)
-        pub AdminList get(fn admin_list_collection): map hasher(blake2_128_concat) CollectionId => Vec<T::AccountId>;
+        pub AdminList get(fn admin_list_collection): map hasher(blake2_128_concat) CollectionId => Vec<T::CrossAccountId>;
         /// Whitelisted collection users
         /// Collection id (controlled?2), user id (controlled?3)
         pub WhiteList get(fn white_list): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) T::AccountId => bool;
@@ -542,11 +549,11 @@
 
         //#region Item collections
         /// Collection id (controlled?2), token id (controlled?1)
-        pub NftItemList get(fn nft_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<NftItemType<T::AccountId>>;
+        pub NftItemList get(fn nft_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<NftItemType<T::CrossAccountId>>;
         /// Collection id (controlled?2), owner (controlled?2)
         pub FungibleItemList get(fn fungible_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) T::AccountId => FungibleItemType;
         /// Collection id (controlled?2), token id (controlled?1)
-        pub ReFungibleItemList get(fn refungible_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<ReFungibleItemType<T::AccountId>>;
+        pub ReFungibleItemList get(fn refungible_item_id) config(): double_map hasher(blake2_128_concat) CollectionId, hasher(blake2_128_concat) TokenId => Option<ReFungibleItemType<T::CrossAccountId>>;
         //#endregion
 
         //#region Index list
@@ -610,7 +617,7 @@
 decl_event!(
     pub enum Event<T>
     where
-        AccountId = <T as system::Config>::AccountId,
+        CrossAccountId = <T as Config>::CrossAccountId,
     {
         /// New collection was created
         /// 
@@ -621,7 +628,7 @@
         /// * mode: [CollectionMode] converted into u8.
         /// 
         /// * account_id: Collection owner.
-        CollectionCreated(CollectionId, u8, AccountId),
+        CollectionCreated(CollectionId, u8, CrossAccountId),
 
         /// New item was created.
         /// 
@@ -632,7 +639,7 @@
         /// * item_id: Id of an item. Unique within the collection.
         ///
         /// * recipient: Owner of newly created item 
-        ItemCreated(CollectionId, TokenId, AccountId),
+        ItemCreated(CollectionId, TokenId, CrossAccountId),
 
         /// Collection item was burned.
         /// 
@@ -654,7 +661,7 @@
         /// * recipient: New owner of item
         ///
         /// * amount: Always 1 for NFT
-        Transfer(CollectionId, TokenId, AccountId, AccountId, u128),
+        Transfer(CollectionId, TokenId, CrossAccountId, CrossAccountId, u128),
 
         /// * collection_id
         ///
@@ -665,7 +672,7 @@
         /// * spender
         ///
         /// * amount
-        Approved(CollectionId, TokenId, AccountId, AccountId, u128),
+        Approved(CollectionId, TokenId, CrossAccountId, CrossAccountId, u128),
     }
 );
 
modifiedruntime/src/lib.rsdiffbeforeafterboth
579 type Event = Event;579 type Event = Event;
580 type WeightInfo = nft_weights::WeightInfo;580 type WeightInfo = nft_weights::WeightInfo;
581
582 type EvmWithdrawOrigin = EnsureAddressTruncated;
583 type EvmBackwardsAddressMapping = pallet_nft::MapBackwardsAddressTruncated;
584 type EvmAddressMapping = HashedAddressMapping<Self::Hashing>;
585 type CrossAccountId = pallet_nft::BasicCrossAccountId<Self>;
586
581 type Currency = Balances;587 type Currency = Balances;
582 type CollectionCreationPrice = CollectionCreationPrice;588 type CollectionCreationPrice = CollectionCreationPrice;
modifiedruntime_types.jsondiffbeforeafterboth
--- a/runtime_types.json
+++ b/runtime_types.json
@@ -1,4 +1,10 @@
 {
+    "CrossAccountId": {
+      "_enum": {
+        "substrate": "AccountId",
+        "ethereum": "H160"
+      }
+    },
     "AccessMode": {
       "_enum": [
         "Normal",
@@ -15,31 +21,31 @@
       }
     },
     "Ownership": {
-      "Owner": "AccountId",
+      "Owner": "CrossAccountId",
       "Fraction": "u128"
     },
     "FungibleItemType": {
       "Value": "u128"
     },
     "NftItemType": {
-      "Owner": "AccountId",
+      "Owner": "CrossAccountId",
       "ConstData": "Vec<u8>",
       "VariableData": "Vec<u8>"
     },
     "ReFungibleItemType": {
-      "Owner": "Vec<Ownership<AccountId>>",
+      "Owner": "Vec<Ownership<CrossAccountId>>",
       "ConstData": "Vec<u8>",
       "VariableData": "Vec<u8>"
     },
     "SponsorshipState": {
       "_enum": {
-        "Disabled": null,
-        "Unconfirmed": "AccountId",
-        "Confirmed": "AccountId"
+        "disabled": null,
+        "unconfirmed": "CrossAccountId",
+        "confirmed": "CrossAccountId"
       }
     },
     "Collection": {
-      "Owner": "AccountId",
+      "Owner": "CrossAccountId",
       "Mode": "CollectionMode",
       "Access": "AccessMode",
       "DecimalPoints": "DecimalPoints",