From 8641e0b6795524351eaa26ad2dd7ba77c8892639 Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Thu, 12 Dec 2024 15:29:37 +0000 Subject: [PATCH 01/28] using single storage unbounded instead of pallet::without_storage_info --- parachain/pallets/omni-account/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parachain/pallets/omni-account/src/lib.rs b/parachain/pallets/omni-account/src/lib.rs index 5e55ec4b0f..2cb0aad7db 100644 --- a/parachain/pallets/omni-account/src/lib.rs +++ b/parachain/pallets/omni-account/src/lib.rs @@ -66,7 +66,6 @@ pub mod pallet { #[pallet::pallet] #[pallet::storage_version(STORAGE_VERSION)] - #[pallet::without_storage_info] pub struct Pallet(_); #[pallet::config] @@ -113,6 +112,7 @@ pub mod pallet { /// A map between OmniAccount and its MemberAccounts (a bounded vector of MemberAccount) #[pallet::storage] + #[pallet::unbounded] #[pallet::getter(fn account_store)] pub type AccountStore = StorageMap>; From ce5ab39349706862c51a7ec988c1e060d2ecaefb Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Thu, 12 Dec 2024 15:36:14 +0000 Subject: [PATCH 02/28] adding integrity_test hook --- parachain/pallets/omni-account/src/lib.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/parachain/pallets/omni-account/src/lib.rs b/parachain/pallets/omni-account/src/lib.rs index 2cb0aad7db..8ac7092df9 100644 --- a/parachain/pallets/omni-account/src/lib.rs +++ b/parachain/pallets/omni-account/src/lib.rs @@ -103,6 +103,15 @@ pub mod pallet { /// Convert an `Identity` to OmniAccount type type OmniAccountConverter: OmniAccountConverter; + + #[pallet::hooks] + impl Hooks> for Pallet { + fn integrity_test() { + assert!( + ::MaxAccountStoreLength::get() > 0, + "MaxAccountStoreLength must be greater than 0" + ); + } } pub type MemberAccounts = BoundedVec::MaxAccountStoreLength>; From 3758f5df85ec10b4c5670bbc90aa5447adb60a43 Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Thu, 12 Dec 2024 15:37:52 +0000 Subject: [PATCH 03/28] adding new types to the pallet config --- parachain/pallets/omni-account/src/lib.rs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/parachain/pallets/omni-account/src/lib.rs b/parachain/pallets/omni-account/src/lib.rs index 8ac7092df9..ae4b0f95b2 100644 --- a/parachain/pallets/omni-account/src/lib.rs +++ b/parachain/pallets/omni-account/src/lib.rs @@ -28,7 +28,7 @@ pub use pallet::*; use frame_support::pallet_prelude::*; use frame_support::{ dispatch::{GetDispatchInfo, PostDispatchInfo}, - traits::{IsSubType, UnfilteredDispatchable}, + traits::{InstanceFilter, IsSubType, UnfilteredDispatchable}, }; use frame_system::pallet_prelude::*; use sp_core::H256; @@ -104,6 +104,20 @@ pub mod pallet { /// Convert an `Identity` to OmniAccount type type OmniAccountConverter: OmniAccountConverter; + /// The permissions that a member account can have + type Permission: Parameter + + Member + + Ord + + PartialOrd + + Default + + InstanceFilter<::RuntimeCall> + + MaxEncodedLen; + + /// The maximum number of permissions that a member account can have + #[pallet::constant] + type MaxPermissions: Get; + } + #[pallet::hooks] impl Hooks> for Pallet { fn integrity_test() { @@ -111,6 +125,10 @@ pub mod pallet { ::MaxAccountStoreLength::get() > 0, "MaxAccountStoreLength must be greater than 0" ); + assert!( + ::MaxPermissions::get() > 0, + "MaxPermissions must be greater than 0" + ); } } From 110c330b22ecd730726e195e62521ceb3ef9d318 Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Thu, 12 Dec 2024 15:38:34 +0000 Subject: [PATCH 04/28] adding storage item for account member permissions --- parachain/pallets/omni-account/src/lib.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/parachain/pallets/omni-account/src/lib.rs b/parachain/pallets/omni-account/src/lib.rs index ae4b0f95b2..b53b63083f 100644 --- a/parachain/pallets/omni-account/src/lib.rs +++ b/parachain/pallets/omni-account/src/lib.rs @@ -149,6 +149,14 @@ pub mod pallet { pub type MemberAccountHash = StorageMap; + /// A map between hash of MemberAccount and its permissions + #[pallet::storage] + pub type MemberAccountPermissions = StorageMap< + Hasher = Blake2_128Concat, + Key = H256, + Value = BoundedVec, + >; + #[pallet::event] #[pallet::generate_deposit(pub(super) fn deposit_event)] pub enum Event { From c8adeac6719ce1e0012c47073d65641e421deb51 Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Thu, 12 Dec 2024 15:39:00 +0000 Subject: [PATCH 05/28] adding new errors --- parachain/pallets/omni-account/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/parachain/pallets/omni-account/src/lib.rs b/parachain/pallets/omni-account/src/lib.rs index b53b63083f..df595fd2ab 100644 --- a/parachain/pallets/omni-account/src/lib.rs +++ b/parachain/pallets/omni-account/src/lib.rs @@ -188,6 +188,8 @@ pub mod pallet { InvalidAccount, UnknownAccountStore, EmptyAccount, + NoPermission, + PermissionsLenLimitReached, } #[pallet::call] From 38f3a1feceee4f69004ce62c37132b176c8c343e Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Thu, 12 Dec 2024 15:40:34 +0000 Subject: [PATCH 06/28] storing default permission on create_account_store --- parachain/pallets/omni-account/src/lib.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/parachain/pallets/omni-account/src/lib.rs b/parachain/pallets/omni-account/src/lib.rs index df595fd2ab..25665f6b56 100644 --- a/parachain/pallets/omni-account/src/lib.rs +++ b/parachain/pallets/omni-account/src/lib.rs @@ -425,6 +425,12 @@ pub mod pallet { MemberAccountHash::::insert(hash, omni_account.clone()); AccountStore::::insert(omni_account.clone(), member_accounts.clone()); + let mut permissions = BoundedVec::::new(); + permissions + .try_push(T::Permission::default()) + .map_err(|_| Error::::PermissionsLenLimitReached)?; + MemberAccountPermissions::::insert(hash, permissions); + Self::deposit_event(Event::AccountStoreCreated { who: omni_account.clone() }); Self::deposit_event(Event::AccountStoreUpdated { who: omni_account, From c06f4469a0195d64cb5a02b80cbc4682562100e8 Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Thu, 12 Dec 2024 16:18:13 +0000 Subject: [PATCH 07/28] adding comments --- parachain/pallets/omni-account/src/lib.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/parachain/pallets/omni-account/src/lib.rs b/parachain/pallets/omni-account/src/lib.rs index 25665f6b56..17db667d20 100644 --- a/parachain/pallets/omni-account/src/lib.rs +++ b/parachain/pallets/omni-account/src/lib.rs @@ -105,6 +105,9 @@ pub mod pallet { type OmniAccountConverter: OmniAccountConverter; /// The permissions that a member account can have + /// The instance filter determines whether a given call may can be dispatched under this type. + /// + /// IMPORTANT: `Default` must be provided and MUST BE the the *most permissive* value. type Permission: Parameter + Member + Ord From 8d6018b87f3efe15c629734da3fe3f654b9ba913 Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Thu, 12 Dec 2024 16:18:49 +0000 Subject: [PATCH 08/28] adding default permissions --- parachain/pallets/omni-account/src/lib.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/parachain/pallets/omni-account/src/lib.rs b/parachain/pallets/omni-account/src/lib.rs index 17db667d20..03dcdb090d 100644 --- a/parachain/pallets/omni-account/src/lib.rs +++ b/parachain/pallets/omni-account/src/lib.rs @@ -34,7 +34,7 @@ use frame_system::pallet_prelude::*; use sp_core::H256; use sp_runtime::traits::Dispatchable; use sp_std::boxed::Box; -use sp_std::vec::Vec; +use sp_std::{vec, vec::Vec}; pub type MemberCount = u32; @@ -152,12 +152,19 @@ pub mod pallet { pub type MemberAccountHash = StorageMap; + #[pallet::type_value] + pub fn DefaultPermissions() -> BoundedVec { + BoundedVec::try_from(vec![T::Permission::default()]).expect("default permission") + } + /// A map between hash of MemberAccount and its permissions #[pallet::storage] pub type MemberAccountPermissions = StorageMap< Hasher = Blake2_128Concat, Key = H256, Value = BoundedVec, + QueryKind = ValueQuery, + OnEmpty = DefaultPermissions, >; #[pallet::event] From 0aeebe3ecc5e21d68b0c0d8fd6dcabc6bee9b70f Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Thu, 12 Dec 2024 16:19:57 +0000 Subject: [PATCH 09/28] small refactoring --- parachain/pallets/omni-account/src/lib.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/parachain/pallets/omni-account/src/lib.rs b/parachain/pallets/omni-account/src/lib.rs index 03dcdb090d..bc0ba70516 100644 --- a/parachain/pallets/omni-account/src/lib.rs +++ b/parachain/pallets/omni-account/src/lib.rs @@ -431,15 +431,14 @@ pub mod pallet { member_accounts .try_push(identity.into()) .map_err(|_| Error::::AccountStoreLenLimitReached)?; - - MemberAccountHash::::insert(hash, omni_account.clone()); - AccountStore::::insert(omni_account.clone(), member_accounts.clone()); - let mut permissions = BoundedVec::::new(); permissions .try_push(T::Permission::default()) .map_err(|_| Error::::PermissionsLenLimitReached)?; + + MemberAccountHash::::insert(hash, omni_account.clone()); MemberAccountPermissions::::insert(hash, permissions); + AccountStore::::insert(omni_account.clone(), member_accounts.clone()); Self::deposit_event(Event::AccountStoreCreated { who: omni_account.clone() }); Self::deposit_event(Event::AccountStoreUpdated { From b584d839bfa48cf5848e1630c6bf73d94c8c9818 Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Thu, 12 Dec 2024 16:20:47 +0000 Subject: [PATCH 10/28] implementing ensure_permission --- parachain/pallets/omni-account/src/lib.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/parachain/pallets/omni-account/src/lib.rs b/parachain/pallets/omni-account/src/lib.rs index bc0ba70516..242ee5f263 100644 --- a/parachain/pallets/omni-account/src/lib.rs +++ b/parachain/pallets/omni-account/src/lib.rs @@ -215,6 +215,7 @@ pub mod pallet { let _ = T::TEECallOrigin::ensure_origin(origin)?; let omni_account = MemberAccountHash::::get(member_account_hash) .ok_or(Error::::AccountNotFound)?; + Self::ensure_permission(call.as_ref(), member_account_hash)?; let result = call.dispatch(RawOrigin::OmniAccount(omni_account.clone()).into()); system::Pallet::::inc_account_nonce(&omni_account); Self::deposit_event(Event::DispatchedAsOmniAccount { @@ -236,6 +237,7 @@ pub mod pallet { let _ = T::TEECallOrigin::ensure_origin(origin)?; let omni_account = MemberAccountHash::::get(member_account_hash) .ok_or(Error::::AccountNotFound)?; + Self::ensure_permission(call.as_ref(), member_account_hash)?; let result: Result< PostDispatchInfo, sp_runtime::DispatchErrorWithPostInfo, @@ -448,6 +450,19 @@ pub mod pallet { Ok(member_accounts) } + + fn ensure_permission( + call: &::RuntimeCall, + member_account_hash: H256, + ) -> Result<(), Error> { + let permissions = MemberAccountPermissions::::get(member_account_hash); + ensure!( + permissions.iter().any(|permission| permission.filter(call)), + Error::::NoPermission + ); + + Ok(()) + } } } From 959c83d19198a6a583b759e8038c410821b90d41 Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Thu, 12 Dec 2024 16:21:14 +0000 Subject: [PATCH 11/28] updating mock --- parachain/pallets/omni-account/src/mock.rs | 60 +++++++++++++++++++++- 1 file changed, 58 insertions(+), 2 deletions(-) diff --git a/parachain/pallets/omni-account/src/mock.rs b/parachain/pallets/omni-account/src/mock.rs index b7ab3f457c..3338da7ef7 100644 --- a/parachain/pallets/omni-account/src/mock.rs +++ b/parachain/pallets/omni-account/src/mock.rs @@ -14,17 +14,18 @@ // You should have received a copy of the GNU General Public License // along with Litentry. If not, see . -use crate::{self as pallet_omni_account, Encode, EnsureOmniAccount}; +use crate::{self as pallet_omni_account, Decode, Encode, EnsureOmniAccount, MaxEncodedLen}; use core_primitives::{DefaultOmniAccountConverter, Identity, MemberAccount}; use frame_support::{ assert_ok, derive_impl, pallet_prelude::EnsureOrigin, parameter_types, - traits::{ConstU32, ConstU64}, + traits::{ConstU32, ConstU64, InstanceFilter}, }; use frame_system::EnsureRoot; pub use pallet_teebag::test_util::get_signer; use pallet_teebag::test_util::{TEST8_CERT, TEST8_SIGNER_PUB, TEST8_TIMESTAMP, URL}; +use sp_core::RuntimeDebug; use sp_keyring::AccountKeyring; use sp_runtime::{ traits::{IdentifyAccount, IdentityLookup, Verify}, @@ -158,6 +159,59 @@ impl pallet_teebag::Config for Test { type WeightInfo = (); } +#[derive( + Copy, + Clone, + PartialEq, + Eq, + Ord, + PartialOrd, + Encode, + Decode, + RuntimeDebug, + MaxEncodedLen, + scale_info::TypeInfo, +)] +pub enum Permission { + All, + Balances, + RemoveAccount, + RequestEthereumIntent, +} + +impl Default for Permission { + fn default() -> Self { + Self::All + } +} + +impl InstanceFilter for Permission { + fn filter(&self, call: &RuntimeCall) -> bool { + match self { + Permission::All => true, + Permission::Balances => matches!(call, RuntimeCall::Balances { .. }), + Permission::RemoveAccount => matches!( + call, + RuntimeCall::OmniAccount(pallet_omni_account::Call::remove_accounts { .. }) + ), + Permission::RequestEthereumIntent => { + if let RuntimeCall::OmniAccount(pallet_omni_account::Call::request_intent { + intent, + }) = call + { + matches!( + intent, + pallet_omni_account::Intent::TransferEthereum(_) + | pallet_omni_account::Intent::CallEthereum(_) + ) + } else { + false + } + }, + } + } +} + impl pallet_omni_account::Config for Test { type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; @@ -166,6 +220,8 @@ impl pallet_omni_account::Config for Test { type MaxAccountStoreLength = ConstU32<3>; type OmniAccountOrigin = EnsureOmniAccount; type OmniAccountConverter = DefaultOmniAccountConverter; + type MaxPermissions = ConstU32<3>; + type Permission = Permission; } pub fn get_tee_signer() -> SystemAccountId { From 5cb8eed8a9479b7ef43ccc4bf3c92aa9c04140de Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Thu, 12 Dec 2024 16:57:38 +0000 Subject: [PATCH 12/28] adding optional permissions to add_account, set defaults if None --- parachain/pallets/omni-account/src/lib.rs | 11 ++++++++++- parachain/pallets/omni-account/src/tests.rs | 19 ++++++++++++++++--- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/parachain/pallets/omni-account/src/lib.rs b/parachain/pallets/omni-account/src/lib.rs index 242ee5f263..e278a6b204 100644 --- a/parachain/pallets/omni-account/src/lib.rs +++ b/parachain/pallets/omni-account/src/lib.rs @@ -266,7 +266,8 @@ pub mod pallet { #[pallet::weight((195_000_000, DispatchClass::Normal))] pub fn add_account( origin: OriginFor, - member_account: MemberAccount, // account to be added + member_account: MemberAccount, // account to be added + permissions: Option>, // permissions for the account ) -> DispatchResult { // mutation of AccountStore requires `OmniAccountOrigin`, same as "remove" and "publicize" let who = T::OmniAccountOrigin::ensure_origin(origin)?; @@ -282,8 +283,16 @@ pub mod pallet { member_accounts .try_push(member_account) .map_err(|_| Error::::AccountStoreLenLimitReached)?; + let member_permissions: BoundedVec = { + let p = match permissions { + Some(p) => p, + None => vec![T::Permission::default()], + }; + p.try_into().map_err(|_| Error::::PermissionsLenLimitReached)? + }; MemberAccountHash::::insert(hash, who.clone()); + MemberAccountPermissions::::insert(hash, member_permissions); AccountStore::::insert(who.clone(), member_accounts.clone()); Self::deposit_event(Event::AccountAdded { diff --git a/parachain/pallets/omni-account/src/tests.rs b/parachain/pallets/omni-account/src/tests.rs index bddfa5e51b..7c0c4d92ff 100644 --- a/parachain/pallets/omni-account/src/tests.rs +++ b/parachain/pallets/omni-account/src/tests.rs @@ -23,7 +23,10 @@ use sp_runtime::{traits::BadOrigin, ModuleError}; use sp_std::vec; fn add_account_call(account: MemberAccount) -> Box { - let call = RuntimeCall::OmniAccount(crate::Call::add_account { member_account: account }); + let call = RuntimeCall::OmniAccount(crate::Call::add_account { + member_account: account, + permissions: None, + }); Box::new(call) } @@ -163,6 +166,16 @@ fn add_account_works() { assert!(MemberAccountHash::::contains_key(bob.hash())); assert!(MemberAccountHash::::contains_key(charlie.hash())); + assert!(MemberAccountPermissions::::contains_key(bob.hash())); + assert_eq!( + MemberAccountPermissions::::get(bob.hash()).to_vec(), + vec![Permission::All] + ); + assert!(MemberAccountPermissions::::contains_key(charlie.hash())); + assert_eq!( + MemberAccountPermissions::::get(charlie.hash()).to_vec(), + vec![Permission::All] + ); }); } @@ -173,12 +186,12 @@ fn add_account_origin_check_works() { let bob = private_member_account(bob()); assert_noop!( - OmniAccount::add_account(RuntimeOrigin::signed(tee_signer), bob.clone()), + OmniAccount::add_account(RuntimeOrigin::signed(tee_signer), bob.clone(), None), BadOrigin ); assert_noop!( - OmniAccount::add_account(RuntimeOrigin::signed(alice().omni_account), bob), + OmniAccount::add_account(RuntimeOrigin::signed(alice().omni_account), bob, None), BadOrigin ); }); From 7b619e2e93c901e55e4bcc2f9768dec26be05008 Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Fri, 13 Dec 2024 09:59:07 +0000 Subject: [PATCH 13/28] setting permissions on update_account_store_by_one --- parachain/pallets/omni-account/src/lib.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/parachain/pallets/omni-account/src/lib.rs b/parachain/pallets/omni-account/src/lib.rs index e278a6b204..ab1f8f3b2a 100644 --- a/parachain/pallets/omni-account/src/lib.rs +++ b/parachain/pallets/omni-account/src/lib.rs @@ -394,8 +394,13 @@ pub mod pallet { .try_push(member_account.clone()) .map_err(|_| Error::::AccountStoreLenLimitReached)?; } + let mut permissions = BoundedVec::::new(); + permissions + .try_push(T::Permission::default()) + .map_err(|_| Error::::PermissionsLenLimitReached)?; MemberAccountHash::::insert(member_account.hash(), who_account.clone()); + MemberAccountPermissions::::insert(member_account.hash(), permissions); AccountStore::::insert(who_account.clone(), member_accounts.clone()); Self::deposit_event(Event::AccountStoreUpdated { who: who_account, From 6200570609d746cdb1222a9ada637fbf0b5bbb70 Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Fri, 13 Dec 2024 11:52:13 +0000 Subject: [PATCH 14/28] improving ensure_permission --- parachain/pallets/omni-account/src/lib.rs | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/parachain/pallets/omni-account/src/lib.rs b/parachain/pallets/omni-account/src/lib.rs index ab1f8f3b2a..9a045ace99 100644 --- a/parachain/pallets/omni-account/src/lib.rs +++ b/parachain/pallets/omni-account/src/lib.rs @@ -469,12 +469,30 @@ pub mod pallet { call: &::RuntimeCall, member_account_hash: H256, ) -> Result<(), Error> { - let permissions = MemberAccountPermissions::::get(member_account_hash); + let member_permissions = MemberAccountPermissions::::get(member_account_hash); + ensure!( - permissions.iter().any(|permission| permission.filter(call)), + member_permissions.iter().any(|permission| permission.filter(call)), Error::::NoPermission ); + if let Some(Call::add_account { permissions: ref new_account_permissions, .. }) = + call.is_sub_type() + { + // If member has default permission, they can add accounts with any permission + if member_permissions.contains(&T::Permission::default()) { + return Ok(()); + } + + if let Some(new_account_permissions) = new_account_permissions { + // an account can only add another account with the same or less permissions + ensure!( + new_account_permissions.iter().all(|p| member_permissions.contains(p)), + Error::::NoPermission + ) + } + } + Ok(()) } } From d76187c4ee63841f17d9225992e5497400f344cf Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Fri, 13 Dec 2024 11:53:43 +0000 Subject: [PATCH 15/28] updating mock --- parachain/pallets/omni-account/src/mock.rs | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/parachain/pallets/omni-account/src/mock.rs b/parachain/pallets/omni-account/src/mock.rs index 3338da7ef7..ad464295c6 100644 --- a/parachain/pallets/omni-account/src/mock.rs +++ b/parachain/pallets/omni-account/src/mock.rs @@ -97,6 +97,10 @@ pub fn charlie() -> Accounts { create_accounts(AccountKeyring::Charlie) } +pub fn dave() -> Accounts { + create_accounts(AccountKeyring::Dave) +} + pub fn public_member_account(accounts: Accounts) -> MemberAccount { MemberAccount::Public(accounts.identity) } @@ -175,7 +179,8 @@ impl pallet_teebag::Config for Test { pub enum Permission { All, Balances, - RemoveAccount, + AddAccounts, + RemoveAccounts, RequestEthereumIntent, } @@ -190,10 +195,14 @@ impl InstanceFilter for Permission { match self { Permission::All => true, Permission::Balances => matches!(call, RuntimeCall::Balances { .. }), - Permission::RemoveAccount => matches!( + Permission::RemoveAccounts => matches!( call, RuntimeCall::OmniAccount(pallet_omni_account::Call::remove_accounts { .. }) ), + Permission::AddAccounts => matches!( + call, + RuntimeCall::OmniAccount(pallet_omni_account::Call::add_account { .. }) + ), Permission::RequestEthereumIntent => { if let RuntimeCall::OmniAccount(pallet_omni_account::Call::request_intent { intent, From d8cfd2c71f18ab40417bf429b03aa65d75e18dc8 Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Fri, 13 Dec 2024 11:54:44 +0000 Subject: [PATCH 16/28] refactoring add_account_call util --- parachain/pallets/omni-account/src/tests.rs | 43 +++++++++++---------- 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/parachain/pallets/omni-account/src/tests.rs b/parachain/pallets/omni-account/src/tests.rs index 7c0c4d92ff..f09afd9f56 100644 --- a/parachain/pallets/omni-account/src/tests.rs +++ b/parachain/pallets/omni-account/src/tests.rs @@ -22,11 +22,12 @@ use sp_core::H160; use sp_runtime::{traits::BadOrigin, ModuleError}; use sp_std::vec; -fn add_account_call(account: MemberAccount) -> Box { - let call = RuntimeCall::OmniAccount(crate::Call::add_account { - member_account: account, - permissions: None, - }); +fn add_account_call>( + account: MemberAccount, + permissions: Option::Permission>>, +) -> Box { + let call = + RuntimeCall::OmniAccount(crate::Call::add_account { member_account: account, permissions }); Box::new(call) } @@ -84,7 +85,7 @@ fn create_account_store_works() { fn add_account_without_creating_store_fails() { new_test_ext().execute_with(|| { let tee_signer = get_tee_signer(); - let call = add_account_call(private_member_account(bob())); + let call = add_account_call::(private_member_account(bob()), None); assert_noop!( OmniAccount::dispatch_as_omni_account( @@ -113,7 +114,7 @@ fn add_account_works() { alice().identity, )); - let call = add_account_call(bob.clone()); + let call = add_account_call::(bob.clone(), None); assert_ok!(OmniAccount::dispatch_as_omni_account( RuntimeOrigin::signed(tee_signer.clone()), alice().identity.hash(), @@ -140,7 +141,7 @@ fn add_account_works() { expected_member_accounts ); - let call = add_account_call(charlie.clone()); + let call = add_account_call::(charlie.clone(), None); assert_ok!(OmniAccount::dispatch_as_omni_account( RuntimeOrigin::signed(tee_signer.clone()), alice().identity.hash(), @@ -208,7 +209,7 @@ fn add_account_with_already_linked_account_fails() { alice().identity.clone(), )); - let call = add_account_call(bob.clone()); + let call = add_account_call::(bob.clone(), None); assert_ok!(OmniAccount::dispatch_as_omni_account( RuntimeOrigin::signed(tee_signer.clone()), alice().identity.hash(), @@ -239,7 +240,7 @@ fn add_account_with_already_linked_account_fails() { charlie().identity, )); - let call = add_account_call(public_member_account(alice())); + let call = add_account_call::(public_member_account(alice()), None); assert_ok!(OmniAccount::dispatch_as_omni_account( RuntimeOrigin::signed(tee_signer.clone()), charlie().identity.hash(), @@ -280,10 +281,10 @@ fn add_account_store_len_limit_reached_works() { AccountStore::::insert(alice().omni_account, member_accounts); - let call = add_account_call(MemberAccount::Private( - vec![7, 8, 9], - H256::from(blake2_256(&[7, 8, 9])), - )); + let call = add_account_call::( + MemberAccount::Private(vec![7, 8, 9], H256::from(blake2_256(&[7, 8, 9]))), + None, + ); assert_ok!(OmniAccount::dispatch_as_omni_account( RuntimeOrigin::signed(tee_signer.clone()), @@ -316,7 +317,7 @@ fn remove_account_works() { alice().identity, )); - let call = add_account_call(bob.clone()); + let call = add_account_call::(bob.clone(), None); assert_ok!(OmniAccount::dispatch_as_omni_account( RuntimeOrigin::signed(tee_signer.clone()), alice().identity.hash(), @@ -402,7 +403,7 @@ fn remove_account_empty_account_check_works() { )); let bob = private_member_account(bob()); - let call = add_account_call(bob); + let call = add_account_call::(bob, None); assert_ok!(OmniAccount::dispatch_as_omni_account( RuntimeOrigin::signed(tee_signer.clone()), alice().identity.hash(), @@ -442,7 +443,7 @@ fn publicize_account_works() { alice().identity.clone(), )); - let call = add_account_call(private_bob.clone()); + let call = add_account_call::(private_bob.clone(), None); assert_ok!(OmniAccount::dispatch_as_omni_account( RuntimeOrigin::signed(tee_signer.clone()), alice().identity.hash(), @@ -517,7 +518,7 @@ fn publicize_account_identity_not_found_works() { alice().identity, )); - let call = add_account_call(bob.clone()); + let call = add_account_call::(bob.clone(), None); assert_ok!(OmniAccount::dispatch_as_omni_account( RuntimeOrigin::signed(tee_signer.clone()), alice().identity.hash(), @@ -555,7 +556,7 @@ fn request_intent_works() { alice().identity )); - let call = add_account_call(bob); + let call = add_account_call::(bob, None); assert_ok!(OmniAccount::dispatch_as_omni_account( RuntimeOrigin::signed(tee_signer.clone()), alice().identity.hash(), @@ -602,7 +603,7 @@ fn dispatch_as_signed_works() { alice().identity, )); - let call = add_account_call(private_member_account(bob())); + let call = add_account_call::(private_member_account(bob()), None); assert_ok!(OmniAccount::dispatch_as_omni_account( RuntimeOrigin::signed(tee_signer.clone()), alice().identity.hash(), @@ -638,7 +639,7 @@ fn dispatch_as_omni_account_increments_omni_account_nonce() { assert_eq!(System::account_nonce(alice().omni_account), 0); - let call = add_account_call(bob.clone()); + let call = add_account_call::(bob.clone(), None); assert_ok!(OmniAccount::dispatch_as_omni_account( RuntimeOrigin::signed(tee_signer.clone()), alice().identity.hash(), From c86a12fe86db28f3aa177034c93cdbc7069b488b Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Fri, 13 Dec 2024 11:55:01 +0000 Subject: [PATCH 17/28] adding tests for permissions --- parachain/pallets/omni-account/src/tests.rs | 89 +++++++++++++++++++++ 1 file changed, 89 insertions(+) diff --git a/parachain/pallets/omni-account/src/tests.rs b/parachain/pallets/omni-account/src/tests.rs index f09afd9f56..f3c559b2da 100644 --- a/parachain/pallets/omni-account/src/tests.rs +++ b/parachain/pallets/omni-account/src/tests.rs @@ -677,3 +677,92 @@ fn dispatch_as_signed_account_increments_omni_account_nonce() { assert_eq!(System::account_nonce(alice().omni_account), 1); }); } + +#[test] +fn ensure_permission_works() { + new_test_ext().execute_with(|| { + // Create account store + let tee_signer = get_tee_signer(); + + assert_ok!(OmniAccount::create_account_store( + RuntimeOrigin::signed(tee_signer.clone()), + alice().identity, + )); + + // Add account member without permissions to remove accounts + let bob = private_member_account(bob()); + let bob_permissions = vec![Permission::RequestEthereumIntent, Permission::AddAccounts]; + + let call = add_account_call::(bob.clone(), Some(bob_permissions.clone())); + assert_ok!(OmniAccount::dispatch_as_omni_account( + RuntimeOrigin::signed(tee_signer.clone()), + alice().identity.hash(), + call, + )); + + // An account with no permissions cannot remove accounts + let call = remove_accounts_call(vec![alice().identity.hash()]); + assert_noop!( + OmniAccount::dispatch_as_omni_account( + RuntimeOrigin::signed(tee_signer.clone()), + bob.hash(), + call, + ), + Error::::NoPermission + ); + + // An Account cannot be added with more permissions than the account that added it + let charlie = private_member_account(charlie()); + let charlie_permissions = vec![Permission::All]; + let call = add_account_call::(charlie.clone(), Some(charlie_permissions)); + assert_noop!( + OmniAccount::dispatch_as_omni_account( + RuntimeOrigin::signed(tee_signer.clone()), + bob.hash(), + call, + ), + Error::::NoPermission + ); + + let mut charlie_permissions = vec![Permission::Balances]; + charlie_permissions.extend_from_slice(&bob_permissions); + let call = add_account_call::(charlie.clone(), Some(charlie_permissions)); + assert_noop!( + OmniAccount::dispatch_as_omni_account( + RuntimeOrigin::signed(tee_signer.clone()), + bob.hash(), + call, + ), + Error::::NoPermission + ); + + let charlie_permissions = vec![Permission::RequestEthereumIntent, Permission::AddAccounts]; + let call = add_account_call::(charlie, Some(charlie_permissions)); + assert_ok!(OmniAccount::dispatch_as_omni_account( + RuntimeOrigin::signed(tee_signer.clone()), + bob.hash(), + call, + )); + + // Permissions should also work for dispatch_as_signed + assert_ok!(Balances::transfer_keep_alive( + RuntimeOrigin::signed(alice().native_account), + alice().omni_account, + 6 + )); + let call = make_balance_transfer_call(dave().native_account, 5); + assert_noop!( + OmniAccount::dispatch_as_signed( + RuntimeOrigin::signed(tee_signer.clone()), + bob.hash(), + call.clone() + ), + Error::::NoPermission + ); + assert_ok!(OmniAccount::dispatch_as_signed( + RuntimeOrigin::signed(tee_signer), + alice().identity.hash(), + call + )); + }); +} From 91ae891f9c57fba0ccab08676cc7625a676cb58f Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Fri, 13 Dec 2024 13:14:02 +0000 Subject: [PATCH 18/28] updating mock --- parachain/pallets/omni-account/src/mock.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/parachain/pallets/omni-account/src/mock.rs b/parachain/pallets/omni-account/src/mock.rs index ad464295c6..f3de2d65ee 100644 --- a/parachain/pallets/omni-account/src/mock.rs +++ b/parachain/pallets/omni-account/src/mock.rs @@ -193,17 +193,17 @@ impl Default for Permission { impl InstanceFilter for Permission { fn filter(&self, call: &RuntimeCall) -> bool { match self { - Permission::All => true, - Permission::Balances => matches!(call, RuntimeCall::Balances { .. }), - Permission::RemoveAccounts => matches!( + Self::All => true, + Self::Balances => matches!(call, RuntimeCall::Balances { .. }), + Self::RemoveAccounts => matches!( call, RuntimeCall::OmniAccount(pallet_omni_account::Call::remove_accounts { .. }) ), - Permission::AddAccounts => matches!( + Self::AddAccounts => matches!( call, RuntimeCall::OmniAccount(pallet_omni_account::Call::add_account { .. }) ), - Permission::RequestEthereumIntent => { + Self::RequestEthereumIntent => { if let RuntimeCall::OmniAccount(pallet_omni_account::Call::request_intent { intent, }) = call From 60d019962af822017274bd145d2ce74101f60533 Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Fri, 13 Dec 2024 13:34:00 +0000 Subject: [PATCH 19/28] adding Permission type to runtimes --- parachain/runtime/litentry/src/lib.rs | 86 +++++++++++++++++++++++++++ parachain/runtime/paseo/src/lib.rs | 86 +++++++++++++++++++++++++++ 2 files changed, 172 insertions(+) diff --git a/parachain/runtime/litentry/src/lib.rs b/parachain/runtime/litentry/src/lib.rs index ff555e4d85..b1416f43f2 100644 --- a/parachain/runtime/litentry/src/lib.rs +++ b/parachain/runtime/litentry/src/lib.rs @@ -1112,6 +1112,90 @@ impl pallet_identity_management::Config for Runtime { type MaxOIDCClientRedirectUris = ConstU32<10>; } +#[derive( + Copy, + Clone, + PartialEq, + Eq, + Ord, + PartialOrd, + Encode, + Decode, + MaxEncodedLen, + RuntimeDebug, + scale_info::TypeInfo, +)] +pub enum OmniAccountPermission { + All, + AccountManagement, + RequestNativeIntent, + RequestEthereumIntent, + RequestSolanaIntent, +} + +impl Default for OmniAccountPermission { + fn default() -> Self { + Self::All + } +} + +impl InstanceFilter for OmniAccountPermission { + fn filter(&self, call: &RuntimeCall) -> bool { + match self { + Self::All => true, + Self::AccountManagement => { + matches!( + call, + RuntimeCall::OmniAccount(pallet_omni_account::Call::add_account { .. }) + | RuntimeCall::OmniAccount( + pallet_omni_account::Call::remove_accounts { .. } + ) | RuntimeCall::OmniAccount( + pallet_omni_account::Call::publicize_account { .. } + ) + ) + }, + Self::RequestNativeIntent => { + if let RuntimeCall::OmniAccount(pallet_omni_account::Call::request_intent { + intent, + }) = call + { + matches!( + intent, + pallet_omni_account::Intent::SystemRemark(_) + | pallet_omni_account::Intent::TransferNative(_) + ) + } else { + false + } + }, + Self::RequestEthereumIntent => { + if let RuntimeCall::OmniAccount(pallet_omni_account::Call::request_intent { + intent, + }) = call + { + matches!( + intent, + pallet_omni_account::Intent::TransferEthereum(_) + | pallet_omni_account::Intent::CallEthereum(_) + ) + } else { + false + } + }, + Self::RequestSolanaIntent => { + if let RuntimeCall::OmniAccount(pallet_omni_account::Call::request_intent { + intent, + }) = call + { + matches!(intent, pallet_omni_account::Intent::TransferSolana(_)) + } else { + false + } + }, + } + } +} + impl pallet_omni_account::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; @@ -1120,6 +1204,8 @@ impl pallet_omni_account::Config for Runtime { type MaxAccountStoreLength = ConstU32<64>; type OmniAccountOrigin = EnsureOmniAccount; type OmniAccountConverter = DefaultOmniAccountConverter; + type MaxPermissions = ConstU32<4>; + type Permission = OmniAccountPermission; } impl pallet_evm_assertions::Config for Runtime { diff --git a/parachain/runtime/paseo/src/lib.rs b/parachain/runtime/paseo/src/lib.rs index 597509e9b2..433257c9cb 100644 --- a/parachain/runtime/paseo/src/lib.rs +++ b/parachain/runtime/paseo/src/lib.rs @@ -1157,6 +1157,90 @@ impl pallet_identity_management::Config for Runtime { type MaxOIDCClientRedirectUris = ConstU32<10>; } +#[derive( + Copy, + Clone, + PartialEq, + Eq, + Ord, + PartialOrd, + Encode, + Decode, + MaxEncodedLen, + RuntimeDebug, + scale_info::TypeInfo, +)] +pub enum OmniAccountPermission { + All, + AccountManagement, + RequestNativeIntent, + RequestEthereumIntent, + RequestSolanaIntent, +} + +impl Default for OmniAccountPermission { + fn default() -> Self { + Self::All + } +} + +impl InstanceFilter for OmniAccountPermission { + fn filter(&self, call: &RuntimeCall) -> bool { + match self { + Self::All => true, + Self::AccountManagement => { + matches!( + call, + RuntimeCall::OmniAccount(pallet_omni_account::Call::add_account { .. }) + | RuntimeCall::OmniAccount( + pallet_omni_account::Call::remove_accounts { .. } + ) | RuntimeCall::OmniAccount( + pallet_omni_account::Call::publicize_account { .. } + ) + ) + }, + Self::RequestNativeIntent => { + if let RuntimeCall::OmniAccount(pallet_omni_account::Call::request_intent { + intent, + }) = call + { + matches!( + intent, + pallet_omni_account::Intent::SystemRemark(_) + | pallet_omni_account::Intent::TransferNative(_) + ) + } else { + false + } + }, + Self::RequestEthereumIntent => { + if let RuntimeCall::OmniAccount(pallet_omni_account::Call::request_intent { + intent, + }) = call + { + matches!( + intent, + pallet_omni_account::Intent::TransferEthereum(_) + | pallet_omni_account::Intent::CallEthereum(_) + ) + } else { + false + } + }, + Self::RequestSolanaIntent => { + if let RuntimeCall::OmniAccount(pallet_omni_account::Call::request_intent { + intent, + }) = call + { + matches!(intent, pallet_omni_account::Intent::TransferSolana(_)) + } else { + false + } + }, + } + } +} + impl pallet_omni_account::Config for Runtime { type RuntimeOrigin = RuntimeOrigin; type RuntimeCall = RuntimeCall; @@ -1165,6 +1249,8 @@ impl pallet_omni_account::Config for Runtime { type MaxAccountStoreLength = ConstU32<64>; type OmniAccountOrigin = EnsureOmniAccount; type OmniAccountConverter = DefaultOmniAccountConverter; + type MaxPermissions = ConstU32<4>; + type Permission = OmniAccountPermission; } impl pallet_bitacross::Config for Runtime { From 7ae5959e545c2c5716aac8585b94e93b235bcbb3 Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Fri, 13 Dec 2024 15:32:14 +0000 Subject: [PATCH 20/28] updating permissions mock and tests --- parachain/pallets/omni-account/src/mock.rs | 60 +++++++++++++++------ parachain/pallets/omni-account/src/tests.rs | 41 +++++++++----- 2 files changed, 72 insertions(+), 29 deletions(-) diff --git a/parachain/pallets/omni-account/src/mock.rs b/parachain/pallets/omni-account/src/mock.rs index f3de2d65ee..c6cd643d1c 100644 --- a/parachain/pallets/omni-account/src/mock.rs +++ b/parachain/pallets/omni-account/src/mock.rs @@ -176,33 +176,49 @@ impl pallet_teebag::Config for Test { MaxEncodedLen, scale_info::TypeInfo, )] -pub enum Permission { +pub enum OmniAccountPermission { All, - Balances, - AddAccounts, - RemoveAccounts, + AccountManagement, + RequestNativeIntent, RequestEthereumIntent, + RequestSolanaIntent, } -impl Default for Permission { +impl Default for OmniAccountPermission { fn default() -> Self { Self::All } } -impl InstanceFilter for Permission { +impl InstanceFilter for OmniAccountPermission { fn filter(&self, call: &RuntimeCall) -> bool { match self { Self::All => true, - Self::Balances => matches!(call, RuntimeCall::Balances { .. }), - Self::RemoveAccounts => matches!( - call, - RuntimeCall::OmniAccount(pallet_omni_account::Call::remove_accounts { .. }) - ), - Self::AddAccounts => matches!( - call, - RuntimeCall::OmniAccount(pallet_omni_account::Call::add_account { .. }) - ), + Self::AccountManagement => { + matches!( + call, + RuntimeCall::OmniAccount(pallet_omni_account::Call::add_account { .. }) + | RuntimeCall::OmniAccount( + pallet_omni_account::Call::remove_accounts { .. } + ) | RuntimeCall::OmniAccount( + pallet_omni_account::Call::publicize_account { .. } + ) + ) + }, + Self::RequestNativeIntent => { + if let RuntimeCall::OmniAccount(pallet_omni_account::Call::request_intent { + intent, + }) = call + { + matches!( + intent, + pallet_omni_account::Intent::SystemRemark(_) + | pallet_omni_account::Intent::TransferNative(_) + ) + } else { + false + } + }, Self::RequestEthereumIntent => { if let RuntimeCall::OmniAccount(pallet_omni_account::Call::request_intent { intent, @@ -217,6 +233,16 @@ impl InstanceFilter for Permission { false } }, + Self::RequestSolanaIntent => { + if let RuntimeCall::OmniAccount(pallet_omni_account::Call::request_intent { + intent, + }) = call + { + matches!(intent, pallet_omni_account::Intent::TransferSolana(_)) + } else { + false + } + }, } } } @@ -229,8 +255,8 @@ impl pallet_omni_account::Config for Test { type MaxAccountStoreLength = ConstU32<3>; type OmniAccountOrigin = EnsureOmniAccount; type OmniAccountConverter = DefaultOmniAccountConverter; - type MaxPermissions = ConstU32<3>; - type Permission = Permission; + type MaxPermissions = ConstU32<4>; + type Permission = OmniAccountPermission; } pub fn get_tee_signer() -> SystemAccountId { diff --git a/parachain/pallets/omni-account/src/tests.rs b/parachain/pallets/omni-account/src/tests.rs index f3c559b2da..ae409a28d7 100644 --- a/parachain/pallets/omni-account/src/tests.rs +++ b/parachain/pallets/omni-account/src/tests.rs @@ -22,7 +22,7 @@ use sp_core::H160; use sp_runtime::{traits::BadOrigin, ModuleError}; use sp_std::vec; -fn add_account_call>( +fn add_account_call>( account: MemberAccount, permissions: Option::Permission>>, ) -> Box { @@ -170,12 +170,12 @@ fn add_account_works() { assert!(MemberAccountPermissions::::contains_key(bob.hash())); assert_eq!( MemberAccountPermissions::::get(bob.hash()).to_vec(), - vec![Permission::All] + vec![OmniAccountPermission::All] ); assert!(MemberAccountPermissions::::contains_key(charlie.hash())); assert_eq!( MemberAccountPermissions::::get(charlie.hash()).to_vec(), - vec![Permission::All] + vec![OmniAccountPermission::All] ); }); } @@ -691,7 +691,11 @@ fn ensure_permission_works() { // Add account member without permissions to remove accounts let bob = private_member_account(bob()); - let bob_permissions = vec![Permission::RequestEthereumIntent, Permission::AddAccounts]; + let bob_permissions = vec![ + OmniAccountPermission::RequestEthereumIntent, + OmniAccountPermission::RequestSolanaIntent, + OmniAccountPermission::AccountManagement, + ]; let call = add_account_call::(bob.clone(), Some(bob_permissions.clone())); assert_ok!(OmniAccount::dispatch_as_omni_account( @@ -700,8 +704,9 @@ fn ensure_permission_works() { call, )); - // An account with no permissions cannot remove accounts - let call = remove_accounts_call(vec![alice().identity.hash()]); + // An Account cannot be added with more permissions than the account that added it + let charlie = private_member_account(charlie()); + let call = add_account_call::(charlie.clone(), None); // default permission assert_noop!( OmniAccount::dispatch_as_omni_account( RuntimeOrigin::signed(tee_signer.clone()), @@ -711,9 +716,7 @@ fn ensure_permission_works() { Error::::NoPermission ); - // An Account cannot be added with more permissions than the account that added it - let charlie = private_member_account(charlie()); - let charlie_permissions = vec![Permission::All]; + let charlie_permissions = vec![OmniAccountPermission::All]; let call = add_account_call::(charlie.clone(), Some(charlie_permissions)); assert_noop!( OmniAccount::dispatch_as_omni_account( @@ -724,7 +727,7 @@ fn ensure_permission_works() { Error::::NoPermission ); - let mut charlie_permissions = vec![Permission::Balances]; + let mut charlie_permissions = vec![OmniAccountPermission::RequestNativeIntent]; charlie_permissions.extend_from_slice(&bob_permissions); let call = add_account_call::(charlie.clone(), Some(charlie_permissions)); assert_noop!( @@ -736,14 +739,28 @@ fn ensure_permission_works() { Error::::NoPermission ); - let charlie_permissions = vec![Permission::RequestEthereumIntent, Permission::AddAccounts]; - let call = add_account_call::(charlie, Some(charlie_permissions)); + let charlie_permissions = vec![ + OmniAccountPermission::RequestEthereumIntent, + OmniAccountPermission::RequestSolanaIntent, + ]; + let call = add_account_call::(charlie.clone(), Some(charlie_permissions)); assert_ok!(OmniAccount::dispatch_as_omni_account( RuntimeOrigin::signed(tee_signer.clone()), bob.hash(), call, )); + // An account with no permissions cannot remove accounts + let call = remove_accounts_call(vec![alice().identity.hash()]); + assert_noop!( + OmniAccount::dispatch_as_omni_account( + RuntimeOrigin::signed(tee_signer.clone()), + charlie.hash(), + call, + ), + Error::::NoPermission + ); + // Permissions should also work for dispatch_as_signed assert_ok!(Balances::transfer_keep_alive( RuntimeOrigin::signed(alice().native_account), From f7297380fbb3529211e9bc3c5ccd52c41bad196b Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Fri, 13 Dec 2024 16:06:12 +0000 Subject: [PATCH 21/28] adding set_permissions call --- parachain/pallets/omni-account/src/lib.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/parachain/pallets/omni-account/src/lib.rs b/parachain/pallets/omni-account/src/lib.rs index 9a045ace99..b3ab9131c7 100644 --- a/parachain/pallets/omni-account/src/lib.rs +++ b/parachain/pallets/omni-account/src/lib.rs @@ -188,6 +188,8 @@ pub mod pallet { IntentRequested { who: T::AccountId, intent: Intent }, /// Intent is executed IntentExecuted { who: T::AccountId, intent: Intent, result: IntentExecutionResult }, + /// Member permission set + AccountPermissionsSet { who: T::AccountId, member_account_hash: H256 }, } #[pallet::error] @@ -422,6 +424,21 @@ pub mod pallet { Self::deposit_event(Event::IntentExecuted { who, intent, result }); Ok(()) } + + #[pallet::call_index(9)] + #[pallet::weight((195_000_000, DispatchClass::Normal))] + pub fn set_permissions( + origin: OriginFor, + member_account_hash: H256, + permissions: Vec, + ) -> DispatchResult { + let who = T::OmniAccountOrigin::ensure_origin(origin)?; + let member_permissions: BoundedVec = + { permissions.try_into().map_err(|_| Error::::PermissionsLenLimitReached)? }; + MemberAccountPermissions::::insert(member_account_hash, member_permissions); + Self::deposit_event(Event::AccountPermissionsSet { who, member_account_hash }); + Ok(()) + } } impl Pallet { From f34e5baf09746bcd811a019be658a9a2a94312c9 Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Fri, 13 Dec 2024 16:06:33 +0000 Subject: [PATCH 22/28] adjusting ensure_permission --- parachain/pallets/omni-account/src/lib.rs | 46 +++++++++++++++-------- 1 file changed, 31 insertions(+), 15 deletions(-) diff --git a/parachain/pallets/omni-account/src/lib.rs b/parachain/pallets/omni-account/src/lib.rs index b3ab9131c7..c9fd1a0baf 100644 --- a/parachain/pallets/omni-account/src/lib.rs +++ b/parachain/pallets/omni-account/src/lib.rs @@ -493,21 +493,37 @@ pub mod pallet { Error::::NoPermission ); - if let Some(Call::add_account { permissions: ref new_account_permissions, .. }) = - call.is_sub_type() - { - // If member has default permission, they can add accounts with any permission - if member_permissions.contains(&T::Permission::default()) { - return Ok(()); - } - - if let Some(new_account_permissions) = new_account_permissions { - // an account can only add another account with the same or less permissions - ensure!( - new_account_permissions.iter().all(|p| member_permissions.contains(p)), - Error::::NoPermission - ) - } + match call.is_sub_type() { + Some(Call::add_account { permissions: ref new_account_permissions, .. }) => { + // If member has default permission, they can add accounts with any permission + if member_permissions.contains(&T::Permission::default()) { + return Ok(()); + } + match new_account_permissions { + Some(new_permissions) => { + // an account can only add another account with the same or less permissions + if !new_permissions.iter().all(|p| member_permissions.contains(p)) { + return Err(Error::::NoPermission); + } + }, + None => { + // None is equivalent to default permission. It should not be allowed + // if the member_permissions have no default permission + return Err(Error::::NoPermission); + }, + } + }, + Some(Call::set_permissions { permissions: ref new_permissions, .. }) => { + // If member has default permission, they can set permissions to any value + if member_permissions.contains(&T::Permission::default()) { + return Ok(()); + } + // an account can only set permissions to the same or less permissions + if !new_permissions.iter().all(|p| member_permissions.contains(p)) { + return Err(Error::::NoPermission); + } + }, + _ => return Ok(()), } Ok(()) From 8779cac516bdd093c99236e51964748a99770501 Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Fri, 13 Dec 2024 16:06:49 +0000 Subject: [PATCH 23/28] updating mock --- parachain/pallets/omni-account/src/mock.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parachain/pallets/omni-account/src/mock.rs b/parachain/pallets/omni-account/src/mock.rs index c6cd643d1c..1c51bff75f 100644 --- a/parachain/pallets/omni-account/src/mock.rs +++ b/parachain/pallets/omni-account/src/mock.rs @@ -202,7 +202,7 @@ impl InstanceFilter for OmniAccountPermission { pallet_omni_account::Call::remove_accounts { .. } ) | RuntimeCall::OmniAccount( pallet_omni_account::Call::publicize_account { .. } - ) + ) | RuntimeCall::OmniAccount(pallet_omni_account::Call::set_permissions { .. }) ) }, Self::RequestNativeIntent => { From eddcf79bea0cbb256a1f644c9382cc12556301cd Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Fri, 13 Dec 2024 16:07:00 +0000 Subject: [PATCH 24/28] updating permission filters in the runtimes --- parachain/runtime/litentry/src/lib.rs | 2 +- parachain/runtime/paseo/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/parachain/runtime/litentry/src/lib.rs b/parachain/runtime/litentry/src/lib.rs index b1416f43f2..80e06926d1 100644 --- a/parachain/runtime/litentry/src/lib.rs +++ b/parachain/runtime/litentry/src/lib.rs @@ -1151,7 +1151,7 @@ impl InstanceFilter for OmniAccountPermission { pallet_omni_account::Call::remove_accounts { .. } ) | RuntimeCall::OmniAccount( pallet_omni_account::Call::publicize_account { .. } - ) + ) | RuntimeCall::OmniAccount(pallet_omni_account::Call::set_permissions { .. }) ) }, Self::RequestNativeIntent => { diff --git a/parachain/runtime/paseo/src/lib.rs b/parachain/runtime/paseo/src/lib.rs index 433257c9cb..38402cc395 100644 --- a/parachain/runtime/paseo/src/lib.rs +++ b/parachain/runtime/paseo/src/lib.rs @@ -1196,7 +1196,7 @@ impl InstanceFilter for OmniAccountPermission { pallet_omni_account::Call::remove_accounts { .. } ) | RuntimeCall::OmniAccount( pallet_omni_account::Call::publicize_account { .. } - ) + ) | RuntimeCall::OmniAccount(pallet_omni_account::Call::set_permissions { .. }) ) }, Self::RequestNativeIntent => { From 81b8c36f0ba3a053294577b6f1ef7142925722cf Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Fri, 13 Dec 2024 16:07:37 +0000 Subject: [PATCH 25/28] adding tests for set_permissions call --- parachain/pallets/omni-account/src/tests.rs | 103 ++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/parachain/pallets/omni-account/src/tests.rs b/parachain/pallets/omni-account/src/tests.rs index ae409a28d7..7cc813cd81 100644 --- a/parachain/pallets/omni-account/src/tests.rs +++ b/parachain/pallets/omni-account/src/tests.rs @@ -51,6 +51,15 @@ fn make_balance_transfer_call(dest: AccountId, value: Balance) -> Box, +) -> Box { + let call = + RuntimeCall::OmniAccount(crate::Call::set_permissions { member_account_hash, permissions }); + Box::new(call) +} + #[test] fn create_account_store_works() { new_test_ext().execute_with(|| { @@ -783,3 +792,97 @@ fn ensure_permission_works() { )); }); } + +#[test] +fn set_permissions_works() { + new_test_ext().execute_with(|| { + // Create account store and add accounts + let tee_signer = get_tee_signer(); + + assert_ok!(OmniAccount::create_account_store( + RuntimeOrigin::signed(tee_signer.clone()), + alice().identity, + )); + + let bob = private_member_account(bob()); + let bob_permissions = vec![ + OmniAccountPermission::RequestEthereumIntent, + OmniAccountPermission::RequestSolanaIntent, + OmniAccountPermission::AccountManagement, + ]; + + let call = add_account_call::(bob.clone(), Some(bob_permissions.clone())); + assert_ok!(OmniAccount::dispatch_as_omni_account( + RuntimeOrigin::signed(tee_signer.clone()), + alice().identity.hash(), + call, + )); + + let charlie = private_member_account(charlie()); + let charlie_permissions = vec![OmniAccountPermission::RequestNativeIntent]; + let call = add_account_call::(charlie.clone(), Some(charlie_permissions.clone())); + assert_ok!(OmniAccount::dispatch_as_omni_account( + RuntimeOrigin::signed(tee_signer.clone()), + alice().identity.hash(), + call, + )); + + // Assert Set permissions + + // The caller cannot upgrade his permissions + let new_permissions = vec![OmniAccountPermission::All]; + let call = set_permissions_call(bob.hash(), new_permissions.clone()); + assert_noop!( + OmniAccount::dispatch_as_omni_account( + RuntimeOrigin::signed(tee_signer.clone()), + bob.hash(), + call, + ), + Error::::NoPermission + ); + + // The caller cannot set a permission that he does not have + let new_permissions = vec![OmniAccountPermission::RequestNativeIntent]; + let call = set_permissions_call(alice().identity.hash(), new_permissions.clone()); + assert_noop!( + OmniAccount::dispatch_as_omni_account( + RuntimeOrigin::signed(tee_signer.clone()), + bob.hash(), + call, + ), + Error::::NoPermission + ); + + // The caller can set permissions he has + let new_permissions = vec![ + OmniAccountPermission::AccountManagement, + OmniAccountPermission::RequestSolanaIntent, + ]; + let call = set_permissions_call(charlie.hash(), new_permissions.clone()); + assert_ok!(OmniAccount::dispatch_as_omni_account( + RuntimeOrigin::signed(tee_signer.clone()), + bob.hash(), + call, + )); + + // The caller most have permission to set_permissions + let call = set_permissions_call(bob.hash(), charlie_permissions); + assert_noop!( + OmniAccount::dispatch_as_omni_account( + RuntimeOrigin::signed(tee_signer.clone()), + charlie.hash(), + call, + ), + Error::::NoPermission + ); + + // The caller can set any permissions as if she has default permissions (All) + let new_permissions = vec![OmniAccountPermission::All]; + let call = set_permissions_call(charlie.hash(), new_permissions.clone()); + assert_ok!(OmniAccount::dispatch_as_omni_account( + RuntimeOrigin::signed(tee_signer.clone()), + alice().identity.hash(), + call, + )); + }); +} From e91a4701ad4e93493d505980585045fc4dfe424a Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Fri, 13 Dec 2024 16:53:36 +0000 Subject: [PATCH 26/28] adding temporary fix for add_account --- .../identity/litentry/core/native-task/receiver/src/lib.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/tee-worker/identity/litentry/core/native-task/receiver/src/lib.rs b/tee-worker/identity/litentry/core/native-task/receiver/src/lib.rs index 914feba597..757c252822 100644 --- a/tee-worker/identity/litentry/core/native-task/receiver/src/lib.rs +++ b/tee-worker/identity/litentry/core/native-task/receiver/src/lib.rs @@ -409,6 +409,10 @@ fn handle_trusted_call> = None; // default permissions + OpaqueCall::from_tuple(&compose_call!( &metadata, "OmniAccount", @@ -418,7 +422,8 @@ fn handle_trusted_call Date: Sat, 14 Dec 2024 09:35:02 +0000 Subject: [PATCH 27/28] update storage on remove accounts --- parachain/pallets/omni-account/src/lib.rs | 1 + parachain/pallets/omni-account/src/tests.rs | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/parachain/pallets/omni-account/src/lib.rs b/parachain/pallets/omni-account/src/lib.rs index c9fd1a0baf..2960a670f9 100644 --- a/parachain/pallets/omni-account/src/lib.rs +++ b/parachain/pallets/omni-account/src/lib.rs @@ -321,6 +321,7 @@ pub mod pallet { member_accounts.retain(|member| { if member_account_hashes.contains(&member.hash()) { MemberAccountHash::::remove(member.hash()); + MemberAccountPermissions::::remove(member.hash()); false } else { true diff --git a/parachain/pallets/omni-account/src/tests.rs b/parachain/pallets/omni-account/src/tests.rs index 7cc813cd81..d30e0d2008 100644 --- a/parachain/pallets/omni-account/src/tests.rs +++ b/parachain/pallets/omni-account/src/tests.rs @@ -175,13 +175,13 @@ fn add_account_works() { ); assert!(MemberAccountHash::::contains_key(bob.hash())); - assert!(MemberAccountHash::::contains_key(charlie.hash())); assert!(MemberAccountPermissions::::contains_key(bob.hash())); + assert!(MemberAccountHash::::contains_key(charlie.hash())); + assert!(MemberAccountPermissions::::contains_key(charlie.hash())); assert_eq!( MemberAccountPermissions::::get(bob.hash()).to_vec(), vec![OmniAccountPermission::All] ); - assert!(MemberAccountPermissions::::contains_key(charlie.hash())); assert_eq!( MemberAccountPermissions::::get(charlie.hash()).to_vec(), vec![OmniAccountPermission::All] @@ -389,6 +389,7 @@ fn remove_account_works() { expected_member_accounts ); assert!(!MemberAccountHash::::contains_key(bob.hash())); + assert!(!MemberAccountPermissions::::contains_key(bob.hash())); let call = remove_accounts_call(vec![alice().identity.hash()]); assert_ok!(OmniAccount::dispatch_as_omni_account( From a4876f150a48af85d7c0f562ace270eb21842a86 Mon Sep 17 00:00:00 2001 From: Francisco Silva Date: Mon, 16 Dec 2024 15:31:41 +0000 Subject: [PATCH 28/28] setting default permission when empty, only if the sender has default permission --- parachain/pallets/omni-account/src/lib.rs | 18 ++++++++++-------- parachain/pallets/omni-account/src/tests.rs | 2 +- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/parachain/pallets/omni-account/src/lib.rs b/parachain/pallets/omni-account/src/lib.rs index 2960a670f9..d724e324af 100644 --- a/parachain/pallets/omni-account/src/lib.rs +++ b/parachain/pallets/omni-account/src/lib.rs @@ -285,13 +285,13 @@ pub mod pallet { member_accounts .try_push(member_account) .map_err(|_| Error::::AccountStoreLenLimitReached)?; - let member_permissions: BoundedVec = { - let p = match permissions { - Some(p) => p, - None => vec![T::Permission::default()], - }; - p.try_into().map_err(|_| Error::::PermissionsLenLimitReached)? - }; + let member_permissions: BoundedVec = permissions + .map_or_else( + || vec![T::Permission::default()], + |p| if p.is_empty() { vec![T::Permission::default()] } else { p }, + ) + .try_into() + .map_err(|_| Error::::PermissionsLenLimitReached)?; MemberAccountHash::::insert(hash, who.clone()); MemberAccountPermissions::::insert(hash, member_permissions); @@ -503,7 +503,9 @@ pub mod pallet { match new_account_permissions { Some(new_permissions) => { // an account can only add another account with the same or less permissions - if !new_permissions.iter().all(|p| member_permissions.contains(p)) { + if new_permissions.is_empty() + || !new_permissions.iter().all(|p| member_permissions.contains(p)) + { return Err(Error::::NoPermission); } }, diff --git a/parachain/pallets/omni-account/src/tests.rs b/parachain/pallets/omni-account/src/tests.rs index d30e0d2008..451fe6a1fd 100644 --- a/parachain/pallets/omni-account/src/tests.rs +++ b/parachain/pallets/omni-account/src/tests.rs @@ -123,7 +123,7 @@ fn add_account_works() { alice().identity, )); - let call = add_account_call::(bob.clone(), None); + let call = add_account_call::(bob.clone(), Some(vec![])); assert_ok!(OmniAccount::dispatch_as_omni_account( RuntimeOrigin::signed(tee_signer.clone()), alice().identity.hash(),